将Pod分配给节点
Kubernetes调度器 提供了调度策略提供 过滤的断言(Predicates)
和 打分的优先级(Priorities)
在配置Pod调度到Node,我们常用的调度插件有
TaintToleration
NodeAffinity
NodeAffinity
在异构的环境中常常使用,例如不同的硬件配置,有的节点提供了GPU,有的节点处理器是ARM架构,在使用节点亲和性上就非常容易实现。
nodeSelector
nodeSelector
是节点选择节点的最简单推荐形式。 nodeSelector
是 PodSpec 的一个字段,包含键值对映射。为了使pod可以在某个节点上运行,这个节点标签中必须包含这个键值对。
要完成一个 nodeSelector
选择节点约束,需要执行以下步骤
步骤一:添加标签到节点
选择要添加标签节点,执行:
kubectl label node <node-name> <label-key>=<label-value>
例如给节点添加 disktype=ssd
或者 accelerator=nvidia-maxwell-jetson-nano
( NVIDIA GPU )
举例,在 部署ARM架构Kubernetes 我部署了 kube-verify
验证容器,创建yaml的脚本:
1cat <<EOF | kubectl create -f -
2apiVersion: apps/v1
3kind: Deployment
4metadata:
5 name: kube-verify
6 namespace: kube-verify
7 labels:
8 app: kube-verify
9spec:
10 replicas: 3
11 selector:
12 matchLabels:
13 app: kube-verify
14 template:
15 metadata:
16 labels:
17 app: kube-verify
18 spec:
19 containers:
20 - name: nginx
21 image: quay.io/clcollins/kube-verify:01
22 ports:
23 - containerPort: 8080
24EOF
在 树莓派Raspberry Pi 4 的两个worker节点,我部署了 树莓派4 USB存储启动Ubuntu Server 20.04 ,所以我添加一个 disktype=ssd
标签:
kubectl label node pi-worker1 disktype=ssd
kubectl label node pi-worker2 disktype=ssd
然后检查可以看到:
kubectl describe nodes pi-worker1
可以看到:
Name: pi-worker1
Roles: <none>
Labels: beta.kubernetes.io/arch=arm64
beta.kubernetes.io/os=linux
disktype=ssd
kubernetes.io/arch=arm64
kubernetes.io/hostname=pi-worker1
kubernetes.io/os=linux
...
步骤二:添加
nodeSelector
字段到Pod配置:kubectl -n kube-verify edit deployments kube-verify
在pod的 Deployment.spec.template.spec
段落添加:
spec:
...
template:
...
spec:
...
nodeSelector:
disktype: ssd
注意,一定要正确添加 nodeSelector
位置,我配置到 Deployment.spec
则会出现以下报错:
# deployments.apps "kube-verify" was not valid:
# * <nil>: Invalid value: "The edited file failed validation": ValidationError(Deployment.spec): unknown field "nodeSelector" in io.k8s.api.apps.v1.DeploymentSpec
然后检查就可以看到,原先配置
replicas: 3
的pod全部迁移到disk-type
为ssd
的ARM节点上:kubectl -n kube-verify -n kube-verify get pods -o wide
容器都运行在 pi-worker1
和 pi-worker2
上:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-verify-7d4878dfdc-9rv6m 1/1 Running 0 24s 10.244.2.13 pi-worker2 <none> <none>
kube-verify-7d4878dfdc-fgc4m 1/1 Running 0 21s 10.244.1.26 pi-worker1 <none> <none>
kube-verify-7d4878dfdc-k7sv5 1/1 Running 0 19s 10.244.2.14 pi-worker2 <none> <none>
内置节点标签
除了用户添加的标签,节点已经预先具备了一组标准标签:
kubernetes.io/hostname
failure-domain.beta.kubernetes.io/zone
failure-domain.beta.kubernetes.io/region
topology.kubernetes.io/zone
topology.kubernetes.io/region
beta.kubernetes.io/instance-type
node.kubernetes.io/instance-type
kubernetes.io/os
kubernetes.io/arch
备注
标签值基于云服务商,所以不能保证可靠。例如 kubernetes.io/hostname
在某些环境可能和节点标签名称相同,但在其他环境中可能是不同值。
案例
在 部署ARM架构Kubernetes 中,我通过 混合架构Kubernetes集群 添加了一个 X86架构的节点 zcloud
,可以通过:
kubectl get nodes --show-labels
看到 kubernetes.io/arch=
差异:
NAME STATUS ROLES AGE VERSION LABELS
...
pi-worker2 Ready <none> 164d v1.21.1 beta.kubernetes.io/arch=arm64,beta.kubernetes.io/os=linux,kubernetes.io/arch=arm64,kubernetes.io/hostname=pi-worker2,kubernetes.io/os=linux
zcloud Ready <none> 54d v1.21.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=zcloud,kubernetes.io/os=linux
可以看到 kubernetes.io/arch
是每个worker节点都具备都内置标签,我们可以按照架构来部署容器。
亲和性与反亲和性
亲和性/反亲和性
扩展了 noetSelector
的简单Pod约束到特定标签的节点功能:
规则是“软需求”/“偏好”,而不是硬性要求,因此, 如果调度器无法满足该要求,仍然调度该 Pod
可以使用节点(或其他拓扑域中)的Pod的标签来约束,而不是使用节点的标签,这样可以实现哪些Pod放在一起或者不能放在一起(类似
合并部署
)
节点亲和性
节点亲和性概念上类似 nodeSelector
,可以根据节点上的标签来约束Pod调度到哪些节点。
节点亲和性分为以下两种:
requiredDuringSchedulingIgnoredDuringExecution
- 硬需求,也就是 必须满足 (required) 的规则,只有规则满足才能够调度到一个节点preferredDuringSchedulingIgnoredDuringExecution
- 软需求,也就是 偏好 (preferred) 的规则,表示调度器将尽力尝试这个偏好规则,不能保证
举例: requiredDuringSchedulingIgnoredDuringExecution
可以仅将Pod运行在具备Intel CPU的节点上,但是使用 preferredDuringSchedulingIgnoredDuringExecution
我们可以设置线尝试运行在Intel CPU节点上,如果没有资源,退一步可以运行在AMD或者其他类型CPU节点上。
节点亲和性通过 PodSpec 的 affinity
字段下的 nodeAffinity
字段指定
在使用上,我们可以结合 required
和 preferred
以实现必须满足,且在满足条件情况下优先调度到某个节点
pod间亲和性与反亲和性
Pod 间亲和性与反亲和性可以基于已经在节点上运行的 Pod 的标签 来约束 Pod 可以调度到的节点,而不是基于节点上的标签。
与节点亲和性一样,当前有两种类型的 Pod 亲和性与反亲和性,即 requiredDuringSchedulingIgnoredDuringExecution
和 preferredDuringSchedulingIgnoredDuringExecution
,分别表示“硬性”与“软性”要求。