k8s——Kubernetes調度之pod調度粘性

kubernetes調度之pod調度粘性

一:三種調度粘性

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>

二:污點(Taints)與容忍(tolerations)

對於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: #添加容忍策略

  • key: 「key1」 #對應咱們添加節點的變量名
    operator: 「Equal」 #操做符
    value: 「value」 #容忍的值 key1=value對應
    effect: NoExecute #添加容忍的規則,這裏必須和咱們標記的五點規則相同

operator值是Exists,則value屬性能夠忽略operator值是Equal,則表示key與value之間的關係是等於operator不指定,則默認爲Equal

相關文章
相關標籤/搜索