etcd Quota Alarm: Keď Váš Kubernetes Cluster Prejde do Read-Only
Cluster vyzeral ok, kym etcd nezacalo kricat o svojej quota. “kubectl apply visí, nové pody stuck v Pending.” Príčina: etcd prekročil svoju storage quota a vstúpil do alarm módu, čím sa cluster stal efektívne read-only kým nespravidlíte compact a defrag.
Prostredie: Kubernetes s etcd (self-managed alebo kubeadm), clustery s vysokým churnom (časté deploymenty, veľa eventov), default etcd konfigurácia
Problém
Náhle Zamrznutie
Časová os zamrznutia clustera:
T+0:00 Normálna prevádzka clustera
etcd DB size: 2GB (quota: 2GB)
Compaction: beží každých 5 min
T+1:00 Compaction job ticho zlyhá
DB size začína rásť s históriou
T+24:00 DB size: 2.05GB
etcd spúšťa ALARM: NOSPACE
Všetky write operácie zamietnuté!
T+24:01 kubectl apply deployment.yaml
Error: etcdserver: mvcc: database space exceeded
T+24:02 Pod crashne, nemôže sa reschedulovať
scheduler: can't create binding: space exceeded
T+24:03 ConfigMap update zlyhá
Všetko je zamrznuté
Ako Vyzerajú Chyby
# API server logy
E0115 03:42:17.123456 etcdserver: mvcc: database space exceeded
# kubectl chyby
$ kubectl apply -f deployment.yaml
Error from server: etcdserver: mvcc: database space exceeded
$ kubectl create namespace test
error: etcdserver: mvcc: database space exceeded
# Dokonca aj mazanie zlyhá!
$ kubectl delete pod stuck-pod
error: etcdserver: mvcc: database space exceeded
Príčina
Ako Funguje etcd Storage
etcd MVCC (Multi-Version Concurrency Control):
┌─────────────────────────────────────────────────────────────┐
│ Každý zápis vytvára NOVÚ revíziu, staré verzie uchované │
│ │
│ Kľúč: /registry/pods/default/nginx │
│ │
│ Rev 1000: {replicas: 1} ← uchovaný pre históriu │
│ Rev 1001: {replicas: 2} ← uchovaný pre históriu │
│ Rev 1002: {replicas: 3} ← uchovaný pre históriu │
│ Rev 1003: {replicas: 5} ← aktuálny │
│ │
│ Bez compaction: │
│ - Všetky revízie uložené navždy │
│ - DB rastie s každým zápisom │
│ - watch operácie môžu čítať starú históriu │
│ │
│ Quota (default 2GB) zabraňuje neobmedzenému rastu │
│ Keď je prekročená → ALARM → read-only mód │
└─────────────────────────────────────────────────────────────┘
Prečo Compaction Prestane
# Bežné dôvody zlyhania compaction:
# 1. etcd beží bez auto-compaction
etcd --auto-compaction-retention=0 # Vypnuté!
# 2. kube-apiserver nenastavuje compaction
# Skontrolujte apiserver flagy:
ps aux | grep kube-apiserver | grep etcd-compaction
# Chýba: --etcd-compaction-interval
# 3. Compaction beží ale defrag nie
# Compaction označí miesto ako uvoľniteľné
# Defragmentácia ho skutočne uvoľní
# DB súbor zostáva veľký bez defrag
# 4. Vysoká rýchlosť zápisov prevyšuje rýchlosť compaction
# Cluster s 1000+ deploymentami/hodinu
# Compaction nestíha
Matematika Quota
# Kontrola aktuálneho stavu etcd
etcdctl endpoint status --write-out=table
# +----------------+------------------+-------+-------+----------+
# | ENDPOINT | ID | V | DB SZ | IS LEADER|
# +----------------+------------------+-------+-------+----------+
# | 127.0.0.1:2379 | 8e9e05c52164694d | 3.5.0 | 2.1GB | true |
# +----------------+------------------+-------+-------+----------+
# Kontrola quota
etcdctl endpoint status --write-out=json | jq '.[] | .Status.dbSize, .Status.dbSizeInUse'
# 2147483648 (DB veľkosť na disku: 2GB)
# 1073741824 (Skutočne použité: 1GB - zvyšok je história!)
# Kontrola alarmov
etcdctl alarm list
# memberID:8e9e05c52164694d alarm:NOSPACE
Diagnostika
Kontrola Zdravia etcd
# Pripojenie k etcd (nájdite certy v /etc/kubernetes/pki/etcd/)
export ETCDCTL_API=3
export ETCDCTL_ENDPOINTS=https://127.0.0.1:2379
export ETCDCTL_CACERT=/etc/kubernetes/pki/etcd/ca.crt
export ETCDCTL_CERT=/etc/kubernetes/pki/etcd/server.crt
export ETCDCTL_KEY=/etc/kubernetes/pki/etcd/server.key
# Kontrola zdravia
etcdctl endpoint health
# Kontrola stavu vrátane DB veľkosti
etcdctl endpoint status --write-out=table
# Vypísanie všetkých alarmov
etcdctl alarm list
Analýza Využitia Storage
# Top kľúče podľa veľkosti
etcdctl get / --prefix --keys-only | \
cut -d/ -f1-4 | sort | uniq -c | sort -rn | head -20
# Výstup ukazuje čo plní váš etcd:
# 15234 /registry/events/default
# 8234 /registry/pods/kube-system
# 5123 /registry/configmaps/default
# Eventy sú často najväčší vinník!
# Default retention: navždy (kým ich nezmažete)
Kontrola Stavu Compaction
# Získanie aktuálnej revízie
etcdctl endpoint status --write-out=json | jq '.[].Status.header.revision'
# 12345678
# Pozrite na akú revíziu je compact hotový
etcdctl endpoint status --write-out=json | jq '.[].Status.header.raft_term'
# Kontrola apiserver compaction nastavení
kubectl -n kube-system get pod kube-apiserver-* -o yaml | \
grep -A5 etcd-compaction
Riešenie
Krok 1: Núdzové - Vymazanie Alarmu
# Najprv compact pre uvoľnenie logického miesta
# Získanie aktuálnej revízie
REVISION=$(etcdctl endpoint status --write-out=json | \
jq -r '.[].Status.header.revision')
# Compact na aktuálnu revíziu (odstráni históriu)
etcdctl compact $REVISION
# Defragmentácia pre uvoľnenie fyzického miesta
etcdctl defrag --endpoints=https://127.0.0.1:2379
# Vymazanie alarmu
etcdctl alarm disarm
# Overenie
etcdctl alarm list
# (malo by byť prázdne)
etcdctl endpoint status --write-out=table
# DB veľkosť by mala byť menšia
Krok 2: Zvýšenie Quota (Dočasné)
# Ak compaction samotný nestačí, zvýšte quota
# Editujte etcd static pod manifest
vim /etc/kubernetes/manifests/etcd.yaml
# Pridajte/upravte:
spec:
containers:
- command:
- etcd
- --quota-backend-bytes=4294967296 # 4GB
# ... ostatné flagy
# etcd sa automaticky reštartuje
# VAROVANIE: Toto lieči symptóm, nie príčinu
Krok 3: Povolenie Auto-Compaction
# etcd auto-compaction (editujte etcd manifest)
spec:
containers:
- command:
- etcd
- --auto-compaction-mode=periodic
- --auto-compaction-retention=1h # Uchovať 1 hodinu histórie
# Pre kube-apiserver (editujte apiserver manifest)
spec:
containers:
- command:
- kube-apiserver
- --etcd-compaction-interval=5m0s # Compact každých 5 minút
Krok 4: Vyčistenie Eventov
# Eventy sú často najväčší konzument miesta
# Zmazanie starých eventov
kubectl delete events --all -A
# Alebo nastavte kratšie TTL (Kubernetes 1.25+)
# V apiserveri:
--event-ttl=1h # Default je 1h, ale skontrolujte váš
Krok 5: Nastavenie Pravidelnej Defragmentácie
# CronJob pre pravidelnú defragmentáciu
apiVersion: batch/v1
kind: CronJob
metadata:
name: etcd-defrag
namespace: kube-system
spec:
schedule: "0 2 * * *" # Denne o 2:00
jobTemplate:
spec:
template:
spec:
hostNetwork: true
containers:
- name: etcd-defrag
image: bitnami/etcd:3.5
command:
- /bin/sh
- -c
- |
etcdctl defrag \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
volumeMounts:
- name: etcd-certs
mountPath: /etc/kubernetes/pki/etcd
readOnly: true
volumes:
- name: etcd-certs
hostPath:
path: /etc/kubernetes/pki/etcd
restartPolicy: OnFailure
nodeSelector:
node-role.kubernetes.io/control-plane: ""
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
Krok 6: Zníženie Objemu Zápisov
# Znížte event spam z controllerov
# V controller-manageri:
spec:
containers:
- command:
- kube-controller-manager
- --event-burst=20 # Default 30
- --event-qps=5 # Default 20
# Znížte leader election churn
# Zvýšte lease duration
spec:
containers:
- command:
- kube-controller-manager
- --leader-elect-lease-duration=30s # Default 15s
- --leader-elect-renew-deadline=20s # Default 10s
Monitoring
groups:
- name: etcd
rules:
- alert: EtcdDatabaseSizeHigh
expr: |
etcd_mvcc_db_total_size_in_bytes /
etcd_server_quota_backend_bytes > 0.8
for: 5m
labels:
severity: warning
annotations:
summary: "etcd databáza {{ $value | humanizePercentage }} z quota"
- alert: EtcdDatabaseSpaceExceeded
expr: |
etcd_server_has_leader == 1 and
etcd_mvcc_db_total_size_in_bytes > etcd_server_quota_backend_bytes
for: 1m
labels:
severity: critical
annotations:
summary: "etcd quota prekročená - cluster read-only!"
- alert: EtcdCompactionPaused
expr: |
increase(etcd_debugging_mvcc_db_compaction_total_duration_milliseconds_count[1h]) == 0
for: 2h
labels:
severity: warning
annotations:
summary: "etcd compaction nebežal 2 hodiny"
- alert: EtcdDefragNeeded
expr: |
(etcd_mvcc_db_total_size_in_bytes - etcd_mvcc_db_total_size_in_use_in_bytes) /
etcd_mvcc_db_total_size_in_bytes > 0.5
for: 1h
labels:
severity: warning
annotations:
summary: "etcd má >50% uvoľniteľného miesta - potrebný defrag"
Checklist
## etcd Quota Alarm Obnova
### Núdzová Obnova
- [ ] Skontrolujte stav alarmu: etcdctl alarm list
- [ ] Získajte aktuálnu revíziu pre compaction
- [ ] Spustite compaction: etcdctl compact $REVISION
- [ ] Spustite defragmentáciu: etcdctl defrag
- [ ] Zrušte alarm: etcdctl alarm disarm
- [ ] Overte že cluster prijíma zápisy
### Prevencia
- [ ] Povoľte auto-compaction v etcd (--auto-compaction-retention)
- [ ] Povoľte compaction v apiserveri (--etcd-compaction-interval)
- [ ] Nastavte plánovanú defragmentáciu
- [ ] Pravidelne mažte staré eventy
- [ ] Monitorujte DB veľkosť vs quota
### Kapacitné Plánovanie
- [ ] Dimenzujte quota vhodne (začnite 2GB, zvyšujte podľa potreby)
- [ ] Odhadnite rýchlosť zápisov a potreby retention
- [ ] Zvážte 3+ node etcd cluster pre HA
Záver
Poučenie: MVCC dizajn etcd uchováva celú históriu kým nebeží compaction. Bez pravidelného compaction a defragmentácie váš cluster dosiahne quota a stane sa read-only.
Kľúčové princípy:
- Každý zápis zväčšuje DB - história sa hromadí rýchlo
- Compaction odstraňuje históriu - ale neuvoľňuje diskové miesto
- Defragmentácia uvoľňuje miesto - musí bežať po compaction
- Eventy sú často najväčší konzument - pravidelne ich čistite
Súvisiace Články
- Kubernetes Pod Stuck in Pending - Scheduling problémy
- Kubernetes Control Plane Debugging - Troubleshooting control plane
Súvisiace články
etcd Watch Replay Búrky: Keď Obrovské ConfigMapy Zabíjajú Control Plane
Apiserver je 'náhodne pomalý'. Príčina: veľké, často aktualizované ConfigMapy spúšťajú watch compaction, čo spôsobuje simultánny relist tisícov kontrolérov.
Kubernetes Headless Service DNS: Zastarané Záznamy Po Zmazaní Podu
Requesty idú na neexistujúce pody. Príčina: headless service DNS záznamy pretrvávajú v klient DNS cache po zmazaní podov, pred propagáciou endpoints update.
Traffic Ide na Mŕtve Pody: Conntrack Zastaralé NAT Mapovanie
Deploy spôsobuje 503 presne 2 minúty. Problém: conntrack drží NAT mapovanie na staré pod IP aj po tom čo Kubernetes odstráni endpointy.
Vyčerpanie Ephemeral Portov: Node Ktorý 'Pokazí'
Jeden Kubernetes node začne zlyhávať pripojenia k externým službám zatiaľ čo pody vyzerajú zdravé. Skrytá príčina: sidecar proxy vyčerpávajú ephemeral porty krátkodobými spojeniami.
Citujte tento článok
Ak na článok odkazujete, pridajte pôvodnú URL a uveďte autora.