Deși Kubernetes promovează conceptul de lansări fără întrerupere (Zero-Downtime Rolling Updates), o configurare incompletă sau superficială a manifestelor de Deployment este una dintre cele mai frecvente cauze ale erorilor 502 Bad Gateway și 504 Gateway Timeout resimțite de utilizatori în timpul lansărilor de versiuni noi. Obținerea unei tranziții 100% invizibile necesită sincronizarea perfectă a trei mecanisme: parametrii de rolling update, sondele de sănătate și ciclul de viață Graceful Shutdown.
1. Parametrii Esențiali ai Strategiei RollingUpdate
În mod implicit, Kubernetes poate opri până la 25% din Pod-urile vechi înainte ca noile Pod-uri să fie gata de lucru. Pentru o disponibilitate absolută în producție, nu permiteți niciunui Pod sănătos să fie oprit prematur:
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
# maxSurge: Permite crearea temporară a Pod-urilor noi peste numărul dorit:
maxSurge: 25%
# maxUnavailable: Garantează că ZERO Pod-uri sănătoase sunt oprite până când cele noi devin Ready:
maxUnavailable: 0
2. De ce apar erori 502/504 la oprirea unui Pod? Cursa Asincronă
Când o versiune nouă este lansată, Kubernetes trimite semnalul de oprire către Pod-ul vechi. În același timp, Control Plane-ul trebuie să actualizeze resursele EndpointSlice și regulile iptables/ipvs pe toate nodurile din cluster pentru a opri trimiterea traficului. Această propagare de rețea durează între 2 și 5 secunde. Dacă aplicația voastră primește semnalul SIGTERM și își închide imediat socket-ul de ascultare HTTP, cererile utilizatorilor care sunt încă pe fir vor lovi un port închis, generând erori 502!
3. Soluția de Aur: Hook-ul lifecycle.preStop cu Sleep
Adăugarea unei scurte pauze (delay) înainte de trimiterea semnalului SIGTERM garantează că toate routerele Ingress și proxy-urile interne au eliminat Pod-ul vechi din rute înainte ca aplicația să înceapă oprirea conexiunilor:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-productie
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 0
template:
metadata:
labels:
app: api-productie
spec:
# Oferim aplicației până la 60 de secunde pentru a procesa cererile în curs:
terminationGracePeriodSeconds: 60
containers:
- name: api
image: my-repo/api:v2.4.1
ports:
- containerPort: 8080
lifecycle:
preStop:
exec:
# 1. Așteaptă 10 secunde ca EndpointSlice-ul să fie actualizat în tot clusterul:
command: ["/bin/sh", "-c", "sleep 10"]
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 2
periodSeconds: 5
failureThreshold: 2
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
failureThreshold: 3
4. Tratarea Semnalului SIGTERM în Codul Aplicației (Node.js / Go / Python)
După expirarea perioadei preStop, nucleul trimite semnalul SIGTERM. Codul aplicației trebuie să intercepteze acest semnal, să refuze conexiuni noi, să finalizeze cererile HTTP active și să închidă conexiunile cu baza de date:
// Exemplu Node.js:
process.on('SIGTERM', () => {
console.log('Semnal SIGTERM primit! Închidere conexiuni active...');
server.close(() => {
console.log('Server HTTP oprit. Închidere conexiune PostgreSQL...');
dbPool.end(() => {
console.log('Oprire curată finalizată. Ieșire.');
process.exit(0);
});
});
});