Bu örnekte, istekleri uygun şekilde ele almak için sağlıksız konteyner/uygulamaları otomatik olarak tespit etmek için Kubernetes readiness ve liveness probeleri kullanacağız. Bunlar en az aksama süresiyle mümkün olduğunca güvenilir hizmet sağlamamıza yardımcı olur.


Readiness probe


Konteyner'in isteklere yanıt vermek için trafiği kabul etmeye "tamamen" hazır olup olmadığını gösterir.


Readiness probesi, Kubernetes'in konteynerinizin trafiğe ne zaman hazır olduğunu bilmesini sağlamak için tasarlanmıştır. Kubernetes, bir Pod'a trafik gönderilmesine izin vermeden önce readiness probenin geçmesini sağlar. Bir readiness probesi başarısız olmaya başlarsa, Kubernetes geçene kadar Pod'a trafik göndermeyi durdurur. Tüm konteynerler bağlantıları veya istekleri kabul etmeye hazır olduğunda, o Pod hazır kabul edilir. Bir konteyner hazır durumda değilse, onu öldürmek istemezsiniz, ancak ona istek de göndermek istemezsiniz. Örneğin, bir Pod'un başlatılması veya yeniden başlatılması zaman alır, bu nedenle bu gibi durumlarda Kubernetes ya trafiği kendisine göndermeyi durdurur ya da varsa trafiği zaten çalışan Podlara yönlendirir.


Readiness probesini ne zaman kullanmalısınız?

Konteynerlerinizin başlatma sırasında büyük veri yükleme, yapılandırma dosyalarını okuma, harici sunucu bağlantılarını bekleme veya diğer işlemler üzerinde çalışması gerekiyorsa, readiness probe kullanın.


Liveness probe


Konteynerin çalışıp çalışmadığını gösterir. Lineves probe başarısız olursa, kubelet konteyneri öldürür ve konteyner kendi "restart policy" değerine tabi olur.


Liveness probeler, Kubernetes'in konteynerinizin canlı mı yoksa ölü mü olduğunu bilmesini sağlar. Uygulamanız canlıysa Kubernetes onu yalnız bırakır. Eğer ölmüşse Kubernetes Pod'u kaldırır ve yerine yenisini başlatır.


Liveness probesini ne zaman kullanmalısınız?

Bir uygulama çökebilir, tepkisiz hale gelebilir vb. Bu gibi durumlarda konteynerinizin yeniden başlatılmasını istiyorsanız, liveness probe kullanın. Ayrıca restartPolicy özelliğini Always veya OnFailure olarak belirleyin. Ancak bazen uygulamaların çökmesine izin verilir. Bu gibi durumlarda linveness probe kullanmanıza gerek yoktur. Kubernetes, restartPolicy değerine göre uygun bir eylem gerçekleştirecek kadar akıllıdır.


Yapılandırma seçenekleri


Command, HTTP ve TCP readiness/liveness yapılandırma seçeneklerinin uygulama şekilleri aynıdır. Probları aşağıdaki şekilde kontrol edebilirsiniz.


Command


Belirtilen konteynerde bir komut çalıştırılır - örneğin: cat /tmp/healthy. Komut başarılı olursa, 0 döndürür. Komut sıfır olmayan bir değer döndürürse (hata), yeniden başlatılır.


HTTP adresi


Belirtilen konteynerda çalışan sunucuya bir HTTP GET isteği gönderme ve belirtilen portu dinleme - örneğin: /health. 200'den büyük veya eşit ve 400'den küçük herhangi bir yanıt kodu başarıyı gösterir. Başka herhangi bir kod arızayı gösterir, bu nedenle yeniden başlatmayı tetikler.


TCP port


Belirtilen bağlantı portundan konteynırınıza bir soket açma girişiminde bulunulacaktır. Bağlantı kurabilirse, konteyner sağlıklı kabul edilir, kuramazsa bir başarısızlık olarak kabul edilir. Bu yöntemde, kubelet bağlantıyı node düzeyinde kurar, Pod değil. Bu nedenle servis isimlerini kullanamazsınız.


Yapı


├── Makefile
├── deploy
│ └── k8s
│ ├── deployment.yaml
│ └── service.yaml
├── docker
│ └── dev
│ └── Dockerfile
└── main.go

Dosyalar


Makefile


## Build application binary.
.PHONY: build
build:
go build -race -ldflags "-s -w" -o bin/main main.go

## Build application binary and run it.
.PHONY: run
run: build
bin/main

## Send a dummy request to the local server.
.PHONY: local-test
local-test:
curl -I --request GET http://localhost:3000/health

## -------------------------------------------------------------

