久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

Kubernetes上如何控制容器的啟動順序

172次閱讀
沒有評論

共計 4076 個字符,預計需要花費 11 分鐘才能閱讀完成。

今天就跟大家聊聊有關 Kubernetes 上如何控制容器的啟動順序,可能很多人都不太了解,為了讓大家更加了解,丸趣 TV 小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。

控制 Pod 內容器的啟動順序,分析了 TektonCD 的容器啟動控制的原理。

為什么要做容器啟動順序控制?我們都知道 Pod 中除了 init-container 之外,是允許添加多個容器的。類似 TektonCD 中 task 和 step 的概念就分別與 pod 和 container 對應,而 step 是按照順序執行的。此外還有服務網格的場景,sidecar 容器需要在服務容器啟動之前完成配置的加載,也需要對容器的啟動順序加以控制。否則,服務容器先啟動,而 sidecar 還無法提供網絡上的支持。

現實

期望

到了這里肯定有同學會問,spec.containers[] 是一個數組,數組是有順序的。Kubernetes 也確實是按照順序來創建和啟動容器,但是 容器啟動成功,并不表示容器可以對外提供服務。

在 Kubernetes 1.18 非正式版中曾在 Lifecycle 層面提供了對 sidecar 類型容器的 支持,但是最終該功能并沒有落地。

那到底該怎么做?

TL;DR

筆者準備了一個簡單的 go 項目,用于模擬 sidecar 的啟動及配置加載。

克隆代碼后可以通過 make build 構建出鏡像,假如你是用的 minikube 進行的實驗,可以通過命令 make load-2-minikube 將鏡像加載到 minikube 節點中。

使用 Deployment 的方式進行部署,直接用 Pod 也可以。

apiVersion: apps/v1
kind: Deployment
metadata:
 creationTimestamp: null
 labels:
 app: sample
 name: sample
spec:
 replicas: 1
 selector:
 matchLabels:
 app: sample
 strategy: {}
 template:
 metadata:
 creationTimestamp: null
 labels:
 app: sample
 spec:
 containers:
 - image: addozhang/k8s-container-sequence-sidecar:latest
 name: sidecar
 imagePullPolicy: IfNotPresent
 lifecycle:
 postStart:
 exec:
 command:
 - /entrypoint
 - wait
 - image: busybox:latest
 name: app
 imagePullPolicy: IfNotPresent
 command: [/bin/sh , -c]
 args: [date; echo  app container started  tail -f /dev/null]

下面的截圖中,演示了在 sample 命名空間中,pod 內兩個容器的執行順序。

Kubernetes 源碼

在 kubelet 的源碼 pkg/kubelet/kuberuntime/kuberuntime_manager.go 中,#SyncPod 方法用于創建 Pod,步驟比較繁瑣,直接看第 7 步:創建普通容器。

// SyncPod syncs the running pod into the desired pod by executing following steps:
// 1. Compute sandbox and container changes.
// 2. Kill pod sandbox if necessary.
// 3. Kill any containers that should not be running.
// 4. Create sandbox if necessary.
// 5. Create ephemeral containers.
// 6. Create init containers.
// 7. Create normal containers.
func (m *kubeGenericRuntimeManager) SyncPod(pod *v1.Pod, podStatus *kubecontainer.PodStatus, pullSecrets []v1.Secret, backOff *flowcontrol.Backoff) (result kubecontainer.PodSyncResult) {
 
 ...
 
 // Step 7: start containers in podContainerChanges.ContainersToStart.
 for _, idx := range podContainerChanges.ContainersToStart {start( container , containerStartSpec( pod.Spec.Containers[idx]))
 return
}

在 #start 方法中調用了 #startContainer 方法,該方法會啟動容器,并返回容器啟動的結果。注意,這里的結果還 包含了容器的 Lifecycle hooks 調用。

也就是說,假如容器的 PostStart hook 沒有正確的返回,kubelet 便不會去創建下一個容器。

// startContainer starts a container and returns a message indicates why it is failed on error.
// It starts the container through the following steps:
// * pull the image
// * create the container
// * start the container
// * run the post start lifecycle hooks (if applicable)
func (m *kubeGenericRuntimeManager) startContainer(podSandboxID string, podSandboxConfig *runtimeapi.PodSandboxConfig, spec *startSpec, pod *v1.Pod, podStatus *kubecontainer.PodStatus, pullSecrets []v1.Secret, podIP string, podIPs []string) (string, error) {
 
 ...
 
 // Step 4: execute the post start hook.
 if container.Lifecycle != nil   container.Lifecycle.PostStart != nil {
 kubeContainerID := kubecontainer.ContainerID{
 Type: m.runtimeName,
 ID: containerID,
 msg, handlerErr := m.runner.Run(kubeContainerID, pod, container, container.Lifecycle.PostStart)
 if handlerErr != nil {m.recordContainerEvent(pod, container, kubeContainerID.ID, v1.EventTypeWarning, events.FailedPostStartHook, msg)
 if err := m.killContainer(pod, kubeContainerID, container.Name,  FailedPostStartHook , reasonFailedPostStartHook, nil); err != nil {klog.ErrorS(fmt.Errorf( %s: %v , ErrPostStartHook, handlerErr),  Failed to kill container ,  pod , klog.KObj(pod),
 podUID , pod.UID,  containerName , container.Name,  containerID , kubeContainerID.String())
 return msg, fmt.Errorf(%s: %v , ErrPostStartHook, handlerErr)
 return  , nil
}

實現方案

cmd/entrypoint/wait.go#L26(這里參考了 Istio 的 pilot-agent 實現)

在 PostStart 中持續的去檢查 /ready 斷點,可以 hold 住當前容器的創建流程。保證 /ready 返回 200 后,kubelet 才會去創建下一個容器。

這樣就達到了前面截圖中演示的效果。

for time.Now().Before(timeoutAt) {err = checkIfReady(client, url)
 if err == nil {log.Println( sidecar is ready)
 return nil
 log.Println(sidecar is not ready)
 time.Sleep(time.Duration(periodMillis) * time.Millisecond)
return fmt.Errorf(sidecar is not ready in %d second(s) , timeoutSeconds)

看完上述內容,你們對 Kubernetes 上如何控制容器的啟動順序有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注丸趣 TV 行業資訊頻道,感謝大家的支持。

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-08-16發表,共計4076字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 湄潭县| 泰宁县| 宿州市| 哈巴河县| 石屏县| 江达县| 克拉玛依市| 兴文县| 方山县| 吴旗县| 明溪县| 阜城县| 乐昌市| 银川市| 吉水县| 岚皋县| 镇安县| 房产| 涟源市| 深州市| 同江市| 德令哈市| 临泉县| 招远市| 毕节市| 蓝山县| 三亚市| 彭州市| 麻城市| 云浮市| 佳木斯市| 夏津县| 文成县| 长治县| 香河县| 荔波县| 松溪县| 城固县| 肃宁县| 青神县| 土默特右旗|