k8s调度之node的亲和性以及pod的亲和性/反亲和性

通常情况下,使用的都是k8s默认的调度调度方式,但是在有些情况下,我们需要将pod运行在具有特定的标签的node上才能都运行,这个时候,pod的调度策略就不能使用k8s默认的调度策略了,这个时候,就需要指定调度策略,告诉k8s需要将pod调度到那些node(节点)上。

nodeSelector

常规情况下,会直接使用nodeSelector这种调度策略。labels(标签) 是k8s里面用来标记资源的一种常用的方式,我们可以给node标记特殊的标签,然后nodeSelector会将pod调度到带有指定labels的node上的。

下面看个示例:

首先,查看node的label信息,通过下面的命令查看的 node 的 label:

$ kubectl get nodes --show-labels
NAME      STATUS    ROLES     AGE       VERSION   LABELS
master    Ready     master    147d      v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=master,node-role.kubernetes.io/master=
node02    Ready     <none>    67d       v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,course=k8s,kubernetes.io/hostname=node02
node03    Ready     <none>    127d      v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,jnlp=haimaxy,kubernetes.io/hostname=node03

然后,可以给node02节点新增一个label:

$ kubectl label nodes node02 com=yijiadashuju
node "node02" labeled

然后通过上面的--show-labels参数可以查看上述标签是否生效。当 node 被打上了相关标签后,在调度的时候就可以使用这些标签了,只需要在 Pod 的spec字段中添加nodeSelector字段,里面是我们需要被调度的节点的 label 即可。比如,要将 Pod 我们要强制调度到 node02 这个节点上去,可以使用 nodeSelector 来表示了:(pod-selector-demo.yaml)

apiVersion: v1
kind: Pod
metadata:labels:app: busybox-podname: test-busybox
spec:containers:- command:- sleep- "3600"image: busyboximagePullPolicy: Alwaysname: test-busyboxnodeSelector:com: yijiadashuju

然后,执行pod-selector-demo.yaml文件后,可以通过下面的命令查看pod运行的节点信息

kubectl get pod -o wide -n default

也可以使用describe命令查看pod被调度到哪个节点上:

$ kubectl create -f pod-selector-demo.yaml
pod "test-busybox" created
$ kubectl describe pod test-busybox
Name:         test-busybox
Namespace:    default
Node:         node02/10.151.30.63
......
QoS Class:       BestEffort
Node-Selectors:  com=youdianzhishi
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300snode.kubernetes.io/unreachable:NoExecute for 300s
Events:Type    Reason                 Age   From               Message----    ------                 ----  ----               -------Normal  SuccessfulMountVolume  55s   kubelet, node02    MountVolume.SetUp succeeded for volume "default-token-n9w2d"Normal  Scheduled              54s   default-scheduler  Successfully assigned test-busybox to node02Normal  Pulling                54s   kubelet, node02    pulling image "busybox"Normal  Pulled                 40s   kubelet, node02    Successfully pulled image "busybox"Normal  Created                40s   kubelet, node02    Created containerNormal  Started                40s   kubelet, node02    Started container

从上面的执行结果可以看出,pod 通过默认的 default-scheduler 调度器到了node02节点上。不过,这种调度方式属于强制性的。如果node02上的资源不足,那么pod的状态将会一直是pending状态。这就是nodeselector的用法了。

通过上面的介绍,可以看出nodeselector使用起来非常方便,但是还有很多的不足,那就是不够灵活,控制粒度偏大,在实际使用中还是有许多的不便。接下来一起看下亲和性和反亲和性调度。

亲和性和反亲和性调度

k8s的默认调度流程实际上是经过了两个阶段:predicates 和 priorities 。使用默认的调度流程的话,k8s会将pod调度到资源充裕的节点上,使用nodeselector的调度方法,又会将pod调度到具有指定标签的pod上。然后在实际生产环境中,我们需要将pod调度到具有某些label的一组node才能满足实际需求,这个时候就需要nodeAffinity(节点亲和性)、podAffinity(pod 亲和性) 以及 podAntiAffinity(pod 反亲和性)。

亲和性可以分为具体可以细分为硬和软两种亲和性,

  • 软亲和性:如果调度的时候,没有满足要求,也可以继续调度,即能满足最好,不能也无所谓
  • 硬亲和性:是指调度的时候必须满足特定的要求,如果不满足,那么pod将不会被调度到当前node

规则可以设置:
软策略: preferredDuringSchedulingIgnoredDuringExecution

