k8s---pod的調度親和性和污點容忍、指定調度節點(nodeSelector)


在k8s集群建設過程中,一般情況下我們部署的 Pod 是通過集群的自動調度策略來選擇節點的,默認情況下調度器考慮的是資源足夠,並且負載盡量平均。但是有的時候我們需要能夠更加細粒度的去控制 Pod 的調度;有時我們希望對內和對外的兩類業務分別跑在不同的節點上,相互有依賴的兩個pod跑在同一節點上,等情況;這就需要我們更好的控制pod的部署;k8s給我們提供了親和性和反親和性,污點(taint)和Toleration(容忍)等概念。


#示例

[root@k8s-master ~]# kubectl explain pod.spec.affinity
KIND:     Pod
VERSION:  v1

RESOURCE: affinity <Object>

DESCRIPTION:
     If specified, the pod's scheduling constraints

     Affinity is a group of affinity scheduling rules.

FIELDS:
   nodeAffinity <Object>----------------#node親和性
     Describes node affinity scheduling rules for the pod.

   podAffinity  <Object>----------------#pod親和性
     Describes pod affinity scheduling rules (e.g. co-locate this pod in the
     same node, zone, etc. as some other pod(s)).

   podAntiAffinity      <Object>--------#pod反親和性
     Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod
     in the same node, zone, etc. as some other pod(s)).


節點node親和性

目前主要的node affinity:

requiredDuringSchedulingIgnoredDuringExecution
表示pod必須部署到滿足條件的節點上,如果沒有滿足條件的節點,就不停重試。其中IgnoreDuringExecution表示pod部署之后運行的時候,如果節點標簽發生了變化,不再滿足pod指定的條件,pod也會繼續運行。

requiredDuringSchedulingRequiredDuringExecution
表示pod必須部署到滿足條件的節點上,如果沒有滿足條件的節點,就不停重試。其中RequiredDuringExecution表示pod部署之后運行的時候,如果節點標簽發生了變化,不再滿足pod指定的條件,則重新選擇符合要求的節點。

preferredDuringSchedulingIgnoredDuringExecution
表示優先部署到滿足條件的節點上,如果沒有滿足條件的節點,就忽略這些條件,按照正常邏輯部署。

preferredDuringSchedulingRequiredDuringExecution
表示優先部署到滿足條件的節點上,如果沒有滿足條件的節點,就忽略這些條件,按照正常邏輯部署。其中RequiredDuringExecution表示如果后面節點標簽發生了變化,滿足了條件,則重新調度到滿足條件的節點。


舉例說明

pod.spec.affinity.nodeAffinity

  • preferredDuringScheculingIgnoredDuringExecution:軟策略
  • requiredDuringSchedulingIgnoredDuringExecution:硬策略

requiredDuringSchedulingIgnoredDuringExecution:硬策略

apiVersion:v1
kind:Pod
metadata:
    name:affinity
    labels:
        app:node-affinity-pod
spec:
    containers:
    -   name:with-node-affinity
        image:nginx:v1
    affinity:
        nodeAffinity:
            requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                -   matchExpressions:
                    -   key:kubernetes.io/hostname
                        operator:NotIn
                        values:
                        -   k8s-node01

preferredDuringScheculingIgnoredDuringExecution:軟策略

apiVersion:v1
kind:Pod
metadata:
    name:affinity
    labels:
        app:node-affinity-pod
spec:
    containers:
    -   name:with-node-affinity
        image:nginx:v1
    affinity:
        nodeAffinity:
            preferredDuringScheculingIgnoredDuringExecution:
            -   weitht:1
                preference:
                    matchExpressions:
                    -   key:source
                        operator:In
                        values:
                        - hahaha

硬策略和軟策略一起用

apiVersion:v1
kind:Pod
metadata:
    name:affinity
    labels:
        app:node-affinity-pod
spec:
    containers:
    -   name:with-node-affinity
        image:nginx:v1
    affinity:
        nodeAffinity:
            requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                -   matchExpressions:
                    -   key:kubernetes.io/hostname
                        operator:NotIn
                        values:
                        -   k8s-node01
            preferredDuringScheculingIgnoredDuringExecution:
            -   weitht:1
                preference:
                    matchExpressions:
                    -   key:source
                        operator:In
                        values:
                        - hahaha

鍵值運算關系

運算符 作用
In lable的值在某個列表中
NotIn label的值不在某個列表中
Gt label的值大於某個值
Lt label的值小於某個值
Exists 某個label存在
DoesNotExist 某個label不存在

Pod親和性

podAffinity規則

pod affinity 可以這樣理解:調度的時候選擇(或者不選擇)這樣的節點 N ,這些節點上已經運行了滿足條件 X。條件 X 是一組 label 選擇器,它必須指明作用的 namespace(也可以作用於所有的 namespace),因為 pod 是運行在某個 namespace 中的。
這里的X指的是集群中的節點、機架、區域等概念,通過kubernetes內置節點標簽中的key來進行聲明。這個key的名字為topologyKey,意為表達節點所屬的topology范圍:

  • kubernetes.io/hostname
  • failure-domain.beta.kubernetes.io/zone
  • failure-domain.beta.kubernetes.io/region

要使用親和性,在 affinity 下面添加 podAffinity 字段,
要使用互斥性,在 affinity 下面添加 podAntiAffinity 字段,

requiredDuringSchedulingIgnoredDuringExecution,
preferredDuringSchedulingIgnoredDuringExecution,
requiredDuringSchedulingRequiredDuringExecution,
preferredDuringSchedulingRequiredDuringExecution,
意義和nodeAffinity一樣。

舉例說明

pod.spec.affinity.podAffinity/podAntiAffinity

  • preferredDuringSchedulingIgnoredDuringExecution: 軟策略
  • requiredDuringSchedulingIgnoredDuringExecution:硬策略
