Kubernetes 应用部署调度策略 NodeSelector、NodeName 与 Affinity

Kubernetes 应用部署调度策略 NodeSelector、NodeName 与 Affinity

文章目录

  !版权声明:本博客内容均为原创,每篇博文作为知识积累,写博不易,转载请注明出处。


系统环境:

  • kubernetes 版本:1.16.4

博文简介:

       在接触 Kubernetes 中,我们会经常接触到部署应用,Kubernetes 中默认的部署方式为根据调度算法分析 Kubernetes 中资源使用情况,进行动态分配的。有时候调度应用时需要设置应用部署到特定的节点上,或者需要将应用部署多个实例,为了保持高可用需要将应用分配到不同的节点上等等,由于有这些特殊情况,就有了后面要介绍的 Kubernetes 的多种调度方式。

一、定向调度策略 NodeName 与 NodeSelector

在 Kubernetes 中有两种定向调度方式,可以通过配置 Kubernetes 对象的 nodeNameNodeSelector 两个参数,来使应用部署到特定的节点上。

1、NodeName 方式

       参数 Pod.spec.nodeName 可用于强制约束 Pod 跳过默认的 Kubernetes 调度规则,直接调度 Pod 到指定的 Node 节点上。下面是调度应用 Podk8s-node-2-12 节点的示例:

(1)、设置 Deployment 对象配置 nodeName 参数

deploy.yaml

 1apiVersion: apps/v1
 2kind: Deployment
 3metadata:
 4  name: hello
 5  labels:
 6    app: hello
 7spec:
 8  replicas: 1
 9  selector:
10    matchLabels:
11      app: hello
12  template:
13    metadata:
14      labels:
15        app: hello
16    spec:
17      containers:
18      - name: hello
19        image: tutum/hello-world:latest
20        ports:
21        - containerPort: 80
22      nodeName: k8s-node-2-12   #指定调度节点为 k8s-node-2-12

(2)、执行部署应用

1$ kubectl create -f deploy.yaml

(3)、查看启动的应用所在节点

1$ kubectl get pods -o wide
2
3NAME                     READY   STATUS    RESTARTS   AGE   IP               NODE            
4hello-768b645b56-wgqp7   1/1     Running     0        17s   10.244.134.228 k8s-node-2-12

2、NodeSelector 方式

       参数 spec.selector.matchLabels 可以设置应用启动到带有指定 Label 的节点上。如果该参数指定有多个标签,那么需要存在带有多个 Label 标签的节点 Pod 才能够被调度,否则被标记为无法调度状态。下面介绍下如何设置应用 Pod 调度到带有 deploy=yes 标签的节点上,可以按如下配置:

(1)、设置节点添加对应 Label 标签

对节点设置 Label 标签:

  • 格式: kubectl label nodes <Node名称> <标签Key>=<标签Value>
1$ kubectl label nodes k8s-node-2-12 deploy=hello

查看节点的 Label 标签:

1$ kubectl get nodes --show-labels 

(2)、设置 Deployment 对象配置 nodeSelector 参数

deploy.yaml

 1apiVersion: apps/v1
 2kind: Deployment
 3metadata:
 4  name: hello
 5  labels:
 6    app: hello
 7spec:
 8  replicas: 1
 9  selector:
10    matchLabels:
11      app: hello
12  template:
13    metadata:
14      labels:
15        app: hello
16    spec:
17      containers:
18      - name: hello
19        image: tutum/hello-world:latest
20        ports:
21        - containerPort: 80
22      nodeSelector:
23        deploy: hello     #调度到拥有 label 为 deploy=hello 的节点

(3)、执行部署应用

1$ kubectl create -f deploy.yaml

(4)、查看启动的应用所在节点

1$ kubectl get pods -o wide
2
3NAME                    READY   STATUS    RESTARTS   AGE   IP               NODE         
4hello-bc58f99c8-fpd5t   1/1     Running   0          17s   10.244.134.232   k8s-node-2-12

二、亲和性 Affinity

