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
posted @ 2021-11-02 10:44  du-z  阅读(1584)  评论(0编辑  收藏  举报