# 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階段。
node 添加標簽
kubectl label nodes 172.16.200.101 disktype=ssd
查看node 節點標簽(label)
kubectl get node --show-labels
刪除一個label
kubectl label node 172.16.200.101 disktype-
修改一個label
# kubectl label node 172.16.200.101 disktype=scsi --overwrite
### 選擇節點(nodeselector)
apiVersion: v1
kind: ReplicationController
metadata:
name: redis-master
labels:
name: redis-master
spec:
replicas: 1
selector:
name: redis-master
template:
metadata:
labels:
name: redis-master
spec:
containers:
- name: master
image: kubeguide/redis-master
ports:
- containerPort: 6379
nodeSelector:
disktype: ssd
## 親和性(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 node 172.16.200.100 cpu=high
kubectl label node 172.16.200.101 cpu=mid
kubectl label node 172.16.200.102 cpu=low
部署pod的預期是到CPU高配的機器上(cpu=high)。
查看滿足條件節點:
kubectl get nodes -l 'cpu=high'
redis-master.yaml 文件內容如下
apiVersion: v1
kind: ReplicationController
metadata:
name: redis-master
labels:
name: redis-master
spec:
replicas: 1
selector:
name: redis-master
template:
metadata:
labels:
name: redis-master
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: cpu
operator: In
values:
- high
containers:
- name: master
image: kubeguide/redis-master
ports:
- containerPort: 6379
檢查結果符合預期,pod nginx成功部署到非master節點且CPU高配的機器上。
# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
redis-master-lbz9f 1/1 Running 0 11s 10.24.77.4 172.16.200.100
### 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舉例
本示例中假設部署場景為:期望redis-slave服務與redis-master服務就近部署,而不希望與frontend服務部署同一拓撲結構上。
redis-slave yaml文件部分內容:
apiVersion: v1
kind: ReplicationController
metadata:
name: redis-slave
spec:
replicas: 2
selector:
name: redis-slave
template:
metadata:
name: redis-slave
labels:
name: redis-slave
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: name
operator: In
values:
- redis-master
topologyKey: kubernetes.io/hostname
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: name
operator: In
values:
- frontend
topologyKey: beta.kubernetes.io/os
containers:
- name: redis-slave
image: kubeguide/guestbook-redis-slave
env:
- name: GET_HOSTS_FROM
value: env
ports:
- containerPort: 6379
查看部署結果,redis-slave服務與redis-master部署到了同一臺機器,而frontend被部署在其他機器上。
# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
frontend-4nmkz 1/1 Running 0 4m 10.24.51.5 172.16.200.101
frontend-xmjsr 1/1 Running 0 4m 10.24.77.5 172.16.200.100
redis-master-lbz9f 1/1 Running 0 41m 10.24.77.4 172.16.200.100
redis-slave-t9tw4 1/1 Running 3 1m 10.24.77.7 172.16.200.100
redis-slave-zvcrg 1/1 Running 3 1m 10.24.77.6 172.16.200.100
### 親和性/反親和性調度策略比較
調度策略 | 匹配標簽 | 操作符 | 拓撲域支持 | 調度目標
---|---|---|---|---
nodeAffinity | 主機|In, NotIn, Exists, DoesNotExist, Gt, Lt | 否| pod到指定主機
podAffinity |Pod |In, NotIn, Exists, DoesNotExist| 是 | pod與指定pod同一拓撲域
PodAntiAffinity|Pod| In, NotIn, Exists, DoesNotExist |是|pod與指定pod非同一拓撲域
- 第一章 kubernetes 功能介紹
- 第二章 在CentOS上部署kubernetes1.7.6集群
- 第三章 創建TLS證書和秘鑰
- 第四章 安裝kubectl命令行工具
- 第五章 創建kubeconfig 文件
- 第六章 etcd 集群部署
- 第七章 部署k8s-master-v1.7.6節點
- 第八章 部署k8s-v1.7.6 node 節點
- 第九章 kubectl 操作示例
- 第十章 在kubernetes 部署第一個應用
- 第十一章 kubernetes之pod 調度
- 第十二章 K8S服務組件之kube-dns&Dashboard
- 第十三章 Kubernetes中的角色訪問控制機制(RBAC)支持
- 第十四章 部署nginx ingress
- 第十五章 使用Prometheus監控Kubernetes集群和應用
- 第十六章 使用helm 應用部署工具
- 第十七章 kubernetes 從1.7 到1.8升級記錄
- 第十八章 在kubernetes 使用ceph
- 第十九章 基于 Jenkins 的 CI/CD(一)
- 第二十章 基于jenkins的CI/CD(二)
- 第二十一章 基于prometheus自定指標HPA彈性伸縮