Init 容器
+v ljx97609760 一起溝通學習
Init 容器是一種特殊容器,在 Pod 內的應用容器啟動之前運行。Init 容器可以包括一些應用鏡像中不存在的實用工具和安裝腳本
理解 Init 容器
每個 Pod 中可以包含多個容器, 應用運行在這些容器里面,同時 Pod 也可以有一個或多個先于應用容器啟動的 Init 容器。
Init 容器與普通的容器非常像,除了如下兩點:
- 它們總是運行到完成
- 每個都必須在下一個啟動之前成功完成
如果 Pod 的 Init 容器失敗,kubelet 會不斷地重啟該 Init 容器直到該容器成功為止。 然而,如果 Pod 對應的 restartPolicy 值為 “Never”,并且 Pod 的 Init 容器失敗, 則 Kubernetes 會將整個 Pod 狀態(tài)設置為失敗。
為 Pod 設置 Init 容器需要在 Pod 規(guī)約中添加 initContainers 字段, 該字段以 Container 類型對象數組的形式組織,和應用的 containers 數組同級相鄰。 參閱 API 參考的容器章節(jié)了解詳情
Init 容器的狀態(tài)在 status.initContainerStatuses 字段中以容器狀態(tài)數組的格式返回 (類似 status.containerStatuses 字段)
與普通容器的不同之處
Init 容器支持應用容器的全部字段和特性,包括資源限制、 數據卷和安全設置。 然而,Init 容器對資源請求和限制的處理稍有不同,在下面資源節(jié)有說明
同時 Init 容器不支持 lifecycle、livenessProbe、readinessProbe 和 startupProbe, 因為它們必須在 Pod 就緒之前運行完成
如果為一個 Pod 指定了多個 Init 容器,這些容器會按順序逐個運行。 每個 Init 容器必須運行成功,下一個才能夠運行。當所有的 Init 容器運行完成時, Kubernetes 才會為 Pod 初始化應用容器并像平常一樣運行
使用 Init 容器
因為 Init 容器具有與應用容器分離的單獨鏡像,其啟動相關代碼具有如下優(yōu)勢:
-
Init 容器可以包含一些安裝過程中應用容器中不存在的實用工具或個性化代碼。 例如,沒有必要僅為了在安裝過程中使用類似 sed、awk、python 或 dig 這樣的工具而去 FROM 一個鏡像來生成一個新的鏡像
-
應用鏡像的創(chuàng)建者和部署者可以各自獨立工作,而沒有必要聯合構建一個單獨的應用鏡像
-
與同一 Pod 中的多個應用容器相比,Init 容器能以不同的文件系統(tǒng)視圖運行。因此,Init 容器可以被賦予訪問應用容器不能訪問的 Secret 的權限
-
由于 Init 容器必須在應用容器啟動之前運行完成,因此 Init 容器提供了一種機制來阻塞或延遲應用容器的啟動,直到滿足了一組先決條件。 一旦前置條件滿足,Pod 內的所有的應用容器會并行啟動
-
Init 容器可以安全地運行實用程序或自定義代碼,而在其他方式下運行這些實用程序或自定義代碼可能會降低應用容器鏡像的安全性。 通過將不必要的工具分開,你可以限制應用容器鏡像的被攻擊范圍
例子
下面是一些如何使用 Init 容器的想法:
- 等待一個 Service 完成創(chuàng)建,通過類似如下 Shell 命令:
for i in {1..100}; do sleep 1; if nslookup myservice; then exit 0; fi; done; exit 1
- 注冊這個 Pod 到遠程服務器,通過在命令中調用 API,類似如下:
curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'
- 在啟動應用容器之前等一段時間,使用類似命令:
sleep 60
- 克隆 Git 倉庫到卷中
- 將配置值放到配置文件中,運行模板工具為主應用容器動態(tài)地生成配置文件。 例如,在配置文件中存放 POD_IP 值,并使用 Jinja 生成主應用配置文件
使用 Init 容器的情況
下面的例子定義了一個具有 2 個 Init 容器的簡單 Pod。 第一個等待 myservice 啟動, 第二個等待 mydb 啟動。 一旦這兩個 Init 容器都啟動完成,Pod 將啟動 spec 節(jié)中的應用容器
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"]
通過運行下面的命令啟動 Pod:
kubectl apply -f myapp.yaml
輸出類似于:
pod/myapp-pod created
使用下面的命令檢查其狀態(tài):
kubectl get -f myapp.yaml
輸出類似于:
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 Init:0/2 0 6m
如果要查看 Pod 內 Init 容器的日志,請執(zhí)行:
kubectl logs myapp-pod -c init-myservice # 查看第一個 Init 容器
kubectl logs myapp-pod -c init-mydb # 查看第二個 Init 容器
Init 容器將會等待至發(fā)現名稱為 mydb 和 myservice 的服務。
如下為創(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 服務的命令:
kubectl apply -f services.yaml
輸出類似于:
service/myservice created
service/mydb created
這樣你將能看到這些 Init 容器執(zhí)行完畢,隨后 my-app 的 Pod 進入 Running 狀態(tài):
kubectl get -f myapp.yaml
輸出類似于:
NAME READY STATUS RESTARTS AGE
myapp-pod 1/1 Running 0 9m
具體行為
在 Pod 啟動過程中,每個 Init 容器會在網絡和數據卷初始化之后按順序啟動。 kubelet 運行依據 Init 容器在 Pod 規(guī)約中的出現順序依次運行之。
每個 Init 容器成功退出后才會啟動下一個 Init 容器。 如果某容器因為容器運行時的原因無法啟動,或以錯誤狀態(tài)退出,kubelet 會根據 Pod 的 restartPolicy 策略進行重試。 然而,如果 Pod 的 restartPolicy 設置為 “Always”,Init 容器失敗時會使用 restartPolicy 的 “OnFailure” 策略。
在所有的 Init 容器沒有成功之前,Pod 將不會變成 Ready 狀態(tài)。 Init 容器的端口將不會在 Service 中進行聚集。正在初始化中的 Pod 處于 Pending 狀態(tài), 但會將狀況 Initializing 設置為 false。
如果 Pod 重啟,所有 Init 容器必須重新執(zhí)行。
對 Init 容器規(guī)約的修改僅限于容器的 image 字段。 更改 Init 容器的 image 字段,等同于重啟該 Pod。
因為 Init 容器可能會被重啟、重試或者重新執(zhí)行,所以 Init 容器的代碼應該是冪等的。 特別地,基于 emptyDirs 寫文件的代碼,應該對輸出文件可能已經存在做好準備。
Init 容器具有應用容器的所有字段。然而 Kubernetes 禁止使用 readinessProbe, 因為 Init 容器不能定義不同于完成態(tài)(Completion)的就緒態(tài)(Readiness)。 Kubernetes 會在校驗時強制執(zhí)行此檢查。
在 Pod 上使用 activeDeadlineSeconds 和在容器上使用 livenessProbe 可以避免 Init 容器一直重復失敗。 activeDeadlineSeconds 時間包含了 Init 容器啟動的時間。 但建議僅在團隊將其應用程序部署為 Job 時才使用 activeDeadlineSeconds, 因為 activeDeadlineSeconds 在 Init 容器結束后仍有效果。 如果你設置了 activeDeadlineSeconds,已經在正常運行的 Pod 會被殺死。
在 Pod 中的每個應用容器和 Init 容器的名稱必須唯一; 與任何其它容器共享同一個名稱,會在校驗時拋出錯誤。文章來源:http://www.zghlxwxcb.cn/news/detail-562408.html
Pod 重啟的原因
Pod 重啟會導致 Init 容器重新執(zhí)行,主要有如下幾個原因:文章來源地址http://www.zghlxwxcb.cn/news/detail-562408.html
- Pod 的基礎設施容器 (譯者注:如 pause 容器) 被重啟,這種情況不多見, 必須由具備 root 權限訪問節(jié)點的人員來完成
- 當 restartPolicy 設置為 Always,Pod 中所有容器會終止而強制重啟。 由于垃圾回收機制的原因, Init 容器的完成記錄將會丟失
- 當 Init 容器的鏡像發(fā)生改變或者 Init 容器的完成記錄因為垃圾收集等原因被丟失時, Pod 不會被重啟。這一行為適用于 Kubernetes v1.20 及更新版本
到了這里,關于【云原生】Init 容器的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!