Kubernetes Readiness ve Liveness Nedir?

Kubernetes Readiness ve Liveness, uygulamaların sağlığını izlemede kullanılan Kubernetes özellikleridir. Uygulamaların sağlık durumlarını takip ederek hizmet kesintileri önleyebilir ve uygulamalarınıza otomatik onarım yeteneği kazandırabilirsiniz.

1. Readiness Probe Nedir?

Readiness, bir uygulamanın hizmet vermeye hazır olup olmadığını belirler. Yani uygulama, kullanıcılardan gelen taleplere cevap verebilecek hale gelmiş mi, yoksa henüz hazır değil mi sorusunun cevabı Readiness probe ile verilir. Örneğin, uygulamanın başlatılması birkaç saniye sürüyor olabilir veya veritabanı bağlantısının kurulması gecikebilir. Bu durumlarda, "readiness" durumunu kontrol eden bir mekanizma, uygulamanın kullanıcılara sunulmadan önce hazır olup olmadığını doğrulayabilir.

Readiness probe, periyodik olarak çağrılır ve bir Pod'un client isteklerini alıp almayacağını belirler. Bir container, readiness probe'a başarılı sonuç döndüğünde, ilgili Pod, istekleri kabul etmeye hazır olarak işaretlenir. Eğer başarılı sonuç dönmezse Pod Unhealthy olarak işaretlenir ve Pod'u yöneten bir Servis varsa ilgili Pod'a trafiği yönlendirmez.

💡
Readiness probe başarılı sonuç alamadığında Pod içindeki container'ları yeniden başlatmaz. Readiness sadece bir Pod'un sağlıklı olup olmadığını belirler.
🛑
Eğer Readiness Probe kullanmazsanız, uygulamanız hazır olmadan trafik almaya başlayacaktır. Bu da client'lar için başarısız ve olumsuz bir deneyim yaratır. Bu nedenle Readiness Probe kullanmanızı kesinlikle öneriyoruz.

2. Liveness Probe Nedir?

Liveness, uygulamanın doğru şekilde çalışıp çalışmadığını düzenli olarak kontrol eder. Uygulama, beklenmeyen bir şekilde çöktüğünde veya donduğunda, liveness durumunu kontrol eden mekanizma bu durumu tespit eder ve uygun bir şekilde işlem yapar. Bu işlem, uygulamanın yeniden başlatılması, kapatılması veya yedek uygulamanın devreye sokulması olabilir.

Normalde bir Container hata verip kapandığında restartPolicy ayarlıysa yeniden başlatılır. Fakat bazen container içindeki uygulamanızda bir sorun olduğunda, uygulama çalışmaya devam edip Container'ı canlı tutsa bile, uygulama doğru bir çalışma tutumu sergilemiyor olabilir. Örneğin bir Java uygulaması çalışırken sürekli OutOfMemoryError hatası atıyor olabilir veya daha farklı sebepler yüzünden beklenen gibi çalışmayabilir. Bu durumda restartPolicy devreye girmez çünkü JVM uygulamayı halen ayakta tutuyordur. Bu tip senaryolar için Liveness probe hayat kurtarıcıdır.

Tıpkı Readiness probe gibi, Liveness probe da periyodik olarak çağrılır ve uygulamanın sağlıklı olup olmadığı belirlenir. Eğer sağlıklı değilse Pod içindeki container'lar yeniden başlatılır.

💡
Liveness probe başarılı sonuç alamadığında Pod içindeki container'ları yeniden başlatır. Readiness probe ile arasındaki en önemli fark budur.
🛑
Eğer Liveness Probe kullanmazsanız, uygulamanız çalışmadığı halde trafik almaya devam edecektir. Bu da client'lar için başarısız ve olumsuz bir deneyim yaratır. Bu nedenle otomatik onarım için Liveness Probe kullanmanızı kesinlikle öneriyoruz.
💡
Liveness probe, kaynak tüketimi açısından kontrol edilmelidir. Eğer düzenli olarak çalışan bir probe, çok fazla cpu ve memory tüketirse ana uygulamanın çalışmasını etkileyebilir. Bu nedenle karışık olmayan, basit ve en fazla bir saniye sürecek bir kontrol işlemi belirlemeniz önerilir.

2. Readiness ve Liveness Probe Tipleri, Parametreleri ve Loglar

