Healthcheck Yazmadan Deploy Etmek
Port açılınca hazır sanmak

Deploy 'bitti' dedi çünkü süreç dinliyordu. İlk istekler 500 döndü: migrasyon kilitte, cache ısınmamış, bağımlı DNS henüz yok. Orchestrator bunu bilemez. Söylemezsen port açık = başarı. Compose'ta da kube'da da aynı yalan.
Üç soru, üç uç
Liveness: süreç kilitli mi, öldürülmeli mi. Readiness: bu replica trafik alsın mı. Startup: ilk boot, yavaş ısınma. Üçünü tek /health yapmak, migrasyon sürerken kutuyu öldürtmek veya bozuk kutuya trafik göndermek. İkisini de yaptım. İkisi de 'probe var' diye geçiyordu.
FROM mcr.microsoft.com/dotnet/aspnet:8.0.10-bookworm-slim
WORKDIR /app
COPY --from=build /out ./
HEALTHCHECK --interval=15s --timeout=2s --start-period=25s --retries=4 \
CMD wget -qO- http://127.0.0.1:8080/health/live || exit 1
ENTRYPOINT ["dotnet", "Api.dll"]
Dockerfile HEALTHCHECK, docker ps ve compose için. Kubernetes onu okumaz; kube livenessProbe ister. İkisini yazmak tekrar değil: biri daemon, biri kubelet. Sadece kube çalıştırıyorsan Dockerfile check'i yine faydalı — lokal compose aynı imajı kullanır.
livenessProbe:
httpGet: { path: /health/live, port: 8080 }
periodSeconds: 15
readinessProbe:
httpGet: { path: /health/ready, port: 8080 }
periodSeconds: 5
startupProbe:
httpGet: { path: /health/live, port: 8080 }
failureThreshold: 20
periodSeconds: 3
TCP yalanı
Port açık diye tcpSocket koymak, listen ile ready'yi tekrar karıştırmaktır. HTTP path, uygulamanın 'kabul ediyorum' dediği yerdir. TCP, çekirdeğin 'bu port meşgul' dediği yerdir. Migrasyon sırasında port meşguldür. TCP yeşil, kullanıcı 500 görür.
Exec probe wget taşır. Distroless imajda wget yoktur — sonraki yazı. Orada HTTP probe, kubelet'ten gelir, imajda kabuk istemez. Compose HEALTHCHECK ise imaj içi komuttur. Distroless + compose health, /busybox sızıntısı veya debug varyantı ister. Üretim imajına wget gömmek, health için kabuk geri almaktır. Tercihim: kube'da HTTP, lokal compose'ta ince bir wget'li debug imajı değil, aynı HTTP'yi curl olmayan bir HEALTHCHECK ile... aslında .NET tarafında küçük bir self-check binary. Kabuk yok, wget yok, process kendi portuna sorar.
failureThreshold × periodSeconds = öldürme süresi. Liveness 15s × 3 = 45s kilit. Startup 3s × 20 = 60s ısınma. Ready 5s × 2 = 10s trafik kesme. Sayıları ezber değil, boot grafiğinden yaz. İlk 90 saniyede live kırmızıysa startup eksiktir, uygulama yavaş değildir.
Compose'ta HEALTHCHECK yoksa depends_on: service_healthy da yoktur. Dosyada condition yazıp imajda check unutmak, compose'un 'health unknown' deyip beklememesine yol açar. İmaj ve compose aynı sözleşmeyi taşır. Biri eksikse diğeri yalan söyler.
# listen is not ready
startupProbe:
httpGet: { path: /health/live, port: 8080 }
failureThreshold: 20
periodSeconds: 3
livenessProbe:
httpGet: { path: /health/live, port: 8080 }
periodSeconds: 15
readinessProbe:
httpGet: { path: /health/ready, port: 8080 }
periodSeconds: 5
Deploy kaydına probe path'lerini de yazıyorum. Bir sonraki kişi /health mi /ready mi diye Slack'te sormasın. Path değişince kayıt değişir. Değişmezse rollback yazısındaki tuzak: eski kutu, yeni path, 404, hiç ready olmayan filo. Path de digest gibi pinlenir; şu anki health yoktur. Health yazmadan deploy, port açılışını tören sanmaktır.
/ready veritabanı ping'i ve 'migrasyon bitti' bayrağı. /live sadece process. Ready içine derin bağımlılık koyup liveness'e bağlamak, DB kesilince kendi kendini öldüren filodur. Ready kırmızı kalsın, live yeşil. Trafik dursun, kutu durmasın.
Yorumlar
Yorumlar (0)
Yorumlar üyelere açık. Üye ol · Giriş yap