Kubernetes 入門:深刻了解 Pod

《Kubernetes 入門:深刻了解 Pod 》最先發布在 blog.hdls.me/15346044250…html

Pod 做爲 k8s 的基本調度單元,是 k8s 的核心資源所在。本文從 Pod 的使用、控制、調度、應用配置等方面入手,全方面講解 k8s 如何發佈和管理應用。node

Pod 基本用法

對長時間運行容器的要求是:其主程序須要一直在前臺運行。kubelet 建立包含這個容器的 Pod 以後運行完命令,即認爲 Pod 執行結束,接着當即銷燬該 Pod ,根據 RS 中定義的 Pod 副本數量,會當即再生成一個新 Pod ,會進入無限循環。json

屬於一個 Pod 的多個容器應用之間僅需經過 localhost 通訊,一組容器被綁定在了一個環境中。api

在同一個 Pod 中的容器共享 Pod 級別的 Volume,而每一個容器便可各自進行掛載,將 Volume 掛載爲容器內部須要的目錄。bash

靜態 Pod

靜態 pod 是指由 kubelet 管理的僅存在特定 Node 上的 Pod。它們不能經過 APIServer 管理,沒法與 RS 等進行關聯。網絡

建立靜態 Pod 的方式:app

靜態 pod 的建立方式有兩種,分別爲配置文件方式和 HTTP 方式。性能

配置文件方式ui

設置 kubelet 的啓動參數 --config,指定 kubelet 須要監控的配置文件所在目錄,kubelet 按期掃描該目錄,根據目錄中的 .yaml 或 .json 文件建立操做。因爲沒法經過 APIServer 對靜態 pod 進行直接管理,在 Master 節點上嘗試刪除這個 Pod 將會將其變成 pending 狀態,不會刪除;若須要刪除該 pod 須要在其所在 Node 上,將其定義文件從 /etc/kubelet.d 目錄下刪除。url

HTTP 方式

設置 kubelet 的啓動參數 --manifest-url ,kubelet 按期從該 URL 地址下載 Pod 的定義文件,並以 .yaml 或 .json 文件的格式解析,而後建立 Pod。實現方式與配置文件方式一致。

Pod 配置管理 —— ConfigMap

應用部署的一個最佳實踐是將應用所需的配置信息與程序分離,好處是能夠實現應用程序被更好的服用,經過不一樣的配置也能實現更靈活的功能。ConfigMap 是 k8s 統一的集羣配置管理方案。

用法

生成爲容器的環境變量,設置容器啓動命令的啓動參數,以 Volume 形式掛載爲容器內部的文件或目錄,以 key:value 的形式保存,既能夠表示變量的值,也能夠表示一個完整配置文件的內容。 blog.cdn.updev.cn

ConfigMap 的建立

經過 yaml 文件的方式:書寫好 yaml 文件後, kubectl create -f ***.yaml 命令便可建立 ConfigMap。

直接使用 kubectl create configmap 命令行的方式:能夠根據目錄、文件或字面值建立 ConfigMap。

  1. 能夠經過 --from-file 參數從目錄中建立
kubectl create configmap <map-name> --from-file=config-files-dir
複製代碼

其中, <map-name> 表明 ConfigMap 的名字,config-files-dir 表明目錄。建立出來的 ConfigMap 的 key 即爲文件名。

  1. 能夠經過 --from-file 參數從文件中建立,並自定義 key
kubectl create configmap <map-name> --from-file=<my-key-name>=<path-to-file>
複製代碼

其中, my-key-name 爲自定義 key,path-to-file 表明文件。

  1. 能夠經過 --from-literal 參數從文件中建立,並指定字面值
kubectl create configmap <map-name> --from-literal=<key>=<value>
複製代碼

其中, <key>=<value> 表明指定的鍵值對。

ConfigMap 的使用方式

下面就是容器中的應用如何使用 ConfigMap 的方法,主要有環境變量方式和掛載 Volume 方式。

環境變量方式

在 Deployment 的 yaml 的 container 中定義 env ,格式以下:

env:
- name: HDLS_KEY
  valueFrom:
    configMapKeyRef:
      name: special-config
      key: hdls
複製代碼

