k8s系列文章:html
Pod是k8s中最小的調度單元,包含了一個「根容器」和其它用戶業務容器。node
若是你使用過k8s的話,固然會了解pod的基本使用,可是爲了更好的應用,你須要深刻了解pod的配置、調度、升級和擴縮容等。本文將會更進一步的介紹pod。nginx
爲何須要pod?docker
pod包含一個或多個相對緊密耦合的容器,處於同一個pod中的容器共享一樣的存儲空間、IP地址和Port端口。後端
爲何k8s要設計出Pod這個概念並做爲最小調度單元呢?api
直接部署一個容器可能會更加容易,每一個容器都有不一樣的配置和功能,k8s須要對這些容器進行管理(重啓、檢測等),那麼爲了不在容器這個實體上增長更多的屬性,就產生了pod這個概念。app
而且,Pod中的多個業務容器共享Pause容器的IP,共享Pause容器掛接的Volume,這樣既簡化了密切關聯的業務容器的通訊問題,也很好的解決了它們之間的文件共享問題。ide
容器配置性能
pod能夠由一個或多個容器組合而成,也就是說, 在建立pod時能夠給一個pod配置多個container,通常狀況下,建議將應用緊耦合的容器打包爲一個pod,原則上一個容器一個進程。設計
共享Volume
同一個pod中的多個容器可以共享pod級別的存儲卷Volume,多個容器各自掛載,將一個volume掛載爲容器內部須要的目錄。
Pod通訊
k8s爲每一個pod都分配了惟一的IP地址,稱之爲pod IP,一個pod中的多個容器共享Pod IP地址,屬於同一個pod的多個應用之間相互訪問時僅經過localhost就能夠通訊。
k8s底層支持集羣內任意兩個pod之間的TCP/IP直接通訊,所以,在k8s中,一個pod中的容器能夠與另外主機上的pod裏的容器直接通訊。
容器限制
須要注意的是:pod中長時間運行的容器需保證其主程序一直在前臺運行。好比建立docker鏡像時啓動命令是經過nohup在後臺運行的:
nohup ./start.sh &
那麼kubelet建立了包含這個容器的pod以後運行完這個命令,則會根據配置發生兩種狀況:
若是沒法前臺執行,只能後端運行的話,該怎麼辦呢?
能夠藉助supervisor。
應用部署的一個最佳實踐就是將配置信息和程序進行分離,在k8s中可使用configmap實現。
詳細使用可參考:K8S configmap使用
在建立pod出錯了,一般會看到pending狀態,而你使用 kubectl get pods 時,也偶爾會看到重啓這個字段,那麼pod的生命週期和重啓策略具體是怎麼實現的呢?
一個pod的狀態信息是保存在PodStatus對象中的,phase字段用來描述pod在其生命週期中的不一樣狀態,包括:
狀態 | 說明 |
---|---|
Pending | 掛起。有一個或多個容器未被建立,能夠經過kubectl get po ** 查看緣由。 |
running | 運行中。全部容器已被建立,至少有一個是運行狀態,可經過kubectl logs -f ** 查看日誌 |
succeeded | 成功。全部容器執行成功並終止,不會再次重啓。 |
failed | 失敗。全部容器都已終止,至少有一個容器以失敗的方式終止。 |
unknown | 未知。通常是由於通訊問題沒法獲取pod的狀態 |
Pod一般使用探針來檢測容器內的應用是否正常,有兩類探針:
在Pod發生故障時對Pod進行重啓(僅在Pod所處的Node上操做),具體的方式包括:
操做方式 | 說明 |
---|---|
Always | 容器失效時,自動重啓 |
OnFailure | 容器以不爲0的狀態碼終止,自動重啓 |
Never | 不管何種狀態,都不會重啓 |
其中,Pod的重啓策略與控制方式息息相關,不一樣的控制器對pod的重啓策略要求不同:
在使用K8S時,咱們不多直接建立Pod,大多數狀況都是會經過RC、Deployment、DaemonSet、Job等控制器來實現對一組Pod副本的建立、調度和全生命週期的自動控制。
官方建議:不該該使用底層的ReplicaSet來控制Pod副本,推薦直接使用管理ReplicaSet的Deployment對象來控制Pod副本。
Deployment或RC的主要功能之一就是自動部署一個容器應用的多份副本,持續監控副本的數量,保證集羣內始終維持指定的副本數量。建立的pod徹底由系統自動完成調度,pod各自運行在哪一個節點上,徹底由master scheduler計算出一個最佳的目標節點進行分配,用戶沒法干預。
舉個例子:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 3 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.0 ports: - containerPort: 80
使用kubectl create -f **.yaml建立該Deployment。
使用kubectl get deployments,就會發現剛纔建立的deployment有三個副本。
使用kubectl get rs和kubectl get pods可查看已建立的RS和pod,使用kubectl get pod -o wide能夠查看pod的分配狀況。
在實際應用中,常常會須要將Pod調度到指定的一些Node節點上,這時候可配置NodeSelector或者NodeAffinity來進行定向調度。
NodeSelector
具體的使用:
NodeAffinity(節點親和力調度)
NodeSelector經過標籤機制,簡單的限制了Pod所在節點的方法,親和力調度機制則更好擴展了Pod的調度能力,可使用軟限制,支持In、NotIn、Exists、DoesNotExist、Gt、LT等操做符。
須要注意如下幾點:
PodAffinity(Pod親和與互斥調度)
根據節點上正在運行的Pod標籤而非節點的標籤進行判斷和調度,對節點和Pod兩個條件進行匹配。
具體的使用:
DaemonSet
用於管理在集羣的每一個Node上僅運行一份pod的副本實例。適用場景:日誌採集、性能監控等。
爲了提升資源利用率,咱們一般會採用優先級方案,即不一樣類型的負載對應不一樣的優先級,而且當發生資源不足時,系統能夠選擇釋放一些不重要的負載,保障最重要的負載以獲取足夠的資源穩定運行。
優先級搶佔調度策略的有兩個核心點:
能夠經過Job來定義並啓動一個批處理任務(並行啓動多個進程去處理一些工做項),處理完成後,整個批處理任務結束。
相似Linux Cron的定時任務Cron Job。
除此之外,你還能夠自定義調度器。
爲了保證服務的高可用,k8s提供了滾動升級功能。主要介紹下deployment。
升級
更新鏡像名的話,有如下方法進行更新:
kubectl set image
命令設置新的鏡像名kubectl edit
命令修改Deployment的配置,根據yaml的結構更新(好比:將spec.template.spec.containers[0].image從nginx:1.0改成nginx:1.1)。對於RC的滾動升級,可使用kubectl rolling-update
命令,該命令會建立一個新的RC,自動控制舊的RC中pod副本數量逐漸減小到0,新的RC中的Pod副本數量從0逐步增長到目標值。
一旦pod的定義發生了修改,則將觸發系統完成Deployment中全部pod的滾動操做,可以使用kubectl rollout status
查看滾動更新過程。
在升級過程當中,deployment可以保證服務不中斷,而且副本數量始終維持在用戶指定數量。可在Deployment定義中,經過spec.strategy指定pod的更新策略,包括:
回滾
服務穩定性或者配置錯誤等緣由會使得咱們須要進行回滾,Deployment的全部發布歷史記錄都被保留在系統中,因此回滾是很方便的。具體操做:
對於相對複雜的配置修改,爲了不頻繁大量觸發更新操做,可以使用kubectl rollout pause
命令暫停更新操做,而後進行配置修改,最後恢復deployment,一次性觸發完整的更新操做。
伴隨着資源的使用狀況,常須要對pod進行擴縮容,能夠利用Deployment/RC的Scale機制來實現,分爲手動和自動兩種模式。
手動
經過kubectl scale deployment *** --replicas 3
命令更新Pod副本數量,將--replicas設置比當前pod副本數量更小的數字的話,系統會kill一些正在運行的pod。
自動
用戶指定pod副本的數量範圍,設定依據的性能指標或者自定義業務指標,系統將自動的在這個範圍內根據性能指標變化調整pod副本數量。
k8s 1.1版本開始新增了HPA控制器,基於Master的kube-controller-manager服務啓動參數--horizontal-pod-autoscal-sync-period定義的探測週期,週期性檢測目標pod的資源性能指標。並與設定的擴容條件進行對比,進行pod副本數量的自動調整。
以上。