文章目錄
- 實驗環境
- 一、探針概述
- 二、liveness probe 存活探針
-
- 實驗1:command探測方式
- 實驗2:httpGet探測方式
- 實驗3:tcpSocket探測方式
- 三、readiness probe 就緒探針
-
- 實驗:command探測方式
實驗環境
完成初始化叢集的環境:
(vms21)192.168.26.21——master1
(vms22)192.168.26.22——worker1
(vms23)192.168.26.23——worker2
一、探針概述
在一個k8s叢集中,deployment作為控制器,當某個worker節點中的pod出現問題了,狀态不是Running了,這種情況下,deployment是會幫我們将這個pod重新建立的
現假設節點的狀态還是Running,但是pod裡的應用程式運作不正常了、不能對外提供服務了,此時,deployment是不會重新開機這個pod的,那怎麼處理這種情況呢?——我們可以去探測、檢測每個pod是不是可以正常對外工作,若發現問題了,根據處理方式的不同,探測可以分為兩類:
1.liveness probe——存活探針:發現問題就重新開機(重新開機:重新建立pod裡的容器)
2.readiness probe——就緒探針:發現問題,不重新開機
二、liveness probe 存活探針
liveness probe的探測方式:
1.command:在容器裡執行一個指令,不在乎指令運作的結果是什麼,隻在乎指令的運作成了還是沒運作成,指令執行成功了,則認為探測成功,否則認為探測失敗,就會馬上重新開機pod
2.httpGet:通路服務,若通路逾時了則認為探測失敗
3.tcpSocket:與服務建立tcp三次握手,若能建立,則認為探測成功,否則認為探測不成功
實驗1:command探測方式
(1)拉取busybox鏡像
nerdctl pull busybox
(2)建立一個pod,寬限期為0,鏡像用busybox
自定義容器的主程序為建立/tmp/healthy檔案,然後休眠30s,然後删除/tmp/healthy檔案,然後休眠100000s
探針在spec.containers下定義,定義一個livenessProbe探針,使用command探測方式,這裡為一個檢視/tmp/healthy檔案的指令
若/tmp/healthy這個檔案存在,則探針的指令能執行成功,否則執行不成功
initialDelaySeconds——定義的是容器啟動内多少秒内不檢測
periodSeconds——定義的是每間隔多少秒檢測一次
還有一些其他的參數如:
timeoutSeconds——定義探測逾時時間,預設1秒,最小1秒,超過這個時間則認為探測失敗(在這裡的command探測方式用不到,在httpGet、tcpSocket網絡探測方式中應用)
failureThreshold——當pod啟動了,并且探測失敗,kubernetes的重試次數,存活探測情況下的放棄就意味着重新啟動容器,就緒探測情況下的放棄pod會被打上未就緒的标簽,預設值是3,最小值是1
successThreshold——探測失敗後,最少連續探測為正常多少次才被認定為成功了,預設值是1,對于liveness必須是1,最小值是1
yaml檔案如下:
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: pod1
spec:
terminationGracePeriodSeconds: 0
containers:
- name: liveness
image: busybox
imagePullPolicy: IfNotPresent
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 100000
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5 #容器啟動的5s内不檢測
periodSeconds: 5 #每5s檢查一次
(3)建立這個pod
kubectl apply -f xxx.yaml
(4)進入pod容器内,執行列出/tmp目錄下檔案,可以看到存在healthy這個檔案
kubectl exec -it pod1 -- ls /tmp

