master节点部署pod_Kubernetes系列之Pod调度

Kubernetes 支持限制 Pod 在指定的 Node 上运行,或者指定更倾向于在某些特定 Node 上运行。

有几种方式可以实现这个功能:

- NodeName: 最简单的节点选择方式,直接指定节点,跳过调度器。
- Taint/Toleration: 通过 Pod 有洁癖的特性进行调整
- NodeSelector: 早期的简单控制方式,直接通过键—值对将 Pod 调度到具有特定 label 的 Node 上。
- NodeAffinity: NodeSelector 的升级版,支持更丰富的配置规则,使用更灵活。(NodeSelector 将被淘汰.)
- PodAffinity: 根据已在节点上运行的 Pod 标签来约束 Pod 可以调度到哪些节点,而不是根据 node label。

1. NodeName

nodeName 是 PodSpec 的一个字段,用于直接指定调度节点,并运行该 pod。调度器在工作时,实际选择的是 nodeName 为空的 pod 并进行调度然后再回填该 nodeName,所以直接指定 nodeName 实际是直接跳过了调度器。换句话说,指定 nodeName 的方式是优于其他节点选择方法。 方法很简单,直接来个示例:

apiVersion

注意: 如果选择的节点不存在,或者资源不足,那该 pod 会运行失败

2. Taint/Toleration

默认情况下 Master 节点是不允许运行用户 Pod 的。Kubernetes 做到这一点,依靠的是 Kubernetes 的 Taint/Toleration 机制。 一旦某个节点被加上了一个 Taint,默认情况下所有 Pod 就都不能在这个节点上运行,因为Pod 有"洁癖"。

为节点打Taints:
# kubectl taint nodes NODE_NAME  KEY=VALUE:TAINT_EFFECT
​
消除节点Taints:
# kubectl taint nodes NODE_NAME KEY-  
在 KEY 后面加上了一个短横线"-",意味着移除所有以 KEY 为键的 Taint

例如: 我们为节点192.168.10.11加上Taint:

[root@master ~]# kubectl taint nodes 192.168.10.11 foo=bar:NoSchedule
node/192.168.10.11 tainted

此时,该节点上就会增加一个键值对格式的 Taint,即:foo=bar:NoSchedule。这时我们再运行Pod将会发现所有的Pod不再被调度到192.168.10.11上了。

需要注意的是, 这个 Taint 只会在调度新 Pod 时产生作用,并不会影响已经在该节点上运行的 Pod。

是不是只要节点上有了污点, 就一定不能运行pod了呢? 不一定. 如果 Pod 声明自己能容忍这个"污点",即声明了 Toleration,它就可以在这个节点上运行。

声明方法:

apiVersion: v1
kind: Pod
...
spec:
  tolerations:
  - key: "foo"
    operator: "Equal"
    value: "bar"
    effect: "NoSchedule"
...

这个 Toleration 的含义是,这个 Pod 能"容忍"所有键值对为 foo=bar ( 操作符为Equal ) 的 Taint。

有些Taint只有键, 没有值, 如:

35ad451c81bb669ce24312908d5160cc.png

对于这类Taint, 在声明Toleration时要用"Exists" 操作符.

apiVersion

3. NodeSelector

可以给节点打上一些标签, 在 Pod 中使用标签选择器( spec.nodeSelector )来让 Pod 调度到具有指定标签的节点.

例如: 希望一个 Pod 运行在 192.168.10.12 ( 磁盘为SSD ) 上, 因为这个 Pod需要更好的I/O性能 将 192.168.10.12 打标签

[root@master ~]# kubectl label nodes 192.168.10.12 DiskType=SSD

在Pod里面定义nodeSelector

apiVersion: v1
kind: Pod
...
spec:
  nodeSelector:
    DiskType: SSD
...

4. NodeAffinity

调度到满足一定条件的 Node 上. nodeAffinity 特性的设计初衷是为了替代 nodeSelector.

Node affinity跟nodeSelector很像, 相对于nodeSelector主要有以下几个优点:

  • 匹配有更多的逻辑组合,不只是字符串的完全相等
  • 调度分成软策略(soft)和硬策略(hard),在软策略下,如果没有满足调度条件的节点,pod会忽略这条规则,继续完成调度。

nodeAffinity 属性:

requiredDuringSchedulingIgnoredDuringExecution: 
调度时必须满足的条件,部署之后如果节点标签被改变,不再满足指定的条件,pod仍继续运行
​
requiredDuringSchedulingRequiredDuringExecution: 
调度时必须满足的条件,部署之后如果节点标签被改变,不再满足指定的条件,重新选择符合要求的节点
​
preferredDuringSchedulingIgnoredDuringExecution: 
优选条件,如果没有满足条件的节点,就忽略这些条件
​
preferredDuringSchedulingRequiredDuringExecution: 
同上,如果后面节点标签发生了变化,满足了条件,则重新调度到满足条件的节点

比如下面的例子中的 Pod 将调度到这样的节点上:

  • 节点必须要有标签 zhiliang=hao 或 zhiliang=you
  • 如果节点还有标签 fangxing=hao 将会被优先考虑
apiVersion

硬策略适用于 pod 必须运行在某种节点,否则会出现问题的情况,比如集群中节点的架构不同,而运行的服务必须依赖某种架构提供的功能;软策略适用于满不满足条件都能工作,但是满足条件更好的情况,比如服务最好运行在某个区域,减少网络传输等。这种区分是按用户的具体需求决定的,并没有绝对的技术依赖。

取消node标签

[root@master ~]# kubectl label no 192.168.10.12 DiskType-
node/192.168.10.12 labeled

5. PodAffinity

nodeSelector & nodeAffinity 都是基于 node label 进行调度。

有时候我们希望调度的时候能考虑 pod 之间的关系,而不只是 pod 和 node 的关系。 例如,希望Pod A 和 B 部署在同一个机房或机器上,因为这些服务可能会对网路延迟比较敏感,需要低延时; 再如,希望Pod C 和 D 尽量分开部署,即使一台主机甚至一个机房出了问题,也不会导致两个服务一起挂而影响服务可用性,提升故障容灾的能力。

podAffinity 会基于节点上已经运行的 pod label 来约束新 pod 的调度。 规则: 如果 X 已经运行了符合规则 Y 的 Pod,那么这个 Pod 应该(如果是反亲和性,则是不应该)调度到 X 上”。

这里提到的 X 是指一个拓扑域, 类似于 node、rack、zone、cloud region 等等,是指 k8s 内置 Node 标签 ,当然也可以自定义。

内置 Node 标签

Kubernetes 内置了一些节点标签:
• kubernetes.io/hostname
• beta.kubernetes.io/instance-type
• beta.kubernetes.io/os
• beta.kubernetes.io/arch
• failure-domain.beta.kubernetes.io/zone
• failure-domain.beta.kubernetes.io/region
有些标签是对云提供商使用。
还有些表示 node role 的 labels(可以指定 master、lb 等):
• kubernetes.io/role
• node-role.kubernetes.io

podAffinity 属性:

podAffinity: 亲和性,  将Pod调度到有运行着的满足条件的 Pod 所在的 Node 上
podAntiAffinity: 反亲和性, 不要将Pod调度到有运行着的满足条件的 Pod 所在的 Node 上
requiredDuringSchedulingIgnoredDuringExecution: 功能类似于 nodeAffinity
preferredDuringSchedulingIgnoredDuringExecution: 功能类似于 nodeAffinity

例如: 下面的 Pod 会调度到这样的节点上:

  • 运行有含 xingge=kailang 标签的 Pod
  • 最好不要运行有含 sex=male 标签的 Pod
apiVersion

podAffinity 和 nodeAffinity 也有较大的差异, pod 是 namespace 资源,所以必然会需要配置 namespaces,支持配置多个 namespace。如果省略的话,默认为待调度 pod 所属的 namespace;如果定义了但是值为空,则表示使用 all namespaces。

TopologyKey 用于定义 "in the same place",即同一拓扑域. 可以是一台主机, 一个机架, 一个机房, 一个地区等

原则上,topologyKey 可以是任何合法的 label key。但是出于性能和安全考虑,topologyKey 存在一些限制:

- 对于亲和性和反亲和性的requiredDuringSchedulingIgnoredDuringExecution模式,topologyKey不能为空
- pod 反亲和性 requiredDuringSchedulingIgnoredDuringExecution 模式下,LimitPodHardAntiAffinityTopology权限控制器会限制 topologyKey 只能设置kubernetes.io/hostname。
当然如果你想要使用自定义 topology,那可以简单禁用即可。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值