細數k8s支持的4種類型的container

截止目前k8s1.18,k8s已經支持標準容器,sidecar容器,init 容器,ephemeral 容器 4種類型的containers。本文咱們詳細介紹一下這4種容器的特性已經使用場景。nginx

Ephemeral 容器

臨時容器與其餘容器的不一樣之處在於,它們缺乏對資源或執行的保證,而且永遠不會自動重啓,所以不適用於構建應用程序。臨時容器使用與常規容器相同的 ContainerSpec 段進行描述,但許多字段是不相容且不容許的。git

  • 臨時容器沒有端口配置,所以像 portslivenessProbereadinessProbe 這樣的字段是不容許的。
  • Pod 資源分配是不可變的,所以 resources 配置是不容許的。
  • 有關容許字段的完整列表,請參見臨時容器參考文檔

臨時容器是使用 API 中的一種特殊的 ephemeralcontainers 處理器進行建立的,而不是直接添加到 pod.spec 段,所以沒法使用 kubectl edit 來添加一個臨時容器。docker

與常規容器同樣,將臨時容器添加到 Pod 後,將不能更改或刪除臨時容器。shell

爲何咱們須要Ephemeral 容器?數據庫

咱們知道容器的優勢是它們經過使用不變方法提供全部必需的依賴項來運行隔離的進程。經過僅將所需的依賴項添加到鏡像中,容器能夠下降攻擊面並提供更快的啓動和部署。使用「distroless」方法構建容器鏡像(基於scratch),經過僅包含已編譯的應用程序二進制文件,將容器鏡像提高到了一個新的水平。與普通的容器鏡像不一樣,它們不基於任何種類的Linux發行版,所以不包含任何其餘可經過kubectl exec執行以進行故障排除的二進制文件和工具。這就決定了該容器有助於提供安全可靠的運行時環境,但也很難在問題發生時進行調試。json

在這種狀況下,臨時容器發揮做用。它們實現了調試容器附加到主進程的功能,而後你能夠用於調試任何類型的問題。調試容器能夠基於任何鏡像,所以能夠根據您的需求進行定製。您能夠構建本身的調試鏡像,其中包含特殊的調試二進制文件或僅包含curl,OpenSSL和MongoDB客戶端之類的工具。可是,您也能夠選擇Linux發行版(如Ubuntu)或僅運行Busybox鏡像,這兩個鏡像都已經包含了許多有用的工具。api

如何使用臨時容器?安全

臨時容器是alpha功能,所以默認狀況下處於禁用狀態。您將須要激活如下功能門才能使用它們:服務器

  • 臨時容器
  • PodShareProcessNamespace(v1.16中的beta版,所以默認狀況下已啓用)

本節中的示例演示了臨時容器如何出如今 API 中。 一般,您可使用 kubectl 插件進行故障排查,從而自動化執行這些步驟。網絡

臨時容器是使用 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
      }
   ]
}

可使用如下命令查看新建立的臨時容器的狀態:

kubectl describe pod example-pod
...
Ephemeral Containers:
  debugger:
    Container ID:  docker://cf81908f149e7e9213d3c3644eda55c72efaff67652a2685c1146f0ce151e80f
    Image:         busybox
    Image ID:      docker-pullable://busybox@sha256:9f1003c480699be56815db0f8146ad2e22efea85129b5b5983d0e0fb52d9ab70
    Port:          <none>
    Host Port:     <none>
    Command:
      sh
    State:          Running
      Started:      Thu, 29 Aug 2019 06:42:21 +0000
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:         <none>
...

可使用如下命令鏈接到新的臨時容器:

kubectl attach -it example-pod -c debugger

若是啓用了進程命名空間共享,則能夠查看該 Pod 全部容器中的進程。 例如,運行上述 attach 操做後,在調試器容器中運行 ps 操做:

# 在 "debugger" 臨時容器內中運行此 shell 命令
ps auxww

運行命令後,輸出相似於:

PID   USER     TIME  COMMAND
    1 root      0:00 /pause
    6 root      0:00 nginx: master process nginx -g daemon off;
   11 101       0:00 nginx: worker process
   12 101       0:00 nginx: worker process
   13 101       0:00 nginx: worker process
   14 101       0:00 nginx: worker process
   15 101       0:00 nginx: worker process
   16 101       0:00 nginx: worker process
   17 101       0:00 nginx: worker process
   18 101       0:00 nginx: worker process
   19 root      0:00 /pause
   24 root      0:00 sh
   29 root      0:00 ps auxww

Init 容器

在Kubernetes中,init容器是在同一Pod中的其餘容器以前開始並執行的容器。它旨在爲Pod上託管的主應用程序執行初始化邏輯。例如,建立必要的用戶賬戶,執行數據庫遷移,建立數據庫結構等。

建立initcontainer時應考慮一些注意事項:

  • 它們老是在Pod中的其餘容器以前執行。所以,它們不該包含須要很長時間才能完成的複雜邏輯。啓動腳本一般很小而簡潔。若是發現要向初始化容器添加太多邏輯,則應考慮將其中的一部分移至應用程序容器自己。
  • 初始化容器按順序啓動和執行。除非一個初始化容器被成功執行,不然下一個初始化容器不會被開始執行。所以,若是啓動任務很長,則能夠考慮將其分爲多個步驟,每一個步驟都由一個初始化容器處理,以便您知道哪些步驟失敗。
  • 若是任何初始化容器失敗,則將從新啓動整個Pod(除非您將restartPolicy設置爲Never)。從新啓動Pod意味着再次從新執行全部容器,包括任何初始化容器。所以,您可能須要確保啓動邏輯容許屢次執行而不會致使重複。例如,若是數據庫遷移已經完成,則應僅忽略再次執行遷移命令。
  • 初始化容器是延遲應用程序初始化直到一個或多個依賴項可用的很好的選擇。例如,若是您的應用程序依賴於施加API請求速率限制的API,則您可能須要等待一段時間才能接收來自該API的響應。在應用程序容器中實現此邏輯可能很複雜;由於它須要與健康和就緒狀態探測器結合使用。一種更簡單的方法是建立一個初始化容器,該容器要等到API準備好後才能成功退出。只有在初始化容器成功完成其工做以後,應用程序容器纔會啓動。
  • 初始化容器不能像應用程序容器那樣使用運行情況和就緒探針。緣由是它們要成功啓動和退出,就像Jobs和CronJobs的行爲同樣。
  • 同一Pod上的全部容器共享相同的卷和網絡。您能夠利用此功能在應用程序及其初始化容器之間共享數據。
正如咱們剛剛討論的那樣,init容器老是比同一個Pod上的其餘應用程序容器先啓動。結果,調度程序對init容器的資源和限制賦予了更高的優先級。必須仔細考慮這種行爲,由於這可能會致使不良後果。例如,若是您有一個初始化容器和一個應用程序容器,而且將初始化容器的資源和限制設置爲高於應用程序容器的資源和限制,那麼只有在有一個可用節點知足初始化的狀況下,才調度整個Pod容器要求。換句話說,即便有一個未使用的節點能夠在其中運行應用程序容器,但若是初始化容器具備該節點能夠處理的更高資源先決條件,則Pod也不會部署到該節點。所以,在定義初始化容器的請求和限制時,您應儘量嚴格。最佳作法是,除非絕對必要,不然請勿將這些參數設置爲高於應用程序容器的值。

標準容器和Sidecar容器

在k8s1.18 以前,這兩種容器從k8s管理的角度來看,並無什麼區別。只不過人爲從功能上作了區分。

