文章目錄
概述:
默認情況下創建pod調度是根據kubernetes scheduler默認的調度規則去進行調度的,但有些時候,有些應用有一些特殊的需求比如指定部署到對應的節點、多個pod之間需要部署在不同一個節點,需要互斥、pod和pod間相互交流比較頻繁需要跑在同一個節點,需要親和。這時就需要靈活配置scheduler來實現了。
場景一:調度到一組具有相同特性的主機上(label+nodeSelector)
比如在整個kubernetes集群內,有一組配置比較好的服務器,然后有一些特殊的應用需要對硬件配置有需求,需要被調度到這些服務器上,這時可以通過kubernetes的label+nodeSelector去實現,實際上在kubernetes里面label是一個非常靈活的概念,kubernetes內不同資源對象之間的關聯就是通過label的方式去進行的。
例
我們給那些配置高的節點打上個label
給高配置的host打上一個label Configuration=hight(這里以rke-node2為例)
kubectl label node rke-node2 Configuration=hight
在show labels可以看見我們剛剛打上去的label
創建pod使用nodeSelector調度到指定label的節點上
mysql-deployment.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: mysql-2
spec: selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - image: mysql:5.6 name: mysql env: - name: MYSQL_ROOT_PASSWORD value: password ports: - containerPort: 3306 name: mysql nodeSelector: Configuration: hight
配置nodeSelector調度到Configuration:hight的host上
創建deployment
kubectl apply -f mysql-deployment.yaml
查看pod被調度到label為 Configuration: hight的host上了
場景二:部署的應用不想調度到某些節點上(nodeaffinity)
比如在一個kubernetes集群內,需要將應用部署到指定標簽的機器上,但如果沒有的話這類機器的話,就按正常調度規則進行調度。這時通過nodeSelector就無法實現這個需求了,在kubernetes內可以通過nodeaffinity的方式的去實現。
nodeaffinity
和nodeSelecotr
非常類似,都是node層面的調度策略的配置,但區別是nodeSelect功能比較單一,只能根據label選擇對應的主機,而nodeaffinity
更加靈活,nodeaffinity
有兩種調度類型requiredDuringSchedulingIgnoredDuringExecution
(硬要求)和preferredDuringSchedulingIgnoredDuringExecution
(軟要求),兩種類型區別在於,硬要求要求調度時必須滿足設置的調度規則,否則拋異常調度失敗,而軟要求,只是調度時優先考慮設置的調度規則,當達不到設置的規則時,則按kube-scheduler默認的調度策略進行調度。nodeaffinity
還支持多種規則匹配條件的配置如
In:label
的值在列表內
NotIn:label
的值不在列表內
Gt:label
的值大於設置的值
Lt:label
的值小於設置的值
Exists:
設置的label 存在
DoesNotExist:
設置的 label 不存在
例
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: mysql-2
spec:
selector:
matchLabels:
app: mysql
template: metadata: labels: app: mysql spec: containers: - image: mysql:5.6 name: mysql env: - name: MYSQL_ROOT_PASSWORD value: password ports: - containerPort: 3306 name: mysql affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: NotIn values: - rke-node3 - rke-node4 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: disk_type operator: In values: - ssd
如上所例,要求pod不能被調度到rke-node3和rke-node4上,但如果有滿足dis_type=ssd
的label的節點則優先選擇。
如果在 nodeAffinity
類型中指定了多個 nodeSelectorTerms
,那么 pod 將會被調度到只要滿足其中一個 nodeSelectorTerms
的 node 上。
如果在 nodeSelectorTerms
中指定了多個 matchExpressions
,那么 pod 將會被調度到 滿足所有 matchExpressions
的 node 上。
場景三:部署的應用關聯性很強,需要盡量在一個節點上
比如在kubernetes集群,有些pod和pod之間的交互很頻繁,這時就需要將它們盡可能的調度到一台主機上,通過pod與pod之間的關系來選擇調度,這時候我們就可以使用podaffinity
。根nodeaffinity
一樣,podaffinity
也有兩種調度類型requiredDuringSchedulingIgnoredDuringExecution
(硬要求)和preferredDuringSchedulingIgnoredDuringExecution
(軟要求),多種規則匹配條件配置。
例 部署一個nginx和mysql因為nginx和mysql之間的交互很頻繁,所以盡量將他們部署在一個host上。
先啟動一個nginx。
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec: containers: - name: nginx image: nginx
啟動mysql
apiVersion: v1
kind: Pod
metadata:
name: mysql
labels:
app: mysql
spec:
containers:
- name: mysql
image: nginx
env:
- name: "MYSQL_ROOT_PASSWORD"
value: "123456" affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - nginx topologyKey: kubernetes.io/hostname
topologyKey
可以設置成如下幾種類型
kubernetes.io/hostname
#Node
failure-domain.beta.kubernetes.io/zone
#Zone
failure-domain.beta.kubernetes.io/region
#Region
可以設置node上的label的值來表示node的name,zone,region
等信息,pod的規則中指定topologykey
的值表示指定topology
范圍內的node上運行的pod滿足指定規則
這里我們配置podaffinity
,mysql會調度到有app:nginx這個label的pod的host上,所以你部署出來的mysql會調度到有nginx的pod上,因為默認部署出來的nginx就自帶app:nginx這個label。
場景四:部署應用需要互斥,不能同時運行在一台主機上,會沖突
我們繼續以我們剛剛的nginx+mysql這個應用組合為例,現在我們修改mysql的podaffinity
為podAntiAffinity
apiVersion: v1
kind: Pod
metadata:
name: mysql
labels:
app: mysql
spec:
containers:
- name: mysql
image: nginx
env:
- name: "MYSQL_ROOT_PASSWORD"
value: "123456" affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - nginx topologyKey: kubernetes.io/hostname
將podaffinity
改為podAntiAffinity
這樣調度mysql這個pod時會避開有label為app:nginx的pod的主機
高級特性Taints and tolerations
Taints其實根nodeaffinity正好相反,nodeaffinity是將設置策略的pod調度到期望的節點上,而taints正好相反,如果一個節點被標記為taints,除非pod配置了tolerations,否則是不會被允許調度過來在生產環境中我們一般會將master節點配置Taints,因為master只跑kubernetes 系統組件,如果跑了用戶應用pod容易把資源耗盡,造成master節點崩潰,當然后期如果要添加額外的系統組件,這時就可以通過給對應的pod配置toleration。
設置rke-node2不能被調度
kubectl taint nodes rke-node2 key=value:NoSchedule
value
可以配置多個值如
NoSchedule
:不能調度,當之前調度的不管。
PreferNoSchedule
:盡量不調度上去,其實就是Noschedule軟策略版。
NoExecute
:不能調度,但之前已經調度上去的也會自動遷移走。
NoSchedule
更像執行kubectl cordon xxx
NoExecute
更想執行kubectl cordon xxx+kubectl drain
取消taints
kubectl taint nodes rke-node2 key-
如何讓pod調度到配置了taints主機上?
通過配置tolerations,可以讓pod調度到配置了taints的機器上
如
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: mysql-2
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:5.6 name: mysql env: - name: MYSQL_ROOT_PASSWORD value: password ports: - containerPort: 3306 name: mysql tolerations: - key: "key" operator: "Equal" value: "value" effect: "NoSchedule"