意爲:該容器中環境變量 HDLS_KEY 的值取自名爲 special-config 的 ConfigMap 中,key 爲 hdls

volumeMount 模式

須要在 Pod 的 yaml 的 container 中定義 volumeMounts (引用 volume 名和掛載到容器內的目錄),且在 volumes 中定義須要掛載的 volume 名和 ConfigMap 等信息。以下:

apiVersion: v1
kind: Pod
metadata:
  name: hdls-pod
spec:
  containers:
  - name: hdls-container
    image: ...
    ports:
      - containerPort: 8080
    volumeMounts:   # 在 container 中定義 volumeMounts
    - name: hdls-server   # 引用的 volume 名
      mountPath: /configfiles   # 掛載到容器中的目錄
  volumes:
  - name: hdls-server   # pod 中掛載的 Volume 名
    configMap:
      name: special-config   # 使用 ConfigMap 「special-config」
  ...
複製代碼

ConfigMap 的限制條件

  1. 必須在 Pod 以前建立
  2. 只有處於相同 namespace 的 Pod 能夠引用
  3. 沒有配額管理
  4. 靜態 Pod 沒法使用 ConfigMap
  5. 在 Pod 對 ConfigMap 進行掛載時,容器內部只能掛載爲目錄,不能是文件

Pod 生命週期和重啓策略

咱們在調度、管理 Pod 時,須要熟悉 Pod 在整個生命週期的各個狀態,而設置 Pod 的重啓策略也是基於對 Pod 的各類狀態的瞭解。

Pod 的狀態

Pod 的全部狀態總共有 5 種,分別以下:

Pending : APIServer 已經建立該 Pod ,但 Pod 內還有容器的鏡像沒有建立或正在下載; Running : Pod 中全部的容器均已建立,且至少有一個容器處於運行、正在啓動、正在重啓狀態; Succeeded : Pod 中全部容器已成功退出,且不會重啓; Failed : Pod 中所求容器均已退出,但至少有一個容器處於失敗狀態; Unknown : 因爲某種緣由沒法獲取該 Pod 的狀態,可能因爲網絡不順暢所致。

Pod 的重啓策略

Pod 的重啓策略有 3 種,默認值爲 Always。

Always : 容器失效時,kubelet 自動重啓該容器; OnFailure : 容器終止運行且退出碼不爲0時重啓; Never : 不論狀態爲什麼, kubelet 都不重啓該容器。

kubelet 重啓失效容器的時間間隔以 sync-frequency 乘以 2n 來計算,最長延遲 5 分鐘,並在成功重啓後的 10 分鐘重置該時間。

每種控制器對 Pod 的重啓策略

Pod 的重啓策略與控制方式有關,每種控制器對 Pod 的重啓策略要求以下:

RS 和 DaemonSet:必須設置爲 Always Job:OnFailure 或 Never kubelet (靜態 Pod):Pod 失效時自動重啓,且不進行健康檢查

健康檢查

Pod 的健康檢查分別兩種:存活檢查和就緒檢查,分別使用 LivenessProbe 探針和 ReadinessProbe 探針。

LivenessProbe (存活檢查)

用於判斷容器是否存活,一旦檢測到容器不健康, kubelet 即殺掉該容器,並根據重啓策略作相應處理,若是容器不包含 LivenessProbe 探針,kubelet 認爲其返回值永遠是 success。

ReadinessProbe (就緒檢查)

用於判斷容器是否啓動完成,便是否 ready 狀態,一旦檢測到失敗,則 Pod 的狀態被改寫,並將該 Pod 的 Endpoint 從 Service 的轉發 Endpoint 中刪除。

探針設置方式

ExecAction :在容器內執行一個命令,若是該命令的返回碼爲0,代表容器健康; TCPSocketAction :經過容器的 IP 和端口號執行 TCP 檢查,若是能創建 TCP 鏈接,代表容器健康; HTTPGetAction :經過容器的 IP 地址、端口號及路徑調用 HTTP Get 方法,若是返回碼 >=200 ,且 <400,認爲容器健康。

以上每種探測方式都須要設置的參數: initialDelaySeconds:延遲檢查的時間,單位爲s timeoutSeconds:健康檢查發送後等待響應的超時時間,單位爲s periodSeconds:執行週期