apiVersion:v1
kind:Pod
metadata:
    name:pod-3
    labels:
    app:pod-3
spec:
    containers:
    -   name:pod-3
        inamge:nginx:v1
    affinity:
        podAffinity:
            requiredDuringSchedulingIgnoredDuringExecution:
            -   labelSelector:
                    matchExpressions:
                    -   key:app
                        operator:In
                        values:
                        -   pod-1
                topologyKey:kubernetes.io/hostname

污點配合容忍度(Taint和toleration)

節點親和性,是pod的一種屬性(偏好或硬性要求),它使得pod被吸引到一類特定的節點上。Taint則相反,它使得節點能夠排斥一類特定的pod
Taint和toleration(容忍)相互配合,可以用來避免pod被分配到不合適的節點上。每個節點上都可以應用一個或多個taint,這表示這些pod可以(但不要求)被調度到具有匹配taint的節點上。

污點

污點的組成

使用kubectl taint 命令可以給節點node設置污點,node被設置污點后,可以讓node拒絕pod的調度執行,甚至可以將本node上已經運行的pod驅逐出去。
任何符合其鍵值規范要求的字符串均可用於定義污點信息:僅可使用字母、數字、連接符、點號和下划線,且僅能以字母或數字開頭,其中鍵名的長度上限為253個字符,值最長為63個字符。實踐中,污點通常用於描述具體的部署規划,它們的鍵名形如node-tppe、node-role、node-project或node-geo等,因此還可在必要時帶上域名以描述其額外的信息,如node-type.linux.io等

通過kubectl查看污點,Taints字段

kubectl describe nodes k8s-master-01

Name:               k8s-master-01
Roles:              master
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=k8s-master-01
                    kubernetes.io/os=linux
                    node-role.kubernetes.io/master=
......
Taints:             node-role.kubernetes.io/master:NoSchedule
Unschedulable:      false

每個污點有一個key和value作為污點的標簽,其中value可以為空,effect描述污點的作用。當前taint effect支持如下三種選項

effect類別 作用
NoSchedule 表示k8s不會將pod調度到具有該污點的Node上
PreferNotSchedule 表示k8s將盡量避免將pod調度到具有該污點的node上
NotExecute 表示k8s將不會將pod調度到具有該污點的node上,同時node上已經存在的pod將驅逐出去

污點的設置與去除

#設置污點
kubectl taint nodes <node-name> <key>=<value>:<effect> 

#kubectl taint nodes node02 node-type=production:NoSchedule
node "node02" tainted


#去除污點(在添加污點的命令后面加"-")
kubectl taint nodes node02 key=value:NoSchedule-

#查詢污點,通過kubectl查看節點說明中的Taints字段
kubectl describe nodes k8s-master-01


Name:               k8s-master-01
Roles:              master
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=k8s-master-01
                    kubernetes.io/os=linux
                    node-role.kubernetes.io/master=
......
Taints:             node-role.kubernetes.io/master:NoSchedule
Unschedulable:      false

容忍(Tolerations)

設置了污點的Node將根據taint的effect和pod之間產生互斥關系,pod將在一定程度上不會被調度到該Node上。但是我們可以在pod上設置容忍(Toleration),意思是設置了容忍的pod將可以容忍污點存在,可以被調度到存在污點的node上

舉例說明

pod.spec.tolerations

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoExecute"
  tolerationSeconds: 3600
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"
- key: "key1"
  operator: "Exists"
  effect: "NoSchedule"


#主要有兩種可用的形式:一種是與污點信息完全匹配的等值關系;另一種是判斷污點信息存在性的匹配方式。
#如果operator是Exists  污點存在性匹配容忍,可以忽略value值;
#如果operator是Equal,污點等值關系匹配容忍,它們的key、value、effect要與node上設置的taint一致。

#tolerationSeconds用於描述pod需要被驅逐時,可以在pod上繼續保留運行的時間

#當不指定key值時,表示容忍所有的污點key
tolerations:
-   operator:"Exists"

#當不指定effect值時,表示容忍所有的污點effect
tolerations:
-   key:"key1"
    operator:"Exists"


指定調度節點

pod.spec.nodeName將pod直接調度到指定的node節點上,會跳過scheduler的調度策略,該匹配規則時強制匹配

apiVersion:extensions/v1beta1
kind:Deployment
metadata:
    name:web
spec:
    replicas:5
    template:
        metadata:
            labels:
                app:web
        spec:
            nodeName:k8s-node01
            containers:
            -   name:web
                image:nginx:v1
                ports:
                - containerPort:80

pod.spec.nodeSelector:通過kubernetes的label-selector機制選擇節點,有調度器策略匹配label,而后調度pod到目標節點,該匹配為強制約束

apiVersion:extensions/v1beta1
kind:Deployment
metadata:
    name:web
spec:
    replicas:2
    template:
        metadata:
            labels:
                app:web
        spec:
            nodeSelector:
                node-key:node-value
            containers:
            -   name:web
                image:nginx:v1
                ports:
                - containerPort:80

使用kubectl label nodes = 為node節點添加label

[root@k8s-master ~]# kubectl label nodes k8s-master role=master
node/k8s-master labeled

使用kubectl get nodes --show-labels 查詢nodes的label

[root@k8s-master ~]# kubectl get nodes --show-labels
NAME         STATUS   ROLES                  AGE    VERSION   LABELS
k8s-master   Ready    control-plane,master   227d   v1.22.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=,role=master
k8s-node1    Ready    <none>                 227d   v1.22.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node1,kubernetes.io/os=linux
k8s-node2    Ready    <none>                 227d   v1.22.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node2,kubernetes.io/os=linux


免責聲明!

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



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