首页 > 其他分享 >k8s之affinity and anti-affinity

k8s之affinity and anti-affinity

时间:2023-09-14 16:04:23浏览次数:33  
标签:标签 cdss 调度 anti io affinity pod k8s 节点

背景介绍:

在k8s环境中,通常情况下,Pod分配到哪些Node是不需要管理员操心的,这个过程会由scheduler调度实现,合理的分配到最优的节点上。但在实际项目中,我们可能需要指定一些调度的限制,例如某些应用需要跑在具有SSD存储或带gpu的节点上,或某些需进行大量计算解析且耗费很多cpu等资源的应用,需要负载均衡的打到集群中的各个节点中,避免调度到同一个node上,影响应用性能;这时候我们就需要用到一些调度机制来干预pod的调度;

nodeSelector

基于上述需求,可能最先想到的是通过nodeSelector来进行调度;基本流程就是给node节点打标签,然后在创建部署的时候,通过使用nodeSelector标签来指定Pod运行在哪些节点上;操作示例如下: 1)给node定义label: 格式:kubectl lable node [node-name] [key=value] image.png

2)通过 --show-labels 可以查看当前nodes的labels: image.png

3)当然,也可通过 kubectl label node 删除指定的 labels (标签 key 接 - 号即可) image.png

4)创建pod,并指定nodeSelector选项绑定节点;示例如下:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: docker.io/nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    gpu: server2

nodeSelector 可以很方便的解决一些简单需求的场景,但是它还不够灵活;比如生产环境中,某个数据治理服务,按需开了12个replicas,需要平均的分散到各个服务器节点上;此时 nodeSelector可能就没办法满足了。因此,kubernetes引入了亲和性和反亲和性的概念。

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

nodeSelector的调度方式略显简单,通过亲和和反亲和配置,能够为调度提供更灵活的策略,主要有以下几点增强:

  • 1,不仅仅是"与"的逻辑操作,支持更多的逻辑表达式。
  • 2,nodeSelect是硬性要求,亲和与反亲和支持软硬两种要求;
  • 3,除了节点标签,亲和与反亲和支持根据节点上已经部署的pod进行节点选择(比如不想将两个计算密集类型的pod部署在同一节点上,后部署pod可选择过滤)。

细分成两种类型的选择器: "节点亲和" 与 "内部pod亲和,反亲和"。节点亲和与nodeSelector相似,具备上述1,2两条优点。内部pod亲和依赖的是节点上已有pod的标签而不是节点的标签;兼具上述三个优点。因为节点亲和能完成nodeSelector所工作并且具备额外的优点。

1,Node affinity(节点亲和) node affinity支持两种形式:

  • requiredDuringSchedulingIgnoredDuringExecution (硬限制, 同nodeSelector)
  • preferredDuringSchedulingIgnoredDuringExecution(软限制) 前一种是必须满足,如果不满足则不进行调度(未调度的pod状态为pending);后一种是倾向满足,不满足的情况下pod会调度到不符合条件的node上。

IgnoreDuringExecution 表示如果在pod运行期间node的标签发生变化,导致亲和性策略不能满足,则继续运行在当前的pod; 示例如下:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:   //硬限制
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - cdss-server1
            - cdss-server2    
preferredDuringSchedulingIgnoredDuringExecution:    //软限制
      - weight: 1               //取值范围1-100
        preference:
          matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - cdss-server3
  containers:
  - name: nginx
    image: docker.io/nginx

以上规则表达的意思是,该pod只能调度到拥有 kubernetes.io/hostname=cdss-server1kubernetes.io/hostname=cdss-server2 标签的节点上,其中在满足之前标签条件的同时更倾向于调度在拥有kubernetes.io/hostname=cdss-server3标签的节点上。

标签判断的操作符除了使用In之外,还支持以下运算符:NotIn,Exists,DoesNotExist,Gt,Lt;可以使用NotIn和DoesNotExist实现节点的反亲和行为。

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

调度匹配规则Notice: 1)如果同时指定nodeSelector和nodeAffinity,则必须满足两个条件,才能将pod调度到候选节点上。

2)如果nodeAffinity类型下指定了多个nodeSelectorTerms对象【对象不能有多个,如果存在多个只有最后一个生效】,那么只有最后一个nodeSelectorTerms对象生效。

3)如果在nodeSelectorTerms下指定了多个matchExpressions列表,那么只要能满足其中一个matchExpressions,就可以将pod调度到某个节点上【针对节点硬亲和】 image.png

4)如果在matchExpressions下有多个key列表,那么只有当所有key满足时,才能将pod调度到某个节点【针对硬亲和】 image.png