1、Affinity 介绍

       由于上面 NodeNameNodeSelector 两种调度方式过于生硬,不能够灵活配置应用能启动在什么节点、不启动在什么节点与配置两个相同的实例启动在不同的节点等等规则。所以 Kubernetes 中还有另一种调度方式,那就是 Affinity 亲和性,这种方式可以非常灵活的配置应用的调度规则。

(1)、Affinity 可以分为三种类

  • NodeAffinity: Node 亲和性
  • PodAffinity: Pod 亲和性
  • PodAntiAffinity: Pod 反亲和性

(2)、亲和性调度可以分成软策略和硬策略两种方式

  • preferredDuringSchedulingIgnoredDuringExecution(软策略): 如果没有满足调度要求的节点,Pod 就会忽略这条规则,继续完成调度过程,即是满足条件最好,没有满足也无所谓的一种策略。
  • requiredDuringSchedulingIgnoredDuringExecution(硬策略): 比较强硬,如果没有满足条件的节点的话,就不断重试直到满足条件为止,即是必须满足该要求,不然不调度的策略。

2、相关参数介绍

(1)、调度条件参数:

  • nodeSelectorTerms:下面有多个选项的话,满足任何一个条件就可以了;
  • matchExpressions:有多个选项的话,则必须同时满足这些条件才能正常调度 POD。

(2)、权重 weight 参数:

  • 权重范围为 1-100,权重的值涉及调度器的优选打分过程,每个节点的评分都会加上这个 weight,最后绑定最高的节点。

(3)、拓扑域 topologyKey 参数及可配置选项:

topologykey 的值表示指作用于 topology 范围内的 node 上运行的 pod,其值可配置为:

  • kubernetes.io/hostname(Node)
  • failure-domain.beta.kubernetes.io/zone(Zone)
  • failure-domain.beta.kubernetes.io/region(Region)

(4)、匹配选项 operator 可用的选项:

  • In: label 的值在某个列表中
  • NotIn: label 的值不在某个列表中
  • Gt: label 的值大于某个值
  • Lt: label 的值小于某个值
  • Exists: 存在某个 label 标签
  • DoesNotExist: 不存在某个 label 标签

3、Node 亲和性 NodeAffinity

       NodeAffinity 是用于调度应用时候,会根据 NodeAffinity 参数去跟 Node 上的 Label 进行匹配,如果有符合条件的 Node 则该应用就可与调度到该节点,其功能跟 NodeSelector 类似,不过设置的条件比其更灵活。例如,下面是设置应用必须运行在 amd64 的节点中,并且设置尽可能启动到 k8s-node-2-12 节点上,可以按如下配置:

(1)、设置 Deployment 对象配置 nodeAffinity 参数

deploy.yaml

 1apiVersion: apps/v1
 2kind: Deployment
 3metadata:
 4  name: hello
 5  labels:
 6    app: hello
 7spec:
 8  replicas: 1
 9  selector:
10    matchLabels:
11      app: hello
12  template:
13    metadata:
14      labels:
15        app: hello
16    spec:
17      containers:
18      - name: hello
19        image: tutum/hello-world:latest
20        ports:
21        - containerPort: 80
22      affinity:  
23        nodeAffinity:    #Pod亲和性
24          requiredDuringSchedulingIgnoredDuringExecution:  #硬策略
25            nodeSelectorTerms:
26            - matchExpressions:
27              - key: kubernetes.io/arch
28                operator: In
29                values:
30                - amd64
31          preferredDuringSchedulingIgnoredDuringExecution:  #软策略
32          - weight: 100  #权重,取值范围为 1-100
33            preference:
34              matchExpressions:
35              - key: kubernetes.io/hostname
36                operator: In
37                values:
38                - k8s-node-2-12            

(2)、执行部署应用

1$ kubectl create -f deploy.yaml

(3)、查看启动的应用所在节点

1$ kubectl get pods -o wide
2
3NAME                    READY   STATUS    RESTARTS   AGE   IP               NODE         
4hello-bc58f99c8-fpd5t   1/1     Running   0          17s   10.244.134.232   k8s-node-2-12