Hem Readiness hem de Liveness probe oluşturmak için üç farklı yöntem vardır. Uygulamanızın nasıl çalıştığına bağlı olarak herhangi bir yöntemi seçip kullanabilirsiniz.

  • Exec probe: Container içinde shell komutu execute edilir. Probe'un durumu bu process'in exit koduna göre belirlenir.
  • HTTP GET probe: Container'ın belirttiğiniz bir endpointine HTTP GET isteği atılır. Response kodu 2xx ve 3xx ise sağlıklı, değilse sağlıksız olarak işaretlenir.
  • TCP Socket probe: Container'ın belirlenen bir portuna bir TCP bağlantısı açılmaya çalışılır. Eğer bağlantı kurulursa  sağlıklı, kurulamazsa sağlıksız olarak işaretlenir.

Ayrıca tüm probe'larda ortak kullanabileceğiniz bazı parametreler vardır. Bu parametreler ve açıklamaları şu şekildedir:

  • initialDelaySeconds: Container'ın başlatılmasından sonra ilk kontrollerin ne kadar süre sonra başlayacağını belirten değerdir.
  • periodSeconds: Kontroller arasındaki süreyi belirten değerdir.
  • timeoutSeconds: Kontrol işleminin kaç saniye içinde tamamlanması gerektiğini belirten değerdir. Bu süre geçtiği halde komut tamamlanmazsa başarısız sayılır.
  • successThreshold: Sağlıklı sayılabilmesi için kontrolün kaç kez ardışık başarılı olması gerektiğini belirten değerdir.
  • failureThreshold: Sağlıksız sayılabilmesi için kontrolün kaç kez ardışık başarısız olması gerektiğini belirten değerdir.
💡
Uygulamanızın anlık yanıt verememesi veya network problemlerini düşündüğünüzde, uygulamanızın gereksiz yere yeniden başlatılmasını istemiyorsanız failureThreshold değerini 1 ayarlamak mantıklı değildir. Bu gibi nedenlerle varsayılan olan 3 değerini kullanmak için bu parametreyi eklemeyebilirsiniz. 

Son olarak ise Pod içindeki container liveness probe'un onu sağlıksız olarak işaretlemesi sonucu kapandıysa ve yeni bir container başladıysa, yine de kubectl logs mypod --previous komutu ile kapatılan container'ın loglarına erişebiliriz. Böylece sorunun ne olduğunu inceleme şansınız olur.

Şimdi her bir probe tipini örneklerle inceleyelim.

2.1. Exec Probe

Exec probe, belirli bir komutu pod içindeki bir container içinde çalıştırır ve sonucuna göre sağlık durumunu belirler.

apiVersion: v1
kind: Pod
metadata:
  name: exec-probe-pod
spec:
  containers:
  - name: readiness
    image: registry.k8s.io/busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600    
    readinessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 10
      timeoutSeconds: 1
      successThreshold: 1
      failureThreshold: 3
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 60
      periodSeconds: 10
      timeoutSeconds: 1
      successThreshold: 1
      failureThreshold: 3

Bu pod, 5sn bekledikten sonra (initialDelaySeconds), her 10 saniyede bir (periodSeconds) komutu çalıştırarak sonucunu değerlendirir. Komut 1 saniyeden uzun sürerse (timeoutSeconds), probe başarısız sayılacaktır. Success threshold, yani kaç defa üst üste başarılı sonuç alınması gerektiği (successThreshold), burada 1 olarak ayarlanmıştır. Aynı şekilde, kaç defa üst üste başarısız sonuç alınması durumunda (failureThreshold) container'ın sağlıksız sayılacağı belirtilir.

Örnekte /tmp/healthy dosyası ilk 30sn boyunca olacağı için Pod Healthy ve Ready olarak işaretlenecek fakat 30. sn den sonra yapılan kontrollerde dosya olmayacağı için Unhealty ve NotReady olarak işaretlenecektir.

Liveness probe ise 60.sn den sonra devreye girecek ve dosyayı bulamadığı için container'ı yeniden başlatacaktır.

$ kubectl get pods -w
NAME                  READY   STATUS    RESTARTS      AGE
exec-probe-pod        0/1     Running   0             12s
exec-probe-pod        1/1     Running   0             21s
exec-probe-pod        0/1     Running   0             61s
exec-probe-pod        0/1     Running   1 (7s ago)    2m8s
exec-probe-pod        1/1     Running   1 (20s ago)   2m21s

kubectl describe komutuyla baktığımızda ise event ve detayları görebilirsiniz.

$ kubectl describe pod exec-probe-pod
•••
Conditions:
  Type              Status
  Initialized       True
  Ready             False
  ContainersReady   False
  PodScheduled      True
