NodeSelector(定向調度)
NodeAffinity(Node親和性)
PodAffinity(Pod親和性)node
一般狀況下,使用的都是k8s默認的調度調度方式,可是在有些狀況下,咱們須要將pod運行在具備特色的標籤的node上才能都運行,這個時候,pod的調度策略就不能使用k8s默認的調度策略了,這個時候,就須要指定調度策略,告訴k8s須要將pod調度到那些node(節點)上。nginx
1.nodeSelector數據庫
常規狀況下,會直接使用nodeSelector這種調度策略。labels(標籤) 是k8s裏面用來編標記資源的一種經常使用的方式,咱們能夠給node標記特殊的標籤,而後nodeSelector會將pod調度到帶有指定labels的node上的。
提供簡單的pod部署限制,pod選擇一個或多個node的label部署
給node添加labelapi
kubectl label nodes <node-name> <label-key>=<label-value>
爲pod添加nodeSelector機制bash
apiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: disktype: ssd
部署podapp
[root@master ~]# kubectl create -f test.yaml pod/nginx created
查看結果frontend
[root@master ~]# kubectl get pod -A -o wide NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES default nginx 0/1 ContainerCreating 0 37s <none> node-1 <none>
從上面的執行結果能夠看出,pod 經過默認的 default-scheduler 調度器到了node-1節點上。不過,這種調度方式屬於強制性的。若是node02上的資源不足,那麼pod的狀態將會一直是pending狀態。這就是nodeselector的用法了。ide
2.親和性和反親和性調度
k8s的默認調度流程其實是通過了兩個階段predicates,priorities 。使用默認的調度流程的話,k8s會將pod調度到資源充裕的節點上,使用nodeselector的調度方法,又會將pod調度具備指定標籤的pod上。而後在實際生產環境中,咱們須要將pod調度到具備些label的一組node才能知足實際需求,這個時候就須要nodeAffinity、podAffinity以及 podAntiAffinity(pod 反親和性)。ui
親和性能夠分爲具體能夠細分爲硬和軟兩種親和性
軟親和性:若是調度的時候,沒有知足要求,也能夠繼續調度,即能知足最好,不能也無所謂
硬親和性:是指調度的時候必須知足特定的要求,若是不知足,那麼pod將不會被調度到當前nodespa
requiredDuringSchedulingIgnoredDuringExecution #硬性強制
preferredDuringSchedulingIgnoredDuringExecution #軟性配置
3.nodeAffinity 節點親和性
節點親和性主要是用來控制 pod 能部署在哪些節點上,以及不能部署在哪些節點上的。它能夠進行一些簡單的邏輯組合了,不僅是簡單的相等匹配。
preferredDuringSchedulingIgnoredDuringExecution
強調優先知足制定規則,調度器會嘗試調度pod到Node上,但並不強求,至關於軟限制。多個優先級規則還能夠設置權重值,以定義執行的前後順序。
接下來看一個示例,使用nodeAffinity控制 pod 的調度,以下例子
apiVersion: v1 kind: Pod metadata: name: with-node-affinity spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: beta.kubernetes.io/arch operator: In values: - amd64 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: disk-type operator: In values: - ssd containers: - name: with-node-affinity image: nginx
設置label
[root@master ~]# kubectl label nodes node-2 disk-type=ssd node/node-2 labeled
建立pod並查看運行結果
[root@master yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES with-node-affinity 0/1 ContainerCreating 0 4m <none> node-2 <none> <none>
NodeAffinity規則設置的注意事項以下:
若是同時定義了nodeSelector和nodeAffinity,name必須兩個條件都獲得知足,pod才能最終運行在指定的node上。
若是nodeAffinity指定了多個nodeSelectorTerms,那麼其中一個可以匹配成功便可。
若是在nodeSelectorTerms中有多個matchExpressions,則一個節點必須知足全部matchExpressions才能運行該pod。
matchExpressions : 匹配表達式,這個標籤能夠指定一段,例如pod中定義的key爲zone,operator爲In(包含那些),values爲 foo和bar。就是在node節點中包含foo和bar的標籤中調度
如今kubernetes提供的操做符有下面的幾種
In:label 的值在某個標籤中
NotIn:label 的值不在某個標籤中
Gt:label 的值大於某個值
Lt:label 的值小於某個值
Exists:某個 label 存在
DoesNotExist:某個 label 不存在
4.podAffinity pod親和性
Pod的親和性主要用來解決pod能夠和哪些pod部署在同一個集羣裏面,即拓撲域(由node組成的集羣)裏面;而pod的反親和性是爲了解決pod不能和哪些pod部署在一塊兒的問題,兩者都是爲了解決pod之間部署問題。須要注意的是,Pod 間親和與反親和須要大量的處理,這可能會顯著減慢大規模集羣中的調度,不建議在具備幾百個節點的集羣中使用,並且Pod 反親和須要對節點進行一致的標記,即集羣中的每一個節點必須具備適當的標籤可以匹配topologyKey。若是某些或全部節點缺乏指定的topologyKey標籤,可能會致使意外行爲。
Pod親和性場景,咱們的k8s集羣的節點分佈在不一樣的區域或者不一樣的機房,當服務A和服務B要求部署在同一個區域或者同一機房的時候,咱們就須要親和性調度了。
labelSelector : 選擇跟那組Pod親和
namespaces : 選擇哪一個命名空間
topologyKey : 指定節點上的哪一個鍵
pod親和性調度須要各個相關的pod對象運行於"同一位置", 而反親和性調度則要求他們不能運行於"同一位置";
這裏指定「同一位置」 是經過 topologyKey 來定義的,topologyKey 對應的值是 node 上的一個標籤名稱,好比各別節點zone=A標籤,各別節點有zone=B標籤,pod affinity topologyKey定義爲zone,那麼調度pod的時候就會圍繞着A拓撲,B拓撲來調度,而相同拓撲下的node就爲「同一位置」。
若是基於各個節點kubernetes.io/hostname標籤做爲評判標準,那麼很明顯「同一位置」意味着同一節點,不一樣節點既爲不一樣位置。
pod親和性
apiVersion: v1 kind: Pod metadata: name: pod-first labels: app: myapp tier: frontend spec: containers: - name: myapp image: daocloud.io/library/nginx:latest --- apiVersion: v1 kind: Pod metadata: name: pod-second labels: app: db tier: db spec: containers: - name: busybox image: daocloud.io/library/busybox imagePullPolicy: IfNotPresent command: ["sh","-c","sleep 3600"] affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - {key: app, operator: In, values: ["myapp"]} topologyKey: kubernetes.io/hostname
查看結果
[root@master yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-first 1/1 Running 0 10m 10.244.1.6 node-1 <none> <none> pod-second 1/1 Running 0 10m 10.244.1.7 node-1 <none> <none>
pod反親和性
Pod反親和性場景,當應用服務A和數據庫服務B要求儘可能不要在同一臺節點上的時候。
apiVersion: v1 kind: Pod metadata: name: pod-first-1 labels: app: myapp tier: frontend spec: containers: - name: myapp image: daocloud.io/library/nginx:latest --- apiVersion: v1 kind: Pod metadata: name: pod-second-2 labels: app: backend tier: db spec: containers: - name: busybox image: daocloud.io/library/busybox:latest imagePullPolicy: IfNotPresent command: ["sh","-c","sleep 3600"] affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - {key: app, operator: In, values: ["myapp"]} topologyKey: kubernetes.io/hostname
查看結果
[root@master yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-first-1 1/1 Running 0 7m28s 10.244.1.8 node-1 <none> <none> pod-second-2 1/1 Running 0 7m28s 10.244.2.6 node-2 <none> <none>
對於nodeAffinity不管是硬策略仍是軟策略方式,都是調度 POD 到預期節點上,而Taints剛好與之相反,若是一個節點標記爲 Taints ,除非 POD 也被標識爲能夠容忍污點節點,不然該 Taints 節點不會被調度pod。
好比用戶但願把 Master 節點保留給 Kubernetes 系統組件使用,或者把一組具備特殊資源預留給某些 POD,則污點就頗有用了,POD 不會再被調度到 taint 標記過的節點。
將節點設置爲污點
[root@master yaml]# kubectl taint node node-2 key=value:NoSchedule node/node-2 tainted
查看污點
[root@master yaml]# kubectl describe node node-1 | grep Taint Taints: <none>
去除節點污點
[root@master yaml]# kubectl taint node node-2 key=value:NoSchedule- node/node-2 untainted
污點分類
NoSchedule:新的不能容忍的pod不能再調度過來,可是以前運行在node節點中的Pod不受影響
NoExecute:新的不能容忍的pod不能調度過來,老的pod也會被驅逐
PreferNoScheduler:表示儘可能不調度到污點節點中去
使用
若是仍然但願某個 POD 調度到 taint 節點上,則必須在 Spec 中作出Toleration定義,才能調度到該節點,舉例以下:
[root@master yaml]# kubectl taint node node-2 key=value:NoSchedule node/node-2 tainted [root@master yaml]# cat b.yaml apiVersion: v1 kind: Pod metadata: name: sss spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: app operator: In values: - myapp containers: - name: with-node-affinity image: daocloud.io/library/nginx:latest 注意:node-2節點設置爲污點,因此label定義到node-2,可是由於有污點因此調度失敗,如下是新的yaml文件 [root@master yaml]# cat b.yaml apiVersion: v1 kind: Pod metadata: name: sss-1 spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: app operator: In values: - myapp containers: - name: with-node-affinity image: daocloud.io/library/nginx:latest tolerations: - key: "key" operator: "Equal" value: "value" effect: "NoSchedule"
結果
舊的調度失敗,新的調度成功
[root@master yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES sss 0/1 Pending 0 3m2s <none> <none> <none> <none> sss-1 1/1 Running 0 7s 10.244.2.9 node-2 <none> <none>
注意
tolerations: #添加容忍策略
operator值是Exists,則value屬性能夠忽略operator值是Equal,則表示key與value之間的關係是等於operator不指定,則默認爲Equal