Skip to content

Commit 69f176f

Browse files
alex-strukclaude
andcommitted
fix(monitoring): stop Loki high-memory false alerts from cgroup-v1 slab
The recurring HighPodMemoryUsage critical alert on bcgov-di-plg-loki-0 is not real memory pressure. On the Silver cluster's cgroup v1 nodes, container_memory_working_set_bytes includes reclaimable kernel slab (dentry/inode caches). Loki's constant chunk create/delete churn inflates that slab until it nears the 2Gi limit, while Loki's actual Go heap is only ~100Mi. The kernel reclaims the slab before any OOM, so the pod sits near 90% working-set indefinitely with zero restarts. Prior memory-limit bumps could never fix this (slab just refills the larger limit), and cutting chunk_idle_period to 5m made it worse by increasing file churn. Two changes: - prometheus-rule-crd.yaml: exclude the Loki pod from HighPodMemoryUsage (working-set is a meaningless signal for it under cgroup v1). A real Loki OOM is still caught by the PodInErrorState (OOMKilled) alert. All other pods keep the early-warning alert. - loki-configmap.yaml: raise chunk_idle_period 5m -> 1h, add explicit max_chunk_age 2h, and enlarge chunk_target_size to 2Mi so Loki writes far fewer chunk files, reducing the dentry/inode slab churn at its source. Heap headroom (~100Mi of 2Gi) makes the longer idle period safe. Documented the cgroup-v1 accounting artifact and the exclusion rationale in docs-md/ALERTING.md. Structural fix is migrating nodes to cgroup v2. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 0428d12 commit 69f176f

3 files changed

Lines changed: 36 additions & 6 deletions

File tree

deployments/openshift/helm/plg/templates/loki-configmap.yaml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,16 @@ data:
3939
ingestion_burst_size_mb: 8
4040
4141
ingester:
42-
# Flush idle log streams to disk after 5m instead of 30m to cap the
43-
# ingester's in-memory chunk footprint (mitigates Loki high-memory alerts).
44-
chunk_idle_period: 5m
45-
chunk_target_size: 1536000
42+
# Hold idle streams in memory longer and flush larger chunks so Loki
43+
# creates far fewer chunk files. Fewer file create/delete cycles means
44+
# less kernel dentry/inode slab churn, which is the real driver of the
45+
# cgroup-v1 working-set growth behind past high-memory alerts. Loki's
46+
# heap has ample headroom (~100Mi used of a 2Gi limit), so a longer
47+
# idle period is safe. (An earlier 5m idle period reduced heap the wrong
48+
# way and increased file churn.)
49+
chunk_idle_period: 1h
50+
max_chunk_age: 2h
51+
chunk_target_size: 2097152
4652
4753
compactor:
4854
working_directory: /loki/compactor

deployments/openshift/helm/plg/templates/prometheus-rule-crd.yaml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,20 @@ spec:
2424
summary: High CPU usage detected on a pod
2525
description: A pod in namespace {{ .Release.Namespace }} is using more than 80% of its CPU limit. Check the pod labels in this alert for the affected pod name.
2626

27+
# The Loki pod is deliberately excluded from this alert. On cgroup v1
28+
# nodes, container_memory_working_set_bytes includes reclaimable kernel
29+
# slab (dentry/inode caches). Loki's chunk create/delete churn inflates
30+
# that slab until it approaches the pod's memory limit, even though
31+
# Loki's actual heap stays around ~100Mi and the kernel reclaims the
32+
# slab before any OOM. Working-set therefore false-fires at >90% for
33+
# Loki with no real memory pressure. A genuine Loki OOM is still caught
34+
# by the PodInErrorState alert below (reason=OOMKilled).
2735
- alert: HighPodMemoryUsage
2836
expr: >-
2937
(
30-
sum(container_memory_working_set_bytes{namespace="{{ .Release.Namespace }}", container!=""}) by (pod)
38+
sum(container_memory_working_set_bytes{namespace="{{ .Release.Namespace }}", container!="", pod!~"{{ include "plg.loki.fullname" . }}-.*"}) by (pod)
3139
/
32-
sum(kube_pod_container_resource_limits{namespace="{{ .Release.Namespace }}", resource="memory"}) by (pod)
40+
sum(kube_pod_container_resource_limits{namespace="{{ .Release.Namespace }}", resource="memory", pod!~"{{ include "plg.loki.fullname" . }}-.*"}) by (pod)
3341
) > 0.9
3442
for: 2m
3543
labels:

docs-md/ALERTING.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,22 @@ Static rules that don't use the shared logger counters (e.g. HTTP error rate, sl
9797

9898
---
9999

100+
## Infrastructure Alert Rules
101+
102+
Infrastructure alerts (pod CPU/memory, PVC capacity, crash/OOM state, Temporal queue depth) are **not** generated from `alert-thresholds.ts`. They are hand-maintained in the Helm template `deployments/openshift/helm/plg/templates/prometheus-rule-crd.yaml`, which renders a `PrometheusRule` CRD carrying the `role: alert-rules` label so OpenShift User Workload Monitoring picks it up. Edit that template directly; the `npm run generate:alert-rules` generator does not touch it.
103+
104+
### Loki is excluded from `HighPodMemoryUsage`
105+
106+
The `HighPodMemoryUsage` rule fires on `container_memory_working_set_bytes / limit > 0.9`. The Loki pod (`<release>-loki-*`) is deliberately excluded via a `pod!~` matcher.
107+
108+
**Why:** the Silver cluster nodes run **cgroup v1**, where `container_memory_working_set_bytes` includes reclaimable kernel slab (dentry/inode caches). Loki continuously creates and deletes chunk files on its filesystem volume (ingester flushes + compaction + retention deletes), which inflates that slab until it approaches the pod's memory limit — even though Loki's actual Go heap stays around ~100 Mi of its 2 Gi limit. The kernel reclaims the slab before any OOM, so working-set sits near 90% indefinitely with no real memory pressure and no restarts. Left in, the rule pages `critical` on a non-problem.
109+
110+
A genuine Loki OOM is still caught by the `PodInErrorState` rule (`reason=OOMKilled`), so no real failure mode is lost by the exclusion. The companion change in `loki-configmap.yaml` (longer `chunk_idle_period`, explicit `max_chunk_age`, larger `chunk_target_size`) reduces the file churn that drives the slab in the first place.
111+
112+
This is a cgroup-v1 accounting artifact; migrating the nodes to cgroup v2 would resolve it structurally and let the exclusion be removed. See Red Hat solution 7126558 for the underlying `xfs_inode`/dentry slab behavior.
113+
114+
---
115+
100116
## In-App Alerting
101117

102118
Any backend-services or Temporal worker code can raise an alert condition by logging at `warn` or `error` level with an `alertType` in the log context.

0 commit comments

Comments
 (0)