Kubernetes 应用部署调度策略 NodeSelector、NodeName 与 Affinity
文章目录
!版权声明:本博客内容均为原创,每篇博文作为知识积累,写博不易,转载请注明出处。
系统环境:
- kubernetes 版本:1.16.4
博文简介:
在接触 Kubernetes 中,我们会经常接触到部署应用,Kubernetes 中默认的部署方式为根据调度算法分析 Kubernetes 中资源使用情况,进行动态分配的。有时候调度应用时需要设置应用部署到特定的节点上,或者需要将应用部署多个实例,为了保持高可用需要将应用分配到不同的节点上等等,由于有这些特殊情况,就有了后面要介绍的 Kubernetes 的多种调度方式。
一、定向调度策略 NodeName 与 NodeSelector
在 Kubernetes 中有两种定向调度方式,可以通过配置 Kubernetes 对象的 nodeName
和 NodeSelector
两个参数,来使应用部署到特定的节点上。
1、NodeName 方式
参数 Pod.spec.nodeName
可用于强制约束 Pod
跳过默认的 Kubernetes
调度规则,直接调度 Pod
到指定的 Node
节点上。下面是调度应用 Pod
到 k8s-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 介绍
由于上面 NodeName
和 NodeSelector
两种调度方式过于生硬,不能够灵活配置应用能启动在什么节点、不启动在什么节点与配置两个相同的实例启动在不同的节点等等规则。所以 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
,那么其中任意一个能够匹配成功即可。 - 如果同时定义了
nodeSelector
和nodeAffinity
,那么必须两个条件都得到满足,Pod
才能最终运行在指定的Node
上。 - 如果在
nodeSelectorTerms
中有多个matchExpressions
,则一个节点必须满足所有matchExpressions
才能运行该Pod
。
4、Pod 亲和性 PodAffinity
Pod 亲和性
主要解决 Pod
可以和哪些 Pod
部署在同一个拓扑域中的问题。一般用于一个应用存在多个实例,或者设置应用与另一个应用间建立关联的时候才会用到,比如,A
应用要启动两个实例,但是要求这两个实例启动在同一个节点上。再比如,有 A
和 B
两个应用,要求这两个引用起动在同一节点上。下面介绍下,如何设置同一应用实例启动在相同节点上,可以按如下配置:
(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---
!版权声明:本博客内容均为原创,每篇博文作为知识积累,写博不易,转载请注明出处。