问题描述
在使用Kubernetes提交作业时,有一个需求是希望在特定的一组节点上排除部署。这组节点目前没有不同的标签来区分它们,因此我们只能通过主机名来排除它们(目前)。
所有关于使用 podAntiAffinity 的示例都使用了 labelSelector
,它期望在Pod上有一个标签来区分它。
那么,我如何限制我的作业只在特定的一组节点上部署呢?从文档中抓取的最接近的示例如下,但不起作用:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector: <--- 这是错误的,这里没有标签
matchExpressions:
- key: "kubernetes.io/hostname"
operator: In
values:
- hostname1
- hostname2
解决方案
请注意以下操作可能涉及版本差异及风险,建议在操作前备份。
在Kubernetes中,要在提交作业时排除特定的一组节点,应使用Node Affinity
,它在概念上类似于nodeSelector
。它允许你基于节点上的标签来约束Pod可调度的节点,你应该能够使用主机名作为标签。
以下是一个示例,我运行一个带有节点亲和性定义的作业,其目标是在我的集群的node-01
上启动5个任务:
apiVersion: batch/v1
kind: Job
metadata:
labels:
run: busybox
name: busybox
spec:
completions: 5
template:
metadata:
labels:
run: busybox
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- k8s-node01
containers:
- image: busybox
name: busybox
resources: {}
restartPolicy: OnFailure
在这个示例中,我们定义了一个作业,设置了5个完成任务。在作业的Pod模板中,我们使用了 affinity
和 nodeAffinity
来指定节点亲和性。在 requiredDuringSchedulingIgnoredDuringExecution
部分,我们使用 nodeSelectorTerms
来设置节点选择条件,这里是通过 matchExpressions
使用 kubernetes.io/hostname
来选择特定的节点。
通过这种方式,我们可以确保作业只在具有特定主机名的节点上运行。
请注意,节点亲和性并不能保证节点的可用性。如果在特定节点上需要等待某些服务准备就绪,还需要相应的等待逻辑来保证作业的正确执行。
结果示例:
以下是在示例中运行作业后的结果:
$ kubectl get all -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/busybox-2gdp6 0/1 Completed 0 3m20s 192.168.85.204 k8s-node01 <none> <none>
pod/busybox-l654d 0/1 Completed 0 3m55s 192.168.85.201 k8s-node01 <none> <none>
pod/busybox-n7dbr 0/1 Completed 0 3m29s 192.168.85.203 k8s-node01 <none> <none>
pod/busybox-pfc79 0/1 Completed 0 4m11s 192.168.85.200 k8s-node01 <none> <none>
pod/busybox-r4xln 0/1 Completed 0 3m16s 192.168.85.205 k8s-node01 <none> <none>
在上面的示例中,我们可以看到作业的5个任务都在k8s-node01
节点上完成。
通过使用节点亲和性,你可以有效地限制作业只在特定的一组节点上运行,从而满足你的需求。