Init Container 為初始化相關(guān)的任務(wù)提供了區(qū)別于主應(yīng)用程序的獨(dú)立的生命周期,從而實(shí)現(xiàn)關(guān)注點(diǎn)分離争群。
初始化在很多編程語(yǔ)言中都備受關(guān)注课梳。比如在 Java 中,為了初始化某個(gè)需要配置的對(duì)象翘紊,我們使用 constructor蔽氨。
Constructor 會(huì)保證在對(duì)象中是第一個(gè)運(yùn)行的,且只被 runtime 運(yùn)行一次帆疟。此外鹉究,還可以使用構(gòu)造函數(shù)驗(yàn)證強(qiáng)制參數(shù)之類(lèi)的先決條件,傳入?yún)?shù)或默認(rèn)值以初始化實(shí)例字段踪宠。
Init Container 與構(gòu)造函數(shù)是類(lèi)似的自赔,只不過(guò)是在 Pod 級(jí)別而不是類(lèi)級(jí)別。
假如 Pod 中有一個(gè)或多個(gè)容器代表主應(yīng)用程序柳琢,這些容器可能需要一些啟動(dòng)前的先決條件绍妨。比如為文件系統(tǒng)設(shè)置特殊的權(quán)限,設(shè)置數(shù)據(jù)庫(kù) schema柬脸,應(yīng)用程序種子數(shù)據(jù)的安裝等他去。同時(shí),這些初始化邏輯可能需要主容器鏡像中不包含的工具和庫(kù)倒堕。
又或者孤页,用戶想要延遲應(yīng)用的啟動(dòng),直到可以確認(rèn)某個(gè)外部的依賴(lài)滿足條件涩馆。
所有上述需求都可以通過(guò) Kubernetes 提供的 Init Container 實(shí)現(xiàn)行施。
Kubernetes 中的 Init Container 屬于 Pod 定義的一部分,可以將容器劃分成兩組:init containers 和 application containers魂那。
所有的 init container 會(huì)以串行的順序一個(gè)接一個(gè)地執(zhí)行蛾号,在應(yīng)用容器開(kāi)始啟動(dòng)之前,所有 init container 的執(zhí)行必須成功完成涯雅。
而應(yīng)用容器是可以并行運(yùn)行的鲜结,啟動(dòng)順序也是任意的。
通常情況下,init container 應(yīng)該是小型快速且能成功完成的精刷,除非它是用來(lái)延遲 Pod 的啟動(dòng)以等待某個(gè)依賴(lài)符合要求拗胜。
當(dāng) init container 失敗時(shí),整個(gè) Pod 會(huì)重新啟動(dòng)(除非配置了 RestartNever
)怒允,導(dǎo)致所有 init container 重新執(zhí)行一遍埂软。因而令它們符合冪等原則可以避免副作用。
一方面纫事,init container 有著和應(yīng)用容器一樣的能力:位于同一個(gè) Pod 中勘畔,共享資源限制、存儲(chǔ)卷和安全設(shè)置丽惶。另一方面炫七,它們的健康檢查和資源處理在語(yǔ)義上有些許不同。它們不存在 rediness check钾唬,因?yàn)橹挥挟?dāng)所有的 init container 成功結(jié)束之后應(yīng)用容器才會(huì)繼續(xù)啟動(dòng)万哪。
在容器調(diào)度、自動(dòng)伸縮抡秆、配額管理方面奕巍,Init container 會(huì)影響 Pod 請(qǐng)求和計(jì)算資源的方式。由于所有的 init container 會(huì)先串行執(zhí)行到終止琅轧,接著應(yīng)用容器并行運(yùn)行伍绳。因而高效的 Pod 級(jí)別的資源分配取決于以下兩組值中較大的那個(gè):
- 所有 init container 中資源請(qǐng)求或限制值最大的那個(gè)
- 所有應(yīng)用容器資源請(qǐng)求或限制的總和
上述行為的限制在于踊挠,當(dāng) init container 的資源需求非常高而應(yīng)用容器相對(duì)很低時(shí)乍桂,這種配置對(duì)于資源的利用就很低效。因?yàn)?init container 一般只運(yùn)行很短的一段時(shí)間效床,其他 Pod 無(wú)法使用 init container 運(yùn)行結(jié)束后空閑下來(lái)的資源睹酌。
Init container 能夠?qū)崿F(xiàn)關(guān)注點(diǎn)分離,從而使容器保持 single-purposed剩檀。應(yīng)用容器可以由只關(guān)注應(yīng)用邏輯的開(kāi)發(fā)工程師創(chuàng)建憋沿,而部署工程師可以為其添加 init container 并只關(guān)注配置和初始化任務(wù)。比如下面的例子沪猴。
apiVersion: v1
kind: Pod
metadata:
name: www
labels:
app: www
spec:
initContainers:
- name: download
image: axeclbr/git
command:
- git
- clone
- https://github.com/mdn/beginner-html-site-scripted
- /var/lib/data
volumeMounts:
- mountPath: /var/lib/data
name: source
containers:
- name: run
image: docker.io/centos/httpd
ports:
- containerPort: 80
volumeMounts:
- mountPath: /var/www/html
name: source
volumes:
- emptyDir: {}
name: source
Init container 克隆外部 Git repo 到掛載的路徑辐啄,該路徑通過(guò) emptyDir
掛載卷實(shí)現(xiàn) init 容器和應(yīng)用容器間的數(shù)據(jù)共享。
總結(jié)
Init container 將 Pod 中的容器分成兩組运嗜,擁有不同的生命周期壶辜、目的甚至作者。
Init 容器分階段地執(zhí)行担租,且只有當(dāng)前容器成功完成后才繼續(xù)進(jìn)行下一階段砸民,意味著我們可以確保應(yīng)用初始化的每一個(gè)階段都是有保障的。
應(yīng)用容器則可以并行運(yùn)行,沒(méi)有提供 init 容器那樣的保證岭参。我們可以根據(jù)目的在 Pod 中合理地組織關(guān)注初始化的 init 容器和關(guān)注應(yīng)用本身的應(yīng)用容器反惕。