Kubernetes之Pod排程
Kubernetes排程器根據特定的演算法與策略將pod排程到工作節點上。在預設情況下,Kubernetes排程器可以滿足絕大多數需求,例如排程pod到資源充足的節點上執行,或排程pod分散到不同節點使叢集節點資源均衡等。但一些特殊的場景,預設排程演算法策略並不能滿足實際需求,例如使用者期望按需將某些pod排程到特定硬體節點(資料庫服務部署到SSD硬碟機器、CPU/記憶體密集型服務部署到高配CPU/記憶體伺服器),或就近部署互動頻繁的pod(例如同一機器、同一機房、或同一網段等)。
Kubernetes中的排程策略主要分為全域性排程與執行時排程2種。其中全域性排程策略在排程器啟動時配置,而執行時排程策略主要包括選擇節點(nodeSelector),節點親和性(nodeAffinity),pod親和與反親和性(podAffinity與podAntiAffinity)。Node Affinity、podAffinity/AntiAffinity以及後文即將介紹的汙點(Taints)與容忍(tolerations)等特性,在Kuberntes1.6中均處於Beta階段。
本文著重介紹執行時排程策略。
設定節點label
Label是Kubernetes核心概念之一,其以key/value的形式附加到各種物件上,如Pod、Service、Deployment、Node等,達到識別這些物件,管理關聯關係等目的,如Node和Pod的關聯。
獲取當前叢集中的全部節點:
kubectl get nodes
為指定節點設定label:
kubectl label nodes <node-name> <label-key>=<label-value>
確認節點label是否設定成功:
kubectl get nodes -l ‘label_key=label_value’
選擇節點(nodeSelector)
nodeSelector是目前最為簡單的一種pod執行時排程限制,目前在Kubernetes1.7.x及以下版本可用。Pod.spec.nodeSelector通過kubernetes的label-selector機制選擇節點,由排程器排程策略匹配label,而後排程pod到目標節點,該匹配規則屬於強制約束。後文要講的nodeAffinity具備nodeSelector的全部功能,所以未來Kubernetes會將nodeSelector廢除。
nodeSelector舉例:
設定label
$ kubectl label nodes bjo-rpt-re-002.dev.fwmrm.net disktype=ssd node "bjo-rpt-re-002.dev.fwmrm.net" labeled
檢視滿足非master節點且disktype型別為ssd的節點:
kubectl get nodes -l `role!=master, disktype=ssd` NAME STATUS AGE VERSION bjo-rpt-re-002.dev.fwmrm.net Ready 39d v1.7.1
pod.yaml檔案內容:
apiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: disktype: ssd
建立pod:
kubectl create -f pod.yaml
檢視pod nginx被排程到預期節點執行:
$ kubectl get po nginx -o wide NAME READY STATUS RESTARTS AGE IP NODE nginx 1/1 Running 0 10s 10.244.3.13 bjo-rpt-re-002.dev.fwmrm.net
注:如果非預設namespace,需要指定具體namespace,例如:
kubectl -n kube-system get pods -o wide
內建節點label
Kubernetes自v1.4開始,節點有一些built-in label,羅列如下:
- kubernetes.io/hostname
- failure-domain.beta.kubernetes.io/zone
- failure-domain.beta.kubernetes.io/region
- beta.kubernetes.io/instance-type
- beta.kubernetes.io/os
- beta.kubernetes.io/arch
built-in label舉例
yaml檔案內容:
apiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: kubernetes.io/hostname: bjo-ep-svc-017.dev.fwmrm.net
建立pod,並檢查結果符合預期,pod被排程在預先設定的節點 bjo-ep-svc-017.dev.fwmrm.net:
$ kubectl get po nginx -o wide NAME READY STATUS RESTARTS AGE IP NODE nginx 1/1 Running 0 3m 10.244.1.58 bjo-ep-svc-017.dev.fwmrm.net
親和性(Affinity)與非親和性(anti-affinity)
前面提及的nodeSelector,其僅以一種非常簡單的方式、即label強制限制pod排程到指定節點。而親和性(Affinity)與非親和性(anti-affinity)則更加靈活的指定pod排程到預期節點上,相比nodeSelector,Affinity與anti-affinity優勢體現在:
- 表述語法更加多樣化,不再僅受限於強制約束與匹配。
- 排程規則不再是強制約束(hard),取而代之的是軟限(soft)或偏好(preference)。
- 指定pod可以和哪些pod部署在同一個/不同拓撲結構下。
親和性主要分為3種型別:node affinity與inter-pod affinity/anti-affinity,下文會進行詳細說明。
節點親和性(Node affinity)
Node affinity在Kubernetes 1.2做為alpha引入,其涵蓋了nodeSelector功能,主要分為requiredDuringSchedulingIgnoredDuringExecution與preferredDuringSchedulingIgnoredDuringExecution 2種型別。前者可認為一種強制限制,如果 Node 的標籤發生了變化導致其沒有符合 Pod 的排程要求節點,那麼pod排程就會失敗。而後者可認為理解為軟限或偏好,同樣如果 Node 的標籤發生了變化導致其不再符合 pod 的排程要求,pod 依然會排程執行。
Node affinity舉例
設定節點label:
$ kubectl label nodes bjo-ep-dep-040.dev.fwmrm.net cpu=high node "bjo-ep-dep-040.dev.fwmrm.net" labeled $ kubectl label nodes bjo-ep-svc-017.dev.fwmrm.net cpu=mid node "bjo-ep-svc-017.dev.fwmrm.net" labeled $ kubectl label nodes bjo-rpt-re-002.dev.fwmrm.net cpu=low node "bjo-rpt-re-002.dev.fwmrm.net" labeled
部署pod的預期是到非master節點(role!=master)、且CPU高配的機器上(cpu=high)。
檢視滿足條件節點:
$ kubectl get nodes -l `cpu=high, role!=master` NAME STATUS AGE VERSION bjo-ep-dep-040.dev.fwmrm.net Ready 41d v1.7.1
pod.yaml檔案內容如下:
apiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: role operator: NotIn values: - master preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: cpu operator: In values: - high containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent
檢查結果符合預期,pod nginx成功部署到非master節點且CPU高配的機器上。
$ kubectl get po nginx -o wide NAME READY STATUS RESTARTS AGE IP NODE nginx 1/1 Running 0 32s 10.244.2.185 bjo-ep-dep-040.dev.fwmrm.net
pod親和性(Inter-pod affinity)與反親和性(anti-affinity)
inter-pod affinity與anti-affinity由Kubernetes 1.4引入,當前處於beta階段,其中podAffinity用於排程pod可以和哪些pod部署在同一拓撲結構之下。而podAntiAffinity相反,其用於規定pod不可以和哪些pod部署在同一拓撲結構下。通過pod affinity與anti-affinity來解決pod和pod之間的關係。
與Node affinity類似,pod affinity與anti-affinity同樣分為requiredDuringSchedulingIgnoredDuringExecution and preferredDuringSchedulingIgnoredDuringExecution等2種型別,前者被認為是強制約束,而後者後者可認為理解軟限(soft)或偏好(preference)。
pod affinity與anti-affinity舉例
本示例中假設部署場景為:期望is服務與oltp服務就近部署,而不希望與solr服務部署同一拓撲結構上。
yaml檔案部分內容:
spec: replicas: 1 template: metadata: labels: app: is spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: NotIn values: - solr topologyKey: kubernetes.io/hostname podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - oltp topologyKey: beta.kubernetes.io/os
檢視部署結果,is服務與oltp部署到了同一臺機器,而solr被部署在其他機器上。
$ kubectl get po -o wide NAME READY STATUS RESTARTS AGE IP NODE is-3059482752-5s14t 0/1 Running 1 1m 10.244.1.60 bjo-ep-svc-017.dev.fwmrm.net oltp-282283610-kdvnp 1/1 Running 0 1m 10.244.1.53 bjo-ep-svc-017.dev.fwmrm.net solr-908150957-rswlm 1/1 Running 0 1m 10.244.3.5 bjo-rpt-re-002.dev.fwmrm.net
親和性/反親和性排程策略比較
排程策略 匹配標籤 操作符 拓撲域支援 排程目標 nodeAffinity 主機 In, NotIn, Exists, 否 pod到指定主機 DoesNotExist, Gt, Lt podAffinity Pod In, NotIn, Exists, 是 pod與指定pod同一拓撲域 DoesNotExist PodAntiAffinity Pod In, NotIn, Exists, 是 pod與指定pod非同一拓撲域 DoesNotExist
汙點(Taints)與容忍(tolerations)
對於Node affinity,無論是強制約束(hard)或偏好(preference)方式,都是排程pod到預期節點上,而Taints恰好與之相反,如果一個節點標記為 Taints ,除非 Pod也被標識為可以耐受汙點節點,否則該Taints節點不會被排程pod。Taints)與tolerations當前處於beta階段,
Taints節點應用場景比如使用者希望把Kubernetes Master節點保留給 Kubernetes 系統元件使用,或者把一組具有特殊資源預留給某些 pod。pod不會再被排程到taint標記過的節點。
taint標記節點舉例如下:
$ kubectl taint nodes bjo-ep-dep-039.dev.fwmrm.net key=value:NoSchedule node "bjo-ep-dep-039.dev.fwmrm.net" tainted
如果仍然希望某個pod排程到taint節點上,則必須在 Spec 中做出Toleration 定義,才能排程到該節點,舉例如下:
tolerations: - key: "key" operator: "Equal" value: "value" effect: "NoSchedule"
effect 共有三個可選項,可按實際需求進行設定:
- NoSchedule:pod不會被排程到標記為taints節點。
- PreferNoSchedule:NoSchedule的“preference”或“soft”版本。
- NoExecute:該選項意味著一旦Taint 生效,如該節點內正在執行的 Pod 沒有對應 Tolerate 設定,會直接被逐出。
總結
使用者可根據實際需求,充分利用pod的相關高階排程策略,使Kubernetes更好的服務於我們的需求。
本文轉自中文社群-Kubernetes之Pod排程
相關文章
- kubernetes實踐之三十八:Pod排程
- k8s之pod排程K8S
- Kubernetes Pod排程:從基礎到高階實戰技巧
- kubernetes 排程
- Pod的排程機制
- Pod的排程是由排程器(kube-scheduler)
- Kubernetes的Pod排程:讓你的應用像乘坐頭等艙!
- 當一個 Pod 被排程時,Kubernetes 內部發生了什麼?
- Kubernetes 排程器
- kubernetes之pod中斷
- Kubernetes之Pod工作負載負載
- kubernetes負載感知排程負載
- Kubernetes資源編排系列之一: Pod YAML篇YAML
- 改造 Kubernetes 自定義排程器
- Kubernetes排程流程與安全(七)
- Kubernetes 排程器實現初探
- kubernetes雜談之(二)Pod初談
- kubernetes高階之pod安全策略
- kubernetes排程概念與工作流程
- Kubernetes原始碼分析之Pod的刪除原始碼
- 進擊的 Kubernetes 排程系統(一):Kubernetes scheduling frameworkFramework
- D8 kubernetes 之pod映象拉取策略
- Kubernetes-15:一文詳解Pod、Node排程規則(親和性、汙點、容忍、固定節點)
- Go語言排程器之排程main goroutine(14)GoAI
- K8S原來如此簡單(六)Pod排程K8S
- Kubernetes 資源拓撲感知排程優化優化
- kubernetes叢集內排程與負載均衡負載
- Kubernetes叢集排程器原理剖析及思考
- 傲視Kubernetes(三):Kubernetes中的Pod
- Kubernetes部署單元-Pod
- Kubernetes Pod 全面知識
- Kubernetes:Pod總結(二)
- Kubernetes Pod驅逐策略
- newsql新品TiDB之排程SQLTiDB
- 在K8S中,Pod常見排程方式有哪些?K8S
- Kubernetes 資源拓撲感知排程最佳化
- Kubernetes高階排程- Taint和Toleration、Node Affinity分析AI
- Flink排程之排程器、排程策略、排程模式模式