硬策略: requiredDuringSchedulingIgnoredDuringExecution

nodeAffinity 节点亲和性

节点亲和性主要是用来控制 pod 能部署在哪些节点上,以及不能部署在哪些节点上的。它可以进行一些简单的逻辑组合了,不只是简单的相等匹配。

接下来看一个示例,使用 Deployment 来管理3个 pod 副本,使用nodeAffinity控制 pod 的调度,如下例子:(node-affinity-demo.yaml

apiVersion: apps/v1beta1
kind: Deployment
metadata:name: affinitylabels:app: affinity
spec:replicas: 3revisionHistoryLimit: 15template:metadata:labels:app: affinityrole: testspec:containers:- name: nginximage: nginx:1.7.9ports:- containerPort: 80name: nginxwebaffinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:  # 硬策略nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostnameoperator: NotInvalues:- node03preferredDuringSchedulingIgnoredDuringExecution:  # 软策略- weight: 1preference:matchExpressions:- key: comoperator: Invalues:- yijiadashuju

这个pod调度的时候,首先要求不能运行在node03节点上,但是如果有节点满足labels为com:yijiadashuju 的话,就会优先调度到这个节点上。

接下来看下节点信息:

$ kubectl get nodes --show-labels
NAME      STATUS    ROLES     AGE       VERSION   LABELS
master    Ready     master    154d      v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=master,node-role.kubernetes.io/master=
node02    Ready     <none>    74d       v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,com=yijiadashuju,course=k8s,kubernetes.io/hostname=node02
node03    Ready     <none>    134d      v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,jnlp=haimaxy,kubernetes.io/hostname=node03

可以看到 node02 节点有com=yijiadashuju的 label,按要求会优先调度到这个节点,接下来创建 pod,然后使用descirbe命令查看调度情况。

$ kubectl create -f node-affinity-demo.yaml
deployment.apps "affinity" created
$ kubectl get pods -l app=affinity -o wide
NAME                        READY     STATUS    RESTARTS   AGE       IP             NODE
affinity-7b4c946854-5gfln   1/1       Running   0          47s       10.244.4.214   node02
affinity-7b4c946854-l8b47   1/1       Running   0          47s       10.244.4.215   node02
affinity-7b4c946854-r86p5   1/1       Running   0          47s       10.244.4.213   node02

从结果可以看到 pod 均被部署到了 node02节点。

现在Kubernetes提供的操作符有下面的几种

In:label 的值在某个标签中
NotIn:label 的值不在某个标签中
Gt:label 的值大于某个值
Lt:label 的值小于某个值
Exists:某个 label 存在
DoesNotExist:某个 label 不存在

如果nodeSelectorTerms下面有多个选项的话,满足任何一个条件就可以了;如果matchExpressions有多个选项的话,则必须同时满足这些条件才能正常调度 POD。

podAffinity pod亲和性

pod的亲和性主要用来解决pod可以和哪些pod部署在同一个集群里面,即拓扑域(由node组成的集群)里面;而pod的反亲和性是为了解决pod不能和哪些pod部署在一起的问题,二者都是为了解决pod之间部署问题。需要注意的是,Pod 间亲和与反亲和需要大量的处理,这可能会显著减慢大规模集群中的调度,不建议在具有几百个节点的集群中使用,而且Pod 反亲和需要对节点进行一致的标记,即集群中的每个节点必须具有适当的标签能够匹配 topologyKey。如果某些或所有节点缺少指定的 topologyKey 标签,可能会导致意外行为。

下面是pod间亲和的示例:

apiVersion: v1
kind: Pod
metadata:name: with-pod-affinity
spec:affinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: securityoperator: Invalues:- S1topologyKey: failure-domain.beta.kubernetes.io/zonepodAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 100podAffinityTerm:labelSelector:matchExpressions:- key: securityoperator: Invalues:- S2topologyKey: failure-domain.beta.kubernetes.io/zonecontainers:- name: with-pod-affinityimage: k8s.gcr.io/pause:2.0

podAntiAffinity pod反亲和性

下面是一个pod反亲和yaml文件示例:

apiVersion: apps/v1
kind: Deployment
metadata:name: redis-cache
spec:selector:matchLabels:app: storereplicas: 3template:metadata:labels:app: storespec:affinity:podAntiAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: appoperator: Invalues:- storetopologyKey: "kubernetes.io/hostname"containers:- name: redis-serverimage: redis:3.2-alpine

Pod Affinity补充

通过《K8S调度之节点亲和性》,我们知道怎么在调度的时候让pod灵活的选择node,但有些时候我们希望调度能够考虑pod之间的关系,而不只是pod与node的关系。于是在kubernetes 1.4的时候引入了pod affinity。

为什么有这样的需求呢?举个例子,我们系统服务 A 和服务 B 尽量部署在同个主机、机房、城市,因为它们网络沟通比较多;再比如,我们系统数据服务 C 和数据服务 D 尽量分开,因为如果它们分配到一起,然后主机或者机房出了问题,会导致应用完全不可用,如果它们是分开的,应用虽然有影响,但还是可用的。

pod affinity 可以这样理解:调度的时候选择(或者不选择)这样的节点 N ,这些节点上已经运行了满足条件 X。条件 X 是一组 label 选择器,它必须指明作用的 namespace(也可以作用于所有的 namespace),因为 pod 是运行在某个 namespace 中的。

这里的X指的是集群中的节点、机架、区域等概念,通过kubernetes内置节点标签中的key来进行声明。这个key的名字为topologyKey,意为表达节点所属的topology范围:

  • kubernetes.io/hostname
  • failure-domain.beta.kubernetes.io/zone
  • failure-domain.beta.kubernetes.io/region

和 node affinity 相似,pod affinity 也有 requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution,意义也和之前一样。如果有使用亲和性,在 affinity 下面添加 podAffinity 字段,如果要使用互斥性,在 affinity 下面添加 podAntiAffinity 字段。

先定义一个参照目标pod:

apiVersion: v1
kind: Pod
metadata:name: pod-flaglabels:security: "S1"app: "nginx"
spec:containers:- name: nginximage: nginx

Pod亲和性调度

下面是一个亲和性调度的示例

apiVersion: v1
kind: Pod
metadata:name: pod-affinity
spec:affinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: securityoperator: Invalues:- S1topologyKey: kubernetes.io/hostnamecontainers:- name: with-pod-affinityimage: gcr.io/google_containers/pause:2.0

创建后可以看到这个pod与上面那个参照的pod位于同一个node上,另外,如果将这个node上的kubernetes.io/hostname标签干掉,将会发现pod会一直处于pending状态,这是因为找不到满足条件的node了。

pod互斥性调度

下面是一个互斥性调度的示例:

apiVersion: v1
kind: Pod
metadata:name: with-pod-affinity
spec:affinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: securityoperator: Invalues:- S1topologyKey: "failure-domain.beta.kubernetes.io/zone"podAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 100podAffinityTerm:labelSelector:matchExpressions:- key: securityoperator: Invalues:- S2topologyKey: kubernetes.io/hostnamecontainers:- name: with-pod-affinityimage: gcr.io/google_containers/pause:2.0

这个例子要求这个新pod与security=S1的pod为同一个zone,但是不与security=S2的pod为同一个node。

原则上,topologyKey可以使用任何合法的标签Key赋值,但是出于性能和安全方面的考虑,对topologyKey有如下限制:

  • 在pod亲和性和RequiredDuringScheduling的pod互斥性的定义中,不允许使用空的topologyKey
  • 如果admission controller包含了LimitPodHardAntiAffinityTopology,那么针对RequiredDuringScheduling的pod互斥性定义就被限制为kubernetes.io/hostname,要使用自定义的topologyKey,就要改写或禁用该控制器
  • 在PerferredDuringScheduling类型的Pod互斥性定义中,空的topologyKey会被解释为kubernetes.io/hostname、failure-domain.beta.kubernetes.io/zone及failure-domain.beta.kubernetes.io/region的组合

podAffinity规则设置的注意事项:

  • 在labelSelector和topologyKey同级,还可以定义namespaces列表,表示匹配哪些namespace里面的pod,默认情况下,会匹配定义的pod所在的namespace,如果定义了这个字段,但是它的值为空,则匹配所有的namespaces。
  • 所有关联requiredDuringSchedulingIgnoredDuringExecution的matchExpressions全都满足之后,系统才能将pod调度到某个node上。

k8s调度之node的亲和性以及pod的亲和性/反亲和性相关推荐

  1. k8s调度之亲和/反亲和

    Pod的调度流程 在k8s集群中kube-scheduler组件负责为Pod选择运行节点,并由对应节点上的kubelet创建Pod.对于每个未绑定至任何节点的Pod对象,无论是新建.被驱逐等,kube ...

  2. Kubernetes调度之亲和性和反亲和性

    背景 Kubernetes中的调度策略可以大致分为两种,一种是全局的调度策略,要在启动调度器时配置,包括kubernetes调度器自带的各种predicates和priorities算法:另一种是运行 ...

  3. K8S调度之pod亲和性

    目录 Pod Affinity Pod亲和性调度 pod互斥性调度 Pod Affinity 通过<K8S调度之节点亲和性>,我们知道怎么在调度的时候让pod灵活的选择node,但有些时候 ...

  4. 【项目实战23】k8s(9)—k8s调度(节点亲和性,Taint污点,pod容忍性)

    k8s调度 一.k8s调度背景介绍 二.nodeName方式调度 三.nodeSelector方式调度 (1).使用方式 (2).节点亲和性 四.Taints污点 (1).介绍 (2).使用 五.to ...

  5. k8s调度(nodeName、nodeSelect、节点、pod的亲和和反亲和、Taints)

    k8s调度 nodeName nodeSelector 亲和与反亲和 节点亲和 pod 亲和性和反亲和性 Taints(污点) 调度器通过 kubernetes 的 watch 机制来发现集群中新创建 ...

  6. k8s(八)—调度因素(nodeName、nodeSelector、亲和与反亲和、Taints 污点)、影响pod调度的指令

    1 调度简介 [root@server2 ~]# kubectl get pod -n kube-system 2 影响kubernetes调度的因素 2.1 nodeName(针对节点) [root ...

  7. k8s node节点停机维护,pod如何迁移?

    需求 k8s集群中的node节点要升级内存,以应对服务迁入.pod扩缩容导致的资源短缺,需要对node节点进行停机维护,那么此时node节点上的pod应该如何处理呢? 下面我们来看一下. 默认迁移 当 ...

  8. Kubernetes对Pod调度指定Node以及Node的Taint 和 Toleration

    1.指定pod到指定的node上 #1.1查看节点的lebel kubectl get nodes --show-labels#1.2获取到该节点的label信息 ip-10-100-2-80 Rea ...

  9. k8s中亲和性与反亲和性

    k8s中亲和性与反亲和性 Kubernetes的默认调度器以预选.优选.选定机制完成将每个新的Pod资源绑定至为其选出的目标节点上,不过,它只是Pod对象的默认调度器,默认情况下调度器考虑的是资源足够 ...

最新文章

  1. 数据通信技术(四:链路聚合)
  2. 基于纯 CSS3 技术实现美观的标签云效果
  3. SAP 采购订单税金抓取方法
  4. 直播预告丨告别后知后觉的指标波动,神策智能预警分析直播来袭
  5. mac的ideal终端中mvn命令不生效 commang not found
  6. 读配置文件能够保持顺序的 Java Properties 类
  7. 纪录片.BBC.数据之趣.The.Joy.of.Data.2016
  8. 什么是响应式设计?为什么要做响应式设计?响应式设计的基本原理是什么?...
  9. 正则表达式的一些符号基础和实例解析
  10. windows下把SD卡格式化成NTFS格式
  11. Mujoco有限状态机以及轨迹追踪
  12. java fly bird小游戏_实战|JavaScript实现Fly Bird小游戏-【安基网】
  13. freemarker的recurse示例代码
  14. 【SAR综述】复杂场景单通道SAR目标检测与鉴别方法
  15. 魅族设置语音录音服务器,魅族手机微信怎么开启录音权限呀有步骤图吗
  16. 袋鼠云数据中台专栏2.0 | 数据中台之数据源
  17. Python入门习题大全——词汇表2
  18. 什么是固态功率放大器?射频固态功率放大器?
  19. 基于javaFX的固定资产管理系统
  20. 如何抓包分析BLE 空口报文(GAP + GATT + LESC procedure)?

热门文章

  1. 【机器学习】异常检测算法速览(Python代码)
  2. 【数据竞赛】2020首届海洋目标智能感知国际挑战赛冠军方案分享
  3. 邹伟博士出书啦!——《强化学习》从基础概念、核心原理到应用案例(文末赠书)...
  4. 入门之路:“机器学习初学者”公众号2019年的精选原创文章
  5. 技术干货 | 高性能短链设计与实现
  6. 申请Let's Encrypt通配符HTTPS证书(转)
  7. PHP 内存泄漏分析定位
  8. Openstack rabbitMQ 安装与配置
  9. CSS深入理解学习笔记之z-index
  10. ADVA收购Overture 扩张NFV产品线