5)在key下的values只要有一个满足条件,那么当前的key就满足条件 image.png

6)如果pod已经调度在该节点,当我们删除或修改该节点的标签时,pod不会被移除;也就是亲和性选择只有在pod调度期间有效,添加完affinity后需要使其重新调度生效

7)软亲和中的weight(权重)字段在1-100范围内。对于每个满足所有调度需求的节点,调度器将通过迭代该字段的元素来计算一个总和,如果节点与相应的匹配表达式匹配,则向该总和添加 "权重",然后将该分数与节点的其他优先级函数的分数结合起来,总得分最高的节点是最受欢迎的。

pod affinity/anti-affinity (pod亲和/反亲和)

这个特性是kubeernetes1.4后增加的。Pod 间亲和性与反亲和性使你可以基于已经在节点上运行的 Pod 的标签来约束 Pod 可以调度到的节点,而不是基于节点上的标签。 规则的形式是:如果X已经运行了一个或多个符合规则Y的pod,则此pod应该在X中运行(如果是反亲和的情况下,则不应该在X中运行)。当然pod必须处在同一名称空间,不然亲和性/反亲和性无作用。从概念上讲,X是一个拓扑域。我们可以使用topologyKey来表示它,topologyKey 的值是node节点标签的键以便系统用来表示这样的拓扑域。当然这里也有个隐藏条件,就是node节点标签的键值相同时,才是在同一拓扑域中;如果只是节点标签名相同,但是值不同,那么也不在同一拓扑域。也就是说 pod的亲和性/反亲和性调度是根据拓扑域来界定调度的,而不是根据node节点

同node affinity,pod亲和性和反亲和也有两种类型:

  • requiredDuringSchedulingIgnoredDuringExecution,硬性要求,必须精确匹配
  • preferredDuringSchedulingIgnoredDuringExecution,软性要求

notice: 1)pod亲和性和反亲和性需要大量的计算,会显著降低集群的调度速度,不建议在数百个节点的集群中使用。 2)pod反亲和性要求集群中的所有节点必须具有topologykey 匹配的标签,否则可能会导致意外情况发生。 //示例如下:

apiVersion: v1
kind: Pod
metadata:
  name: cdss-deploy
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - cdss-server1
        topologyKey: "kubernetes.io/hostname"  
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:  //生产环境中反亲和建议使用"软亲和",否则会导致不符合条件的pod pending;                                                                                                                                                                                                                                                                                                                                                                gnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - cdss-standard-baidu-cdss-cdss-server       //service name
          topologyKey: "kubernetes.io/hostname"
          namespaces: [baidu-cdss]    //需指定生效于pod所运行的namespace
  containers:
  - name: cdss-deploy
    image: k8s.gcr.io/pause:2.0

dbe01d3b63de5e25c4423c6f6d0598f.jpg 以上示例分别表示pod的亲和和反亲和;首先pod必须调度在至少运行一个kubernetes.io/hostname=cdss-server1 标签的pod的节点上(更准确的说,这个pod可以运行在节点N上,如果该节点有topologyKeykubernetes.io/hostname,而且运行着标签为kubernetes.io/hostname=cdss-server1的实例)

反亲和的规则表示:最好不要调度到运行·有app=cdss-standard-baidu-cdss-cdss-server 标签的pod的节点上。(更准确的说,如果这个节点拥有topologyKey为kubernetes.io/hostname,但运行有app=cdss-standard-baidu-cdss-cdss-server标签的pod,那么这个节点就不会被优化选择调度);有效限制创建的实例的时候,如果节点上已经存在具有相同标签的实例,则不进行调度,避免了一个节点上部署多个相同的实例;

总结:

podAffinity(pod亲和) 和 podAntiAffinity(pod反亲和)支持 In, NotIn, Exists,DoesNotExist 四种表达式。

原则上,topologykey 可以为任何合法的键值对。但是因为性能和安全的原因,有以下限制:

  • 1,针对 podAffinity 和 podAntiAffinity 中的requiredDuringSchedulingIgnoredDuringExecution(硬限制)preferredDuringSchedulingIgnoredDuringExecution(软限制), topologyKey为空是不允许的。

  • 2,针对 podAntiAffinity 中的requiredDuringSchedulingIgnoredDuringExecution ,准入控制器选项LimitPodHardAntiAffinityTopology 可以把 topologyKey 限制为 kubernetes.io/hostname ,如果想自定义值,可以修改准入控制器或者直接禁用。

  • 3,除上述情况外,topologyKey 可以为任意合法的键值对。

