Prometheus exporters as HelmReleases: Kafka, MongoDB, Redis, RabbitMQ
Published: 2026-02-21
kube-prometheus-stack gives you node metrics, kubelet metrics, and Kubernetes API metrics out of the box. Application-level metrics — Kafka consumer lag, Redis memory hit ratio, MongoDB operation rates — need dedicated exporters. Here's how we deploy and wire them all via FluxCD with a consistent pattern.
Pattern
Each exporter follows the same HelmRelease pattern:
- Deploy to the same namespace as the workload (not
observability) - Enable
serviceMonitorwithrelease: kube-prom-stacklabel — this is how the Prometheus operator discovers the ServiceMonitor - Set relabelings to fix the
joblabel to a stable, human-readable value - Set resource requests/limits — exporters are cheap, but unbounded they can consume significant memory during metric collection spikes
Why the same namespace as the workload? Exporters need network access to the service they scrape. Putting them in the same namespace means short hostnames work (redis-master.db.svc.cluster.local vs cross-namespace). It also co-locates observability concerns with the service they observe, making it easier to understand what's being monitored and by whom.
kafka-exporter
yamlapiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: kafka-exporter
namespace: kafka
spec:
chart:
spec:
chart: prometheus-kafka-exporter
version: "3.0.1"
sourceRef:
kind: HelmRepository
name: prometheus-community
namespace: flux-system
values:
kafkaServer:
- kafka.kafka.svc.cluster.local:9092
prometheus:
serviceMonitor:
enabled: true
additionalLabels:
release: kube-prom-stack
interval: 30s
relabelings:
- targetLabel: job
replacement: kafka
resources:
requests:
cpu: 25m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
Exposes: consumer group lag (per partition, per group), topic partition counts, broker up/down, under-replicated partitions, message rates.
Key metrics for alerting:
kafka_consumergroup_lag_sum— total lag per consumer groupkafka_topic_partition_under_replicated_partition— replication healthkafka_brokers— number of visible brokers
For multi-broker clusters, add all brokers:
yamlkafkaServer:
- kafka-0.kafka-headless.kafka.svc.cluster.local:9092
- kafka-1.kafka-headless.kafka.svc.cluster.local:9092
- kafka-2.kafka-headless.kafka.svc.cluster.local:9092
mongodb-exporter
yamlapiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: mongodb-exporter
namespace: db
spec:
chart:
spec:
chart: prometheus-mongodb-exporter
version: "3.8.0"
sourceRef:
kind: HelmRepository
name: prometheus-community
namespace: flux-system
values:
mongodb:
uri: "mongodb://exporter:${MONGO_EXPORTER_PASS}@mongodb.db.svc.cluster.local:27017/admin"
serviceMonitor:
enabled: true
additionalLabels:
release: kube-prom-stack
interval: 30s
relabelings:
- targetLabel: job
replacement: mongodb
resources:
requests:
cpu: 25m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
The mongodb.uri contains credentials — injected via ExternalSecret from Vault, never hardcoded in Git.
MongoDB exporter user
Create a dedicated MongoDB user with minimal permissions:
javascriptuse admin
db.createUser({
user: "exporter",
pwd: "secure-password",
roles: [
{ role: "clusterMonitor", db: "admin" },
{ role: "read", db: "local" }
]
})
Exposes: document counts per collection, replication lag, index stats, operation rates by type (insert/update/delete/query), WiredTiger cache hit ratio, connection pool usage.
Key metrics for alerting:
mongodb_mongod_replset_member_replication_lag— replica lagmongodb_mongod_wiredtiger_cache_bytes{type="currently in cache"}— cache pressuremongodb_mongod_connections{state="current"}— connection count
redis-exporter
yamlapiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: redis-exporter
namespace: db
spec:
chart:
spec:
chart: prometheus-redis-exporter
version: "6.9.0"
sourceRef:
kind: HelmRepository
name: prometheus-community
namespace: flux-system
values:
redisAddress: redis://redis-master.db.svc.cluster.local:6379
auth:
enabled: true
secret:
name: redis-password
key: redis-password
serviceMonitor:
enabled: true
labels:
release: kube-prom-stack
interval: 15s
relabelings:
- targetLabel: job
replacement: redis
resources:
requests:
cpu: 10m
memory: 32Mi
limits:
cpu: 100m
memory: 64Mi
interval: 15s — Redis metrics change fast (cache hit rates, command rates). More frequent scraping gives better signal for alerting on Redis latency issues.
Exposes: keyspace hits/misses, connected clients, memory used/max, evicted keys, command rates per operation type, replication offset (for replicas).
Key metrics for alerting:
redis_keyspace_hits_total/redis_keyspace_misses_total— cache hit ratioredis_memory_used_bytesvsredis_memory_max_bytes— memory pressureredis_evicted_keys_total— evictions (indicates memory pressure)redis_connected_clients— connection pool saturation
Redis hit ratio recording rule
yaml- record: job:redis_hit_ratio:5m
expr: |
rate(redis_keyspace_hits_total[5m])
/
(rate(redis_keyspace_hits_total[5m]) + rate(redis_keyspace_misses_total[5m]))
Alert when hit ratio drops below 80%:
yaml- alert: RedisLowHitRatio
expr: job:redis_hit_ratio:5m < 0.8
for: 10m
labels:
severity: warning
event: 'Redis Low Hit Ratio |{{$value | humanize}}'
rabbitmq-exporter
RabbitMQ ships with a built-in Prometheus endpoint — no separate exporter needed. Enable it in the RabbitMQ Helm chart values:
yamlvalues:
metrics:
enabled: true
serviceMonitor:
enabled: true
labels:
release: kube-prom-stack
interval: 30s
relabelings:
- targetLabel: job
replacement: rabbitmq
Exposes: queue depths, consumer counts, message rates (published/delivered/acked), channel stats, node memory/disk alarms, connection count.
Key metrics for alerting:
rabbitmq_queue_messages— messages in queue (consumer lag proxy)rabbitmq_queue_consumers— active consumers (0 = no one consuming)rabbitmq_node_mem_alarm— memory alarm flag (1 = alarm triggered)rabbitmq_node_disk_free_alarm— disk alarm flag
helm-exporter
Track Helm release versions and status across clusters:
yamlapiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: helm-exporter
namespace: observability
spec:
chart:
spec:
chart: helm-exporter
sourceRef:
kind: HelmRepository
name: sstarcher
values:
serviceMonitor:
create: true
labels:
release: kube-prom-stack
Exposes one gauge per Helm release with chart, version, namespace, and status labels. Use it to build a Grafana panel showing all releases and their statuses at a glance, and to alert on releases stuck in failed or pending-upgrade state:
yaml- alert: HelmReleaseFailed
expr: helm_chart_info{status!="deployed"} > 0
for: 15m
labels:
severity: warning
event: 'Helm Release Failed |{{$labels.chart}}|{{$labels.namespace}}'
ServiceMonitor discovery: how it works
The key mechanism: Prometheus operator watches for ServiceMonitor CRDs with labels matching the Prometheus CR's serviceMonitorSelector:
yaml# kube-prometheus-stack default Prometheus CR
serviceMonitorSelector:
matchLabels:
release: kube-prom-stack
If your ServiceMonitor doesn't have this label, Prometheus never scrapes the target. Check with:
bashkubectl get servicemonitor -A -l release=kube-prom-stack
# Should list your exporter's ServiceMonitor
And verify the targets are in Prometheus:
bashkubectl port-forward -n observability svc/kube-prom-stack-prometheus 9090:9090
# localhost:9090/targets — should show kafka, mongodb, redis, rabbitmq