使用sidecar容器(模塊化)具備的優勢

  • 加速應用程序開發,由於容器能夠在團隊甚至更大的社區之間重複使用
  • 整理專家知識,由於每一個人都在一個容器化的實現上進行協做,該實現反映了最佳實踐,而不是無數種功能大體相同的自家生產的不一樣容器
  • 啓用敏捷團隊,由於容器邊界是天然邊界,是團隊職責的契約
  • 提供關注點分離,並專一於特定功能,以減小意大利麪條的依賴性和不可測的組件

對於Sidecar容器通常來講主要體如今如下4種角色

  • 代理。例如如今Istio中的Envoy。

經過這種Sidercar 模式,代理能夠攔截進出主容器的流量從而Istio能夠提取有關流量行爲的大量信號做爲屬性。 Istio可使用這些屬性來執行策略決策,並將其發送到監視系統以提供有關整個網格行爲的信息。

Sidecar代理模型還容許您將Istio功能添加到現有部署中,而無需從新構造或重寫代碼。

  • 適配器。適配器容器對輸出進行標準化。考慮監視N個不一樣應用程序的任務。可使用不一樣的導出監視數據的方式來構建每一個應用程序。 (例如JMX,StatsD,特定於應用程序的統計信息),但每一個監控系統都但願其收集的監控數據具備一致且統一的數據模型。經過使用複合容器的適配器模式,您能夠經過建立Pod來未來自不一樣系統的異構監視數據轉換爲一個統一的表示形式,該Pod將應用程序容器與知道如何進行轉換的適配器分組在一塊兒。一樣,因爲這些Pod共享名稱空間和文件系統,所以這兩個容器的協調很是簡單明瞭。

  • 加強主容器功能。Sidecar容器擴展並加強了「主」容器,它們可使用現有的容器並使它們變得更好。例如,考慮一個運行Nginx Web服務器的容器。添加另外一個將文件系統與git存儲庫同步的容器,在這些容器之間共享文件系統,而且您已經構建了Git Push-to-deploy。可是您已經以模塊化的方式完成了此工做,其中git同步器能夠由不一樣的團隊構建,而且能夠在許多不一樣的Web服務器(Apache,Python,Tomcat等)上重複使用。因爲這種模塊化,您只需編寫和測試git同步器一次,便可在衆多應用程序中重複使用它。並且,若是有人編寫它,您甚至不須要這樣作。
  • 實現輔助功能 。這種場景通常出如今DevOps中。好比將收集日誌的組件以Sidecar的方式部署,實現收集日誌的用途,或是部署一個Sidecar組件從配置中心監聽配置變化,實時更新本地配置。

生命週期

Sidecar容器的全部問題都與容器生命週期相關性有關。因爲Pod中的常規容器之間沒有區別,所以沒法控制哪一個容器首先啓動或最後終止,可是先正確運行Sidecar容器一般是應用程序容器正確運行的要求。

從1.18版本開始,K8S內置的Sidecar功能將確保Sidecar容器在正常業務流程開始以前就啓動並運行,即經過更改pod的啓動生命週期,在init容器完成後啓動sidecar容器,在sidecar容器就緒後啓動業務容器,從啓動流程上保證順序性。

經過更改Pod規範中的container.lifecycle.type將容器標記爲Sidecar類型:Sidecar,默認爲Standard,以下:

apiVersion: v1
kind: Pod
metadata:
  name: bookings-v1-b54bc7c9c-v42f6
  labels:
    app: demoapp
spec:
  containers:
  - name: bookings
    image: banzaicloud/allspark:0.1.1
    ...
  - name: istio-proxy
    image: docker.io/istio/proxyv2:1.4.3
    lifecycle:
      type: Sidecar
    ...

總結

本文簡單介紹了標準容器,sidecar容器,init 容器,ephemeral 容器 4種類型的containers。隨着kubernetes日益普及,咱們須要充分掌握着幾種類型容器原理和使用方法,才能更好地服務業務。

此外Sidecar容器將會成爲將來軟件交付的一種新的方式,參照Dapr等,不一樣的團隊提供本身的功能容器,而後選擇性注入Sidecar到主業務容器,實現解耦。

相關文章
相關標籤/搜索