NodeAffinity 规则设置的注意事项如下:

  • 如果 nodeAffinity 指定了多个 nodeSelectorTerms,那么其中任意一个能够匹配成功即可。
  • 如果同时定义了 nodeSelectornodeAffinity,那么必须两个条件都得到满足,Pod 才能最终运行在指定的 Node 上。
  • 如果在 nodeSelectorTerms 中有多个 matchExpressions,则一个节点必须满足所有 matchExpressions 才能运行该 Pod

4、Pod 亲和性 PodAffinity

       Pod 亲和性 主要解决 Pod 可以和哪些 Pod 部署在同一个拓扑域中的问题。一般用于一个应用存在多个实例,或者设置应用与另一个应用间建立关联的时候才会用到,比如,A 应用要启动两个实例,但是要求这两个实例启动在同一个节点上。再比如,有 AB 两个应用,要求这两个引用起动在同一节点上。下面介绍下,如何设置同一应用实例启动在相同节点上,可以按如下配置:

(1)、设置 Deployment 对象配置 podAffinity 参数

deploy.yaml

 1apiVersion: apps/v1
 2kind: Deployment
 3metadata:
 4  name: hello
 5  labels:
 6    app: hello
 7spec:
 8  replicas: 2  #两个示例
 9  selector:
10    matchLabels:
11      app: hello
12  template:
13    metadata:
14      labels:
15        app: hello
16    spec:
17      containers:
18      - name: hello
19        image: tutum/hello-world:latest
20        ports:
21        - containerPort: 80
22      affinity:  
23        podAffinity:    #Pod亲和性
24          requiredDuringSchedulingIgnoredDuringExecution:  #硬策略
25          - topologyKey: kubernetes.io/hostname
26            labelSelector:
27              matchExpressions:
28              - key: app
29                operator: In
30                values:
31                - hello

(2)、执行部署应用

1$ kubectl create -f deploy.yaml

(3)、查看启动的应用所在节点

1$ kubectl get pods -o wide
2
3NAME                     READY   STATUS    RESTARTS   AGE   IP              NODE
4hello-57db96b746-7xk89   1/1     Running   0          20s   10.244.39.254   k8s-node-2-13
5hello-57db96b746-q55xk   1/1     Running   0          20s   10.244.39.252   k8s-node-2-13

5、Pod 反亲和性 PodAntiAffinity

       Pod 反亲和性 主要是解决 Pod 不能和哪些 Pod 部署在同一个拓扑域中的问题,是用于处理的 Pod 之间的关系。比如一个 Pod 被调度到某一个节点上,新起的 Pod 不想和这个 Pod 调度到一起,就可以使用 Pod 的反亲和性 podAntiAffinity。例如,设置应用启动在不同节点上,可以按如下配置:

(1)、设置 Deployment 对象配置 podAntiAffinity 参数

deploy.yaml

 1apiVersion: apps/v1
 2kind: Deployment
 3metadata:
 4  name: hello
 5  labels:
 6    app: hello
 7spec:
 8  replicas: 2
 9  selector:
10    matchLabels:
11      app: hello
12  template:
13    metadata:
14      labels:
15        app: hello
16    spec:
17      containers:
18      - name: hello
19        image: tutum/hello-world:latest
20        ports:
21        - containerPort: 80
22      affinity:  
23        podAntiAffinity:    #Pod反亲和性
24          requiredDuringSchedulingIgnoredDuringExecution:  #硬策略
25          - topologyKey: kubernetes.io/hostname
26            labelSelector:
27              matchExpressions:
28              - key: app
29                operator: In
30                values:
31                - hello
32            

(2)、执行部署应用

1$ kubectl create -f deploy.yaml

(3)、查看启动的应用所在节点

1$ kubectl get pods -o wide
2
3NAME                     READY   STATUS    RESTARTS   AGE   IP               NODE
4hello-67c8bbb758-qhhvg   1/1     Running   0          14s   10.244.134.238   k8s-node-2-12
5hello-67c8bbb758-x6lrd   1/1     Running   0          14s   10.244.39.251    k8s-node-2-13

---END---


  !版权声明:本博客内容均为原创,每篇博文作为知识积累,写博不易,转载请注明出处。