除了 labelSelectortopologyKey,你也可以指定 labelSelector 作为匹配。labelSelectortopologykey 属于同一级别,如果未定义或设置为空值,那么默认为定义 pod affinity亲和 和 anti-affinity 反亲和所在的空间。

更多案例及内容参考官方文档: https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity

标签:标签,cdss,调度,anti,io,affinity,pod,k8s,节点
From: https://blog.51cto.com/u_13972012/7470862

相关文章

  • k8s安装kube-promethues(0.7版本)
    k8s安装kube-promethues(0.7版本)一.检查本地k8s版本,下载对应安装包kubectlversion如图可见是1.19版本进入kube-promethus下载地址,查找自己的k8s版本适合哪一个kube-promethues版本。然后下载自己合适的版本#还可以通过如下地址,在服务器上直接下已经打包好的包。或者复......
  • k8s笔记14
    摘要:多播路由守护程序;autogen;SMCRoute;pimd;mrouted;mcjointroglobit/pim6sd:PIMforIPv6sparsemodedaemon(github.com)Tip:为了安1、pim6sd自动将自身配置为在所有支持多播的接口interfaces(IFF_MULTICASTflag)上转发 forward,即设置了IFF_MULTICAST标志的接口(不包括excluding......
  • K8S系列(八)持久化存储(Pod Volumes,PV和PVC)
    一、概述:官方文档:https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/在kubernetes集群中,使用subPath,有时,在单个Pod中共享卷以供多方使用是很有用的。volumeMounts.subPath属性可用于指定所引用的卷内的子路径,而不是其根路径。1、subPath是在挂载的卷......
  • k8s Pod管理脚本
    1.背景场景:1  测试环境k8s集群中例如业务启动的pod长时间没有进行维护导致僵死场景:2pod输出的日志文件太多量太大导致日志收集容器出现收集不到或者日志内容延迟的相关问题. 场景:3应用多容器采用pod代理管控流量方式代码层面导致容器连接长时间失败. 故  1.降低人工......
  • 注册到K8S上的Nacos报错com.alibaba.nacos.api.exception.NacosException: Client not
    契机近期升级SpringCloudAlibaba版本,从2021.0.1.0升级到2021.0.5问题现象注册到K8S平台上2.1.2版本的Nacos报错,错误信息如下:2023-09-1309:29:53.712INFO19988—[main]c.a.n.p.a.s.c.ClientAuthPluginManager:ClientAuthPluginManagerLoadClientAuthServiceco......
  • 如何像 Sealos 一样在浏览器中打造一款 K8s 终端?
    在Kubernetes的世界中,命令行工具(如kubectl和helm)是我们与集群交互的主要方式。然而,有时候,我们可能希望能够在Web页面中直接打开一个终端,执行这些命令,而不需要在本地环境中安装和配置这些工具。本文将深入探讨如何通过Kubernetes自定义资源定义(CRD)实现这个功能,并通过一个真......
  • 解决部署K8S无法拉取镜像问题,K8S拉取离线镜像
    #catpull-images.sh#阿里云镜像#!/bin/bashimages=(kube-apiserver:v1.18.0kube-controller-manager:v1.18.0kube-scheduler:v1.18.0kube-proxy:v1.18.0pause:3.2etcd:3.4.3-0coredns:1.6.7)forimageNamein${images[@]};dodo......
  • K8S集群常见问题总结 集群服务访问失败 集群服务访问失败 集群服务暴露失败 外网无法
    问题1:K8S集群服务访问失败?原因分析:证书不能被识别,其原因为:自定义证书,过期等。解决方法:更新证书即可。问题2:K8S集群服务访问失败?curl:(7)Failedconnectto10.103.22.158:3000;Connectionrefused原因分析:端口映射错误,服务正常工作,但不能提供服务。解决方法:删除svc,重新映射端口......
  • K8s kubectl管理工具使用技巧
    kubectl是K8s官方附带的命令行工具,可以方便的操作K8s集群.这篇文章主要介绍一些kubectl的别样用法,希望读者有基础的K8s使用经验.打印当前使用的API#kubectl的主要作用就是与ApiServer进行交互,而交互的过程,我们可以通过下面的方式来打印,#这个命令尤其适合调试自己的a......
  • k8s集群-spring cloud 集成seata的时候:can not register RM,err:can not connect to s
    背景说明seate和其他微服务在k8s集群中部署,都在同一个命名空间。注册到nacos的同一个命名空间seate是官方提供,无改动k8s中部署情况:报错提示core服务的报错内容:2023-09-1211:07:06.524ERROR7---[eoutChecker_2_1]i.s.c.r.netty.NettyClientChannelManager:0101c......