《Kubernetes 入門:深刻了解 Pod 》最先發布在 blog.hdls.me/15346044250…html
Pod 做爲 k8s 的基本調度單元,是 k8s 的核心資源所在。本文從 Pod 的使用、控制、調度、應用配置等方面入手,全方面講解 k8s 如何發佈和管理應用。node
對長時間運行容器的要求是:其主程序須要一直在前臺運行。kubelet 建立包含這個容器的 Pod 以後運行完命令,即認爲 Pod 執行結束,接着當即銷燬該 Pod ,根據 RS 中定義的 Pod 副本數量,會當即再生成一個新 Pod ,會進入無限循環。json
屬於一個 Pod 的多個容器應用之間僅需經過 localhost 通訊,一組容器被綁定在了一個環境中。api
在同一個 Pod 中的容器共享 Pod 級別的 Volume,而每一個容器便可各自進行掛載,將 Volume 掛載爲容器內部須要的目錄。bash
靜態 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。實現方式與配置文件方式一致。
應用部署的一個最佳實踐是將應用所需的配置信息與程序分離,好處是能夠實現應用程序被更好的服用,經過不一樣的配置也能實現更靈活的功能。ConfigMap 是 k8s 統一的集羣配置管理方案。
生成爲容器的環境變量,設置容器啓動命令的啓動參數,以 Volume 形式掛載爲容器內部的文件或目錄,以 key:value 的形式保存,既能夠表示變量的值,也能夠表示一個完整配置文件的內容。 blog.cdn.updev.cn
經過 yaml 文件的方式:書寫好 yaml 文件後, kubectl create -f ***.yaml
命令便可建立 ConfigMap。
直接使用 kubectl create configmap
命令行的方式:能夠根據目錄、文件或字面值建立 ConfigMap。
--from-file
參數從目錄中建立kubectl create configmap <map-name> --from-file=config-files-dir
複製代碼
其中, <map-name>
表明 ConfigMap 的名字,config-files-dir
表明目錄。建立出來的 ConfigMap 的 key 即爲文件名。
--from-file
參數從文件中建立,並自定義 keykubectl create configmap <map-name> --from-file=<my-key-name>=<path-to-file>
複製代碼
其中, my-key-name
爲自定義 key,path-to-file
表明文件。
--from-literal
參數從文件中建立,並指定字面值kubectl create configmap <map-name> --from-literal=<key>=<value>
複製代碼
其中, <key>=<value>
表明指定的鍵值對。
下面就是容器中的應用如何使用 ConfigMap 的方法,主要有環境變量方式和掛載 Volume 方式。
在 Deployment 的 yaml 的 container 中定義 env ,格式以下:
env:
- name: HDLS_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: hdls
複製代碼
意爲:該容器中環境變量 HDLS_KEY
的值取自名爲 special-config
的 ConfigMap 中,key 爲 hdls
。
須要在 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」
...
複製代碼
咱們在調度、管理 Pod 時,須要熟悉 Pod 在整個生命週期的各個狀態,而設置 Pod 的重啓策略也是基於對 Pod 的各類狀態的瞭解。
Pod 的全部狀態總共有 5 種,分別以下:
Pending : APIServer 已經建立該 Pod ,但 Pod 內還有容器的鏡像沒有建立或正在下載; Running : Pod 中全部的容器均已建立,且至少有一個容器處於運行、正在啓動、正在重啓狀態; Succeeded : Pod 中全部容器已成功退出,且不會重啓; Failed : Pod 中所求容器均已退出,但至少有一個容器處於失敗狀態; Unknown : 因爲某種緣由沒法獲取該 Pod 的狀態,可能因爲網絡不順暢所致。
Pod 的重啓策略有 3 種,默認值爲 Always。
Always : 容器失效時,kubelet 自動重啓該容器; OnFailure : 容器終止運行且退出碼不爲0時重啓; Never : 不論狀態爲什麼, kubelet 都不重啓該容器。
kubelet 重啓失效容器的時間間隔以 sync-frequency 乘以 2n 來計算,最長延遲 5 分鐘,並在成功重啓後的 10 分鐘重置該時間。
Pod 的重啓策略與控制方式有關,每種控制器對 Pod 的重啓策略要求以下:
RS 和 DaemonSet:必須設置爲 Always Job:OnFailure 或 Never kubelet (靜態 Pod):Pod 失效時自動重啓,且不進行健康檢查
Pod 的健康檢查分別兩種:存活檢查和就緒檢查,分別使用 LivenessProbe 探針和 ReadinessProbe 探針。
用於判斷容器是否存活,一旦檢測到容器不健康, kubelet 即殺掉該容器,並根據重啓策略作相應處理,若是容器不包含 LivenessProbe 探針,kubelet 認爲其返回值永遠是 success。
用於判斷容器是否啓動完成,便是否 ready 狀態,一旦檢測到失敗,則 Pod 的狀態被改寫,並將該 Pod 的 Endpoint 從 Service 的轉發 Endpoint 中刪除。
ExecAction :在容器內執行一個命令,若是該命令的返回碼爲0,代表容器健康; TCPSocketAction :經過容器的 IP 和端口號執行 TCP 檢查,若是能創建 TCP 鏈接,代表容器健康; HTTPGetAction :經過容器的 IP 地址、端口號及路徑調用 HTTP Get 方法,若是返回碼 >=200 ,且 <400,認爲容器健康。
以上每種探測方式都須要設置的參數: initialDelaySeconds:延遲檢查的時間,單位爲s timeoutSeconds:健康檢查發送後等待響應的超時時間,單位爲s periodSeconds:執行週期
Pod 實爲 k8s 中的最小調度單元,只是容器的載體,其自己沒法完成自動調度的功能。 k8s 採用了 RS、Deployment、DaemonSet、Job 等方式實現 Pod 的調度和自動控制。
RS 的主要功能之一就是自動部署一個容器應用的多份副本,及持續監控副本的數量。而 RS/RC 在 k8s 中通常不多單獨使用,都是在 Deployment 中使用,而 Deployment 是 k8s 引入的一個更好解決 Pod 編排問題的概念,經過 Deployment 咱們能夠隨時知道 Pod 的調度狀況。
在 Pod 的定義中,能夠採用 NodeSelector 或 NodeAffinity 兩種方式進行調度。
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 意爲 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 是 Kubernetes 1.2 版本中新增的一種資源對象,用於確保所有(或指定的某些)Node 上運行一個 Pod 副本。其 Pod 調度策略與 RC 相似。
使用場景:
Job 是 Kubernetes 1.2 版本中新增的支持批處理的資源對象。批處理任務一般並行或串行啓動多個計算進程去處理一批工做項(work item),處理完後整個 Job 結束。
考慮到批處理的並行問題,Job 被分爲如下幾種類型:
在實際生產系統中,服務擴容是個不容忽視的場景。在 k8s 中,有兩種方式來實現 Pod 的擴容和縮容,分別爲 RC 的 Scale 機制和 HPA (Horizontal Pod Autoscaler)。
經過 kebectl
命令可設置 Pod 的副本數:
kubectl scale rc <rc-name> --replicas=3
複製代碼
經過 --replicas=<num>
參數將 Pod 的副本數手動調高,便可完成 Pod 的擴容;相應的,將該參數設置爲較低的數,系統將 kill 掉一些運行中的 Pod ,以實現應用集羣縮容。
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
命令一鍵完成。整個過程爲:
須要注意的是,新舊 RC 必須在同一 namespace 下。
若採用 yaml 配置文件來實現滾動升級,須要先手動建立一個新的 RC yaml,且 yaml 文件中須要注意的是:
再運行 kubectl
命令完成滾動升級:
kubectl rolling-update <RC-name> -f <new-RC-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 版本的回滾。