kubernetes 親和性調度詳解


概述:

默認情況下創建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的方式的去實現。

nodeaffinitynodeSelecotr非常類似,都是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的podaffinitypodAntiAffinity

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"


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM