Kubernetes Pod Lifecycle Yönetimi

Mehmet Utku Tatlıdede
LCW Digital
Published in
3 min readFeb 4, 2022

Kubernetes de podumuz ayağa kalktığında yük almadan önce yapmamız gereken işlerimiz olabilir. Ayrıca yaşamı boyunca eğer kitlenirse vs terkrar restart edilmesi gerekiyor. Bunun için Kubernetes de pod icin 3 farklı probe bulunyor.
Özellikle deploy anında ve eğer Horizontal Pod Autoscaler (HPA) kullanıyor isek podlar otomatik olarak ayağa kalkıp indiğinde doğru şekilde yönetmez isek hataya sebep oluyoruz. bizim şu ana kadar tespit ettigimiz en sık
hata timeout oluşması sekilinde oluyor.

Pod ilk ayağa kalkarken dbden initial birseyler okuması belli seyleri compute etmesi dependencylerini kontrol etmesi gerekebilir. Gerçek hayat uygulaması olarak mobil api gatewayde startup da depend ettiğimiz tüm rest servislerin ping endpointlerinin çağırılması ve databaseden basit bir değer okunması işlemi yapılıyor. Bu sayede hem depencyler kontrol edilyor hem de EntityContext, HttpClient ve HttpConnectionPool lar uygulama içinde ayağa kalmış oluyor. Bunu yapmadığımızda zaman zaman timeout hataları aldıgımızı net bir şekilde tesbit ettik.

ilk ayaga kalkarken kullanmamız gereken probe tipi startupProbe buradaki end pointi her uygulama kendine ozel implement etmeli. Eger bir dependcymiz var ise kesinlikle implement etmeliyiz. aşağıdaki ornekte /startup/init
mobilapigateway uzerinde yukarıdaki paragrafta bahsettigimzi gibi implement edilmistir.

Pod’umuzun ayakta oldgunu kuberntes in surekli kontrol edebilmesi eger kitlendi ise restart edilmesi cok guzel bir nimet. bunun icin livenessProbe kullanıyoruz. /probe/ping Pars.Core içinde var ve ping işleminde hostname de döndüğü için tercih ediyoruz. Pars.Core monitoring içerisindeki bir endpoint. AppMetrics’le gelen ping end pointinden daha sonra eklendiği için Pars.Core un sağlıklı ayağa kalkmasını da bir şekilde kontrol etmiş oluyoruz.

readinessProbe biraz ilginç bir case podumuzun sağlıklı ve ayakta olduğunu ancak şu an request almaması gerektigini belirtmek icin kullanılıyor. Genel pratik pod bir kere basarılı şekilde ayaga kalktıktan sonra request almaya devam etmesi seklinde. Diger türlü ortak bir depency’nin hata alması tüm sistemi durma noktasına götürebilecek bir cascading reaksiyon başlatabilir. kısaca /probe/ready end pointi de /probe/ping gibi basit bir cevap donuyor.

Kullanılan ortak parametreler

  • periodSeconds : kaç saniyede bir tekrarlanacağı
  • successThreshold : kaç başarılı işlem (http 2xx — 3xx arası bir kod) başarılı kabul edilecek
  • failureThreshold : kaç başarısız işlem (http 5xx) başarısız kabul edilecek
  • timeoutSeconds : probe icin set edilen end point icin timeout suresi
  • initialDelaySeconds : probe’a request ilk ne zaman atılmaya başlasın. pod 3 probe dan da başarılı almak zorunda olduğu için en erken ne zaman açılabileğini göstermektedir.

aşağıdaki paramtreler yük altında test edilmiş şu ana kadar en iyi sonucları vermis değerlerdir. Ama tabiki subject to change :)

livenessProbe ve readinessProbe ların 1 sn timeout ile sağlıklı çalışmadığı podları sürekli restart ettigi durumlar yaşanmıştır.

        startupProbe:
httpGet:
path: /startup/init
port: 8080
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
failureThreshold: 5
readinessProbe:
httpGet:
path: /probe/ready
port: 8080
scheme: HTTP
initialDelaySeconds: 15
timeoutSeconds: 15
periodSeconds: 20
successThreshold: 1
failureThreshold: 3
terminationMessagePath: /dev/termination-log
livenessProbe:
httpGet:
path: /probe/ping
port: 8080
scheme: HTTP
initialDelaySeconds: 15
timeoutSeconds: 15
periodSeconds: 20
successThreshold: 1
failureThreshold: 5

Yeni versiyonun deployu sırasında ya da HPA poda gerek olmadığınıa karar verdiğinde podu terminate eder. Bu durumda pod üzerinde requestlerin sonuçlandığından emin olmak için .Net Core lifetime event OnAppStopping implement edilmis ve 25 sn sleep etmesi sagladık. Uygulamaya göre süre değişebilir. Mobil app de uyguladgımız timeout politikası sayesinde en uzun islem 8–10 sn oldugu icin 25 sn oldukca yeterlidir ve implement edildikten sonra canlıda hataların azatltımızı net şekilde gözlemledik

public virtual void Configure(IApplicationBuilder app, IApplicationLifetime lifetime)
{
app.UseTxTrackMiddleware();
app.UseUserSellectionMiddleware();
app.UseSessionValidationMiddleware();
app.UseInfrastructure(liveBuilder =>
{


}, devBuilder =>
{
devBuilder
.UseSwaggerDocumentation();
});


lifetime.ApplicationStarted.Register(OnAppStarted);

lifetime.ApplicationStopping.Register(OnAppStopping);

lifetime.ApplicationStopped.Register(OnAppStopped);

app.UseCors("MyAllowSpecificOrigins");
}
public void OnAppStarted()
{
Console.WriteLine("Mobile Api Gateway Started");
}


public void OnAppStopping()
{
int terminationTime = _configuration.GetValue<int>("TerminationGracePeriodSeconds");
if (terminationTime == 0)
{
Console.WriteLine("Terminate Immediately");
}
else
{
Console.WriteLine($"ApplicationStopping called, sleeping for {terminationTime}s");
Thread.Sleep(terminationTime*1000);
}

}


public void OnAppStopped()
{
Console.WriteLine("Application Terminated");
}

Yararlandığım bazı kaynaklar

https://andrewlock.net/deploying-asp-net-core-applications-to-kubernetes-part-6-adding-health-checks-with-liveness-readiness-and-startup-probes/

https://andrewlock.net/deploying-asp-net-core-applications-to-kubernetes-part-11-avoiding-downtime-in-rolling-deployments-by-blocking-sigterm/

https://blog.markvincze.com/graceful-termination-in-kubernetes-with-asp-net-core/

--

--