在Kubernetes
集群當中,我們可以通過配置liveness probe
(存活探針)和readiness probe
(可讀性探針)來影響容器的生存周期。參考文檔:https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/
kubelet 通過使用 liveness probe 來確定你的應用程序是否正在運行,通俗點將就是是否還活着。一般來說,如果你的程序一旦崩潰了, Kubernetes 就會立刻知道這個程序已經終止了,然后就會重啟這個程序。而我們的 liveness probe 的目的就是來捕獲到當前應用程序還沒有終止,還沒有崩潰,如果出現了這些情況,那么就重啟處於該狀態下的容器,使應用程序在存在 bug 的情況下依然能夠繼續運行下去。
kubelet使用活躍度探頭知道什么時候重新啟動的容器。例如,liveness probe可以捕獲死鎖,應用程序正在運行,但無法取得進展。在這種狀態下重新啟動容器可以繼續存活。
kubelet 使用 readiness probe 來確定容器是否已經就緒可以接收流量過來了。這個探針通俗點講就是說是否准備好了,現在可以開始工作了。只有當 Pod 中的容器都處於就緒狀態的時候 kubelet 才會認定該 Pod 處於就緒狀態,因為一個 Pod 下面可能會有多個容器。當然 Pod 如果處於非就緒狀態,那么我們就會將他從我們的工作隊列(實際上就是我們后面需要重點學習的 Service)中移除出來,這樣我們的流量就不會被路由到這個 Pod 里面來了。
使用readiness probe來了解容器何時准備開始接受流量。當所有容器准備就緒時,Pod被認為已准備就緒。此信號的一個用途是控制哪些Pod用作服務的后端。當Pod未就緒時,它將從服務負載平衡器中刪除。例如當一個應用服務有大文件加載時,這種情況下不允許接受用戶訪問,readiness probe就不會對這類型的程序啟動服務。
許多運行很長時間的應用程序最終會轉換到損壞狀態,除非重新啟動,否則無法恢復。Kubernetes提供活體探測器來檢測和糾正這種情況。
通過busybox來練習一下liveness probe
liveness-exec.yaml liveness-http.yaml pod-example.yaml poststart-hook.yaml prestop-hook.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
在配置文件中,您可以看到Pod具有單個Container。該periodSeconds
字段指定kubelet應每5秒執行一次活躍度探測。該initialDelaySeconds
字段告訴kubelet它應該在執行第一次探測之前等待5秒。要執行探測,kubelet將cat /tmp/healthy
在Container中執行命令。如果命令成功,則返回0,並且kubelet認為Container是活動且健康的。如果該命令返回非零值,則kubelet會終止Container並重新啟動它。
當Container啟動時,它會執行以下命令:
/bin/sh -c "touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600"
在Container的生命的前30秒,有一個/tmp/healthy
文件。因此,在前30秒內,該命令cat /tmp/healthy
返回成功代碼。30秒后,cat /tmp/healthy
返回失敗代碼。
創建Pod:
kubectl apply -f liveness-exec.yaml
在30秒內,查看Pod事件:
kubectl describe pod liveness-exec
有消息指示活動探測失敗,並且容器已被殺死並重新創建。
另一種活動探測器使用HTTP GET請求
apiVersion: v1
kind: Pod
metadata:
name: liveness-http
labels:
app: liveness
spec:
containers:
- name: liveness
image: cnych/liveness
args:
- /server
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 3
periodSeconds: 3
在配置文件中,您可以看到Pod具有單個Container。該periodSeconds
字段指定kubelet應每3秒執行一次活躍度探測。該initialDelaySeconds
字段告訴kubelet它應該在執行第一次探測之前等待3秒。為了執行探測,kubelet向在Container中運行的服務器發送HTTP GET請求並偵聽端口8080.如果服務器/healthz
路徑的處理程序返回成功代碼,則kubelet認為Container是活動且健康的。如果處理程序返回失敗代碼,則kubelet會終止Container並重新啟動它。
任何大於或等於200且小於400的代碼表示成功。任何其他代碼表示失敗。
您可以在server.go中查看服務器的源代碼 。
對於Container /healthz
處於活動狀態的前10秒,處理程序返回狀態200.之后,處理程序返回狀態500。
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
duration := time.Now().Sub(started)
if duration.Seconds() > 10 {
w.WriteHeader(500)
w.Write([]byte(fmt.Sprintf("error: %v", duration.Seconds())))
} else {
w.WriteHeader(200)
w.Write([]byte("ok"))
}
})
在容器啟動3秒后,kubelet開始執行運行狀況檢查。因此,前幾次健康檢查將成功。但是10秒后,運行狀況檢查將失敗,並且kubelet將終止並重新啟動Container。
要嘗試HTTP活躍度檢查,請創建一個Pod:
kubectl apply -f liveness-http.yaml
10秒后,查看Pod事件以驗證活動探測失敗並且Container已重新啟動:
kubectl describe pod liveness-http
在v1.13之前的版本(包括v1.13)中,如果在運行pod的節點上設置了環境變量http_proxy(或HTTP_PROXY
),則HTTP活動探針將使用該代理。在v1.13之后的版本中,本地HTTP代理環境變量設置不會影響HTTP活動探測。
定義TCP活動探測
第三種類型的活動探測器使用TCP套接字。使用此配置,kubelet將嘗試在指定端口上打開容器的套接字。如果它可以建立連接,則容器被認為是健康的,如果它不能被認為是失敗的話。
apiVersion: v1
kind: Pod
metadata:
name: goproxy
labels:
app: goproxy
spec:
containers:
- name: goproxy
image: cnych/goproxy
ports:
- containerPort: 8080
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
我們可以看到,TCP 檢查的配置與 HTTP 檢查非常相似,只是將httpGet
替換成了tcpSocket
。 而且我們同時使用了readiness probe
和liveness probe
兩種探針。 容器啟動后5秒后,kubelet
將發送第一個readiness probe
(可讀性探針)。 該探針會去連接容器的8080端,如果連接成功,則該 Pod 將被標記為就緒狀態。然后Kubelet
將每隔10秒鍾執行一次該檢查。
除了readiness probe
之外,該配置還包括liveness probe
。 容器啟動15秒后,kubelet
將運行第一個 liveness probe
。 就像readiness probe
一樣,這將嘗試去連接到容器的8080端口。如果liveness probe
失敗,容器將重新啟動。
有的時候,應用程序可能暫時無法對外提供服務,例如,應用程序可能需要在啟動期間加載大量數據或配置文件。 在這種情況下,您不想殺死應用程序,也不想對外提供服務。 那么這個時候我們就可以使用readiness probe
來檢測和減輕這些情況。 Pod中的容器可以報告自己還沒有准備,不能處理Kubernetes服務發送過來的流量。
從上面的YAML
文件我們可以看出readiness probe
的配置跟liveness probe
很像,基本上一致的。唯一的不同是使用readinessProbe
而不是livenessProbe
。兩者如果同時使用的話就可以確保流量不會到達還未准備好的容器,准備好過后,如果應用程序出現了錯誤,則會重新啟動容器。
另外除了上面的initialDelaySeconds
和periodSeconds
屬性外,探針還可以配置如下幾個參數:
- timeoutSeconds:探測超時的秒數。默認為1秒。最小值為1。
- initialDelaySeconds:啟動活動或准備就緒探測之前容器啟動后的秒數。
- periodSeconds:執行探測的頻率(以秒為單位)。默認為10秒。最小值為1。
- failureThreshold:當Pod啟動並且探測失敗時,Kubernetes會failureThreshold在放棄之前嘗試一次。在活動探測的情況下放棄意味着重新啟動Pod。如果准備好探測,Pod將被標記為未准備好。默認為3.最小值為1。
- successThreshold:失敗后探測成功的最小連續成功次數。默認為1.活躍度必須為1。最小值為1。
[HTTP探針] 具有可以設置的其他字段httpGet
:
host
:要連接的主機名,默認為pod IP。您可能希望在httpHeaders中設置“主機”。scheme
:用於連接主機的方案(HTTP或HTTPS)。默認為HTTP。path
:HTTP服務器上的訪問路徑。httpHeaders
:要在請求中設置的自定義標頭。HTTP允許重復標頭。port
:容器上要訪問的端口的名稱或編號。數字必須在1到65535的范圍內。
對於HTTP探測,kubelet將HTTP請求發送到指定的路徑和端口以執行檢查。kubelet將探測器發送到pod的IP地址,除非地址被可選host
字段覆蓋httpGet
。如果 scheme
字段設置為HTTPS
,則kubelet會發送跳過證書驗證的HTTPS請求。在大多數情況下,您不希望設置該host
字段。這是您設置它的一個場景。假設Container偵聽127.0.0.1並且Pod的hostNetwork
字段為true。然后host
,在httpGet
,應設置為127.0.0.1。如果您的pod依賴虛擬主機,這可能是更常見的情況,您不應該使用host
,而是設置Host
標頭httpHeaders
。
對於探測器,kubelet在節點處而不是在pod中進行探測連接,這意味着您無法在host
參數中使用服務名稱,因為kubelet無法解析它。