梳理概念:
? ? ? ? 初始化容器,顧名思義容器啟動的時候,會先啟動可一個或多個容器,如果有多個,那么這幾個Init Container按照定義的順序依次執行,只有所有的Init Container執行完后,主容器才會啟動。由于一個Pod里的存儲卷是共享的,所以Init Container里產生的數據可以被主容器使用到。
? ? ? ? Init Container可以在多種K8S資源里被使用到如Deployment、Daemon Set, Pet Set, Job等,但歸根結底都是在Pod啟動時,在主容器啟動前執行,做初始化工作。
應用場景:
? ? ? ? 第一種場景:等待其它模塊Ready,比如我們有一個應用里面有兩個容器化的服務,一個是Web Server,另一個是數據庫。其中Web Server需要訪問數據庫。但是當我們啟動這個應用的時候,并不能保證數據庫服務先啟動起來,所以可能出現在一段時間內Web Server有數據庫連接錯誤。為了解決這個問題,我們可以在運行Web Server服務的Pod里使用一個InitContainer,去檢查數據庫是否準備好,直到數據庫可以連接,Init Container才結束退出,然后Web Server容器被啟動,發起正式的數據庫連接請求。
? ? ? ? 第二種場景:初始化配置,比如集群里檢測所有已經存在的成員節點,為主容器準備好集群的配置信息,這樣主容器起來后就能用這個配置信息加入集群。
? ? ? ? 其它使用場景:如將pod注冊到一個中央數據庫、下載應用依賴等。
參照樣例:
? ? ? ? 初始化容器有兩種寫法,一種是注解的形式,樣例如下圖所示:
? 另一種是轉換為PodSpec字段的形式,樣例如下圖所示:
? ? ? ? Kubernetes 1.6有一個新的語法,盡管舊的注釋語法仍然適用于1.6和1.7。新的語法必須用于1.8或更高版本。我們已經將init容器的聲明移至spec,可以在PodSpec中指定Init Containers以及應用程序containers數組。測試版批注值仍將受到尊重并覆蓋PodSpec字段值,但是,它們在1.6和1.7中已棄用。在1.8中,注釋不再受支持,并且必須轉換為PodSpec字段。
? ? ? ? k8s中,spec.volumes指的是Pod中的卷,spec.container.volumeMounts,是將指定的卷mount到容器指定的位置,相當于docker里面的‘-v 宿主機目錄:容器目錄’,上圖emptyDir{}相當于一個共享卷,是一個臨時的目錄,生命周期等同于pod的生命周期。
? ? ? ? 初始化容器執行完,會下載一個html文件映射到emptyDir{},而主容器也是和spec.volumes里的emptyDir{}進行映射,故nginx容器的/usr/share/nginx/html目錄下會映射index.html文件。
執行結果:
由于我的k8s版本是1.9,所以我采用PodSpec的形式來啟動容器,執行命令如下:
kubectl apply -f init-container.yaml
它會先啟動一個初始化的容器,當初始化容器執行完成之后,然后啟動主容器。
接下來看容器的詳情,會先啟動init-containers,再接著啟動containers主容器,如下圖:
整個初始化容器過程就完了,下一節容器講述的健康檢查。