Kubernetes调度之亲和与反亲和

部署pod时,大多数情况下kubernetes的调度程序能将pod调度到集群中合适的节点上。但有些情况下用户需要对pod调度到哪个节点上施加更多控制,比如将特定pod部署到拥有SSD存储节点、将同一个服务的多个后端部署在不同的机器上提高安全性、将通信频繁的服务部署在同一个可用区域降低通信链路长度。用户对pod部署的节点施加控制都与"label selector"有关。

nodeSelector(节点选择器)

nodeSelector也是标签选择器,是最简单、最直接控制pod部署node的方法,在daemonset用nodeSelector过滤可部署节点,以下是其普通的应用示例。

步骤1:为节点添加标签

kubectl get nodes,返回集群中所有node。

kubectl node label =,为node选定的node添加标签。如kubectl label nodes kubernetes-foo-node-1.c.a-robinson.internal disktype=ssd

为pod configuration添加节点选择器:

apiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: disktype: ssd

当运行kubectl create -f https://k8s.io/examples/pods/pod-nginx.yaml命令创建pod时,节点选择器选中有上述节点,如果没有符合条件的node则调度失败,为pod输出调度失败事件并指明失败原因。pod一直处于pending状态,直到找到合适的节点。

运行kubectl get pods -o wide查看调度程序为pod选定的节点。

Interlude: built-in node labels(插曲:内置节点标签)

上例中使用用户自定义标签,也可以使用系统自动生成的内置节点标签。不同kubernetes版本、不同的基础设备供应商,默认添加的内置节点标签可能不同,需查询相关文档确认,以下是kubernetes1.4的内置节点标签:

kubernetes.io/hostname

failure-domain.beta.kubernetes.io/zone

failure-domain.beta.kubernetes.io/region

beta.kubernetes.io/instance-type

beta.kubernetes.io/os

beta.kubernetes.io/arch 

亲和与反亲和(Affinity and anti-affinity)

nodeSelector只能基于节点标签控制pod部署node,并且选择器只支持“与”逻辑操作。亲和与反亲和特性目前处于测试阶段,相比于节点选择器,其更灵活,功能更强大,体现在以下三点:

1) 不仅仅是“与”,支持更多的逻辑表达式。

2) nodeSelector是硬性要求,亲和与反亲和支持软硬两种要求。

3) 除了节点标签,亲和与反亲和支持根据节点上已经部署的pod进行节点选择,这一点很重要。比如不想将两种计算密集类型的pod部署在同一节点上,后部署pod可选择过滤。

细分成两种类型的选择器:"节点亲和"与"内部pod亲和、反亲和"。节点亲和与nodeSelector相似,具备上述1、2两条优点。内部pod亲和依赖的是节点上已有pod的标签而不是节点标签,兼俱上述三个优点。因为节点亲和能完成nodeSelector所工作并且具备额外的优点,因此nodeSelector虽然还能用,但已经不再维护,并且将来可能删除。

节点亲和(测试特性)

节点亲和与nodeSelector工作原理相同,都是其于node标签选择节点。有两点不同,第一是节点亲和支持软硬两种节点选择requiredDuringSchedulingIgnoredDuringExecution、preferredDuringSchedulingIgnoredDuringExecution。前者是硬性条件必需满足,后者是软性条件,属于偏好部署。第二点是在选择节点时,节点亲和比nodeSelector支持更多更灵活的表达式,示例如下:

apiVersion: v1 kind: Pod metadata: name: with-node-affinity spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/e2e-az-name operator: In values: - e2e-az1 - e2e-az2 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: another-node-label-key operator: In values: - another-node-label-value containers: - name: with-node-affinity image: k8s.gcr.io/pause:2.0

符合条件的节点必需满足requiredDuringSchedulingIgnoredDuringExecution的条件,在此基础上,如果有节点满足
preferredDuringSchedulingIgnoredDuringExecution的条件,则更倾向部署在后者上。查询表达式中可以使用的操作符有:
In, NotIn, Exists, DoesNotExist, Gt, Lt等。

在requiredDuringSchedulingIgnoredDuringExecution中的matchExpressions可以包含多条选择表达式,相互之间是"逻辑与"的关系,必需同时满足。preferredDuringSchedulingIgnoredDuringExecution中的matchExpressions也可以有多条,因为它是软性条件,因为并非一定要全匹配,匹配的条目越多越符合条件。另外还可以为偏好中的表达式赋予不同的权重weight,可取的值在0-100之间,最后通过计算权重和决定那个节点更符合条件。

如果同时使用了nodeSelector与nodeAffinity,那么目标节点必需同时满足这两个选择器。

内部pod亲和与反亲和(测试特性)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpwzgx.html