系列目录

部署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亲和与反亲和(测试特性)

内部pod亲和与反亲和特性由kubernetes1.4版本初次引入,其基于节点上已部署pod的标签计算亲和与反亲和,如实现将两种通信频繁pod部署在相同节点,将两种计算密集型pod部署在不同节点等。

提示:实现内部亲和与反亲和需要数量可观的计算步骤,会明显降低pod调度的速度,集群规模越大、节点越多降速越明显,呈指数级增长,需要在使用此特性时考虑对调度速度的影响。

在配置时,内部pod亲和用podAffinity字段表示,内部pod反亲和用podAntiAffinity字段表示,其它与节点亲和一样,也有软硬两种选择器,每种选择器可以多个过滤条件。

内部pod亲和示例:

apiVersion: v1
kind: Pod
metadata:
name: with-pod-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: failure-domain.beta.kubernetes.io/zone
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S2
topologyKey: kubernetes.io/hostname
containers:
- name: with-pod-affinity
image: k8s.gcr.io/pause:2.0

上例中的topologyKey用来缩小节点选择范围,其值可以是任何合法的节点标签,在大规模集群中,为此字段不指定或者指定错误值,可能引发巨大的性能、安全问题。因此,对其使用有如下限制:

  • 对于亲和与硬性反亲和,topologyKey字段值不能为空。

  • 对于硬性反亲和,topoloygKey只能是kubernetes.io/hostname,除非禁止LimitPodHardAntiAffinityTopology允入控制器或者修改其实现。

  • 对于软件反亲和,允许topoloygKey为空,表示对节点拓扑没有限制。

  • 以上情况外,topologyKey可以是任何合法标签。

示例1:用反亲和特性实现pod位置协商

假设集群有五个工作节点,部署一个web应用,假设其用redis作内存缓存,共需要三个副本,通过反亲和将三个redis副本分别部署在三个不同的节点上,提高可用性,Deployment配置如下:

apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-cache
spec:
selector:
matchLabels:
app: store
replicas: 3
template:
metadata:
labels:
app: store
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- store
topologyKey: "kubernetes.io/hostname"
containers:
- name: redis-server
image: redis:3.2-alpine

反亲和会阻止同相的redis副本部署在同一节点上。

现在部署三个nginx web前端,要求三个副本不对分别部署在不同的节点上,通过与上列相似的反亲和实现。同时需要将三个web前端部署在其上已经部署redis的节点上,降低通信成本,通过亲和实现,配置如下:

apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
spec:
selector:
matchLabels:
app: web-store
replicas: 3
template:
metadata:
labels:
app: web-store
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-store
topologyKey: "kubernetes.io/hostname"
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- store
topologyKey: "kubernetes.io/hostname"
containers:
- name: web-app
image: nginx:1.12-alpine

参考

最新文章

  1. 1Z0-053 争议题目解析577
  2. 【leetcode】Permutations (middle)
  3. mycat 插入语句导致的一个Dobbo问题
  4. thinkphp和uploadfiy
  5. 如何更新Linux源
  6. hibernate基础(1)
  7. hdu 1269
  8. Swift 全功能的绘图板开发
  9. Backup Exec Inventory 与Catalog的含义(转载)
  10. XML的解析(DOM以及SAX方式)
  11. linux下的磁盘挂载
  12. php 数组排序得方法
  13. [USACO13DEC]假期计划(黄金)Vacation Planning (gold)
  14. Java/JSP/JS Debug笔记
  15. 并行(Parallelism)与并发(Concurrency)
  16. list对象中根据两个参数过滤数据
  17. #6284. 数列分块入门 8(区间询问等于一个数 cc 的元素,并将这个区间的所有元素改为 c)
  18. 【PyTorch深度学习60分钟快速入门 】Part3:神经网络
  19. Oracle Comment 获取并修改表或字段注释
  20. 使用nmap查看web服务支持的http methods

热门文章

  1. Apache2 FastCGI C Demo
  2. 【bzoj3439】Kpm的MC密码 可持久化Trie树
  3. HDU-1534 Schedule Problem
  4. 浅谈Linux下的五种I/O模型 两篇别人的博客
  5. Linux用户空间与内核空间(理解高端内存)【转】
  6. Java原来如此-随机数
  7. Python的格式化输出,基本运算符,编码
  8. Java 经典笔试题
  9. 一维数组解最长上升公共子序列(LCIS)
  10. Codeforces 835F Roads in the Kingdom (环套树 + DP)