Pod 調度

Pod 實爲 k8s 中的最小調度單元,只是容器的載體,其自己沒法完成自動調度的功能。 k8s 採用了 RS、Deployment、DaemonSet、Job 等方式實現 Pod 的調度和自動控制。

RS、Deployment 全自動調度

RS 的主要功能之一就是自動部署一個容器應用的多份副本,及持續監控副本的數量。而 RS/RC 在 k8s 中通常不多單獨使用,都是在 Deployment 中使用,而 Deployment 是 k8s 引入的一個更好解決 Pod 編排問題的概念,經過 Deployment 咱們能夠隨時知道 Pod 的調度狀況。

在 Pod 的定義中,能夠採用 NodeSelector 或 NodeAffinity 兩種方式進行調度。

NodeSelector 定向調度

Pod 調度是經過 Master 上的 Scheduler 負責實現的,原理是經過 Node 標籤和 Pod 的 nodeSelector 屬性匹配。

NodeSelector 定向調度的過程爲:經過 kubectl label 給目標 Node 打上標籤;在 Pod 的定義上加上 nodeSelector 的設置。須要注意的是,一旦 Pod 指定了 nodeSelector ,若集羣中不存在匹配的 Node ,即便有空閒的 Node,也不會調度。

經過 kubectl 進行打標籤的方法:

kubectl label nodes <node-name> <label-key>=<label_value>
複製代碼

在 Pod 中指定 nodeSelector:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hdls
spec:
  template:
    metadata:
      name: hdls-pod
    spec:
      containers:
      - name: hdls-container
        image: ...
        ports:
        - containerPort: 8080
      nodeSelector:
        <label-key>: <label_value>
複製代碼

NodeAffinity 親和性調度

NodeAffinity 意爲 Node 親和性的調度策略,是替換 NodeSelector 的下一代調度策略。在 NodeSelector 的基礎上增長了 In/NotIn/Exists/DoesNotExsist/Gt/Lt 等操做。

設置親和性: requiredDuringSchedulingRequiredDuringExecution:相似於 NodeSelector ,在 Node 不知足條件時,系統從該 Node 上移除以前調度上的 Pod ; requiredDuringSchedulingIgnoredDuringExecution:在 Node 不知足條件時,系統不必定從該 Node 上移除以前調度上的 Pod; preferredDuringSchedulingIgnoredDuringExecution:指定在知足條件的 Node 中,哪些 Node 更優先地調度;同時,Node 不知足條件時,不必定從該 Node 上移除以前調度上的 Pod。

DaemonSet 特定場景調度

DaemonSet 是 Kubernetes 1.2 版本中新增的一種資源對象,用於確保所有(或指定的某些)Node 上運行一個 Pod 副本。其 Pod 調度策略與 RC 相似。

使用場景:

  1. 在每一個 Node 上運行一個 GlusterFS 存儲或者 Ceph 存儲的 daemon 進程
  2. 在每一個 Node 上運行一個日誌採集程序,如 fluentd 、logstach
  3. 在每一個 Node 上運行一個健康程序,採集該 Node 的運行性能數據

Job 批處理調度

Job 是 Kubernetes 1.2 版本中新增的支持批處理的資源對象。批處理任務一般並行或串行啓動多個計算進程去處理一批工做項(work item),處理完後整個 Job 結束。

Job 的模式:

  1. Job Template Expansion 模式:一個 Job 對應一個 work item 。一般適合 work item 較少、每一個 work item 要處理的數據量較大的場景;
  2. Queue with Pod Per Work Item 模式:採用一個任務隊列存放 work item,Job 對象去消費這些 work item 。這種模式是一個 Pod 對應一個 work item,一個 Job 啓動多個 Pod;
  3. Queue with Variable Pod Count 模式:與上面一種模式相同,惟一不一樣的是 Job 啓動的 Pod 數量時可變的;
  4. Single Job with Static Work Assignment 模式:也是一個 Job 產生多個 Pod 的模式,但採用的是程序靜態方式分配任務,而不是隊列模式。

Job 的類型

