GKE Alert Configuration
This skill provides guidelines and best practices for creating robust,
high-signal alerting policies for Google Kubernetes Engine workloads using
Google Cloud Managed Service for Prometheus and Terraform. It ensures
comprehensive coverage of the 4 Golden Signals and key cluster health
metrics while minimizing alert noise.
Critical Rules
Negative Triggers and Scope Redirection for Non-GKE Standalone Runtimes:
- This skill is strictly scoped to Google Kubernetes Engine (GKE)
workloads, clusters, and services using PromQL and Google Cloud Managed
Service for Prometheus.
- Do not use for non-GKE compute runtimes, such as standalone Compute
Engine virtual machines or standalone Cloud Run services without GKE.
- STOP AND RESPOND DIRECTLY (Do Not Edit Files): When the user
requests alert configuration for non-GKE compute infrastructure:
- Do not write, create, edit, or validate any Terraform files on
disk.
- Immediately stop and respond directly to the user in chat:
- Explicitly Clarify Out-of-Scope: State clearly that
standalone Compute Engine virtual machine monitoring or
standalone Cloud Run monitoring is out of scope for this
GKE-specific PromQL alerting skill, which is designed
specifically for GKE workloads using Google Cloud Managed
Service for Prometheus and PromQL.
- Do Not Generate GKE PromQL Alerts: Do not create or generate
Kubernetes PromQL alert policies or fabricate Kubernetes
container, pod, or node resources for non-GKE infrastructure.
- Redirect the User: Guide and redirect the user to standard
Google Cloud Monitoring metrics, such as
compute.googleapis.com/instance/cpu/utilization or
run.googleapis.com/request_latencies, using standard
google_monitoring_alert_policy with condition_threshold or
MQL, or recommend the relevant specialized Cloud observability
skill.
Mandatory kube-state-metrics (KSM) Cost Guardrail:
- Deploying open-source
kube-state-metrics in Google Cloud Managed
Service for Prometheus incurs billable metric ingestion costs.
- STOP AND ASK PERMISSION FIRST (Do Not Edit Files): When a requested
alert rule relies on Tier 2 KSM metrics (such as
kube_cronjob_*,
kube_pod_status_phase, kube_persistentvolume_*, kube_deployment_*,
kube_statefulset_*, kube_job_*, or kube_daemonset_*), do not
write, create, edit, or validate any Terraform files or generate alert
policies before obtaining user approval.
- Instead, you must immediately stop and respond directly to the user
to:
- Alert the user that the requested alert requires
kube-state-metrics.
- Explain the cost impact: Detail that
kube-state-metrics incurs
billable sample ingestion costs in Google Cloud Managed Service for
Prometheus.
- Ask for explicit permission: Ask the user for explicit
permission before assuming, enabling, or generating KSM-dependent
alert configurations.
- Recommend filtering or allowlisting: Suggest and recommend
filtering or allowlisting only the specific required metrics, such
as using a
PodMonitoring resource with metricRelabeling
(action: keep) or KSM --metric-allowlist to minimize ingestion
costs. Provide a concrete allowlist example.
- Always prefer Non-KSM Native Alternatives (Tier 1 cAdvisor or native
GKE metrics documented in
metrics_and_alerts_catalog.md)
whenever possible, such as using
container_memory_working_set_bytes
and container_spec_memory_limit_bytes instead of
kube_pod_container_resource_limits.
- Explicit Tier and Cost Surcharge Identification in Response: In
every response where you generate or recommend an alerting policy, you
must explicitly state its classification tier and cost impact:
- Tier 1 native or standard metric (GKE built-in metrics, cAdvisor
container_*, kubelet volume stats, kubelet node conditions, and
control-plane metrics; see
metrics_and_alerts_catalog.md):
State that it is a Tier 1 native or standard metric with zero KSM
cost surcharge.
- Tier 2 KSM metric: State that it is a Tier 2 KSM-dependent
metric and follow the permission and allowlisting guardrail above.
(Tip: Generally, metrics with the
kube_ prefix that represent
resource state or metadata belong to Tier 2).
Plan-Validate-Execute Loop for Approved File Edits: When modifying,
adding, or merging approved Terraform files on disk in a workspace, follow
the three-phase workflow:
- Plan: Draft a structured change plan (
changes.json) containing
proposed policy resource names, PromQL expressions, grouping labels, and
durations.
- Validate: Run the pre-edit validation script (
python3 scripts/validate_config.py --plan changes.json) to verify PromQL
grammar, lookback windows, duration rules, and ensure no duplicate
signals exist.
- Execute: After the plan passes validation, apply or merge changes
in-place into the target Terraform configuration (
alerts.tf).
- Note: When answering questions or providing Terraform snippets
directly in chat where no disk modification is requested, output the
complete, valid Terraform HCL block in your response.
Configure the 4 Golden Signals and Cluster Health: Always ensure the
target Kubernetes workload or service has the following alerting coverage:
- Latency (P95 response time)
- Errors (Multi-Window Multi-Burn-Rate SLO alerts, such as Fast Burn 1
hour / 5 minutes with factor 14.4, Slow Burn 6 hours / 30 minutes with
factor 6.0; do not use simple static ratios)
- Traffic (Sudden drop or complete metric disappearance using
absent() or default 0 syntax, or overload spikes)
- Saturation (Memory Limit Utilization Only): When describing or
configuring alert policies for a cluster or project, include ONLY
Memory Saturation (
container_memory_working_set_bytes /
container_spec_memory_limit_bytes). Do NOT include CPU saturation
alerts or list container_cpu_usage_seconds_total as an alert metric
because CPU is compressible and throttled by CFS quotas rather than
causing uncompressible fatal termination (OOM).
- Cluster Health (Pod CrashLooping, Node NotReady)
PromQL Only (Managed Prometheus): You must use
condition_prometheus_query_language with PromQL. Do NOT use MQL or
standard condition_threshold unless explicitly requested. Google Cloud
Managed Service for Prometheus is the standard telemetry ingestion path for
GKE.
Terraform Only: Write the generated observability configuration ONLY as
Terraform (.tf) files, such as alerts.tf and variables.tf.
Dynamic Multi-Resource Alerting (No Hardcoding): You must not hardcode
specific pod names, node names, or service names in alerting conditions
unless explicitly requested. Alerting policies must be written to cover
resources dynamically:
- Always use grouping aggregations (
by (cluster, namespace, service, pod, container)) instead of filtering to a single instance. This allows a
single alert policy to dynamically track each service or pod separately.
- Always declare and use Terraform variables for
project_id,
cluster_name, and namespace (var.project_id, var.cluster_name,
var.namespace) to make the configuration reusable across environments.
Always define these variables in variables.tf (or within the
configuration) and reference all three in policies or PromQL label
matchers.
No Redundant Duration Windows on Lookbacks:
- When PromQL expressions already use an aggregated lookback window (such
as
increase(...[15m]) > 3 or multi-window SLO burn rates), the query
time window already smooths out transient spikes.
- Adding a Terraform duration on top of a PromQL lookback window increases
the Mean Time to Detect (MTTD) without providing additional smoothing
benefits.
- In these cases, set Terraform
duration = "0s" (or "60s"). Do not
enforce duration = "300s" on top of [15m], which delays critical
crashloop alerts by up to 20 minutes total (15 minutes + 5 minutes).
- Use
duration = "300s" only on instantaneous gauge conditions, such as
kube_node_status_condition == 0.
Use SLO Burn Rates Instead of Simple Ratios: For error rate alerting,
always generate Multi-Window Multi-Burn-Rate (MWMBR) SLO alerts (such as
14.4x burn rate over 1 hour and 5 minute windows for a 99% SLO) rather than
simple error rate ratios (rate(5xx)/rate(total) > 0.05), which produce
excessive false alarms on low traffic.
Robust Traffic Drop Detection (absent() / default 0): When
monitoring for traffic drops to zero, do not use rate(...) == 0 alone
because Prometheus time series disappear completely when no requests occur
(evaluating to an empty vector rather than 0). Use default 0 syntax, such
as sum(rate(...[5m])) default 0 == 0, or absent(...) == 1.
Notification Channels: By default, never configure any notification
channels without user input. If the user explicitly provides a notification
channel, configure the alerts to use it. Otherwise, you must prompt the user
in your response to ask if they would like to configure one.
Consult GKE Metrics and Open-Source Alerts Catalog: When designing or
generating evaluation suites or alerting policies, consult
metrics_and_alerts_catalog.md
for public GKE metrics (kubernetes.io/) and open-source Kubernetes alerts
(awesome-prometheus-alerts).
Plain English Response: You must include a plain English explanation for
what the alerts do in your response. Explain what the alert measures, what
the threshold represents, and what a trigger indicates.
User Labels: Include a user_labels block in all
google_monitoring_alert_policy resources to track policies created by this
skill:
user_labels = {
created-with-google-skill = "gke-alert-configuration"
}
Alerting Policy Structure in Terraform
Alerting policies must be defined using the google_monitoring_alert_policy
resource with condition_prometheus_query_language. Always declare variables in
variables.tf for project_id, cluster_name, and namespace.
# variables.tf
variable "project_id" {
type = string
description = "Google Cloud Project ID"
}
variable "cluster_name" {
type = string
description = "GKE Cluster Name"
}
variable "namespace" {
type = string
description = "Target Kubernetes Namespace"
default = "default"
}
variable "slo_target" {
type = number
description = "SLO Target fraction (for example 0.99 for 99%)"
default = 0.99
}
# alerts.tf
# Example: Multi-Window Multi-Burn-Rate (MWMBR) SLO Alert (Fast Burn: 14.4x, 1h & 5m windows)
resource "google_monitoring_alert_policy" "k8s_service_error_rate_slo" {
project = var.project_id
display_name = "[K8s] ${var.cluster_name} - Service Error Rate SLO Fast Burn"
combiner = "OR"
conditions {
display_name = "Error Budget Fast Burn (14.4x over 1h and 5m)"
condition_prometheus_query_language {
query = <<-EOT
(
(
sum(
rate(
http_requests_total{
cluster="${var.cluster_name}",
namespace="${var.namespace}",
status=~"5.."
}[5m]
)
) by (service, namespace, cluster)
/
sum(
rate(
http_requests_total{
cluster="${var.cluster_name}",
namespace="${var.namespace}"
}[5m]
)
) by (service, namespace, cluster)
) > (1 - ${var.slo_target}) * 14.4
)
and
(
(
sum(
rate(
http_requests_total{
cluster="${var.cluster_name}",
namespace="${var.namespace}",
status=~"5.."
}[1h]
)
) by (service, namespace, cluster)
/
sum(
rate(
http_requests_total{
cluster="${var.cluster_name}",
namespace="${var.namespace}"
}[1h]
)
) by (service, namespace, cluster)
) > (1 - ${var.slo_target}) * 14.4
)
EOT
duration = "0s"
}
}
}
Telemetry Metrics and PromQL Examples
For GKE metrics (kubernetes.io/), community open-source alerts
(awesome-prometheus-alerts), KSM cost guardrails, and non-KSM native
alternatives, you must read and follow:
- metrics_and_alerts_catalog.md
For specific PromQL queries corresponding to each of the Golden Signals, you
must read and follow:
For GKE cluster prerequisites, enabling Google Cloud Managed Service for
Prometheus collection, configuring PodMonitoring custom scraping, and enabling
control plane metrics collection (API Server, Controller Manager, Scheduler),
you must read and follow:
- gke_configuration_prerequisites.md
Tooling Scripts and Validation Loop
Use the validate_config.py script to validate change plans and Terraform
configurations when working in a repository:
- Pre-Edit Plan Validation: Draft a
changes.json plan specifying the
proposed policies, queries, and durations, and validate it before editing:
- Command:
python3 scripts/validate_config.py --plan changes.json
- Post-Edit and Directory Validation: Scan existing or modified Terraform
files in a directory to ensure no duplicates or syntax errors exist:
- Command:
python3 scripts/validate_config.py --directory [TARGET_TF_DIR] --cluster-var "${var.cluster_name}"
- Single file validation:
python3 scripts/validate_config.py --file [PATH_TO_TF_FILE]
Technical Considerations and Gotchas
- Lookback Windows versus Duration Buffers:
- Do not add large
duration = "300s" buffers to alerts that already use
aggregated lookback windows like increase(...[15m]) or multi-window
SLO rates.
- The
[15m] window in increase(...[15m]) > 3 already smooths spikes.
Adding duration = "300s" increases MTTD by forcing the restart count
to remain above 3 for an extra 5 continuous minutes, delaying alerts by
up to 20 minutes total.
- Use
duration = "0s" or "60s" when using lookback window functions.
Reserve duration = "300s" for raw instantaneous gauge conditions, such
as kube_node_status_condition == 0.
- Memory Saturation Only for Cluster Alerting:
- Do not configure CPU saturation alerts for cluster or workload
monitoring. CPU is compressible (throttled by the CFS scheduler), while
memory is uncompressible (triggers OOMKills).
- Configure Memory Saturation using
container_memory_working_set_bytes /
container_spec_memory_limit_bytes.
- Missing Resource Limits Blind Spot (Mandatory Explanation): Saturation
alerts that compare usage to limits (such as
container_spec_memory_limit_bytes) will fail to resolve or return
NaN if workloads do not have explicit Memory limits configured in their
Kubernetes manifests.
- Mandatory Instruction: Whenever you generate, discuss, or recommend
any memory saturation alert comparing usage against limits (including
non-KSM cAdvisor alternatives using
container_spec_memory_limit_bytes), you must explicitly explain and
warn the user in your response that container memory limits must be
explicitly configured in the Kubernetes pod specs or manifests
(resources.limits.memory) for the saturation query to resolve (and not
return NaN or fail to resolve).
- Linear Disk Predictions (
predict_linear): When forecasting volume
exhaustion using
predict_linear(kubelet_volume_stats_available_bytes[6h:5m], 4 * 24 * 3600) < 0, explain that predict_linear uses linear regression over the recent
lookback window (for example, 6 hours) to project when available disk will
drop below 0 (for example, within 4 days). Identify
kubelet_volume_stats_available_bytes as a Tier 1 native kubelet metric
with zero KSM surcharge.
- API Server Error and Client Metrics:
apiserver_request_total and rest_client_requests_total are Tier 1
Control Plane metrics with zero KSM cost surcharge. Explain that
apiserver_request_total monitors 5xx HTTP error rates across API
server endpoints, while rest_client_requests_total monitors 4xx and
5xx requests sent by REST clients communicating with the API server.
- Traffic Disappearance Gotcha (
absent() / default 0):
- When traffic drops completely to zero, Prometheus and GMP stop emitting
the
http_requests_total time series.
sum(rate(...[5m])) == 0 evaluates to an empty vector, preventing the
alert from triggering.
- Always use
sum(rate(...[5m])) default 0 == 0 or absent(...) == 1 to
reliably detect total traffic loss.
- CrashLooping versus Normal Restarts: A container restarting occasionally
might be normal, for example job completion or a minor rolling update. Alert
on frequent restarts (such as more than 3 restarts in 15 minutes with
duration = "0s") using kube_pod_container_status_restarts_total rather
than a single restart to avoid noise.
- Node Upgrades: During GKE cluster upgrades, nodes are drained and
restarted, which can trigger "Node NotReady" alerts. Warn the user that
these alerts might fire during maintenance windows, or suggest configuring
maintenance windows if supported.
Additional Resources
1---2name: gke-alert-configuration3description: Configures alerting policies in Terraform for Google Kubernetes Engine (GKE) clusters, workloads, and services using PromQL and Google Cloud Managed Service for Prometheus. Use when writing, analyzing, validating, or deploying Terraform alerting policies to monitor GKE service latency, traffic, error rates using Multi-Window Multi-Burn-Rate SLO alerts, memory saturation, and cluster health such as CrashLoopBackOff and Node NotReady conditions. Don't use for non-GKE compute runtimes such as standalone Compute Engine VMs or standalone Cloud Run services without GKE.4---56# GKE Alert Configuration78This skill provides guidelines and best practices for creating robust,9high-signal alerting policies for Google Kubernetes Engine workloads using10Google Cloud Managed Service for Prometheus and Terraform. It ensures11comprehensive coverage of the **4 Golden Signals** and key cluster health12metrics while minimizing alert noise.1314--------------------------------------------------------------------------------1516## Critical Rules1718* **Negative Triggers and Scope Redirection for Non-GKE Standalone Runtimes**:19 * This skill is strictly scoped to Google Kubernetes Engine (GKE)20 workloads, clusters, and services using PromQL and Google Cloud Managed21 Service for Prometheus.22 * **Do not use for non-GKE compute runtimes**, such as standalone Compute23 Engine virtual machines or standalone Cloud Run services without GKE.24 * **STOP AND RESPOND DIRECTLY (Do Not Edit Files)**: When the user25 requests alert configuration for non-GKE compute infrastructure:26 1. **Do not write, create, edit, or validate any Terraform files on27 disk**.28 2. **Immediately stop and respond directly to the user in chat**:29 * **Explicitly Clarify Out-of-Scope**: State clearly that30 standalone Compute Engine virtual machine monitoring or31 standalone Cloud Run monitoring is out of scope for this32 GKE-specific PromQL alerting skill, which is designed33 specifically for GKE workloads using Google Cloud Managed34 Service for Prometheus and PromQL.35 * **Do Not Generate GKE PromQL Alerts**: Do not create or generate36 Kubernetes PromQL alert policies or fabricate Kubernetes37 container, pod, or node resources for non-GKE infrastructure.38 * **Redirect the User**: Guide and redirect the user to standard39 Google Cloud Monitoring metrics, such as40 `compute.googleapis.com/instance/cpu/utilization` or41 `run.googleapis.com/request_latencies`, using standard42 `google_monitoring_alert_policy` with `condition_threshold` or43 MQL, or recommend the relevant specialized Cloud observability44 skill.45* **Mandatory `kube-state-metrics` (KSM) Cost Guardrail**:46 * Deploying open-source `kube-state-metrics` in Google Cloud Managed47 Service for Prometheus incurs billable metric ingestion costs.48 * **STOP AND ASK PERMISSION FIRST (Do Not Edit Files)**: When a requested49 alert rule relies on **Tier 2 KSM metrics** (such as `kube_cronjob_*`,50 `kube_pod_status_phase`, `kube_persistentvolume_*`, `kube_deployment_*`,51 `kube_statefulset_*`, `kube_job_*`, or `kube_daemonset_*`), **do not52 write, create, edit, or validate any Terraform files or generate alert53 policies before obtaining user approval**.54 * Instead, you **must immediately stop and respond directly to the user**55 to:56 1. **Alert the user** that the requested alert requires57 `kube-state-metrics`.58 2. **Explain the cost impact**: Detail that `kube-state-metrics` incurs59 billable sample ingestion costs in Google Cloud Managed Service for60 Prometheus.61 3. **Ask for explicit permission**: Ask the user for explicit62 permission before assuming, enabling, or generating KSM-dependent63 alert configurations.64 4. **Recommend filtering or allowlisting**: Suggest and recommend65 filtering or allowlisting only the specific required metrics, such66 as using a `PodMonitoring` resource with `metricRelabeling`67 (`action: keep`) or KSM `--metric-allowlist` to minimize ingestion68 costs. Provide a concrete allowlist example.69 * **Always prefer Non-KSM Native Alternatives** (Tier 1 cAdvisor or native70 GKE metrics documented in71 [metrics_and_alerts_catalog.md](references/metrics_and_alerts_catalog.md))72 whenever possible, such as using `container_memory_working_set_bytes`73 and `container_spec_memory_limit_bytes` instead of74 `kube_pod_container_resource_limits`.75 * **Explicit Tier and Cost Surcharge Identification in Response**: In76 every response where you generate or recommend an alerting policy, you77 **must explicitly state its classification tier and cost impact**:78 * **Tier 1 native or standard metric** (GKE built-in metrics, cAdvisor79 `container_*`, kubelet volume stats, kubelet node conditions, and80 control-plane metrics; see81 [metrics_and_alerts_catalog.md](references/metrics_and_alerts_catalog.md)):82 State that it is a **Tier 1 native or standard metric with zero KSM83 cost surcharge**.84 * **Tier 2 KSM metric**: State that it is a **Tier 2 KSM-dependent85 metric** and follow the permission and allowlisting guardrail above.86 *(Tip: Generally, metrics with the `kube_` prefix that represent87 resource state or metadata belong to Tier 2).*88* **Plan-Validate-Execute Loop for Approved File Edits**: When modifying,89 adding, or merging approved Terraform files on disk in a workspace, follow90 the three-phase workflow:91 1. **Plan**: Draft a structured change plan (`changes.json`) containing92 proposed policy resource names, PromQL expressions, grouping labels, and93 durations.94 2. **Validate**: Run the pre-edit validation script (`python395 scripts/validate_config.py --plan changes.json`) to verify PromQL96 grammar, lookback windows, duration rules, and ensure no duplicate97 signals exist.98 3. **Execute**: After the plan passes validation, apply or merge changes99 in-place into the target Terraform configuration (`alerts.tf`).100 4. *Note*: When answering questions or providing Terraform snippets101 directly in chat where no disk modification is requested, output the102 complete, valid Terraform HCL block in your response.103* **Configure the 4 Golden Signals and Cluster Health**: Always ensure the104 target Kubernetes workload or service has the following alerting coverage:105 1. **Latency** (P95 response time)106 2. **Errors** (Multi-Window Multi-Burn-Rate SLO alerts, such as Fast Burn 1107 hour / 5 minutes with factor 14.4, Slow Burn 6 hours / 30 minutes with108 factor 6.0; do not use simple static ratios)109 3. **Traffic** (Sudden drop or complete metric disappearance using110 `absent()` or `default 0` syntax, or overload spikes)111 4. **Saturation (Memory Limit Utilization Only)**: When describing or112 configuring alert policies for a cluster or project, include ONLY113 **Memory Saturation** (`container_memory_working_set_bytes` /114 `container_spec_memory_limit_bytes`). Do **NOT** include CPU saturation115 alerts or list `container_cpu_usage_seconds_total` as an alert metric116 because CPU is compressible and throttled by CFS quotas rather than117 causing uncompressible fatal termination (OOM).118 5. **Cluster Health** (Pod CrashLooping, Node NotReady)119* **PromQL Only (Managed Prometheus)**: You must use120 `condition_prometheus_query_language` with PromQL. Do **NOT** use MQL or121 standard `condition_threshold` unless explicitly requested. Google Cloud122 Managed Service for Prometheus is the standard telemetry ingestion path for123 GKE.124* **Terraform Only**: Write the generated observability configuration ONLY as125 Terraform (`.tf`) files, such as `alerts.tf` and `variables.tf`.126* **Dynamic Multi-Resource Alerting (No Hardcoding)**: You must not hardcode127 specific pod names, node names, or service names in alerting conditions128 unless explicitly requested. Alerting policies must be written to cover129 resources dynamically:130 * Always use grouping aggregations (`by (cluster, namespace, service, pod,131 container)`) instead of filtering to a single instance. This allows a132 single alert policy to dynamically track each service or pod separately.133 * Always declare and use Terraform variables for `project_id`,134 `cluster_name`, and `namespace` (`var.project_id`, `var.cluster_name`,135 `var.namespace`) to make the configuration reusable across environments.136 Always define these variables in `variables.tf` (or within the137 configuration) and reference all three in policies or PromQL label138 matchers.139* **No Redundant Duration Windows on Lookbacks**:140 * When PromQL expressions already use an aggregated lookback window (such141 as `increase(...[15m]) > 3` or multi-window SLO burn rates), the query142 time window already smooths out transient spikes.143 * Adding a Terraform duration on top of a PromQL lookback window increases144 the Mean Time to Detect (MTTD) without providing additional smoothing145 benefits.146 * In these cases, set Terraform `duration = "0s"` (or `"60s"`). Do not147 enforce `duration = "300s"` on top of `[15m]`, which delays critical148 crashloop alerts by up to 20 minutes total (15 minutes + 5 minutes).149 * Use `duration = "300s"` only on instantaneous gauge conditions, such as150 `kube_node_status_condition == 0`.151* **Use SLO Burn Rates Instead of Simple Ratios**: For error rate alerting,152 always generate Multi-Window Multi-Burn-Rate (MWMBR) SLO alerts (such as153 14.4x burn rate over 1 hour and 5 minute windows for a 99% SLO) rather than154 simple error rate ratios (`rate(5xx)/rate(total) > 0.05`), which produce155 excessive false alarms on low traffic.156* **Robust Traffic Drop Detection (`absent()` / `default 0`)**: When157 monitoring for traffic drops to zero, do not use `rate(...) == 0` alone158 because Prometheus time series disappear completely when no requests occur159 (evaluating to an empty vector rather than 0). Use `default 0` syntax, such160 as `sum(rate(...[5m])) default 0 == 0`, or `absent(...) == 1`.161* **Notification Channels**: By default, never configure any notification162 channels without user input. If the user explicitly provides a notification163 channel, configure the alerts to use it. Otherwise, you must prompt the user164 in your response to ask if they would like to configure one.165* **Consult GKE Metrics and Open-Source Alerts Catalog**: When designing or166 generating evaluation suites or alerting policies, consult167 [metrics_and_alerts_catalog.md](references/metrics_and_alerts_catalog.md)168 for public GKE metrics (`kubernetes.io/`) and open-source Kubernetes alerts169 (`awesome-prometheus-alerts`).170* **Plain English Response**: You must include a plain English explanation for171 what the alerts do in your response. Explain what the alert measures, what172 the threshold represents, and what a trigger indicates.173* **User Labels**: Include a `user_labels` block in all174 `google_monitoring_alert_policy` resources to track policies created by this175 skill:176177 ```terraform178 user_labels = {179 created-with-google-skill = "gke-alert-configuration"180 }181 ```182183--------------------------------------------------------------------------------184185## Alerting Policy Structure in Terraform186187Alerting policies must be defined using the `google_monitoring_alert_policy`188resource with `condition_prometheus_query_language`. Always declare variables in189`variables.tf` for `project_id`, `cluster_name`, and `namespace`.190191```hcl192# variables.tf193variable "project_id" {194 type = string195 description = "Google Cloud Project ID"196}197198variable "cluster_name" {199 type = string200 description = "GKE Cluster Name"201}202203variable "namespace" {204 type = string205 description = "Target Kubernetes Namespace"206 default = "default"207}208209variable "slo_target" {210 type = number211 description = "SLO Target fraction (for example 0.99 for 99%)"212 default = 0.99213}214```215216```hcl217# alerts.tf218# Example: Multi-Window Multi-Burn-Rate (MWMBR) SLO Alert (Fast Burn: 14.4x, 1h & 5m windows)219resource "google_monitoring_alert_policy" "k8s_service_error_rate_slo" {220 project = var.project_id221 display_name = "[K8s] ${var.cluster_name} - Service Error Rate SLO Fast Burn"222 combiner = "OR"223224 conditions {225 display_name = "Error Budget Fast Burn (14.4x over 1h and 5m)"226 condition_prometheus_query_language {227 query = <<-EOT228 (229 (230 sum(231 rate(232 http_requests_total{233 cluster="${var.cluster_name}",234 namespace="${var.namespace}",235 status=~"5.."236 }[5m]237 )238 ) by (service, namespace, cluster)239 /240 sum(241 rate(242 http_requests_total{243 cluster="${var.cluster_name}",244 namespace="${var.namespace}"245 }[5m]246 )247 ) by (service, namespace, cluster)248 ) > (1 - ${var.slo_target}) * 14.4249 )250 and251 (252 (253 sum(254 rate(255 http_requests_total{256 cluster="${var.cluster_name}",257 namespace="${var.namespace}",258 status=~"5.."259 }[1h]260 )261 ) by (service, namespace, cluster)262 /263 sum(264 rate(265 http_requests_total{266 cluster="${var.cluster_name}",267 namespace="${var.namespace}"268 }[1h]269 )270 ) by (service, namespace, cluster)271 ) > (1 - ${var.slo_target}) * 14.4272 )273 EOT274 duration = "0s"275 }276 }277}278```279280--------------------------------------------------------------------------------281282## Telemetry Metrics and PromQL Examples283284For GKE metrics (`kubernetes.io/`), community open-source alerts285(`awesome-prometheus-alerts`), KSM cost guardrails, and non-KSM native286alternatives, you must read and follow:287288* [metrics_and_alerts_catalog.md](references/metrics_and_alerts_catalog.md)289290For specific PromQL queries corresponding to each of the Golden Signals, you291must read and follow:292293* [promql_queries.md](references/promql_queries.md)294295For GKE cluster prerequisites, enabling Google Cloud Managed Service for296Prometheus collection, configuring PodMonitoring custom scraping, and enabling297control plane metrics collection (API Server, Controller Manager, Scheduler),298you must read and follow:299300* [gke_configuration_prerequisites.md](references/gke_configuration_prerequisites.md)301302--------------------------------------------------------------------------------303304## Tooling Scripts and Validation Loop305306Use the `validate_config.py` script to validate change plans and Terraform307configurations when working in a repository:308309* **Pre-Edit Plan Validation**: Draft a `changes.json` plan specifying the310 proposed policies, queries, and durations, and validate it before editing:311 * Command: `python3 scripts/validate_config.py --plan changes.json`312* **Post-Edit and Directory Validation**: Scan existing or modified Terraform313 files in a directory to ensure no duplicates or syntax errors exist:314 * Command: `python3 scripts/validate_config.py --directory [TARGET_TF_DIR]315 --cluster-var "${var.cluster_name}"`316 * Single file validation: `python3 scripts/validate_config.py --file317 [PATH_TO_TF_FILE]`318319--------------------------------------------------------------------------------320321## Technical Considerations and Gotchas322323* **Lookback Windows versus Duration Buffers**:324 * Do not add large `duration = "300s"` buffers to alerts that already use325 aggregated lookback windows like `increase(...[15m])` or multi-window326 SLO rates.327 * The `[15m]` window in `increase(...[15m]) > 3` already smooths spikes.328 Adding `duration = "300s"` increases MTTD by forcing the restart count329 to remain above 3 for an extra 5 continuous minutes, delaying alerts by330 up to 20 minutes total.331 * Use `duration = "0s"` or `"60s"` when using lookback window functions.332 Reserve `duration = "300s"` for raw instantaneous gauge conditions, such333 as `kube_node_status_condition == 0`.334* **Memory Saturation Only for Cluster Alerting**:335 * Do not configure CPU saturation alerts for cluster or workload336 monitoring. CPU is compressible (throttled by the CFS scheduler), while337 memory is uncompressible (triggers OOMKills).338 * Configure Memory Saturation using `container_memory_working_set_bytes` /339 `container_spec_memory_limit_bytes`.340* **Missing Resource Limits Blind Spot (Mandatory Explanation)**: Saturation341 alerts that compare usage to limits (such as342 `container_spec_memory_limit_bytes`) will **fail to resolve** or return343 `NaN` if workloads do not have explicit Memory limits configured in their344 Kubernetes manifests.345 * **Mandatory Instruction**: Whenever you generate, discuss, or recommend346 any memory saturation alert comparing usage against limits (including347 non-KSM cAdvisor alternatives using348 `container_spec_memory_limit_bytes`), you **must explicitly explain and349 warn the user in your response** that container memory limits must be350 explicitly configured in the Kubernetes pod specs or manifests351 (`resources.limits.memory`) for the saturation query to resolve (and not352 return `NaN` or fail to resolve).353* **Linear Disk Predictions (`predict_linear`)**: When forecasting volume354 exhaustion using355 `predict_linear(kubelet_volume_stats_available_bytes[6h:5m], 4 * 24 * 3600)356 < 0`, explain that `predict_linear` uses linear regression over the recent357 lookback window (for example, 6 hours) to project when available disk will358 drop below 0 (for example, within 4 days). Identify359 `kubelet_volume_stats_available_bytes` as a Tier 1 native kubelet metric360 with zero KSM surcharge.361* **API Server Error and Client Metrics**:362 * `apiserver_request_total` and `rest_client_requests_total` are Tier 1363 Control Plane metrics with zero KSM cost surcharge. Explain that364 `apiserver_request_total` monitors 5xx HTTP error rates across API365 server endpoints, while `rest_client_requests_total` monitors 4xx and366 5xx requests sent by REST clients communicating with the API server.367* **Traffic Disappearance Gotcha (`absent()` / `default 0`)**:368 * When traffic drops completely to zero, Prometheus and GMP stop emitting369 the `http_requests_total` time series.370 * `sum(rate(...[5m])) == 0` evaluates to an empty vector, preventing the371 alert from triggering.372 * Always use `sum(rate(...[5m])) default 0 == 0` or `absent(...) == 1` to373 reliably detect total traffic loss.374* **CrashLooping versus Normal Restarts**: A container restarting occasionally375 might be normal, for example job completion or a minor rolling update. Alert376 on **frequent** restarts (such as more than 3 restarts in 15 minutes with377 `duration = "0s"`) using `kube_pod_container_status_restarts_total` rather378 than a single restart to avoid noise.379* **Node Upgrades**: During GKE cluster upgrades, nodes are drained and380 restarted, which can trigger "Node NotReady" alerts. Warn the user that381 these alerts might fire during maintenance windows, or suggest configuring382 maintenance windows if supported.383384--------------------------------------------------------------------------------385386## Additional Resources387388* [Google Cloud Managed Service for Prometheus Documentation](https://docs.cloud.google.com/monitoring/managed-prometheus.md.txt)389* [GKE Observability and Monitoring Concepts](https://docs.cloud.google.com/kubernetes-engine/docs/concepts/monitoring.md.txt)390* [Google Cloud Alerting Policies in Terraform](https://docs.cloud.google.com/monitoring/alerts/terraform-alert-policy.md.txt)391* [Google Cloud Monitoring Pricing](https://docs.cloud.google.com/monitoring/pricing.md.txt)392* [Google SRE Workbook: Alerting on SLOs](https://sre.google/workbook/alerting-on-slos/)393* [Awesome Prometheus Alerts Repository](https://github.com/samber/awesome-prometheus-alerts)