Späť na blog

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:

  1. Každý zápis zväčšuje DB - história sa hromadí rýchlo
  2. Compaction odstraňuje históriu - ale neuvoľňuje diskové miesto
  3. Defragmentácia uvoľňuje miesto - musí bežať po compaction
  4. Eventy sú často najväčší konzument - pravidelne ich čistite

Súvisiace Články

Súvisiace články

Citujte tento článok

Ak na článok odkazujete, pridajte pôvodnú URL a uveďte autora.

Michal Drozd. "etcd Quota Alarm: Keď Váš Kubernetes Cluster Prejde do Read-Only". https://www.michal-drozd.com/sk/blog/etcd-compaction-quota-alarm/ (Publikované 27. novembra 2024).