k8s-ephemeral和init容器

姚紅發表於2020-06-06

  截止到目前k8s1.18版本,k8s已經支援四種型別的container:標準容器,sidecar容器,init容器,ephemeral容器。

    

 

一:ephemeral容器

1.1.什麼是ephemeral容器

      臨時容器與其他容器的不同之處在於,它們缺少對資源或執行的保證,並且永遠不會自動重啟,因此不適用於構建應用程式。臨時容器使用與常規容器相同的 ContainerSpec 段進行描述,但許多欄位是不相容且不允許的。

  • 臨時容器沒有埠配置,因此像 portslivenessProbereadinessProbe 這樣的欄位是不允許的。
  • Pod 資源分配是不可變的,因此 resources 配置是不允許的。
  • 有關允許欄位的完整列表,

1.2.ephemeral容器的用途

  當由於容器崩潰或容器映象不包含除錯實用程式而導致 kubectl exec 無用時,臨時容器對於互動式故障排查很有用

  尤其是,distroless 映象能夠使得部署最小的容器映象,從而減少攻擊面並減少故障和漏洞的暴露。由於 distroless 映象不包含 shell 或任何的除錯工具,因此很難單獨使用 kubectl exec 命令進行故障排查。

使用臨時容器時,啟用程式名稱空間共享很有幫助,可以檢視其他容器中的程式。

1.3.使用ephemeral容器

  臨時容器是使用 Pod 的 ephemeralcontainers 子資源建立的,可以使用 kubectl --raw 命令進行顯示。首先描述臨時容器被新增為一個 EphemeralContainers 列表:

{
    "apiVersion": "v1",
    "kind": "EphemeralContainers",
    "metadata": {
            "name": "example-pod"
    },
    "ephemeralContainers": [{
        "command": [
            "sh"
        ],
        "image": "busybox",
        "imagePullPolicy": "IfNotPresent",
        "name": "debugger",
        "stdin": true,
        "tty": true,
        "terminationMessagePolicy": "File"
    }]
}

  使用如下命令更新已執行的臨時容器 example-pod

kubectl replace --raw /api/v1/namespaces/default/pods/example-pod/ephemeralcontainers  -f ec.json

  這將返回臨時容器的新列表:

{
   "kind":"EphemeralContainers",
   "apiVersion":"v1",
   "metadata":{
      "name":"example-pod",
      "namespace":"default",
      "selfLink":"/api/v1/namespaces/default/pods/example-pod/ephemeralcontainers",
      "uid":"a14a6d9b-62f2-4119-9d8e-e2ed6bc3a47c",
      "resourceVersion":"15886",
      "creationTimestamp":"2019-08-29T06:41:42Z"
   },
   "ephemeralContainers":[
      {
         "name":"debugger",
         "image":"busybox",
         "command":[
            "sh"
         ],
         "resources":{

         },
         "terminationMessagePolicy":"File",
         "imagePullPolicy":"IfNotPresent",
         "stdin":true,
         "tty":true
      }
   ]
}

 

二.Init容器

 2.1.什麼是Init容器

  一個pod中可以執行多個容器,也可以執行多個init 容器,init容器先於應用容器執行。

  Init 容器與普通的容器非常像,除了如下兩點:

  • 它們總是執行到完成。
  • 每個都必須在下一個啟動之前成功完成。

 2.2.與普通容器的不同之處

  Init 容器支援應用容器的全部欄位和特性,包括資源限制、資料卷和安全設定。 然而,Init 容器對資源請求和限制的處理稍有不同,在下面 資源 處有說明。

  同時 Init 容器不支援 Readiness Probe,因為它們必須在 Pod 就緒之前執行完成。

  如果為一個 Pod 指定了多個 Init 容器,這些容器會按順序逐個執行。每個 Init 容器必須執行成功,下一個才能夠執行。當所有的 Init 容器執行完成時,Kubernetes 才會為 Pod 初始化應用容器並像平常一樣執行。

 2.3.Init 容器作用

  因為 Init 容器具有與應用容器分離的單獨映象,其啟動相關程式碼具有如下優勢:

  • Init 容器可以包含一些安裝過程中應用容器中不存在的實用工具或個性化程式碼。例如,沒有必要僅為了在安裝過程中使用類似 sed、 awk、 python 或 dig 這樣的工具而去FROM 一個映象來生成一個新的映象。
  • Init 容器可以安全地執行這些工具,避免這些工具導致應用映象的安全性降低。
  • 應用映象的建立者和部署者可以各自獨立工作,而沒有必要聯合構建一個單獨的應用映象。
  • Init 容器能以不同於Pod內應用容器的檔案系統檢視執行。因此,Init容器可具有訪問 Secrets 的許可權,而應用容器不能夠訪問。
  • 由於 Init 容器必須在應用容器啟動之前執行完成,因此 Init 容器提供了一種機制來阻塞或延遲應用容器的啟動,直到滿足了一組先決條件。一旦前置條件滿足,Pod內的所有的應用容器會並行啟動。

2.4使用Init容器

  下面的例子定義了一個具有 2 個 Init 容器的簡單 Pod。 第一個等待 myservice 啟動,第二個等待 mydb 啟動。 一旦這兩個 Init容器 都啟動完成,Pod 將啟動spec區域中的應用容器。

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: 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"]

  這是 Kubernetes 1.6 版本的新語法,儘管老的 annotation 語法仍然可以使用。我們已經把 Init 容器的宣告移到 spec 中:

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox
    command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
  - name: init-mydb
    image: busybox
    command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']

  1.5 版本的語法在 1.6 版本仍然可以使用,但是我們推薦使用 1.6 版本的新語法。 在 Kubernetes 1.6 版本中,Init 容器在 API 中新建了一個欄位。 雖然期望使用 beta 版本的 annotation,但在未來發行版將會被廢棄掉。

  在所有的 Init 容器沒有成功之前,Pod 將不會變成 Ready 狀態。 Init 容器的埠將不會在 Service 中進行聚集。 正在初始化中的 Pod 處於 Pending 狀態,但應該會將條件 Initializing 設定為 true。

  如果 Pod 重啟,所有 Init 容器必須重新執行。

  對 Init 容器 spec 的修改,被限制在容器 image 欄位中。 更改 Init 容器的 image 欄位,等價於重啟該 Pod。

 

相關文章