考慮到批處理的並行問題,Job 被分爲如下幾種類型:

  1. Non-parallel Jobs :一個 Job 啓動一個 Pod;
  2. Parallel Jobs with a fixed completion count :並行 Job 啓動多個 Pod。須要設置 Job 的 .spec.completions 參數爲一個正數,此爲正常結束的 Pod 的上限值;.spec.parallelism 參數爲並行數,即同時處理 work item 的 Pod 數;
  3. Parallel Jobs with a work queue :並行 Job 有個獨立的 queue 來存放 work item ,此時不能設置 .spec.completions 參數。

Pod 擴容和縮容

在實際生產系統中,服務擴容是個不容忽視的場景。在 k8s 中,有兩種方式來實現 Pod 的擴容和縮容,分別爲 RC 的 Scale 機制和 HPA (Horizontal Pod Autoscaler)。

RC 的 Scale 機制

經過 kebectl 命令可設置 Pod 的副本數:

kubectl scale rc <rc-name> --replicas=3
複製代碼

經過 --replicas=<num> 參數將 Pod 的副本數手動調高,便可完成 Pod 的擴容;相應的,將該參數設置爲較低的數,系統將 kill 掉一些運行中的 Pod ,以實現應用集羣縮容。

HPA

HPA (Horizontal Pod Autoscaler) 是 Kubernetes v1.1 新增的控制器,用以實現基於 CPU 使用率進行自動 Pod 擴縮容的功能。HPA 基於 Master 的 kube-controller-manager 服務啓動參數 --horizontal-pod-autoscaler-sync-period 定義的時長(默認爲 30 秒),週期性的檢測目標 Pod 的 CPU 使用率,並在知足條件時對 RC 或 Deployment 中的 Pod 副本數進行調整,以符合用戶定義的平均 Pod CPU 使用率。PodCPU 使用率來源於 heapster 組件,因此須要預先安裝好 heapster。

建立 HPA 時可使用 kubectlautoscale 命令或使用 yaml 配置文件。在建立 HPA 以前,須要確保已經存在一個 RC 或 Deployment 對象,且該 RC 或 Deployment 中的 Pod 必須定義 resources.requests.cpu 的資源請求值。

滾動升級

在實際生產環境中,應用的升級也是一個很重要的場景。在集羣規模較大時,先所有中止再逐步升級的方式會致使較長時間內服務不可用,升級工做就成了一個不小的挑戰。 k8s 提供了滾動升級功能來解決這個問題。

滾動升級經過執行 kubectl rolling-update 命令一鍵完成。整個過程爲:

  1. 建立一個新的 RC;
  2. 自動控制舊的 RC 中的 Pod 副本的數量逐漸減小到 0;
  3. 同時新 RC 中的 Pod 副本數從 0 逐步增長到到目標值,舊的 Pod 每減小 1,新的 Pod 就增長 1。

須要注意的是,新舊 RC 必須在同一 namespace 下。

採用 yaml 配置文件

若採用 yaml 配置文件來實現滾動升級,須要先手動建立一個新的 RC yaml,且 yaml 文件中須要注意的是:

  1. RC 的名字不可與舊 RC 名字相同;
  2. 在 selector 在應至少有一個 Label 與舊的 RC 的 Label 不一樣,以標識爲新的 RC ;

再運行 kubectl 命令完成滾動升級:

kubectl rolling-update <RC-name> -f <new-RC-yaml>
複製代碼

不使用 yaml 配置文件

若不使用 yaml 配置文件,可直接用 kubectl rolling-update 命令,加上 --image 參數指定新版鏡像名。

kubectl rolling-update <RC-name> --image=<image-name>
複製代碼

與使用配置文件的方式不一樣,該方法執行的結果是舊的 RC 被刪除,新的 RC 仍使用舊的 RC 名,且完成升級後,新 RC 多一個 key 爲 「deployment」(這個名字可經過 --deployment-label-key 參數進行修改) 的 Label ,值爲 RC 的內容進行 Hash 計算後的值。

最後,若 Pod 須要回滾,可中斷更新操做,執行 kubectl rolling-update-rollback 完成 Pod 版本的回滾。

相關文章
相關標籤/搜索