Compose'ta Restart Policy Yetmiyor
unless-stopped, sürecin ayakta olduğunu sanır

restart: unless-stopped bir söz: süreç ölürse tekrar aç. Söz, sürecin işe yarar olduğunu kapsamaz. Migrasyon bitmeden listen eden API, compose gözünde ayakta. Bağımlı servis ona bağlanır, 500 yer, kendi restart'ına düşer. Döngü 'dayanıklılık' gibi durur.
Restart ile sağlık ayrı
Restart, exit code görür. Healthcheck, senin yazdığın komutu görür. İkisini karıştırmak, PID 1'in yaşamasını ürünün hazır olması sanmaktır. depends_on varsayılanı da sadece start sırasıdır. condition: service_healthy yoksa sıra, yarış.
services:
db:
image: postgres:16.2-bookworm
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d app"]
interval: 5s
timeout: 3s
retries: 10
api:
image: api:1.4.2
restart: unless-stopped
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8080/health"]
interval: 10s
timeout: 2s
retries: 6
start_period: 20s
start_period ilk boot'u cezalandırmasın diye var. Onu 5 dakikaya çekmek, bozuk migrasyonu gizlemek. 20-40 saniye çoğu API için yeter. Daha uzunsa health yanlış yerde: hazır değil, sadece açık.
Crash loop ile unhealthy
Çöküp kalkan kutu restart log'unda görünür. Listen edip yanlış cevap veren kutu unhealthy olur, restart etmez. Policy yetmez çünkü ölmemiştir. Orchestrator'a (veya compose'un health'ine) söylemezsen kimse kesmez. Load balancer hâlâ o porta yollar.
Üç policy, üç yalan
no hiç açmaz. Geliştirme için dürüst. always elle stop ettiğin kutuyu da açar; host reboot'ta sürpriz. unless-stopped elle durdurulanı açmaz, çökeni açar. on-failure sadece sıfır dışı exit'te açar; deneme sayısı yoksa sonsuz. Sonsuz, log'u doldurur, disk'i yer, 'dayanıklı' görünür.
PID 1'de uygulama doğrudan duruyorsa zombie çocuklar birikir. tini veya dumb-init bir init'tir, health değildir. Init + restart + health üç ayrı vida. Birini sıkmak diğerini gevşetmez. init: true compose'ta tini ekler. Onu 'artık health yazmama gerek yok' diye okumayın.
services:
worker:
image: api:1.4.2
init: true
restart: on-failure:5
stop_grace_period: 20s
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8080/health/live"]
interval: 15s
timeout: 2s
retries: 4
start_period: 30s
depends_on:
db:
condition: service_healthy
restart: true
depends_on.restart: true bağımlı unhealthy olunca üstteki servisi de yeniden düşünür. Yoksa db ayağa kalkmadan api bir kez patlar, restart policy api'yi açar, db hâlâ hazır değildir, döngü. Condition tek başına ilk start içindir. Sonraki ölümler policy ve restart flag.
stop_grace_period SIGTERM sonrası beklenen süre. 10 saniyede kapanmayan worker, SIGKILL yer, yarım iş bırakır. Restart onu temiz sanıp tekrar açar. Grace'i işin gerçek süresine yaz. Healthcheck o sürede kırmızıya düşsün ki üst katman trafik kesmiş olsun.
Compose healthcheck çıktısını docker compose ps satırında gösterir. unhealthy görüp restart bekleyen kişi, policy'nin o durumu görmediğini unutur. Unhealthy'yi kesmek için on-failure yetmez; bir yan süreç veya dış load balancer o durumu okumalı. Yoksa kutu yaşar, trafik ölür.
# policy without health: process alive, product dead
services:
api:
image: api:1.4.2
restart: unless-stopped
ports: ["8080:8080"]
Log'a restart count bakıyorum. Sayı artıyor, health yeşil kalıyorsa check yanlış yerde. Sayı duruyor, health kırmızıysa policy yanlış yerde. İki sayaç, iki vida. Birini okumadan 'compose dayanıklı' demiyorum. Dayanıklılık, ölüyü diriltmek değil, hazır olmayanı trafikten kesmek. Kesilmeyen trafik, yeşil bir yalandır.
Üçüncüsü: deploy.replicas compose'da Swarm olmadan dekor. Tek host compose'ta replica büyütmek, restart policy ile çözülmez. O sınır, serinin Kubernetes yazısının konusu. Burada bırakılan ders küçük: process alive ≠ ready. Policy ikincisini bilmez. Bilmesini istiyorsan health yaz, condition bağla, sayaçları ayrı oku.
Yorumlar
Yorumlar (0)
Yorumlar üyelere açık. Üye ol · Giriş yap