•••
Events:
  Type     Reason     Age                  From               Message
  ----     ------     ----                 ----               -------
  •••
  Normal   Scheduled  3m24s                 default-scheduler  Successfully assigned default/exec-probe-pod to minikube
  Normal   Pulled     3m17s                 kubelet            Successfully pulled image "registry.k8s.io/busybox" in 6.473781714s (6.473799548s including waiting)
  Warning  Unhealthy  114s (x3 over 2m14s)  kubelet            Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
  Normal   Killing    114s                  kubelet            Container readiness failed liveness probe, will be restarted
  Normal   Pulling    84s (x2 over 3m24s)   kubelet            Pulling image "registry.k8s.io/busybox"
  Normal   Created    78s (x2 over 3m17s)   kubelet            Created container readiness
  Normal   Started    78s (x2 over 3m17s)   kubelet            Started container readiness
  Normal   Pulled     78s                   kubelet            Successfully pulled image "registry.k8s.io/busybox" in 6.444312214s (6.444332022s including waiting)
  Warning  Unhealthy  34s (x13 over 2m44s)  kubelet            Readiness probe failed: cat: can't open '/tmp/healthy': No such file or directory

2.2. HTTP Get Probe

HTTP Get probe, uygulamanızın belirlediğiniz bir endpointine HTTP Get isteği gönderir ve sonucuna göre sağlık durumunu belirler. Probe'un başarılı sayılabilmesi için response kodunun 2xx veya 3xx olması gerekir.

apiVersion: v1
kind: Pod
metadata:
  name: http-probe-pod
spec:
  containers:
  - name: my-app
    image: my-image:latest
    readinessProbe:
      httpGet:
        path: /health
        port: 8080
        httpHeaders:
        - name: Custom-Header
          value: Awesome
      initialDelaySeconds: 5
      periodSeconds: 10
      timeoutSeconds: 1
      successThreshold: 1
      failureThreshold: 3

Exec probe örneğinde detaylı açıklama ve örnek verdiğimiz için burada sadece probe syntax'ını gösterip sıradaki başlığa geçiyoruz. Dilerseniz livenessProbe içinde readinessProbe'da kullandığımız aynı syntax'ı kullanabilirsiniz.

💡
HTTP Get probe kullanacağınız endpoint'lerinizin herhangi bir authentication gerektirmediğine veya gerekiyorsa bile http header parametreleriyle authenticated olabileceğinize emin olunuz. Aksi halde container'larınız unhealthy işaretlenip sürekli yeniden başlatılacaktır.

2.3. TCP Socket Probe

TCP socket probe, uygulamanızın belirlediğiniz bir portuna socket bağlantısı yapmaya çalışır ve sağlık durumunu belirler.

apiVersion: v1
kind: Pod
metadata:
  name: tcp-probe-pod
spec:
  containers:
  - name: my-app
    image: my-image:latest
    livenessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
      timeoutSeconds: 1
      successThreshold: 1
      failureThreshold: 3

Exec probe örneğinde detaylı açıklama ve örnek verdiğimiz için burada sadece probe syntax'ını gösterip sıradaki başlığa geçiyoruz. Dilerseniz readinessProbe içinde livenessProbe'da kullandığımız aynı syntax'ı kullanabilirsiniz.

3. Container Exit Code

Bir container'a Liveness probe ayarlarsanız ve unhealthy bir durumda container yeniden başlatılırsa kubectl describe komutunun çıktısında LastState altında Exit Code değerini görebilirsiniz.

$ kubectl describe pod mypod
•••
    Last State:     Terminated
    Reason:       Error
    Exit Code:    137
    Started:      Wed, 10 May 2023 14:44:24 +0300
    Finished:     Wed, 10 May 2023 14:46:18 +0300
•••

Container'ın neden terminate edilğine dair alınan kodu 137 olarak görüyoruz. B değerlerin özel bir anlamı vardır.

137 sayısı, iki sayının toplamıdır: 128+X. Burada X, sürecin sonlanmasına neden olan işleme gönderilen sinyal numarasıdır. Örnekte x, SIGKILL sinyalinin numarası olan 9'a eşittir, yani çalışan process force kill  ile sonlandırılmıştır.

Eğer bu sayı 143 olsaydı, X değeri 15 yani SIGTERM sinyali kullanılmış anlamına gelecekti.

💡
Her iki değerde (137 ve 143), container'ın harici bir komutla sonlandırıldığını belirtir. Bu exit code'lardan birini gördüğünüzde readiness ve liveness probe'larınızı kontrol etmenizde fayda vardır.

Sıradaki yazı ile eğitim serisine devam edebilirsiniz.

Kubernetes Endpoints Nedir?
Kubernetes Endpoints, bir Service’in yönlendirme yapacağı adresleri tutmak için kullanılan bir Kubernetes nesnesidir.