← Projecten

Kubernetes-platform: upgrade, NetworkPolicies en rightsizing

Een productiecluster op managed Kubernetes (Gardener) naar 1.34 gebracht, NetworkPolicies ontworpen op basis van gemeten verkeer, en de gereserveerde capaciteit teruggebracht van 45 naar 27 GiB, alles via GitOps met Flux.

De upgrade

Productie ging in twaalf minuten van 1.33 naar 1.34, met vooraf een geschreven plan, controlescripts en een nacontrole. Wat er toch misging, was leerzamer dan wat goed ging:

  • DNS op Gardener luistert op poort 8053. De service kube-dns biedt poort 53 aan, maar de pods luisteren op 8053. Een NetworkPolicy die alleen 53 toestaat, breekt DNS. Een lokaal kind-cluster vangt dit niet, want daar is het wél 53.
  • Twee PDB's op dezelfde pods blokkeren elke eviction. De Helm-chart had zijn eigen PodDisruptionBudget, en er stond nog een handmatige naast. De eviction-API weigert dan alles. Na het verwijderen bleef de status van de overgebleven PDB hangen, tot een annotatie op een pod de controller liet herberekenen.
  • Cilium heeft tijd nodig. Een pod op een verse node krijgt ~40 seconden Operation not permitted tot de policy actief is.

NetworkPolicies op basis van metingen

In plaats van policies te schrijven op basis van wat je denkt dat er praat, heb ik eerst gemeten. Hubble per Cilium-agent legde een uur lang alle verbindingen vast in acceptatie en drie kwartier in productie. Samen met de routes van de ingress gaf dat een volledige verkeersmatrix.

De policies zijn daarna gesimuleerd tegen die meting: nul gemeten verbindingen geblokkeerd. Eerst een periode op acceptatie zonder drops, daarna productie. Valkuilen: selectors op app.kubernetes.io/name in plaats van app, en langlopende verbindingen die in een SYN-meting niet voorkomen.

Rightsizing

Een dashboard "Clustercapaciteit en rightsizing" zet per workload de requests naast het werkelijke gebruik over dagen. Door Loki, istiod en caches op maat te zetten, ging de gereserveerde capaciteit van ~45 naar ~27 GiB, en kon de autoscaler een node terugschalen.

Kleine fixes die grote storingen voorkomen

  • RabbitMQ-cookie na een kubelet-herstart. fsGroup met de standaard fsGroupChangePolicy: Always zette groepsrechten op het Erlang-cookie, en RabbitMQ weigert dan te starten. OnRootMismatch lost het blijvend op.
  • RabbitMQ en het geheugen van de node. RabbitMQ rekende zijn watermark uit op het geheugen van de hele node, niet op zijn eigen limiet. Bij een limiet van 2 GiB betekent dat een OOMKill in plaats van flow control. Een expliciete total_memory_available_override_value repareert dat.
  • Een Helm-release in pending-upgrade blokkeert elke volgende upgrade, terwijl Flux zichtbaar niets doet. Diagnose: vergelijk de laatst geprobeerde config-digest met de geschiedenis; oplossing: een helm rollback naar de laatste goede versie.

Werkwijze

Alles loopt via Git: wijzigingen op een ontwikkelbranch, een merge request, en Flux rolt main uit. Productiewijzigingen staan klaar als merge request met een beschrijving van impact en terugdraaien, en worden door een tweede persoon gemerged.