【云原生Kubernetes】08-Pod中的Init容器
簡(jiǎn)介
Init 容器是一種特殊容器,在 Pod內(nèi)的應(yīng)用容器啟動(dòng)之前運(yùn)行。Init 容器可以包括一些應(yīng)用鏡像中不存在的實(shí)用工具和安裝腳本。
你可以在 Pod 的spec中與用來描述應(yīng)用容器的
containers
數(shù)組平行的位置指定 Init 容器。containers: - name: myapp-container image: busybox:1.28 initContainers: - name: init-myservice image: busybox:1.28
- Init 容器的狀態(tài)在
status.initContainerStatuses
字段中以容器狀態(tài)數(shù)組的格式返回 (類似status.containerStatuses
字段)。
理解 Init 容器
- 每個(gè) Pod中可以包含多個(gè)容器, 應(yīng)用運(yùn)行在這些容器里面,同時(shí) Pod 也可以有一個(gè)或多個(gè)先于應(yīng)用容器啟動(dòng)的 Init 容器。
Init 容器與普通的容器非常像,除了如下兩點(diǎn):
- 它們總是運(yùn)行到完成。
- 每個(gè)都必須在下一個(gè)啟動(dòng)之前成功完成。
-
如果 Pod 的 Init 容器失敗,kubelet 會(huì)不斷地重啟該 Init 容器直到該容器成功為止。 然而,如果 Pod 對(duì)應(yīng)的
restartPolicy
值為 “Never”,并且 Pod 的 Init 容器失敗, 則 Kubernetes 會(huì)將整個(gè) Pod 狀態(tài)設(shè)置為失敗。 -
如果為一個(gè) Pod 指定了多個(gè) Init 容器,這些容器會(huì)按順序逐個(gè)運(yùn)行。 每個(gè) Init 容器必須運(yùn)行成功,下一個(gè)才能夠運(yùn)行。當(dāng)所有的 Init 容器運(yùn)行完成時(shí), Kubernetes 才會(huì)為 Pod 初始化應(yīng)用容器并像平常一樣運(yùn)行。
與普通容器的不同之處:
- Init 容器支持應(yīng)用容器的全部字段和特性,包括資源限制、數(shù)據(jù)卷和安全設(shè)置。 然而,Init 容器對(duì)資源請(qǐng)求和限制的處理稍有不同;
- Init 容器不支持
lifecycle
、livenessProbe
、readinessProbe
和startupProbe
, 因?yàn)樗鼈儽仨氃?Pod 就緒之前運(yùn)行完成。
Init容器使用場(chǎng)景
因?yàn)?Init 容器具有與應(yīng)用容器分離的單獨(dú)鏡像,其啟動(dòng)相關(guān)代碼具有如下優(yōu)勢(shì):
-
Init 容器可以包含一些安裝過程中應(yīng)用容器中不存在的實(shí)用工具或個(gè)性化代碼。 例如,沒有必要僅為了在安裝過程中使用類似
sed
、awk
、python
或dig
這樣的工具而去FROM
一個(gè)鏡像來生成一個(gè)新的鏡像。 -
應(yīng)用鏡像的創(chuàng)建者和部署者可以各自獨(dú)立工作,而沒有必要聯(lián)合構(gòu)建一個(gè)單獨(dú)的應(yīng)用鏡像。
-
與同一 Pod 中的多個(gè)應(yīng)用容器相比,Init 容器能以不同的文件系統(tǒng)視圖運(yùn)行。因此,Init 容器可以被賦予訪問應(yīng)用容器不能訪問的 Secret 的權(quán)限。
-
由于 Init 容器必須在應(yīng)用容器啟動(dòng)之前運(yùn)行完成,因此 Init 容器提供了一種機(jī)制來阻塞或延遲應(yīng)用容器的啟動(dòng),直到滿足了一組先決條件。 一旦前置條件滿足,Pod 內(nèi)的所有的應(yīng)用容器會(huì)并行啟動(dòng)。
-
Init 容器可以安全地運(yùn)行實(shí)用程序或自定義代碼,而在其他方式下運(yùn)行這些實(shí)用程序或自定義代碼可能會(huì)降低應(yīng)用容器鏡像的安全性。 通過將不必要的工具分開,你可以限制應(yīng)用容器鏡像的被攻擊范圍。
創(chuàng)建包含Init容器的Pod
- 應(yīng)用容器和 Init 容器共享了一個(gè)卷。Init 容器將共享卷掛載到了
/work-dir
目錄,應(yīng)用容器將共享卷掛載到了/usr/share/nginx/html
目錄。 Init 容器執(zhí)行完下載index.html的指令后就終止;實(shí)現(xiàn)nginx Pod的展示文件,在啟動(dòng)前自動(dòng)在線下載。
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: workdir
mountPath: /usr/share/nginx/html
# 這些容器在 Pod 初始化期間運(yùn)行
initContainers:
- name: install
image: busybox:1.28
command:
- wget
- "-O"
- "/work-dir/index.html"
- http://info.cern.ch
volumeMounts:
- name: workdir
mountPath: "/work-dir"
dnsPolicy: Default
volumes:
- name: workdir
emptyDir: {}
- Init 容器將共享卷掛載到了
/work-dir
目錄,應(yīng)用容器將共享卷掛載到了/usr/share/nginx/html
目錄。 Init 容器執(zhí)行完下面的命令就終止:wget -O /work-dir/index.html http://info.cern.ch
- 請(qǐng)注意 Init 容器在 nginx 服務(wù)器的根目錄寫入
index.html
。- 創(chuàng)建Pod
kubectl apply -f init-containers.yaml
- 檢查 init-demo Pod運(yùn)行正常:
[root@master pod]# kubectl get pods init-demo NAME READY STATUS RESTARTS AGE init-demo 1/1 Running 0 7m34s [root@master pod]#
- 查看Pod中initcontainer的日志
[root@master pod]# kubectl logs init-demo -c install Connecting to info.cern.ch (188.184.21.108:80) index.html 100% |*******************************| 646 0:00:00 ETA [root@master pod]#
- 通過 shell 進(jìn)入 init-demo Pod 中的 nginx 容器,在 shell 中,發(fā)送個(gè) GET 請(qǐng)求到 nginx 服務(wù)器,結(jié)果表明 nginx 正在為 Init 容器編寫的 web 頁面服務(wù):
[root@master pod]# kubectl exec -it init-demo -- /bin/bash Defaulted container "nginx" out of: nginx, install (init) root@init-demo:/# root@init-demo:/# curl localhost <html><head></head><body><header> <title>http://info.cern.ch</title> </header> <h1>http://info.cern.ch - home of the first website</h1> <p>From here you can:</p> <ul> <li><a >Browse the first website</a></li> <li><a >Browse the first website using the line-mode browser simulator</a></li> <li><a >Learn about the birth of the web</a></li> <li><a >Learn about CERN, the physics laboratory where the web was born</a></li> </ul> </body></html> root@init-demo:/# exit
- 定義了一個(gè)具有 2 個(gè) Init 容器的簡(jiǎn)單 Pod。 第一個(gè)等待
myservice
啟動(dòng), 第二個(gè)等待mydb
啟動(dòng)。 一旦這兩個(gè) Init 容器都啟動(dòng)完成,Pod 將啟動(dòng)spec
節(jié)中的應(yīng)用容器。
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app.kubernetes.io/name: MyApp
spec:
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox:1.28
command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
- name: init-mydb
image: busybox:1.28
command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
- 通過運(yùn)行下面的命令啟動(dòng) Pod:
kubectl apply -f two-init.yaml
- 檢查其Pod狀態(tài):
[root@master pod]# kubectl get pods myapp-pod
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 Init:0/2 0 2s
[root@master pod]#
- 如需查看 Pod 內(nèi) Init 容器的日志,請(qǐng)執(zhí)行:
kubectl logs myapp-pod -c init-myservice # 查看第一個(gè) Init 容器
kubectl logs myapp-pod -c init-mydb # 查看第二個(gè) Init 容器
創(chuàng)建這些 Service 的配置文件
---
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377
- 創(chuàng)建
mydb
和myservice
服務(wù)的命令:
kubectl apply -f services.yaml
- 這樣你將能看到這些 Init 容器執(zhí)行完畢,隨后
my-app
的 Pod 進(jìn)入Running
狀態(tài):
[root@master pod]# kubectl get pods myapp-pod
NAME READY STATUS RESTARTS AGE
myapp-pod 1/1 Running 0 15m
[root@master pod]#
具體行為
- 在 Pod 啟動(dòng)過程中,每個(gè) Init 容器會(huì)在網(wǎng)絡(luò)和數(shù)據(jù)卷初始化(即pause容器)之后按順序啟動(dòng)。 kubelet 運(yùn)行依據(jù) Init 容器在 Pod 規(guī)約中的出現(xiàn)順序依次運(yùn)行之。
- 每個(gè) Init 容器成功退出后才會(huì)啟動(dòng)下一個(gè) Init 容器。 如果某容器因?yàn)槿萜鬟\(yùn)行時(shí)的原因無法啟動(dòng),或以錯(cuò)誤狀態(tài)退出,kubelet 會(huì)根據(jù) Pod 的
restartPolicy
策略進(jìn)行重試。 然而,如果 Pod 的restartPolicy
設(shè)置為 “Always”,Init 容器失敗時(shí)會(huì)使用restartPolicy
的 “OnFailure” 策略。- 在所有的 Init 容器沒有成功之前,Pod 將不會(huì)變成
Ready
狀態(tài)。 Init 容器的端口將不會(huì)在 Service 中進(jìn)行聚集。正在初始化中的 Pod 處于Pending
狀態(tài), 但會(huì)將狀況Initializing
設(shè)置為 false。- 如果 Pod 重啟,所有 Init 容器必須重新執(zhí)行。對(duì) Init 容器規(guī)約的修改僅限于容器的
image
字段。 更改 Init 容器的image
字段,等同于重啟該 Pod。- 因?yàn)?Init 容器可能會(huì)被重啟、重試或者重新執(zhí)行,所以 Init 容器的代碼應(yīng)該是冪等的。 特別地,基于
emptyDirs
寫文件的代碼,應(yīng)該對(duì)輸出文件可能已經(jīng)存在做好準(zhǔn)備。- nit 容器具有應(yīng)用容器的所有字段。然而 Kubernetes 禁止使用
readinessProbe
, 因?yàn)?Init 容器不能定義不同于完成態(tài)(Completion)的就緒態(tài)(Readiness)。 Kubernetes 會(huì)在校驗(yàn)時(shí)強(qiáng)制執(zhí)行此檢查。- 在 Pod 上使用
activeDeadlineSeconds
和在容器上使用livenessProbe
可以避免 Init 容器一直重復(fù)失敗。activeDeadlineSeconds
時(shí)間包含了 Init 容器啟動(dòng)的時(shí)間。 但建議僅在團(tuán)隊(duì)將其應(yīng)用程序部署為 Job 時(shí)才使用activeDeadlineSeconds
, 因?yàn)?activeDeadlineSeconds
在 Init 容器結(jié)束后仍有效果。 如果你設(shè)置了activeDeadlineSeconds
,已經(jīng)在正常運(yùn)行的 Pod 會(huì)被殺死。- 在 Pod 中的每個(gè)應(yīng)用容器和 Init 容器的名稱必須唯一; 與任何其它容器共享同一個(gè)名稱,會(huì)在校驗(yàn)時(shí)拋出錯(cuò)誤。
資源
在給定的 Init 容器執(zhí)行順序下,資源使用適用于如下規(guī)則:
- 所有 Init 容器上定義的任何特定資源的 limit 或 request 的最大值,作為 Pod 有效初始 request/limit。 如果任何資源沒有指定資源限制,這被視為最高限制。
- Pod 對(duì)資源的有效 limit/request是如下兩者中的較大者:
- 所有應(yīng)用容器對(duì)某個(gè)資源的 limit/request 之和;
- 對(duì)某個(gè)資源的有效初始 limit/request。
- 基于有效 limit/request 完成調(diào)度,這意味著 Init 容器能夠?yàn)槌跏蓟^程預(yù)留資源, 這些資源在 Pod 生命周期過程中并沒有被使用。
- Pod 的 有效 QoS 層,與 Init 容器和應(yīng)用容器的一樣。
Pod 重啟的原因
Pod 重啟會(huì)導(dǎo)致 Init 容器重新執(zhí)行,主要有如下幾個(gè)原因:
- Pod 的基礎(chǔ)設(shè)施容器 (譯者注:如
pause
容器) 被重啟。這種情況不多見, 必須由具備 root 權(quán)限訪問節(jié)點(diǎn)的人員來完成。- 當(dāng)
restartPolicy
設(shè)置為Always
,Pod 中所有容器會(huì)終止而強(qiáng)制重啟。 由于垃圾收集機(jī)制的原因,Init 容器的完成記錄將會(huì)丟失。當(dāng) Init 容器的鏡像發(fā)生改變或者 Init 容器的完成記錄因?yàn)槔占仍虮粊G失時(shí), Pod 不會(huì)被重啟。這一行為適用于 Kubernetes v1.20 及更新版本。文章來源:http://www.zghlxwxcb.cn/news/detail-483916.html
調(diào)試Init容器
- 檢查 Init 容器的狀態(tài)
- 顯示你的 Pod 的狀態(tài)
kubectl get pod <pod-name>
如,狀態(tài) Init:1/2 表明兩個(gè) Init 容器中的一個(gè)已經(jīng)成功完成:
NAME READY STATUS RESTARTS AGE
<pod-name> 0/1 Init:1/2 0 7s
- 獲取 Init 容器詳情
- Init 容器運(yùn)行的更多詳情
kubectl describe pod <pod-name>
- 與 Pod 名稱一起傳遞 Init 容器名稱,以訪問容器的日志。
kubectl logs <pod-name> -c <init-container-2>
理解 Pod 的狀態(tài)
以 Init:
開頭的 Pod 狀態(tài)匯總了 Init 容器執(zhí)行的狀態(tài)。 下表介紹調(diào)試 Init 容器時(shí)可能看到的一些狀態(tài)值示例。文章來源地址http://www.zghlxwxcb.cn/news/detail-483916.html
狀態(tài) | 含義 |
---|---|
Init:N/M | Pod 包含 M 個(gè) Init 容器,其中 N 個(gè)已經(jīng)運(yùn)行完成。 |
Init:Error | Init 容器已執(zhí)行失敗。 |
Init:CrashLoopBackOff | Init 容器執(zhí)行總是失敗。 |
Pending | Pod 還沒有開始執(zhí)行 Init 容器。正在被調(diào)度 |
PodInitializingor Running |
Pod 已經(jīng)完成執(zhí)行 Init 容器。 |
到了這里,關(guān)于【云原生|Kubernetes】08-Pod中的Init容器的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!