> Per AI Blitz Plan §platform.runbooks. Layer: 1. Repo: devops-infra-helm-charts. # Runbook — Metrics gap on a cluster / namespace > **Type:** Decision tree. > **Entry symptom:** "Grafana panels are blank for `` / `` / ``," or an alert that should be firing isn't, or VictoriaMetrics shows `no data`. > **Layer:** mostly Layer 2 (advisory). Layer 1 only when the fix is a values diff in this repo. The observability path on Meesho's GKE fleet is: ``` workload Pod (exposes /metrics) └→ victoria-metrics-agent (vmagent) scrapes └→ remote_write to victoria-metrics-cluster (vmstorage) └→ vmselect ← Grafana / vmalert query ``` A metrics gap can be at any hop. Walk this tree top-down — the most common root cause is hop 1 (scrape config). --- ## Entry — gather context ```bash CLUSTER= CTX= NS= METRIC= # Confirm the cluster runs VM agent + cluster ls helm-overrides/$CLUSTER | grep -E '^victoria-metrics-(agent|cluster)' # Confirm pods are healthy kubectl --context=$CTX -n monitoring get pods -l app.kubernetes.io/name=victoria-metrics-agent -o wide kubectl --context=$CTX -n monitoring get pods -l app.kubernetes.io/name=vmstorage -o wide ``` If pods are missing/CrashLooping → that's the gap. Skip to §5. --- ## Decision tree ```text START │ ├── Is the metric known to be emitted by the workload? │ ├── No → §0 — Workload not emitting; out of scope (app team) │ └── Yes → │ ├── §1 — Is vmagent scraping the workload? │ ├── No → fix scrape config (Layer 1) │ └── Yes → │ ├── §2 — Are scrape targets healthy (status=up)? │ ├── Down → fix endpoint reachability (Layer 2 / Layer 1) │ └── Up → │ ├── §3 — Are relabel rules dropping the metric? │ ├── Yes → adjust relabel_configs (Layer 1) │ └── No → │ ├── §4 — Is remote_write succeeding? │ ├── No → vmagent → vmstorage path broken (Layer 2 / Layer 1) │ └── Yes → │ ├── §5 — Is vmstorage healthy and ingesting? │ ├── No → vmstorage outage (Layer 2) │ └── Yes → │ └── §6 — Is the Grafana datasource / tenant correct? └── Misrouted query → fix datasource URL or tenant header (Layer 1) ``` --- ## §0 — Workload not emitting Out of scope for this repo. Confirm with: ```bash # Port-forward and curl /metrics directly kubectl --context=$CTX -n $NS port-forward 9090: & curl -s localhost:9090/metrics | grep -i "$METRIC" ``` If `/metrics` is empty or doesn't contain `$METRIC` → app team. Stop. --- ## §1 — Is vmagent scraping the workload? ```bash # vmagent UI exposes /api/v1/targets kubectl --context=$CTX -n monitoring port-forward svc/victoria-metrics-agent 8429:8429 & curl -s localhost:8429/api/v1/targets | jq '.data.activeTargets[] | select(.labels.namespace=="'$NS'")' ``` If no targets for `$NS`: - Look at `helm-overrides/$CLUSTER/victoria-metrics-agent/custom-values.yaml`. - Check the `additionalScrapeConfigs` (or `config.scrape_configs`) for a job that matches the workload's labels / namespace selector. - Common cause: a `kubernetes_sd_configs` `namespaces.names` filter excludes `$NS`. - Common cause: a missing `Pod`/`Service`/`PodMonitor` annotation `prometheus.io/scrape: "true"` on the workload. **Layer 1 fix** (if the gap is in the scrape config): edit `helm-overrides/$CLUSTER/victoria-metrics-agent/custom-values.yaml` per [../procedures/modify-observability-config.md](../procedures/modify-observability-config.md). **Layer 2 fix** (if the gap is on the workload — missing annotation): hand off to app team. --- ## §2 — Targets healthy? ```bash # In the same vmagent /targets output curl -s localhost:8429/api/v1/targets | jq '.data.activeTargets[] | select(.health!="up") | {labels, lastError}' ``` If targets are `down`: | `lastError` | Cause | Fix | |-------------|-------|-----| | `connection refused` | Workload not listening on declared port | App team — Layer 2. | | `i/o timeout` | NetworkPolicy / firewall blocking vmagent → workload | Check `NetworkPolicy` in `$NS`. Often a NetworkPolicy allowing only intra-namespace traffic and not vmagent's namespace. **Layer 2** — recommend the workload team allow vmagent. | | `x509: certificate signed by unknown authority` | mTLS misconfigured | App team — Layer 2. | | `404 Not Found` | Wrong path (default `/metrics` vs custom) | Add `metrics_path:` in scrape config. **Layer 1.** | --- ## §3 — Relabel rules dropping the metric? ```bash yq e '.config.scrape_configs[].metric_relabel_configs, .config.scrape_configs[].relabel_configs' \ helm-overrides/$CLUSTER/victoria-metrics-agent/custom-values.yaml ``` Look for: - `action: drop` rules with regexes matching `$METRIC`. - `action: keep` rules whose regex *excludes* `$METRIC`. - `action: labeldrop` removing a label the query uses. Test in vmagent's UI under the *Targets* tab — it shows the labels post-relabel. **Layer 1 fix:** loosen the relabel rule. Re-PR per [../procedures/modify-observability-config.md](../procedures/modify-observability-config.md). --- ## §4 — Remote_write succeeding? ```bash kubectl --context=$CTX -n monitoring logs deploy/victoria-metrics-agent | grep -i 'remote_write\|error\|failed' | tail -20 ``` | Symptom | Cause | Fix | |---------|-------|-----| | `429 Too Many Requests` from vmstorage | vmstorage ingest saturated | Scale vmstorage / vminsert (Layer 1 — see [observability.md](../../global/coding-guidelines/observability.md)). | | `connection refused` to vmstorage URL | vmstorage Service down or wrong URL | Verify `remoteWrite.url` in vmagent values matches the live `vmstorage` Service DNS. Layer 1. | | `out of bounds timestamp` | Clock skew on vmagent's node | Layer 2 — node time sync. | | `series limit exceeded` | Cardinality bomb on vmstorage tenant | Layer 1 — drop the offending label. See [observability.md §Cardinality](../../global/coding-guidelines/observability.md). | --- ## §5 — vmstorage healthy? ```bash kubectl --context=$CTX -n monitoring get pods -l app.kubernetes.io/name=vmstorage -o wide kubectl --context=$CTX -n monitoring describe pod vmstorage-0 | tail -30 kubectl --context=$CTX -n monitoring exec vmstorage-0 -- df -h /storage ``` Failure modes: | Symptom | Layer | Fix | |---------|-------|-----| | Pod CrashLooping with `out of disk` | Layer 1 | Bump `persistence.size`. Note: PVC growth requires the StorageClass to support `allowVolumeExpansion: true`. See [../schemas/storageclass-priorityclass-schema.md](../schemas/storageclass-priorityclass-schema.md). | | Pod CrashLooping with retention/index errors | Layer 2 | Escalate — may need data-side intervention. | | Pod Pending | Layer 1 | Scheduling issue. See [pod-pending-scheduling.md](pod-pending-scheduling.md) and [../../../wiki/analyses/ADR-A3-per-cluster-scheduling.md](../../../wiki/analyses/ADR-A3-per-cluster-scheduling.md). | | Pod Running but vmselect can't reach it | Layer 1 / 2 | Verify the headless Service and StatefulSet pod-DNS records. | --- ## §6 — Grafana datasource / tenant correct? ```bash yq e '.datasources.datasources.yaml.datasources[] | select(.name == "*VictoriaMetrics*" or .type == "prometheus")' \ helm-overrides/$CLUSTER/grafana/custom-values.yaml ``` | Sub-check | Action | |-----------|--------| | `url:` points at the correct in-cluster vmselect Service DNS | If wrong, **Layer 1** — fix the values per [../procedures/modify-observability-config.md](../procedures/modify-observability-config.md). | | `httpHeaderName1: X-Scope-OrgID` (multi-tenant clusters only) | If the cluster runs multi-tenant VM, the tenant header must be set. Layer 1 fix. | | Datasource `url:` points at an external `*.meeshogcp.in` host | Forbidden — see [../../global/SANCTITY_RULES.md](../../global/SANCTITY_RULES.md) R3. Repoint at in-cluster Service DNS. | --- ## Remediation summary | Hop | Likely fix | Layer | Procedure | |-----|-----------|-------|-----------| | §1 scrape | Add scrape config / fix selector | 1 | [../procedures/modify-observability-config.md](../procedures/modify-observability-config.md) | | §2 endpoint | Workload-side / NetworkPolicy | 2 | Hand off to app team | | §3 relabel | Loosen drop rule | 1 | [../procedures/modify-observability-config.md](../procedures/modify-observability-config.md) | | §4 remote_write | Scale vmstorage / fix URL | 1/2 | [../procedures/modify-observability-config.md](../procedures/modify-observability-config.md) | | §5 vmstorage | PVC grow / scheduling fix | 1/2 | [pod-pending-scheduling.md](pod-pending-scheduling.md) | | §6 datasource | Fix Grafana datasource | 1 | [../procedures/modify-observability-config.md](../procedures/modify-observability-config.md) | --- ## Escalation triggers - §5 vmstorage outage with no obvious values-side fix → platform team (observability owner). - Multi-cluster simultaneous metrics gap → platform team — cluster-level / control-plane issue. - Cardinality explosion impacting vmstorage stability → platform team + workload owner — joint fix. --- ## Done conditions - The query that was returning `no data` returns the expected series in Grafana Explore. - No remote_write errors in vmagent logs for at least 5 minutes post-fix. - Alerts that depend on the metric have transitioned from `pending` / silent back to expected state. --- ## Related - Procedure: [../procedures/modify-observability-config.md](../procedures/modify-observability-config.md). - Procedure: [../procedures/modify-alert-rules.md](../procedures/modify-alert-rules.md) — if the gap is "alert silent" not "metric missing." - Coding guideline: [../../global/coding-guidelines/observability.md](../../global/coding-guidelines/observability.md). - Runbook: [pod-pending-scheduling.md](pod-pending-scheduling.md) — for §5 vmstorage scheduling failures. - Runbook: [argocd-sync-failure.md](argocd-sync-failure.md) — if a sync didn't take.