您好,登錄后才能下訂單哦!
原文:https://i4t.com/4424.html
首先我們先簡(jiǎn)單的分析一下"優(yōu)雅的停止Pod"
優(yōu)雅停止(Graceful shutdown)這個(gè)說(shuō)法來(lái)自于操作系統(tǒng),比如我們windows關(guān)機(jī)系統(tǒng)首先會(huì)退出軟件然后一步步到達(dá)關(guān)機(jī),而相對(duì)的就是硬終止(Hard shutdown),簡(jiǎn)單的理解就是直接拔電源
到了微服務(wù)中,網(wǎng)關(guān)會(huì)把流量分配給每個(gè)Pod節(jié)點(diǎn)上,比如我們上線更新Pod的時(shí)候
Pod Hook是由kubelet發(fā)起的,當(dāng)容器中的進(jìn)程啟動(dòng)前或者容器中的進(jìn)程終止之前運(yùn)行,這是包含在容器的生命周期之中。我們可以同時(shí)為Pod中的所有容器都配置hook
在k8s中,理想的狀態(tài)是pod優(yōu)雅釋放,并產(chǎn)生新的Pod。但是并不是每一個(gè)Pod都會(huì)這么順利
對(duì)于以上問(wèn)題,k8s的Pod終止流程中還有一個(gè)"最多可以容忍的時(shí)間",即grace period (在pod的.spec.terminationGracePeriodSeconds
字段定義),這個(gè)值默認(rèn)是30秒,當(dāng)我們執(zhí)行kubectl delete
的時(shí)候也可以通過(guò)--grace-period
參數(shù)顯示指定一個(gè)優(yōu)雅退出時(shí)間來(lái)覆蓋Pod中的配置,如果我們配置的grace period超過(guò)時(shí)間之后,k8s就只能選擇強(qiáng)制kill Pod
Kubernetes為我們提供了兩種鉤子函數(shù):
如果PostStart或者PreStop鉤子失敗,它會(huì)殺死容器。所以我們應(yīng)該讓鉤子函數(shù)盡可能的輕量。當(dāng)然有些情況下,長(zhǎng)時(shí)間運(yùn)行命令是合理的,比如在停止容器之前預(yù)先保留狀態(tài)。
這里稍微簡(jiǎn)單說(shuō)一下Pod終止的過(guò)程
在Pod Hook鉤子函數(shù)中有Exec和HTTP兩種方式
首先我們先進(jìn)行演示PostStart的兩種方式
第一種Exec
我們echo一段話追加到 /tmp/message,在Pod啟動(dòng)前進(jìn)行操作
cat >>exec_test.yaml<<EOF
apiVersion: v1
kind: Pod
metadata:
name: abcdocker
labels:
name: abcdocker
spec:
containers:
- name: abcdocker
image: nginx
ports:
- containerPort: 80
lifecycle:
postStart:
exec:
command:
- bash
- -c
- 'echo "https://i4t.com" > /tmp/message'
EOF
使用kubectl apply -f exec_test.yaml
進(jìn)行創(chuàng)建
可以通過(guò)下面查看結(jié)果,pod的目錄已經(jīng)有我們?cè)趛aml文件寫(xiě)的測(cè)試文件
[root@abcdocker yaml]# kubectl get pod
NAME READY STATUS RESTARTS AGE
abcdocker 1/1 Running 0 37s
[root@abcdocker yaml]# kubectl exec -it -n default abcdocker /bin/bash
root@abcdocker:/# cat /tmp/message
https://i4t.com
root@abcdocker:/#
root@abcdocker:/# exit
創(chuàng)建容器后,Kubernetes立即發(fā)送postStart事件。但是,不能保證在調(diào)用Container的入口點(diǎn)之前先調(diào)用postStart處理程序。postStart處理程序相對(duì)于Container的代碼異步運(yùn)行,但是Kubernetes對(duì)容器的管理會(huì)阻塞,直到postStart處理程序完成。在postStart處理程序完成之前,容器的狀態(tài)不會(huì)設(shè)置為RUNNING。
第二種HTTP方式
使用HttpGet配置Host、Path、Port
apiVersion: v1
kind: Pod
metadata:
name: abcdocker
labels:
name: abcdocker
spec:
containers:
- name: abcdocker
image: nginx
ports:
- containerPort: 80
lifecycle:
postStart:
httpGet:
host: i4t.com
path: index.html
port: 80
這里就不進(jìn)行演示了,因?yàn)槿罩緯?huì)看不到這個(gè)請(qǐng)求
起因:
在生產(chǎn)環(huán)境中使用spring框架,由于服務(wù)更新過(guò)程中,服務(wù)容器被直接充值,部分請(qǐng)求仍被分發(fā)到終止的容器(沒(méi)有配置鉤子,熟悉默認(rèn)環(huán)境),導(dǎo)致服務(wù)出現(xiàn)500錯(cuò)誤,這部分錯(cuò)誤請(qǐng)求數(shù)據(jù)占用比較少,因?yàn)镻od滾動(dòng)更新都是一對(duì)一。因?yàn)椴糠钟脩?hù)會(huì)產(chǎn)生服務(wù)器錯(cuò)誤的情況,考慮使用優(yōu)雅的終止方式,將錯(cuò)誤請(qǐng)求降到最低,直至滾動(dòng)更新不影響用戶(hù)
Eureka是一個(gè)基于REST的服務(wù),作為Spring Cloud服務(wù)注冊(cè)中心,用于定位服務(wù)來(lái)進(jìn)行中間層服務(wù)器的負(fù)載均衡和故障轉(zhuǎn)移。各服務(wù)啟動(dòng)時(shí),會(huì)向Eureka Server注冊(cè)自己的信息(IP、端口、服務(wù)信息等),Eureka Server會(huì)存儲(chǔ)這些信息,微服務(wù)啟動(dòng)后,會(huì)周期性(默認(rèn)30秒)的向Eureka Server發(fā)送心跳以續(xù)約自己的租期,并且可以從eureka中獲取其他微服務(wù)的地址信息,執(zhí)行相關(guān)邏輯
由于Eureka默認(rèn)的心跳檢測(cè)為30秒,當(dāng)K8S下線Pod時(shí)Eureka會(huì)有30秒的異常問(wèn)題,所以我們需要在Pod 停止前發(fā)送一條請(qǐng)求,通知Eureka進(jìn)行下線操作,這樣進(jìn)行優(yōu)雅的停止對(duì)用戶(hù)的影響做到最小
具體yaml如下
apiVersion: v1
kind: Pod
metadata:
name: abcdocker
labels:
name: abcdocker
spec:
containers:
- name: abcdocker
image: nginx
ports:
- containerPort: 80
lifecycle:
preStop:
exec:
command:
- bash
- -c
- 'curl -X POST --data DOWN http://127.0.0.1:8080/service-registry/instance-status -H
"Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8";sleep 30'
####### 參數(shù)解釋
127.0.0.1:8080 #代表eureka地址
service-registry #代表注冊(cè)中心
DOWN #執(zhí)行down請(qǐng)求
sleep #等待30秒
當(dāng)我們刪除Pod的時(shí)候就會(huì)執(zhí)行上面的命令操作,并且等待30秒
[root@yzsjhl82-135 yaml]# kubectl get pod
NAME READY STATUS RESTARTS AGE
abcdocker 1/1 Running 0 2m16s
[root@yzsjhl82-135 yaml]# kubectl delete pod abcdocker
pod "abcdocker" deleted
#此刻Pod不會(huì)馬上刪除,而是執(zhí)行Exec中的命令,并等待30秒
配置中添加了一個(gè)sleep時(shí)間,主要是作為服務(wù)停止的緩沖時(shí)間
總結(jié): Hook調(diào)用的日志沒(méi)有暴露給Pod的Event,所以只能到通過(guò)describe
命令來(lái)獲取,如果是正常的操作是不會(huì)有event,如果有錯(cuò)誤可以看到FailedPostStartHook和FailedPreStopHook這種event。并且如果Hook調(diào)用出現(xiàn)錯(cuò)誤,則Pod狀態(tài)不會(huì)是Running
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。