这里的背景是遇到了一个小问题:我目前有3台机器(1台ssd+40m 带宽高性能),有些服务对网络、机器都有较大的要求,而其他一些则没有,请问我如何才能让特定服务运行在特定 node 上。
固展开了k8s对pod调度的学习。
k8s对pod调度的方法有:
1.通过标签nodeSelector
对pod进行硬性的强制匹配调度
2.通过affinity
对pod进行规则匹配,下文补充
3.也可以通过封锁,驱逐节点的方法调度pod,但是远不及上面两种方式好
理论部分:
让pod调度到指定node上有几种方法,1是nodeSelector,这里先不讲,而是节点亲和性(node affinity)也是本文的重点
nodeSelector
提供了一个非常简单的方法来将 pod 约束到具有特定标签的节点。
而亲和性/反亲和性特性(目前处于 beta 阶段),极大地扩展了您可以表达的约束类型。关键的改进有
nodeSelector
,但是拥有上述的第一和第二个优点。Pod 间的亲和性/反亲和性以 pod 标签作为约束,而不仅仅是 node 标签,就像上述第三点所述,它同时也拥有上述第一和第二个特性。nodeSelector
将会像往常一样继续工作,但最终将被弃用,因为 node 亲和性可以表达 nodeSelector
能够表达的所有约束。
Node 亲和性在 Kubernetes 1.2 版本中作为 alpha 特性引入。 Node 亲和性在概念上类似于 nodeSelector – 它能够基于 node 标签约束哪些 pod 能够被分配到 node 上。
目前有两种类型的 node 亲和性,分别是:
requiredDuringSchedulingIgnoredDuringExecution
preferredDuringSchedulingIgnoredDuringExecution
您可以认为它们分别是 “硬性” 和 “软性” 的,即前者要求 pod 必须 满足指定的规则才能调度到 node 上(就像 nodeSelector,但使用更具表达性的语法),后者指定 偏向,即让 scheduler 尝试但是不保证完全满足规则。
与 nodeSelector 工作方式类似,名称中的 “IgnoredDuringExecution” 部分意味着,如果一个 node 的标签在运行时发生改变,从而导致 pod 的亲和性规则不再被满足时,pod 也仍然会继续运行在 node上。以后我们计划提供 requiredDuringSchedulingRequiredDuringExecution,这类似于 requiredDuringSchedulingIgnoredDuringExecution,但是它会从不再满足 pod 的 node 亲和性的 node 上驱逐 Pod。
因此 requiredDuringSchedulingIgnoredDuringExecution 的一个例子是 “只能在有 Intel CPU 的 node 上运行 pod”,preferredDuringSchedulingIgnoredDuringExecution 的例子是 “尝试在可用域 XYZ 的范围内运行 pod,但是如果不满足,那么也允许在其它地方运行 pod”。
开始实操过程
# kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
10.0.0.12 Ready <none> 1h v1.10.5-qcloud beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=QCLOUD,beta.kubernetes.io/os=linux,cpu=high,failure-domain.beta.kubernetes.io/region=gz,failure-domain.beta.kubernetes.io/zone=100002,kubernetes.io/hostname=10.0.0.12
10.0.0.15 Ready <none> 1h v1.10.5-qcloud beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=QCLOUD,beta.kubernetes.io/os=linux,cpu=mid,failure-domain.beta.kubernetes.io/region=gz,failure-domain.beta.kubernetes.io/zone=100002,kubernetes.io/hostname=10.0.0.15
这里可以看到 LABELS列下多了cpu=high cpu=mid
#标签打错挽救
# kubectl label node 10.0.0.15 cpu=mid
error: 'cpu' already has a value (high), and --overwrite is false
# kubectl label --overwrite node 10.0.0.15 cpu=mid
node "10.0.0.15" labeled
亲和性yaml文件示例
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: cpu
operator: In
values:
- high
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- another-node-label-value
containers:
- name: with-node-affinity
image: nginx
这个 node 亲和性规则意思是,pod 只能被调度在标签满足 key 为 cpu 并且 value 为 high 的 node 上。
另外,在满足条件的所有 node 中,更倾向于拥有 key 为 another-node-label-key 并且 value 为 another-node-label-value 的标签的 node(这里并没有实践这个)
通过yaml文件创建pod后,查看pod可以看到 with-node-affinity
运行在node 10.0.0.12上,而with-node-affinity-mid
运行在node 10.0.0.15上符合预期(10.0.0.15的yaml没有贴出,请自行修改),
root@VM_0_17_centos ~# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
with-node-affinity 1/1 Running 0 26m 192.168.15.6 10.0.0.12
with-node-affinity-mid 1/1 Running 0 24m 192.168.14.3 10.0.0.15
您可以在例子中看到 In 运算符。新的 node 亲和性语法支持以下运算符:In、NotIn、Exists、DoesNotExist、Gt 和 Lt。 实际上并没有明确的 “node 反亲和性” 概念,不过 NotIn 和 DoesNotExist 提供了这种行为。
如果您指定了 nodeSelector 和 nodeAffinity,那么 pod 必须满足这 两个 规则才能调度到候选节点上。
如果您在 nodeAffinity 类型中指定了多个 nodeSelectorTerms,那么 pod 将会被调度到 只要满足其中一个 nodeSelectorTerms 的 node 上。
如果您在 nodeSelectorTerms 中指定了多个 matchExpressions,那么 pod 将会被调度到 满足所有 matchExpressions 的 node 上。
如果需要了解更多关于 node 亲和性的信息,请 点击这里 查看设计文档
后续补充其他特性
url:https://k8smeetup.github.io/docs/concepts/configuration/assign-pod-node/
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。