引言

Kubernetes(K8s)是一款开源的容器编排平台,通过调度系统,能够智能地将容器化应用程序部署到集群中的节点。Node Affinity是Kubernetes调度器的一个重要特性,它允许开发者通过定义Pod与节点之间的亲和性关系,影响Pod的调度位置。本文将深入讨论Node Affinity的概念、用法,并通过详细的示例演示如何在实际场景中应用Node Affinity。

什么是Node Affinity?

Node Affinity是Kubernetes调度器的一种机制,用于指定Pod与节点之间的亲和性关系。通过Node Affinity,我们可以要求或禁止将某个Pod调度到具有特定亲和性关系的节点上,以满足应用程序的性能和资源需求。

Node Affinity的主要应用场景包括:

  • 硬件亲和性: 将需要特定硬件资源的Pod调度到具有相应硬件标签的节点上。
  • 数据本地性: 将依赖特定数据存储的Pod调度到具有相同存储特性的节点上。
  • 地理位置感知: 将需要在同一地理位置运行的Pod调度到具有相同地理位置标签的节点上。

Node Affinity的基本结构

在使用Node Affinity之前,我们需要了解其基本结构。Node Affinity通过以下两个关键组件来实现:

  • requiredDuringSchedulingIgnoredDuringExecution: 指定Pod必须调度到具有特定标签的节点上。
  • preferredDuringSchedulingIgnoredDuringExecution: 指定Pod更倾向于调度到具有特定标签的节点上,但不是必须的。

以下是一个简单的Node Affinity示例:

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
apiVersion: apps/v1
kind: Deployment
metadata:
name: affinity-deployment
spec:
replicas: 3
selector:
matchLabels:
app: affinity-app
template:
metadata:
labels:
app: affinity-app
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: "gpu"
operator: In
values:
- "true"
containers:
- name: affinity-container
image: affinity-app:latest

在这个示例中,我们创建了一个名为affinity-deployment的Deployment,其中的Pod被标记为app: affinity-app。通过Node Affinity的设置,我们要求这些Pod在调度时具有硬件亲和性,即它们应该被调度到具有gpu: true标签的节点上。

Node Affinity的使用方法

定义Node Affinity

要使用Node Affinity,首先需要在Pod的定义中配置Affinity。以下是一个具有多个匹配条件的Node Affinity的示例:

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
apiVersion: apps/v1
kind: Deployment
metadata:
name: complex-affinity-deployment
spec:
replicas: 3
selector:
matchLabels:
app: complex-affinity-app
template:
metadata:
labels:
app: complex-affinity-app
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: "gpu"
operator: In
values:
- "true"
- key: "cpu"
operator: NotIn
values:
- "low-performance"
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: "zone"
operator: In
values:
- "us-west"
containers:
- name: complex-affinity-container
image: complex-affinity-app:latest

在这个示例中,我们创建了一个名为complex-affinity-deployment的Deployment,其中的Pod被标记为app: complex-affinity-app。通过Node Affinity的设置,我们要求这些Pod在调度时具有硬件亲和性:

  • requiredDuringSchedulingIgnoredDuringExecution条件表示,这些Pod必须被调度到具有gpu: true且不具有cpu: low-performance标签的节点上。
  • preferredDuringSchedulingIgnoredDuringExecution条件表示,如果可能,这些Pod更倾向于被调度到具有zone: us-west标签的节点上,并设置了100的权重。

应用Node Affinity

将定义好的Node Affinity应用于实际的应用场景。以下是一个示例,演示了如何在一个具有多个硬件配置的集群中使用Node Affinity:

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
apiVersion: apps/v1
kind: Deployment
metadata:
name: hardware-affinity-deployment
spec:
replicas: 3
selector:
matchLabels:
app: hardware-affinity-app
template:
metadata:
labels:
app: hardware-affinity-app
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: "gpu"
operator: In
values:
- "true"
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 50
preference:
matchExpressions:
- key: "cpu"
operator: In
values:
- "high-performance"
containers:
- name: hardware-affinity-container
image: hardware-affinity-app:latest

在这个示例中,我们创建了一个名为hardware-affinity-deployment的Deployment,其中的Pod被标记为app: hardware-affinity-app。通过Node Affinity的设置,我们要求这些Pod在调度时具有硬件亲和性:

  • requiredDuringSchedulingIgnoredDuringExecution条件表示,这些Pod必须被调度到具有gpu: true标签的节点上。
  • preferredDuringSchedulingIgnoredDuringExecution条件表示,如果可能,这些Pod更倾向于被调度到具有cpu: high-performance标签的节点上,并设置了50的权重。

验证Node Affinity

通过查看Pod的描述,我们可以验证Node Affinity是否被正确应用。执行以下命令:

1
kubectl describe pod <pod-name>

在输出中,你应该能够看到与Node Affinity中定义的标签和条件相对应的信息,确认Pod是否按照预期被调度到了正确的节点上。

实际应用示例

假设我们有一个具有多种硬件配置的Kubernetes集群,我们有两类应用程序,一类需要GPU资源,另一类则对CPU性能更为敏感。通过Node Affinity,我们可以实现这一资源分配策略。

以下是一个示例,演示了如何在一个具有多种硬件配置的集群中使用Node Affinity:

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
apiVersion: apps/v1
kind: Deployment
metadata:
name: gpu-intensive-app-deployment
spec:
replicas: 3
selector:
matchLabels:
app: gpu-intensive-app
template:
metadata:
labels:
app: gpu-intensive-app
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: "gpu"
operator: In
values:
- "true"
containers:
- name: gpu-intensive-app-container
image: gpu-intensive-app:latest
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: high-performance-app-deployment
spec:
replicas: 3
selector:
matchLabels:
app: high-performance-app
template:
metadata:
labels:
app: high-performance-app
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: "cpu"
operator: In
values:
- "high-performance"
containers:
- name: high-performance-app-container
image: high-performance-app:latest

在这个示例中,我们创建了两个Deployment,分别属于gpu-intensive-app和high-performance-app两个应用程序。通过Node Affinity的设置,我们要求:

  • gpu-intensive-app的Pod必须被调度到具有gpu: true标签的节点上。
  • high-performance-app的Pod必须被调度到具有cpu: high-performance标签的节点上。

通过这样的方式,我们可以灵活地控制不同类型应用程序的资源分配,更好地利用集群中不同节点的硬件特性。

结论

Node Affinity是Kubernetes中非常有用的调度特性,通过定义Pod与节点之间的亲和性关系,影响Pod的调度位置。