一个计算机技术爱好者与学习者

0%

好好学K8S:K8S中的调度

1. 调度是啥?

在 K8S 中,调度 是指将 Pod 放置到合适的节点上,以便对应节点上的 Kubelet 能够运行这些 Pod。
调度器通过 K8S 的监测(Watch)机制来发现集群中新创建且尚未被调度到节点上的 Pod,把它调度到一个合适的节点上运行。
K8S调度分为两个阶段:过滤和打分。过滤阶段会将所有满足 Pod 调度需求的节点选出来;在打分阶段会为 Pod 从所有可调度节点中选取一个最合适的节点。最后,会将pod调度到得分最高的节点上。

我们可以约束一个 Pod 限制其只能在特定的节点上运行,或优先在特定的节点上运行。具体方法包括:

  • nodeName
  • label和nodeSelector
  • 亲和性与反亲和性
  • Pod 拓扑分布约束

我们也可以约束一些 Pod 不能在特定的节点上运行。具体方法是使用污点(taint)和容忍(tolerations)。

参考文档:

2. 调度规则

每个节点具有每种资源类型的最大容量:可为 Pod 提供的 CPU 和内存量。调度程序确保对于每种资源类型,调度的容器的资源请求的总和小于节点的容量。
哪怕节点上实际CPU或内存的资源使用量非常低,但如果容量检查失败,则调度程序仍然拒绝在该节点上放置 Pod。

参考文档:管理容器的计算资源

3. nodeName

pod想要指定调度到某个node,可以直接在spec下制定nodeName字段

1
2
spec:
nodeName: node1

4. label和nodeSelector

4.1. 添加label

1
kubectl label nodes node1 key1=value1,key2=value2

4.2. 添加nodeSelector

node添加label后,pod想要指定调度到这个node,可以在spec下添加nodeSelector字段

1
2
3
spec:
nodeSelector:
key1: value1

4.3. 删除label

如果不再使用某个label,可以进行删除。

1
kubectl label nodes node1 key2-

5. 亲和性与反亲和性

5.1. 节点亲和性

节点亲和性(Node Affinity)是一种 Pod 调度器机制,用于指定 Pod 可以调度到哪些节点上运行。它可以通过指定节点的标签来实现,从而确保 Pod 运行在它所需要的节点上,以实现更好的资源利用率和性能表现。

1、节点添加label

1
kubectl label nodes node1 key1=value1,key2=value2

2、spec添加affinity
node添加label后,pod想要指定调度到这个node,也可以在spec下添加affinity字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: key1
operator: In
values:
- value1
- valuex
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: key2
operator: In
values:
- value2
- valuey

5.2. 节点反亲和性

节点反亲和性(Node Anti-Affinity)?不存在这种机制。

5.3. pod亲和性

Pod 亲和性(Pod Affinity)是一种 Pod 调度器机制,用于指定多个 Pod 之间的亲和性关系,以便它们可以被调度到同一节点上运行。这种亲和性配置可以用于实现分布式应用程序的高可用性和资源利用率,以及避免数据传输延迟等问题。

服务A和服务B的pod想要部署在同一个主机上:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-a
namespace: namespace-a
spec:
replicas: 3
selector:
matchLabels:
app: my-app-a
template:
metadata:
labels:
app: my-app-a
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- my-app-b
topologyKey: "kubernetes.io/hostname"
namespaceSelector:
matchLabels:
name: namespace-b
containers:
- name: my-container
image: nginx

---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-b
namespace: namespace-b
spec:
replicas: 3
selector:
matchLabels:
app: my-app-b
template:
metadata:
labels:
app: my-app-b
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- my-app-a
topologyKey: "kubernetes.io/hostname"
namespaceSelector: {}
containers:
- name: my-container
image: nginx

注意:

  • 上面的例子中配置的亲和,是双向的亲和,服务A亲和服务B,服务B也亲和服务A。但是,如果两个服务都不可用时,可能会出现互相等待的情况。因此,大多数情况下最好配置单向的亲和。
  • 默认情况下,Pod 亲和性规则是在同一命名空间内生效的。如果我们希望实现跨命名空间的亲和性,我们需要使用 namespaceSelector 来指定目标 Pod 所在的命名空间。这样可以确保亲和性规则适用于其他命名空间中的 Pod。空的 namespaceSelector: {} 表示匹配所有命名空间。

5.4. pod反亲和性

Pod 反亲和性(Pod Anti-Affinity)是一种 Pod 调度器机制,用于指定多个 Pod 之间的反亲和性关系,以便它们不会被调度到同一节点上运行。这种反亲和性配置可以用于实现分布式应用程序的高可用性和避免资源冲突,以及确保容器之间的相互独立性。

参考文档Pod 打散调度

相同服务的pod必须打散,强反亲和:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
app: nginx
containers:
- name: nginx
image: nginx

相同服务的pod尽量打散,弱反亲和:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- podAffinityTerm:
topologyKey: kubernetes.io/hostname
weight: 100

6. Pod 拓扑分布约束

未完待续。。。

7. 污点和容忍

7.1. 添加taint

1
2
3
kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key2=value2:PreferNoSchedule
kubectl taint nodes node1 key3=value3:NoExecute

7.2. 添加tolerations

node添加taint后,pod想要调度到这个node,需要在spec下添加tolerations字段:

1
2
3
4
5
6
7
8
9
10
11
12
13
spec:
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
- key: "key2"
operator: "Exists"
effect: "PreferNoSchedule"
- key: "key3"
operator: "Equal"
value: "value3"
effect: "NoExecute"

7.3. 删除taint

1
kubectl taint nodes node1 key1:NoSchedule-

8. node封锁

如果node存在问题,或者node需要升级维护,这时需要对node进行封锁,并且驱除pod。

8.1. 封锁node,不允许分配pod

1
kubectl cordon nodename

8.2. 从指定node驱除pod

1
kubectl drain nodename --ignore-daemonsets

9. 解除node的封锁,允许分配pod

1
kubectl uncordon nodename
  • 本文作者: 好好学习的郝
  • 原文链接: https://www.voidking.com/dev-k8s-schedule/
  • 版权声明: 本文采用 BY-NC-SA 许可协议,转载请注明出处!源站会即时更新知识点并修正错误,欢迎访问~
  • 微信公众号同步更新,欢迎关注~