過了30s後,/tmp/healthy被删除,可以看到/tmp下healthy檔案沒有了(探測指令執行不成功)
每隔5s會探測一次,這時候會探測失敗,失敗後,預設的重試次數為3,是以會探測3次(15s),還是探測失敗,大概在pod建立的47s時,加上這裡的寬限期為0,是以大概47s的時候會立馬重新開機pod
實驗2:httpGet探測方式
(1)删除實驗1中的pod1,重新建立一個pod,使用nginx鏡像
livenessProbe中定義使用httpGet的探測方式,path定義httpGet的位址,端口為80,使用HTTP協定
探測失敗後重試次數failureThreshold為3,initialDelaySeconds容器啟動10s内不檢測
每次探測間隔時間periodSeconds為10s,逾時時間timeoutSeconds為10s,successThreshold連續探測1次成功即認為成功
yaml檔案如下:
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: pod2
spec:
containers:
- name: liveness
image: nginx
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
path: /index.html #這裡的index.html不是指主控端中的index.html,而是在容器内的/usr/share/nginx/html/index.html
port: 80
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 10
(3)建立這個pod
kubectl apply -f xxx.yaml
(4)進入pod内容器,檢視/usr/share/nginx/html目錄下檔案,可以看到index.html
kubectl exec -it pod2 -- ls /usr/share/nginx/html
然後我們大概在pod建立後的10s後删除index.html,這樣探針就通路不到這個頁面了
yaml中httpGet探測方式中定義的path: index.html不是指主控端中的index.html,而是在容器内的/usr/share/nginx/html/index.html
kubectl exec -it pod2 -- rm -rf /usr/share/nginx/html/index.html
我們定義的探針在容器啟動後10s内不檢測,每隔10s檢測一次,是以大概在20s時,會通路不到index.html(10s時删除了index.html)
定義的探針的httpGet探測逾時時間為10s,是以大概在30s時會認為探測失敗,并進行第一次重試,預設的探測失敗後的重試次數為3,是以在50s後認為探測失敗,這時候會重新開機pod
實驗3:tcpSocket探測方式
(1)删除實驗2中的pod2,重新建立一個pod,使用nginx鏡像,寬限期為0,
lvenessProbe中定義使用tcpSocket探測方式
tcpSocket下定義端口port為80,意為與容器端口80能夠建立三次握手,即認為探測成功
yaml檔案如下:
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: pod3
spec:
terminationGracePeriodSeconds: 0
containers:
- name: liveness
image: nginx
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
tcpSocket:
port: 80
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 10
(2)建立這個pod
(3)假設在yaml檔案中,将tcpSocket通路的端口改為其他,不為80,會怎麼樣呢?
因為容器使用nginx鏡像,預設端口為80,是以能夠成功建立三次握手,若設定通路端口不為80,則建立不起三次握手,認為探測失敗,會不停地重新開機pod
...
livenessProbe:
failureThreshold: 3
tcpSocket:
port: 808
initialDelaySeconds: 10
...
重新建立這個pod,會發現它不停地重新開機
三、readiness probe 就緒探針
readiness probe探測方式,同liveness,也是這三種
1.command
2.httpGet
3.tcpSocket
就緒探針與存活探針的差別就是:探測失敗後不會去重新開機pod,并且後續不會繼續将使用者請求轉發到該pod(會掐斷svc到該pod的線路),但是pod仍然是通的,若直接通路pod(不通過svc轉發)還是能通路
實驗:command探測方式
(1)我們建立一個deployment,建立3個副本
pod模闆中使用nginx鏡像,寬限期為0
容器中使用鈎子程序或初始化程序來使容器建立/tmp/healthy檔案(這裡使用鈎子程序),這樣又可以不影響nginx主程序,又可以啟動一個程序建立/tmp/healthy檔案
使用readinessProbe定義就緒探針,使用command探測方式,指令為檢視/tmp/healthy檔案,指令執行成功則認為探測成功
yaml檔案如下:
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web1
name: web1
spec:
replicas: 3
selector:
matchLabels:
app: web1
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: web1
spec:
terminationGracePeriodSeconds: 0
containers:
- image: nginx
name: c1
imagePullPolicy: IfNotPresent
lifecycle:
postStart:
exec:
command: ["/bin/sh","-c","touch /tmp/healthy"]
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 2 #容器啟動5s内不檢測
periodSeconds: 5 #每間隔5s檢測一次
resources: {}
status: {}
(2)建立這個deployment,可以看到建立了3個pod副本
kubectl apply -f xxx.yaml
(3)為了友善示範,将内容“111”、“222”、“333”寫入3個pod内的index.html
kubectl exec -it web1-656db66885-njhjq -- sh -c "echo 111 > /usr/share/nginx/html/index.html"
kubectl exec -it web1-656db66885-nzjq6 -- sh -c "echo 222 > /usr/share/nginx/html/index.html"
kubectl exec -it web1-656db66885-vg7r4 -- sh -c "echo 333 > /usr/share/nginx/html/index.html"
(4)建立一個負載均衡器svc
(5)檢視svc通路位址
kubectl get svc
#輸出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc1 ClusterIP 10.97.6.220 <none> 80/TCP 20s
(6)每隔1s循環通路svc,都能輸出index.html内容,探針也能探測成功
安ctrl+c退出
(7)現在模拟将web1-656db66885-vg7r4(index.html内容為333)的這個pod内的/tmp/healthy檔案删除
kubectl exec -it web1-656db66885-vg7r4 -- rm -rf /tmp/healthy
此時,可以看到該pod的Ready已為未就緒狀态
可想而知,此時探針也會探測失敗
此時通路svc,将不會繼續把請求轉發給該pod(掐斷svc到該pod的線路)
但是readiness探針并不會将該pod重新開機,是以,若直接通路該pod,還是能通路通
curl 10.244.70.120
httpGet、與tcpSocket探測方式同理