POD亲和性的引入
在真实的生产环境中还存在如下所述的特殊需求
- 不同Pod之间的亲和性(Affinity):比如MySQL数据库与 Redis中间件不能被调度到同一个目标节点上,或者两种不同的Pod必须 被调度到同一个Node上,以实现本地文件共享或本地网络通信等特殊需 求,这就是PodAffinity要解决的问题
- 在每个Node上调度并且仅仅创建一个Pod副本。这种调度通 常用于系统监控相关的Pod,比如主机上的日志采集、主机性能采集等 进程需要被部署到集群中的每个节点,并且只能部署一个副本,这就是 DaemonSet这种特殊Pod副本控制器所解决的问题。
- 对于批处理作业,需要创建多个Pod副本来协同工作,当这些 Pod副本都完成自己的任务时,整个批处理作业就结束了。这种Pod运行 且仅运行一次的特殊调度,用常规的RC或者Deployment都无法解决, 所以Kubernates引入了新的Pod调度控制器Job来解决问题,并继续延伸 了定时作业的调度控制器CronJob
NodeSelector:定向调度
Kubernetes Master上的Scheduler服务(kube-scheduler进程)负责实 现Pod的调度,整个调度过程通过执行一系列复杂的算法,最终为每个 Pod都计算出一个最佳的目标节点,这一过程是自动完成的,通常我们 无法知道Pod最终会被调度到哪个节点上。在实际情况下,也可能需要 将Pod调度到指定的一些Node上,可以通过Node的标签(Label)和Pod 的nodeSelector属性相匹配,来达到上述目的
1.给node节点打标签
kubectl label node 192.168.8.129 zone=north
kubectl label node <node-name> <label-key>=<label-value>
2.在Pod的定义中加上nodeSelector的设置
apiVersion: v1
kind: Pod
metadata:
labels:
test: nginx
name: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- name: http
containerPort: 80
nodeSelector: #设置选择的node标签
zone: north
总结
- 如果我们给多个Node都定义了相同的标签(例如zone=north),则 scheduler会根据调度算法从这组Node中挑选一个可用的Node进行Pod调度
- 通过基于Node标签的调度方式,我们可以把集群中具有不同特点的 Node都贴上不同的标签,例 如“role=frontend”“role=backend”“role=database”等标签,在部署应用时就 可以根据应用的需求设置NodeSelector来进行指定Node范围的调度。
需要注意的是,如果我们指定了Pod的nodeSelector条件,且在集群 中不存在包含相应标签的Node,则即使在集群中还有其他可供使用的Node,这个Pod也无法被成功调度。
亲和性调度(NodeAffinity)
NodeSelector通过标签的方式,简单实现了限制Pod所在节点的方 法。亲和性调度机制则极大扩展了Pod的调度能力,主要的增强功能如下
- 更具表达力(不仅仅是“符合全部”的简单情况)
- 可以使用软限制、优先采用等限制方式,代替之前的硬限制, 这样调度器在无法满足优先需求的情况下,会退而求其次,继续运行该 Pod。
NodeAffinity意为Node亲和性的调度策略,是用于替换NodeSelector 的全新调度策略。目前有两种节点亲和性表达
- RequiredDuringSchedulingIgnoredDuringExecution:必须满足指 定的规则才可以调度Pod到Node上(功能与nodeSelector很像,但是使用 的是不同的语法),相当于硬限制
- PreferredDuringSchedulingIgnoredDuringExecution:强调优先满
足指定规则,调度器会尝试调度Pod到Node上,但并不强求,相当于软 限制。多个优先级规则还可以设置权重(weight)值,以定义执行的先 后顺序 - IgnoredDuringExecution的意思是:如果一个Pod所在的节点在Pod运 行期间标签发生了变更,不再符合该Pod的节点亲和性需求,则系统将 忽略Node上Label的变化,该Pod能继续在该节点运行。
示例
192.168.8.130 标签为 zone=south
apiVersion: v1
kind: Pod
metadata:
labels:
test: nginx
name: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- name: http
containerPort: 80
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution: #强调优先满足
- preference:
matchExpressions:
- key: zone #label
operator: In
values:
- south
weight: 1 #权重,
硬性要求
requiredDuringSchedulingIgnoredDuringExecution:
apiVersion: v1
kind: Pod
metadata:
labels:
test: nginx
name: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- name: http
containerPort: 80
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: zone
operator: In
values:
- east
下图显示pod是pending状态
下图说明因为没有可用的标签
PodAffinity:Pod亲和与互斥调度策略
PodAffinity:
根据在节点上正在运行的 Pod的标签而不是节点的标签进行判断和调度,要求对节点和Pod两个条件进行匹配
- 这种规则可以描述为:如果在具有标签X的Node上运行了 一个或者多个符合条件Y的Pod,那么Pod应该(如果是互斥的情况,那么就变成拒绝)运行在这个Node上.
这里X指的是一个集群中的节点、机架、区域等概念,通过 Kubernetes内置节点标签中的key来进行声明这个key的名字为 topologyKey,意为表达节点所属的topology范围。
与节点不同的是,Pod是属于某个命名空间的,所以条件Y表达的 是一个或者全部命名空间中的一个Label Selector
Pod的亲和性被定义 于PodSpec的affinity字段下的podAffinity子字段中。
Pod间的互斥性则被 定义于同一层次的podAntiAffinity子字段中
apiVersion: v1
kind: Pod
metadata:
labels:
test: nginx
name: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- name: http
containerPort: 80
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx
topologyKey: zone