環境介紹
主機 | IP地址 | 服務 |
---|---|---|
master | 192.168.1.21 | k8s+httpd+nginx |
node01 | 192.168.1.22 | k8s |
node02 | 192.168.1.23 | k8s |
基於[ https://blog.51cto.com/14320361/2464655]() 的實驗繼續進行
一、Pod的liveness和readiness探針
Kubelet使用liveness probe(存活探針)來確定何時重啓容器。例如,當應用程序處於運行狀態但無法做進一步操作,liveness探針將捕獲到deadlock,重啓處於該狀態下的容器,使應用程序在存在bug的情況下依然能夠繼續運行下去
Kubelet使用readiness probe(就緒探針)來確定容器是否已經就緒可以接受流量。只有當Pod中的容器都處於就緒狀態時kubelet纔會認定該Pod處於就緒狀態。該信號的作用是控制哪些Pod應該作爲service的後端。如果Pod處於非就緒狀態,那麼它們將會被從service的load balancer中移除。
Probe支持以下三種檢查方法:
<1>exec-命令
在用戶容器內執行一次命令,如果命令執行的退出碼爲0,則認爲應用程序正常運行,其他任務應用程序運行不正常。
livenessProbe:
exec:
command:
- cat
- /home/laizy/test/hostpath/healthy
<2>TCPSocket
將會嘗試打開一個用戶容器的Socket連接(就是IP地址:端口)。如果能夠建立這條連接,則認爲應用程序正常運行,否則認爲應用程序運行不正常。
livenessProbe:
tcpSocket:
port: 8080
<3>HTTPGet
調用容器內Web應用的web hook,如果返回的HTTP狀態碼在200和399之間,則認爲應用程序正常運行,否則認爲應用程序運行不正常。每進行一次HTTP健康檢查都會訪問一次指定的URL。
httpGet: #通過httpget檢查健康,返回200-399之間,則認爲容器正常
path: / #URI地址
port: 80 #端口號
#host: 127.0.0.1 #主機地址
scheme: HTTP #支持的協議,http或者https
httpHeaders:’’ #自定義請求的header
參數說明
initialDelaySeconds:容器啓動後第一次執行探測是需要等待多少秒。
periodSeconds:執行探測的頻率。默認是10秒,最小1秒。
timeoutSeconds:探測超時時間。默認1秒,最小1秒。
successThreshold:探測失敗後,最少連續探測成功多少次才被認定爲成功。默認是1。對於liveness必須是1。最小值是1。
探針探測的結果有以下三者之一:
Success:Container通過了檢查。
Failure:Container未通過檢查。
Unknown:未能執行檢查,因此不採取任何措施。1. LivenessProbe(活躍度)
(1)編寫一個livenss的yaml文件
[root@node02 ~]# vim livenss.yaml
kind: Pod
apiVersion: v1
metadata:
name: liveness
labels:
test: liveness
spec:
restartPolicy: OnFailure
containers:
- name: liveness
image: busybox
args:
- /bin/sh
- -c
- touch /tmp/test; sleep 60; rm -rf /tmp/test; sleep 300
livenessProbe: #存活探測
exec: #通過執行命令來檢查服務是否正常
command: #命令模式
- cat
- /tmp/test
initialDelaySeconds: 10 #pod運行10秒後開始探測
periodSeconds: 5 #檢查的頻率,每5秒探測一次
該配置文件給Pod配置了一個容器。periodSeconds 規定kubelet要每隔5秒執行一次liveness probe。initialDelaySeconds 告訴kubelet在第一次執行probe之前要的等待10秒鐘。探針檢測命令是在容器中執行 cat /tmp/healthy 命令。如果命令執行成功,將返回0,kubelet就會認爲該容器是活着的並且很健康。如果返回非0值,kubelet就會殺掉這個容器並重啓它。
(2)運行一下
[root@master ~]# kubectl apply -f liveness.yaml
(3)查看一下
[root@master ~]# kubectl get pod -w
Liveness活躍度探測,根據探測某個文件是否存在,來確定某個服務是否正常運行,如果存在則正常,負責,它會根據你設置的Pod的重啓策略操作Pod。
2. Readiness(敏感探測、就緒性探測)
ReadinessProbe探針的使用場景livenessProbe稍有不同,有的時候應用程序可能暫時無法接受請求,比如Pod已經Running了,但是容器內應用程序尚未啓動成功,在這種情況下,如果沒有ReadinessProbe,則Kubernetes認爲它可以處理請求了,然而此時,我們知道程序還沒啓動成功是不能接收用戶請求的,所以不希望kubernetes把請求調度給它,則使用ReadinessProbe探針。
ReadinessProbe和livenessProbe可以使用相同探測方式,只是對Pod的處置方式不同,ReadinessProbe是將Pod IP:Port從對應的EndPoint列表中刪除,而livenessProbe則Kill容器並根據Pod的重啓策略來決定作出對應的措施。
ReadinessProbe探針探測容器是否已準備就緒,如果未準備就緒則kubernetes不會將流量轉發給此Pod。
ReadinessProbe探針與livenessProbe一樣也支持exec、httpGet、TCP的探測方式,配置方式相同,只不過是將livenessProbe字段修改爲ReadinessProbe。
(1)編寫一個readiness的yaml文件
[root@master ~]# vim readiness.yaml
kind: Pod
apiVersion: v1
metadata:
name: readiness
labels:
test: readiness
spec:
restartPolicy: Never
containers:
- name: readiness
image: busybox
args:
- /bin/sh
- -c
- touch /tmp/test; sleep 60; rm -rf /tmp/test; sleep 300
readinessProbe:
exec:
command:
- cat
- /tmp/test
initialDelaySeconds: 10
periodSeconds: 5
(2)運行一下
[root@master ~]# kubectl apply -f readiness.yaml
(3)查看一下
[root@master ~]# kubectl get pod -w
3. 總結liveness和readiness探測
(1)liveness和readiness是兩種健康檢查機制,k8s將兩種探測採取相同的默認行爲,即通過判斷容器啓動進程的返回值是否爲零,來判斷探測是否成功。
(2)兩種探測配置方法完全一樣,不同之處在於探測失敗後的行爲。
liveness探測是根據重啓策略操作容器,大多數是重啓容器。
readiness則是將容器設置爲不可用,不接收Service轉發的請求。
(3)兩種探測方法可建議獨立存在,也可以同時存在。用livensess判斷是否需要重啓,實現自愈;用readiness判斷容器是否已經準備好對外提供服務。
二、 檢測的應用
1. 在scale(擴容/縮容) 中的應用。
(1)編寫一個readiness的yaml文件
[root@master ~]# vim hcscal.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: web
spec:
replicas: 3
template:
metadata:
labels:
run: web
spec:
containers:
- name: web
image: httpd
ports:
- containerPort: 80
readinessProbe:
httpGet:
scheme: HTTP #探測的協議
path: /healthy #訪問的目錄
port: 80
initialDelaySeconds: 10
periodSeconds: 5
---
kind: Service
apiVersion: v1
metadata:
name: web-svc
spec:
type: NodePort
selector:
run: web
ports:
- protocol: TCP
port: 90
targetPort: 80
nodePort: 30321
在配置文件中,使用httpd鏡像,創建出一個Pod,其中periodSeconds字段指定kubelet每5秒執行一次探測,initialDelaySeconds字段告訴kubelet延遲等待10秒,探測方式爲向容器中運行的服務發送HTTP GET請求,請求8080端口下的/healthz, 任何大於或等於200且小於400的代碼表示成功。任何其他代碼表示失敗。
(2) httpGet探測方式有如下可選的控制字段
host:要連接的主機名,默認爲Pod IP,可以在http request head中設置host頭部。
scheme: 用於連接host的協議,默認爲HTTP。
path:http服務器上的訪問URI。
httpHeaders:自定義HTTP請求headers,HTTP允許重複headers。
port: 容器上要訪問端口號或名稱。
(3)運行一下
[root@master ~]# kubectl apply -f readiness.yaml
(4)查看一下
[root@master ~]# kubectl get pod -w
[root@master ~]# kubectl get pod -o wide
[root@master ~]# kubectl get service -o wide
(5)訪問一下
[root@master ~]# curl 10.244.1.21/healthy
(6)pod在指定目錄創建一個文件
[root@master ~]# kubectl exec web-69d659f974-7s9bc touch /usr/local/apache2/htdocs/healthy
(7)查看一下
[root@master ~]# kubectl get pod -w
2. 在更新過程中的使用
(1)編寫一個readiness的yaml文件
[root@master ~]# vim app.v1.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: app
spec:
replicas: 10
template:
metadata:
labels:
run: app
spec:
containers:
- name: app
image: busybox
args:
- /bin/sh
- -c
- sleep 10; touch /tmp/healthy; sleep 3000
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 10
periodSeconds: 5
(2)運行一下並記錄版本信息
[root@master ~]# kubectl apply -f readiness.yaml --record
查看一下
[root@master ~]# kubectl rollout history deployment app
(3)查看一下
[root@master ~]# kubectl get pod -w
3.升級一下Deployment
(1)編寫一個readiness的yaml文件
[root@master ~]# cp app.v1.yaml app.v2.yaml
[root@master ~]# vim app.v2.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: app
spec:
replicas: 10
template:
metadata:
labels:
run: app
spec:
containers:
- name: app
image: busybox
args:
- /bin/sh
- -c
- sleep 3000 #修改命令
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 10
periodSeconds: 5
(2)運行一下並記錄版本信息
[root@master ~]# kubectl apply -f readiness.yaml --record
查看一下
[root@master ~]# kubectl rollout history deployment app
(3)查看一下
[root@master ~]# kubectl get pod -w
(4)再次升級一下deployment
<1> 編寫一個readiness的yaml文件
[root@master ~]# cp app.v1.yaml app.v3.yaml
[root@master ~]# vim app.v2.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: app
spec:
replicas: 10
template:
metadata:
labels:
run: app
spec:
containers:
- name: app
image: busybox
args:
- /bin/sh
- -c
- sleep 3000 #修改命令
<2> 運行一下並記錄版本信息
[root@master ~]# kubectl apply -f readiness.yaml --record
查看一下
[root@master ~]# kubectl rollout history deployment app
<3> 查看一下
[root@master ~]# kubectl get pod -w
4. 回滾v2版本
[root@master ~]# kubectl rollout undo deployment app --to-revision=2
查看一下
[root@master ~]# kubectl get pod
(1)編寫一個readiness的yaml文件
[root@master ~]# vim app.v2.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: app
spec:
strategy:
rollingUpdate:
maxSurge: 2
maxUnavailable: 2
replicas: 10
template:
metadata:
labels:
run: app
spec:
containers:
- name: app
image: busybox
args:
- /bin/sh
- -c
- sleep 3000
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 10
periodSeconds: 5
參數介紹
minReadySeconds:
Kubernetes在等待設置的時間後才進行升級
如果沒有設置該值,Kubernetes會假設該容器啓動起來後就提供服務了
如果沒有設置該值,在某些極端情況下可能會造成服務服務正常運行maxSurge:
升級過程中最多可以比原先設置多出的POD數量
例如:maxSurage=1,replicas=5,則表示Kubernetes會先啓動1一個新的Pod後才刪掉一箇舊的POD,整個升級過程中最多會有5+1個POD。maxUnavaible:
升級過程中最多有多少個POD處於無法提供服務的狀態
當maxSurge不爲0時,該值也不能爲0
例如:maxUnavaible=1,則表示Kubernetes整個升級過程中最多會有1個POD處於無法服務的狀態。
(2) 運行一下並記錄版本信息
[root@master ~]# kubectl apply -f app.v2.yaml --record
查看一下
[root@master ~]# kubectl rollout history deployment app
(3) 查看一下
[root@master ~]# kubectl get pod -w
三、小實驗
1)寫一個Deployment資源對象,要求2個副本,nginx鏡像。使用Readiness探測,自定義文件/test是否存在,容器開啓之後10秒開始探測,時間間隔爲10秒。
(1)編寫一個readiness的yaml文件
[root@master yaml]# vim nginx.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: web
spec:
replicas: 2
template:
metadata:
labels:
run: web
spec:
containers:
- name: readiness
image: 192.168.1.21:5000/nginx:v1
readinessProbe:
exec:
command:
- cat
- /usr/share/nginx/html/test
initialDelaySeconds: 10
periodSeconds: 10
(2)運行一下並記錄版本信息
[root@master ~]# kubectl apply -f nginx.yaml --record
查看一下
[root@master ~]# kubectl rollout history deployment web
(3)查看一下
[root@master ~]# kubectl get pod -w
2)在運行之後兩個Pod裏,進入一個Pod,創建文件/test。
[root@master yaml]# kubectl exec -it web-864c7cf7fc-gpxq4 /bin/bash
root@web-68444bff8-xm22z:/# touch /usr/share/nginx/html/test
查看一下
[root@master yaml]# kubectl get pod -w
3)創建一個Service資源對象,跟上述Deployment進行關聯,運行之後,查看Service資源詳細信息,確認EndPoint負載均衡後端Pod。
(1)編寫service的yaml文件
[root@master yaml]# vim nginx-svc.yaml
kind: Service
apiVersion: v1
metadata:
name: web-svc
spec:
type: NodePort
selector:
run: web
ports:
- protocol: TCP
port: 90
targetPort: 80
nodePort: 30321
(2)執行一下
[root@master yaml]# kubectl apply -f nginx-svc.yaml
(3)給兩個pod剛更改頁面
查看一下pod
[root@master yaml]# kubectl get pod -o wide
更改頁面
[root@master yaml]# kubectl exec -it web-864c7cf7fc-gpxq4 /bin/bash
root@web-864c7cf7fc-gpxq4:/# echo "123">/usr/share/nginx/html/test
root@web-864c7cf7fc-gpxq4:/# exit
[root@master yaml]# kubectl exec -it web-864c7cf7fc-pcrs9 /bin/bash
root@web-864c7cf7fc-pcrs9:/# echo "321">/usr/share/nginx/html/test
root@web-864c7cf7fc-pcrs9:/# exit
4)觀察狀態之後,嘗試將另一個Pod也寫入/test文件,然後再去查看SVC對應的EndPoint的負載均衡情況。
(1)查看一下service
[root@master yaml]# kubectl get service
(2)訪問一下
[root@master ~]# curl 192.168.1.21:30321/test
5)通過httpGet的探測方式,重新運行一下deployment資源,總結對比一下這兩種Readiness探測方式。
(1)修改deployment的yaml文件
[root@master yaml]# vim nginx.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: web
spec:
replicas: 2
template:
metadata:
labels:
run: web
spec:
containers:
- name: readiness
image: 192.168.1.21:5000/nginx:v1
readinessProbe:
httpGet:
scheme: HTTP
path: /usr/share/nginx/html/test
port: 80
initialDelaySeconds: 10
periodSeconds: 10
(2)執行一下
[root@master yaml]# kubectl apply -f nginx.yaml
(3)查看一下pod
[root@master yaml]# kubectl get pod -w
maxSurge:此參數控制滾動更新過程中,副本總數超過預期數的值。可以是整數,也可以是百分比,默認是1。所以現在是3臺pod
(4)訪問一下
[root@master yaml]# curl 192.168.1.21:30321/test
6)總結對比liveness和readiness探測的相同和不同之處,以及它們的使用場景。
<1>readiness和liveness的核心區別
實際上readiness 和liveness 就如同字面意思。readiness 就是意思是否可以訪問,liveness就是是否存活。如果一個readiness 爲fail 的後果是把這個pod 的所有service 的endpoint裏面的改pod ip 刪掉,意思就這個pod對應的所有service都不會把請求轉到這pod來了。但是如果liveness 檢查結果是fail就會直接kill container,當然如果你的restart policy 是always 會重啓pod。
<2>什麼樣才叫readiness/liveness檢測失敗呢?
實際上k8s提供了3中檢測手段,
http get 返回200-400算成功,別的算失敗
tcp socket 你指定的tcp端口打開,比如能telnet 上
cmd exec 在容器中執行一個命令 推出返回0 算成功。
每中方式都可以定義在readiness 或者liveness 中。比如定義readiness 中http get 就是意思說如果我定義的這個path的http get 請求返回200-400以外的http code 就把我從所有有我的服務裏面刪了吧,如果定義在liveness裏面就是把我kill 了。
<3>readiness和readiness的使用環境
比如如果一個http 服務你想一旦它訪問有問題我就想重啓容器。那你就定義個liveness 檢測手段是http get。反之如果有問題我不想讓它重啓,只是想把它除名不要讓請求到它這裏來。就配置readiness。
注意,liveness不會重啓pod,pod是否會重啓由你的restart policy(重啓策略)控制。