2025,每天10分钟,跟我学K8S(二十七)- 对象属性 - 亲和性(Affinity)​ 和 ​反亲和性(Anti-Affinity)

        上一章节了解了pod对node节点的选择,可以通过nodeSelector来进行选择节点进行部署,这一章节讲解另一种操作更精细化调度的属性:亲和性(Affinity)​ 和 ​反亲和性(Anti-Affinity)。

        在 Kubernetes 中,​亲和性(Affinity)​ 和 ​反亲和性(Anti-Affinity)​ 是控制 Pod 调度的核心机制,通过标签匹配实现资源的智能分布。

一、核心概念与分类

1. ​亲和性(Affinity)​
  • ​定义:通过规则定义 Pod 调度的偏好,使 Pod ​趋向于与特定节点或 Pod 共存。
  • ​分类:
    • ​节点亲和性(Node Affinity)​:基于节点标签调度,例如将 GPU 计算任务调度到带有 gpu=true 标签的节点。
    • ​Pod 亲和性(Pod Affinity)​:基于已存在 Pod 的标签调度,例如将前端服务与缓存服务部署到同一节点以减少网络延迟。
2. ​反亲和性(Anti-Affinity)​
  • ​定义:通过规则定义 Pod 调度的排斥,使 Pod ​远离特定节点或 Pod。
  • ​分类:
    • 节点反亲和性:避免调度到特定标签的节点(如 zone=us-west)。
    • ​Pod 反亲和性:确保 Pod 分散到不同节点或拓扑域,例如数据库主从分离部署。

二、调度规则类型

1. ​硬性约束(Required)​
  • ​作用:​必须满足的条件,否则 Pod 无法调度。
  • ​语法示例:强制调度到 标签为 env=prod的node节点:
nodeAffinity:
  requiredDuringSchedulingIgnoredDuringExecution:
    nodeSelectorTerms:
      - matchExpressions:
          - key: env
            operator: In
            values: [prod]
    1.1.nodeAffinity​举例说明:
    # cat required.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      name: required-affinity-demo
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:  # 硬性约束
            nodeSelectorTerms:
            - matchExpressions:
              - key: env
                operator: In
                values: [prod]  # 必须调度到 env=prod 的节点
      containers:
      - name: nginx
        image: m.daocloud.io/docker.io/nginx
    

    通过下图可以看到,pod启动在node01这个节点,而这个节点我们上一章节的时候打标过env=prod,并且成功分配到了想要去的node节点

      1.2.podAffinity​举例说明:

      上面是针对node进行打标亲和性,下面讲解一个针对pod进行打标亲和性

       先将一个已经存在的pod进行打标 <app=nginx2>

      kubectl label pod required-affinity-demo app=nginx2

      查看yaml文件

      # cat preferred.yaml 
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: web-app
      spec:
        replicas: 3
        selector:
          matchLabels:
            app: web
        template:
          metadata:
            labels:
              app: web
          spec:
            affinity:
              podAffinity:
                requiredDuringSchedulingIgnoredDuringExecution:  # 硬性约束
                  - labelSelector:
                      matchExpressions:
                        - key: app
                          operator: In
                          values: [nginx2]  # 必须与带有 app=nginx2 的 Pod 共存
                    topologyKey: kubernetes.io/hostname  # 同一节点拓扑域
            containers:
              - name: web-container
                image: m.daocloud.io/docker.io/nginx:latest
      

      通过下图可以看到,已经和想要分配的pod分配到了一起。

      2. ​软性偏好(Preferred)​
      • ​作用:​优先满足的条件,若无匹配则降级调度。
      • ​语法示例:优先调度到env=dev的node节点:

      特别说明:由于现在的环境只有一个master和一个node,默认master是不允许分配pod节点的,而env=dev又恰好是master节点的标签。所以这里需要提前将master设置为允许调度。

      查看master是否允许调度

      # 查看master节点是否允许调度,如果出现下面就说明不允许调度
      # kubectl describe nodes k8s-master | grep Taint
      Taints:             node-role.kubernetes.io/control-plane:NoSchedule
      
      
      # 设置master允许调度节点
      # kubectl taint nodes k8s-master node-role.kubernetes.io/control-plane:NoSchedule-
      node/k8s-master untainted
      

      2.1 node节点的软性偏好

      查看yaml文件并应用

      # cat preferred.yaml 
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: nginx-preferred-demo
        labels:
          app: nginx
      spec:
        replicas: 3
        selector:
          matchLabels:
            app: nginx
        template:
          metadata:
            labels:
              app: nginx
          spec:
            affinity:
              nodeAffinity:  # 节点亲和性软性偏好
                preferredDuringSchedulingIgnoredDuringExecution:
                  - weight: 80  # 权重越高优先级越高(范围1-100)
                    preference:
                      matchExpressions:
                        - key: env
                          operator: In
                          values: [dev]  # 优先调度到 env=dev 节点
            containers:
              - name: nginx
                image: m.daocloud.io/docker.io/nginx
                ports:
                  - containerPort: 80
      

      验证结果,发现确实都调度到了master上

      2.2 pod节点的软性偏好

              上面的2个例子都是针对node的选择,那是否可以针对pod进行选择,答案当然也是可以。

      先将一个已经存在的pod进行打标 <app=nginx2>,这一操作上面已经操作过,这里不再重复演示

      查看yaml文件

      # cat preferred2.yaml 
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: nginx-preferred-pod-demo
        labels:
          app: nginx
      spec:
        replicas: 3
        selector:
          matchLabels:
            app: nginx
        template:
          metadata:
            labels:
              app: nginx
          spec:
            affinity:
              podAffinity:  # Pod 反亲和性软性偏好
                preferredDuringSchedulingIgnoredDuringExecution:
                  - weight: 100
                    podAffinityTerm:
                      labelSelector:
                        matchExpressions:
                          - key: app
                            operator: In
                            values: [nginx2]  # 选择app=nginx2的标签
                      topologyKey: kubernetes.io/hostname  # 拓扑域为节点级别
            containers:
              - name: nginx
                image: m.daocloud.io/docker.io/nginx
                ports:
                  - containerPort: 80
      

      查看结果,新创建的pod确实和打标的pod在一起

      3. 反亲和性(Anti-Affinity)

      学了上面的亲和性案例,那顾名思义就知道反亲和性就是指不分配到打标的pod一起。

      3.1. 硬性约束

      yaml演示:

      apiVersion: v1
      kind: Pod
      metadata:
        name: example-pod
      spec:
        affinity:
          podAntiAffinity:
            requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - nginx2
              topologyKey: "kubernetes.io/hostname" # 同一节点,在这里表示禁止同一节点部署多个pod
        containers:
        - name: myapp-container
          image: m.daocloud.io/docker.io/nginx
      

      查看结果,确实没有和app=nginx2的pod分配到一个节点上

      3.2. 软性约束

      yaml演示:

      # cat anti2.yaml 
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: my-app
      spec:
        replicas: 3
        selector:
          matchLabels:
            app: nginx
        template:
          metadata:
            labels:
              app: nginx
          spec:
            affinity:
              podAntiAffinity:
                preferredDuringSchedulingIgnoredDuringExecution:  # 软亲和性规则
                  - weight: 100  # 权重值(范围 1-100)
                    podAffinityTerm:
                      labelSelector:
                        matchExpressions:
                          - key: app
                            operator: In
                            values: [nginx2]
                      topologyKey: kubernetes.io/hostname  # 拓扑域(如节点、可用区)
            containers:
              - name: app
                image: m.daocloud.io/docker.io/nginx
      

      结果验证,与我们规划的一致,没有调度到app=nginx2的pod所在的node上

      三、关键配置参数

      1. ​标签选择器(Label Selector)​
      • ​操作符:
        • In:标签值匹配(如 app=nginx)。
        • NotIn:标签值不匹配。
        • Exists/DoesNotExist:标签键是否存在(不关注值)。
      • ​示例:匹配标签 app=backend 的 Pod:
      labelSelector:
        matchExpressions:
          - key: app
            operator: In
            values: [backend]
      2. ​拓扑域(Topology Key)​
      • ​作用:定义调度规则的生效范围,决定 Pod 分布的粒度。
      • ​常用值:
        • kubernetes.io/hostname:单节点。
        • failure-domain.beta.kubernetes.io/zone:可用区。
        • failure-domain.beta.kubernetes.io/region:地域。
      • ​示例:跨可用区部署数据库副本:
      podAntiAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          - topologyKey: failure-domain.beta.kubernetes.io/zone

      四、典型应用场景

      1. ​高可用性设计
      • ​Pod 反亲和性:将同一应用的多个副本分散到不同节点或可用区,避免单点故障。
      podAntiAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
                - key: app
                  operator: In
                  values: [my-app]
            topologyKey: kubernetes.io/hostname
      2. ​资源优化
      • ​节点亲和性:将计算密集型任务(如 AI 训练)调度到 GPU 节点,存储任务调度到 SSD 节点。
      3. ​服务协同
      • ​Pod 亲和性:将关联服务(如前端与缓存)部署到同一节点,减少网络延迟:
      podAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
                - key: tier
                  operator: In
                  values: [cache]
            topologyKey: kubernetes.io/hostname
        4. ​多租户隔离
        • ​节点反亲和性:将不同团队的 Pod 隔离到不同节点,避免资源争抢。

        五、注意事项与调试

        1. ​常见问题
        • ​调度失败:检查标签是否匹配(kubectl describe pod 查看 Events 报错)。
        • ​规则冲突:硬性规则优先级高于软性规则,需避免矛盾配置。
        • ​拓扑域不匹配:确保 topologyKey 对应的标签已正确标注在节点上。
        2. ​最佳实践
        • ​标签标准化:使用 env=prodapp=frontend 等统一命名规范。
        • ​动态调整:节点标签更新后,需重新调度 Pod(如删除后重建)。
        • ​组合策略:先通过反亲和性分散 Pod,再通过亲和性优化局部性能。

        六、与 nodeSelector 的对比

        ​特性nodeSelector亲和性/反亲和性
        ​灵活性仅支持简单键值匹配支持复杂逻辑(AND/OR、权重)
        ​拓扑域支持不支持支持跨节点、可用区、地域
        ​策略类型仅硬性约束支持硬性约束 + 软性偏好

        通过灵活运用亲和性与反亲和性,可实现集群资源的精细化调度,平衡性能、可用性与成本。实际配置时需结合业务需求,优先保障关键服务的稳定性。

        评论
        添加红包

        请填写红包祝福语或标题

        红包个数最小为10个

        红包金额最低5元

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

        抵扣说明:

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

        余额充值