## Build, tag and push application image to registry then clean up.
.PHONY: push
push:
docker build -t you/address-finder:latest -f ./docker/dev/Dockerfile .
docker push you/address-finder:latest
docker rmi you/address-finder:latest
docker system prune --volumes --force

## Deploy application to kubernetes cluster.
.PHONY: deploy
deploy:
kubectl apply -f deploy/k8s/deployment.yaml
kubectl apply -f deploy/k8s/service.yaml

## Send a dummy request to the exposed pod on kubernetes.
.PHONY: k8s-test
k8s-test:
curl -I --request GET $(shell minikube service address-finder-service --url)/health

Dockerfile


#
# STAGE 1: build
#
FROM golang:1.15-alpine3.12 as build

WORKDIR /source
COPY . .

RUN CGO_ENABLED=0 go build -ldflags "-s -w" -o bin/main main.go

#
# STAGE 2: run
#
FROM alpine:3.12 as run

COPY --from=build /source/bin/main /main

ENTRYPOINT ["/main"]

main.go


package main

import (
"log"
"net/http"
"time"
)

func main() {
log.Println("app will be read in 10 sec")
time.Sleep(time.Second*10)
log.Println("app is ready")

rtr := http.NewServeMux()
rtr.HandleFunc("/health", health)

if err := http.ListenAndServe(":3000", rtr); err != nil {
log.Fatalln(err)
}
}

func health(_ http.ResponseWriter, r *http.Request) {
log.Println("X-Probe:", r.Header.Get("X-Probe"))
}

deployment.yaml


apiVersion: apps/v1
kind: Deployment

metadata:
name: address-finder-deployment
labels:
app: address-finder

spec:
replicas: 1
selector:
matchLabels:
app: address-finder
template:
metadata:
labels:
app: address-finder
spec:
containers:
- name: golang
image: you/address-finder:latest
ports:
- containerPort: 3000
readinessProbe:
httpGet:
path: /health
port: 3000
httpHeaders:
- name: X-Probe
value: readiness
initialDelaySeconds: 10 # Wait x seconds before initialising probe.
periodSeconds: 10 # Probe ever x seconds.
timeoutSeconds: 5 # Time out probe after x seconds.
successThreshold: 1 # Consider probe to be successful after minimum x consecutive successes.
failureThreshold: 5 # Try x times before giving up. Pod will be marked as "Unready".
livenessProbe:
httpGet:
path: /health
port: 3000
httpHeaders:
- name: X-Probe
value: liveness
initialDelaySeconds: 10 # Wait x seconds before initialising probe.
periodSeconds: 10 # Probe ever x seconds.
timeoutSeconds: 5 # Time out probe after x seconds.
successThreshold: 1 # Consider probe to be successful after minimum x consecutive successes.
failureThreshold: 2 # Try x times before giving up. Container will be restarted.

service.yaml


apiVersion: v1
kind: Service

metadata:
name: address-finder-service

spec:
type: NodePort
selector:
app: address-finder
ports:
- protocol: TCP
port: 80
targetPort: 3000

Test


Öncelikle dağıtımı bitirmek için make push ve make deploy komutlarını çalıştırın. Burada dağıtım probelerini doğruluyoruz.


$ kubectl describe deployment.apps/address-finder-deployment

Liveness: http-get http://:3000/health delay=10s timeout=5s period=10s #success=1 #failure=2
Readiness: http-get http://:3000/health delay=10s timeout=5s period=10s #success=1 #failure=5


Dağıtımdan hemen sonra ve 10 saniyeden önce test ettiğimiz zaman.


$ make k8s-test
curl -I --request GET http://192.168.99.100:32560/health
curl: (7) Failed to connect to 192.168.99.100 port 32560: Connection refused
make: *** [k8s-test] Error 7

Başladıktan 10 saniye sonra test ettiğimiz zaman.


$ make k8s-test
curl -I --request GET http://192.168.99.100:32560/health
HTTP/1.1 200 OK
Date: Sun, 13 Dec 2020 17:19:49 GMT
Content-Length: 0

Bunlar günlükler.


$ kubectl logs pod/address-finder-deployment-6f5fc66d4d-k7pb2
2020/12/13 17:19:28 app will be read in 10 sec
2020/12/13 17:19:38 app is ready
2020/12/13 17:19:40 X-Probe: liveness
2020/12/13 17:19:46 X-Probe: readiness
2020/12/13 17:19:49 X-Probe: // This is the moment when we got 200 OK while testing, compare the time
2020/12/13 17:19:50 X-Probe: liveness
2020/12/13 17:19:56 X-Probe: readiness
2020/12/13 17:20:00 X-Probe: liveness
2020/12/13 17:20:06 X-Probe: readiness
2020/12/13 17:20:10 X-Probe: liveness
2020/12/13 17:20:16 X-Probe: readiness