Расскажите пример сложного инцидента в Kubernetes и как вы его решили.


Один из типичных сложных инцидентов (реалистичный сценарий), который часто вызывает серьёзные сбои в кластере — перегрузка etcd из-за «взрыва» количества объектов (ConfigMap/Secret/CR) в результате багнутого CI/оператора. Ниже — хронология, как это диагностируют и устраняют, точные команды и пост-инцидентные меры.

Симптомы и обнаружение

  • Вечером начали приходить алерты: etcd DiskUsage близок к 100%, apiserver latency (request duration p95/p99) резко выросла, контроллеры (Deployment/ReplicaSet) не успевали reconcile, kubectl часто возвращал 504/etcdserver: request timed out.

  • Приложения начали сообщать о таймаутах, новые Pod’ы оставались в Pending, rollout’ы зависали.

Быстрая проверка (команды для triage)

kubectl get --raw='/metrics' | grep apiserver_request_latencies_summary
etcdctl --endpoints=$ETCD_ENDPOINTS endpoint status --write-out=table
kubectl get events --all-namespaces --sort-by=.lastTimestamp | tail -n 50
kubectl get configmap -A --no-headers | wc -l
kubectl top nodes
journalctl -u kube-apiserver -n 200

Мы увидели: резкий рост числа ConfigMap в namespace ci (тысячи новых объектов за минуту), высокая частота операций create в apiserver и большая задержка ответов etcd.

Триаж и ограниченная «тушилка»

  1. Остановить источник шторма. Немедленно приостановили CI-pipeline/робота, который генерировал ConfigMap (в админке CI выключили job). Это снижает входящую нагрузку.

  2. Ограниченное удаление мусора: нельзя удалять тысячи объектов одномоментно (ещё больше нагружает API). Удаляли порциями:

kubectl get cm -n ci -l ci-build=true -o name | split -l 200 - cm_batch_
for f in cm_batch_\*; do kubectl delete -f $f & sleep 2; done
  1. Снижение нагрузки на etcd: уменьшили apiserver concurrency (если есть возможность) или временно ограничили внешние интеграции, чтобы дать etcd «остыть».

Восстановление состояния etcd (если compaction/defrag требуется)

  • Проверили метрики compaction/DB size:
etcdctl --endpoints=$ETCD_ENDPOINTS endpoint status --write-out=table
etcdctl --endpoints=$ETCD_ENDPOINTS snapshot status /backups/snap.db
  • Запустили ручную компактацию по последнему ревизионному номеру (вне пикового времени, после уменьшения записей):
REV=$(etcdctl --endpoints=$ETCD_ENDPOINTS endpoint status --write-out=json | jq '.\[0\].Status.header.revision')
etcdctl --endpoints=$ETCD_ENDPOINTS compact $REV
etcdctl --endpoints=$ETCD_ENDPOINTS defrag

Компактация + дефрагментация освободили место и снизили IO.

Коррекция control-plane и нагрузки

  • Увеличили временно IOPS/диск для etcd (в cloud) и масштабировали Prometheus scrape interval (если он делал heavy write/label cardinality).

  • Включили авто-throttling у CI (rate limits), чтобы избежать повторного шторма.

Root cause

  • Выяснилось, что CI job создавал per-build ConfigMap (уникальные имена) и не удалял их при завершении из-за бага в скрипте. Через сутки накопилось огромное количество мелких объектов, что привело к экспоненциальному росту размера etcd и к нагрузке на диск/IOPS.

Пост-инцидентные меры (конкретные изменения)

  • ResourceQuota в namespace CI, чтобы ограничить число ConfigMap:
apiVersion: v1
kind: ResourceQuota
metadata: { name: cm-quota, namespace: ci }
spec:
hard:
count/configmaps: "100"
  • CI fix: переписать job — переиспользовать один ConfigMap или обеспечивать корректный cleanup, добавить retry/backoff и проверку успешного удаления.

  • Alerting: добавить алерты на рост etcd DB size, rate of object creations (apiserver_admission_*), и на резкий рост count of objects per namespace.

  • Admission guard: выставили OPA/Gatekeeper правило, запрещающее создание ConfigMap с определёнными шаблонами имен или/и ограничивающее creation rate: временный fail-open в тестовой среде, затем enforce.

  • Etcd ops: настроили автоматическую компактацию и дефрагментирование по расписанию, мониторинг IOPS/latency, резервные снапшоты.

  • Throttling apiserver: при повторении проблемы можно скорректировать --max-requests-inflight и --max-mutating-requests-inflight у kube-apiserver, чтобы нагрузка не вывела его из строя.

Что проверяли после исправлений

  • Наблюдали за p99 latency apiserver, скоростью создания/удаления объектов, размером etcd, количеством ConfigMap в namespace. Тестировали прогон CI в контролируемом режиме (ограниченный rate).

Пост-мортемные артефакты (что оставили)

  • Runbook: шаги остановки источника, batch-удаление, компактация etcd, масштабирование storage.

  • Автотест для CI: проверка cleanup шагов перед merge.

  • Регулярный rehearsal restore etcd + тесты восстановления.

Этот сценарий показывает, как баг в прикладном коде (CI) может превратиться в кластерный инцидент из-за ограничений etcd; ключевые элементы успешного реагирования — быстрое отключение источника нагрузки, аккуратная порционная очистка, оптимизация etcd (compaction/defrag) и внедрение guardrails (quota, admission rules, alerting).