Runbook: Kafka consumer lag
Severity (default): P2 (P1 для consumer’а на критическом пути pricing/search). Owner: on-call. Связанные алерты:
kafka_consumer_lag{group="<name>"} > 10000за 5 мин.kafka_consumer_lagне уменьшается > 30 мин.
Симптом
- Алерт по lag.
- Stale данные в проекциях (ES не отражает свежие изменения; CH аналитика отстаёт).
- Признаки каскада:
outbox_lag_secondsтоже растёт (если consumer находится downstream от outbox).
Диагностика
# 1. Какие группы лагают?
kubectl -n tracium exec deploy/kafka-tools -- \
kafka-consumer-groups.sh --bootstrap-server kafka:9092 \
--describe --all-groups | sort -k6 -n -r | head -30# 2. Состояние подов consumer'а
kubectl -n tracium get pods -l app=<consumer-service>
kubectl -n tracium top pods -l app=<consumer-service># 3. Логи consumer'а — есть ли panic / повторяющаяся ошибка?
kubectl -n tracium logs -l app=<consumer-service> --since=15m --tail=500 \
| grep -E "ERROR|panic|FATAL"# 4. Состояние топика
kubectl -n tracium exec deploy/kafka-tools -- \
kafka-topics.sh --bootstrap-server kafka:9092 \
--describe --topic <topic_name>Возможные причины:
- A: Consumer упал / убит OOM.
- B: Медленный consumer (спикнула latency десериализации / записи в БД).
- C: Hot partition (перекос в
partition_key). - D: Пауза в downstream (PG / ES недоступен).
- E: Плохое сообщение poison-pill (consumer бесконечно ретраит).
Смягчение
A: scale + restart
kubectl -n tracium rollout restart deploy/<consumer-service>
# затем
kubectl -n tracium scale deploy/<consumer-service> --replicas=$(($(kubectl -n tracium get deploy/<consumer-service> -o jsonpath='{.spec.replicas}')+2))B: проверить latency downstream
# Медленные запросы в PG
kubectl -n tracium exec deploy/pg -- psql -c "
SELECT pid, state, query_start, query
FROM pg_stat_activity WHERE state != 'idle' ORDER BY query_start LIMIT 20;
"Снизить batch size consumer’а через config override (env <SERVICE>_KAFKA_MAX_POLL_RECORDS=100), перезапустить.
C: hot partition
Проверить распределение:
kubectl -n tracium exec deploy/kafka-tools -- \
kafka-consumer-groups.sh --bootstrap-server kafka:9092 \
--describe --group <group> | sort -k6 -n -rЕсли одна партиция держит большую часть lag — проверить partition_key в producer (ADR-0020 §“Гарантии и ordering”).
D: downstream недоступен
Сначала восстановить downstream (соответствующий runbook). Consumer догонит после.
E: poison pill
# Найти offset, на котором consumer застрял
kubectl -n tracium logs deploy/<consumer-service> --since=5m | grep -E "offset=[0-9]+" | tail -5Опции:
- Перенести offset вперёд (skip):
kafka-consumer-groups.sh --reset-offsets --to-offset <N+1> --topic <T> --group <G> --execute. Только с явным согласованием — мы пропускаем сообщение. - Если сообщение — подтверждённый poison — отправить в DLQ вручную.
Устранение root cause
- A: настройка limits/requests для consumer’а; предсказание OOM по бенчмаркам.
- B: оптимизация downstream (индексы, batch insert).
- C: пересмотр
partition_keyв producer’е, увеличение числа партиций. - D: более ранние алерты на доступность downstream.
- E: лучший error handling в consumer’е (skip → DLQ автоматически после N попыток).
Эскалация
- 30 мин lag не уменьшается →
#oncall-data. -
1 ч lag на топиках критического пути (
canonical.events.v1,offer.observation.v1) →#oncall-product(клиенты видят stale data).
Связано
- ADR-0002 (Kafka).
- ADR-0020 (Outbox).
20-architecture/schemas/events/topics.md- runbook
event-store-projection-lag.md