91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

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

發布時間:2021-12-22 16:55:01 來源:億速云 閱讀:140 作者:柒染 欄目:云計算

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

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

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

現實

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

期望

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

到了這里肯定有同學會問,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上如何控制容器的啟動順序

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
}

實現方案

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

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上如何控制容器的啟動順序有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

嘉黎县| 买车| 行唐县| 克什克腾旗| 和平区| 潜江市| 慈利县| 湖南省| 虞城县| 宿迁市| 循化| 玛曲县| 江陵县| 耿马| 老河口市| 汉沽区| 定南县| 股票| 瑞金市| 东源县| 哈巴河县| 建阳市| 镇坪县| 科技| 余姚市| 泰和县| 黄浦区| 翼城县| 福海县| 松桃| 额敏县| 建水县| 阳春市| 从江县| 弋阳县| 锡林郭勒盟| 牡丹江市| 五常市| 庆安县| 静海县| 贵州省|