CSI VolumeAttachment zaseknutý: pody v ContainerCreating a drain, ktorý sa nepohne
Toto je storage incident, ktorý vie zobrať hodiny, lebo symptómy vyzerajú ako “Kubernetes je pomalý”:
- pody visia v ContainerCreating donekonečna
kubectl drainvisí, lebo volume sa neodpojí- v eventoch vidíš
AttachVolume.Attach failedaleboMulti-Attach error - appka ani neštartuje, takže app debug je zbytočný
Pri CSI je často “pravda” v VolumeAttachment objekte a jeho finalizeroch — nie v pode.
Testované na: Kubernetes 1.29–1.31, CSI drivery pre cloud block storage aj on-prem, StatefulSety, managed aj self-managed clustre.
Incident (anonymizovaný)
Odišiel nám node (hard failure). StatefulSet pod sa prescheduloval na nový node, ale nikdy nenabehol.
Čo som videl:
- Pod ostal v ContainerCreating.
- Eventy sa striedali medzi “waiting for volume attachment” a “multi-attach”.
- VolumeAttachment objekty sa kopili so starými node referenciami.
Skutočný root cause nebol “disk je pokazený”. CSI controller path bol degradovaný: external-attacher bežal s jednou replikou a počas chaosu sa vyhodil. Finalizery potom ostali zaseknuté a attach/detach sa nevedel zrovnať.
Constraint: toto bol stateful workload. Zlé “force” rozhodnutie môže spôsobiť data corruption. Potreboval som runbook, kde je “safe vs risky” explicitné.
Timeline
- T-0: node padne; StatefulSet pod sa rescheduluje.
- T+10m: pod stuck v ContainerCreating; pozriem Pod eventy.
- T+20m: nájdem PV/PVC a related VolumeAttachmenty.
- T+30m: VolumeAttachment ukazuje starý node; finalizer nepostupuje.
- T+45m: mitigácia: opraviť CSI controller path (external-attacher hore) a počkať na clean detach/attach.
- T+90m: pod nabehne; volume je attached na nový node.
- T+1d: fix: CSI controllery ako HA + alerty na stuck VolumeAttachment.
Mechanizmus: prečo je VolumeAttachment “pravda” pri CSI incidentoch
Pody nepripájajú volume, robia to controllery
Pri CSI attach/detach koordinujú controllery a stav sa sleduje cez objekty:
- PVC/PV popisujú čo chceš
- VolumeAttachment je intent + stav attachu pre konkrétny node
- external-attacher/external-provisioner + kube-controller-manager hýbu state machine
Finalizery existujú, aby Kubernetes “nezabudol” na attachment predtým, než driver potvrdí detach. Je to správne — ale keď je controller path nezdravý, finalizer je klin.
Najčastejšie failure modes
- Multi-Attach
- veľa block volume podporuje iba jeden attach
- keď node zomrie a volume je stále “attached”, nový node ho nedostane
- CSI controller path degradovaný
- external-attacher nebeží / je stuck / nemá leadera
- RBAC alebo cloud API chyby
- control-plane congestion
- Node je NotReady, ale nie je “mŕtvy”
- detach môže trvať dlho
- force detach priskoro = dva nody píšu na to isté volume
Runbook: od symptómu v pode po bezpečné zotavenie
Čo skontrolovať ako prvé
1) Pod eventy (často ukážu presné volume)
kubectl -n <ns> describe pod <pod> | sed -n '/Events:/,$p'
Hľadaj:
AttachVolume.Attach failedMulti-Attach errortimed out waiting for the condition
2) Nájsť PVC a PV
kubectl -n <ns> get pod <pod> -o jsonpath='{.spec.volumes[*].persistentVolumeClaim.claimName}{"\n"}'
kubectl -n <ns> get pvc <pvc> -o wide
kubectl get pv <pv> -o wide
3) Pozrieť VolumeAttachment (cluster-scoped)
kubectl get volumeattachment
kubectl describe volumeattachment <name>
Ak ich je veľa, vyhľadaj PV v YAML:
kubectl get volumeattachment -o yaml | grep -n "<pv>" -n | head
V describe ma zaujíma:
- target node
attached: true/false- chyby z CSI drivera
- finalizery, ktoré sa neodstraňujú
4) Skontrolovať CSI controller komponenty
Názvy závisia od drivera, ale typicky hľadáš:
- external-attacher
- external-provisioner
- controller pody CSI drivera
kubectl -n kube-system get pods | grep -E 'csi|attacher|provisioner' | head -n 50
Ako potvrdiť hypotézu
Máš “VolumeAttachment stuck” incident, ak:
- Pod je blokovaný na volume attach
- VolumeAttachment referencuje starý node alebo sedí v error stave
- CSI controller komponenty sú nezdravé alebo volume je attached inde
Silné potvrdenie je, keď po oprave controller path začnú VolumeAttachmenty postupovať bez force.
Bezpečné mitigácie
1) Najprv sprav CSI controller path zdravý
Ak external-attacher padol alebo je wedged, oprav to:
- vrátiť repliky
- opraviť RBAC
- opraviť cloud API rate limit
- reštartnúť iba controller komponenty (nie “všetko”)
Toto je bezpečné, lebo necháva state machine spraviť to, na čo je navrhnutá.
2) Pred “force” si dokáž, že starý node je fakt mŕtvy
Pri multi-attach:
- potvrdiť NotReady a že node sa nevráti
- potvrdiť, že FS nie je mountnuté nikde inde
- až potom zvážiť provider-side detach
3) Drain v správnom poradí
Pri draina:
- najprv cordon
- podľa potreby zmazať pody, ktoré držia volume
- počkať na detach pred pokračovaním
Rizikové mitigácie (reálny risk data loss)
- zmazať VolumeAttachment alebo ručne strhnúť finalizer
- Kubernetes si môže myslieť, že volume je safe na reattach, aj keď je stále mountnuté
- force detach v provideri bez dokazania, že node je mŕtvy
- filesystem split-brain
- reštartovať všetko
- viac chaosu, skrytie príčiny
Čo sme zmenili (konkrétne)
1) CSI controllery ako HA
Predtým: 1 replika, bez PDB, ľahko sa evictne pri strese.
Potom: 2 repliky + PDB + priority class (reprezentatívne):
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: csi-controller
namespace: kube-system
spec:
minAvailable: 1
selector:
matchLabels:
app: csi-controller
A deployment tweak (náčrt):
spec:
replicas: 2
template:
spec:
priorityClassName: system-cluster-critical
2) Alert na stuck VolumeAttachment
Zámer:
- alert ak VolumeAttachment existuje viac než 15 minút a nepostupuje
- alert ak je volume attached na NotReady node príliš dlho
Príklad tvaru query (názvy metrík závisia):
time() - kube_volumeattachment_created > 900
3) “Safe detach checklist” do dokumentácie
Checklist:
- stav nodu
- mount stav
- VolumeAttachment target
- až potom force detach
Ako verifikovať (merateľné)
1) VolumeAttachment sa zrovná
kubectl get volumeattachment
kubectl describe volumeattachment <name>
Očakávam:
- chyby prestanú
attachedsedí s realitou- finalizery sa odstránia keď majú
2) Pod prejde do Running
kubectl -n <ns> get pod <pod> -w
Očakávam: ContainerCreating → Running bez opakovaných attach eventov.
3) Stateful workload prejde basic integritou
Pri DB spravím minimálny read-only check, ktorý reálne číta dáta. Nechcem “recovery” za cenu korupcie.
Prevencia / guardrails
- CSI controllery ako control-plane
- HA, PDB, priority class, observability
- Time budgety
- “detach musí skončiť do N minút” ako SLO
- Alerty
- stuck VolumeAttachment, opakované attach errors, multi-attach
- Runbook
- explicitné “safe vs risky” kroky pre storage incidenty
Súvisiace čítanie
- Pod zaseknutý v Terminating: produkčný rozhodovací strom pre finalizery, volume a mŕtve nody
- Kubernetes graceful shutdown ako kontrakt: nula 502 počas rolloutov (HTTP + gRPC)
- Kubernetes rollout bez výpadku DB: Ako zastaviť PostgreSQL connection storm
- Zero-downtime migrácie PostgreSQL: Expand/Contract, backfill a rollback stratégie
- ‘No space left on device’ s 40% voľného disku: Inode a OverlayFS Death Spiral
- PostgreSQL Idle in Transaction: Núdzový Playbook pre Zaseknuté Spojenia
Súvisiace články
Pod zaseknutý v Terminating: produkčný rozhodovací strom pre finalizery, volume a mŕtve nody
Konzervatívny runbook na bezpečné odblokovanie Terminating Podov: finalizery, CSI/volume cleanup, mŕtve nody a kedy (a ako) použiť force delete.
Ephemeral-storage evictions v Kubernetes: logová búrka, ktorá vyhodila zdravé pody
Pody sú evicted kvôli ephemeral-storage aj keď disk vyzerá voľný. Runbook: nodefs/imagefs, logy, kubelet GC a nastavenie budgetov + log rotácia.
Redis AOF fsync latency špičky: keď sa durabilita stane tvojím p99
Redis AOF vie spraviť z durability p99 špičky: fsync tlak a BGREWRITEAOF fork CoW. Runbook na dôkaz, bezpečné mitigácie a guardrails.
etcd Quota Alarm: Keď Váš Kubernetes Cluster Prejde do Read-Only
Cluster prestane prijímať zápisy, pody sa nedajú naplánovať. Príčina: etcd dosiahol storage quota lebo compaction nebežal, história sa nahromadila nad limity.
Citujte tento článok
Ak na článok odkazujete, pridajte pôvodnú URL a uveďte autora.