k8s中topologyKey 的作用

发布于:2025-07-03 ⋅ 阅读:(24) ⋅ 点赞:(0)
spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: rcs-msg-notify-prod
                    operator: In
                    values:
                      - 'true'
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector: {}
              topologyKey: rcs-msg-notify-prod
        podAntiAffinity: {}

topologyKey 的作用

一、topologyKey 的核心作用

topologyKey 通过 节点的标签(Label) 划分逻辑上的“拓扑域”,用于实现:

  1. Pod 亲和性(PodAffinity)

    • 将 Pod 调度到与目标 Pod 相同的拓扑域(例如同一机架、可用区或自定义分组)。

  2. Pod 反亲和性(PodAntiAffinity)

    • 阻止 Pod 调度到与目标 Pod 相同的拓扑域(例如避免单节点或单可用区部署)。


二、topologyKey 的值来源

topologyKey 的值是 节点标签的键(Key),可以是:

  1. Kubernetes 内置标签

    • kubernetes.io/hostname(节点主机名,粒度最细)

    • topology.kubernetes.io/zone(可用区,如 AWS 的 us-east-1a

    • topology.kubernetes.io/region(地域,如 us-east-1

topologyKey 是 Pod 亲和性/反亲和性规则中用于定义"拓扑域"的节点标签键。它决定了如何将节点分组以实现 Pod 的共置或隔离:

  1. 当两个 Pod 在具有相同 topologyKey 值的节点上时,它们被视为在同一拓扑域中

  2. 对于 podAffinity,Kubernetes 会尝试将 Pod 调度到与指定 Pod 在同一拓扑域的节点上

  3. 对于 podAntiAffinity,Kubernetes 会确保 Pod 不会被调度到与指定 Pod 在同一拓扑域的节点上

调度器如何工作

当调度器决定pod调度到哪里时,它首先检查pod的podAffinity配置,找 出那些符合标签选择器的pod, 接着查询这些pod运行在哪些节点上。特别的是, 它会寻找标签能匹配podAffinity配置中topologyKey的节点。接着,它会优 先选择所有的标签匹配pod的值的节点。

配置详细解释

nodeAffinity 部分

nodeAffinity:
  requiredDuringSchedulingIgnoredDuringExecution:
    nodeSelectorTerms:
      - matchExpressions:
          - key: rcs-msg-notify-prod
            operator: In
            values:
              - 'true'
  • 含义:Pod 必须被调度到带有标签 rcs-msg-notify-prod=true 的节点上

  • requiredDuringSchedulingIgnoredDuringExecution 表示这是硬性要求,调度时必须满足

podAffinity 部分

podAffinity:
  requiredDuringSchedulingIgnoredDuringExecution:
    - labelSelector: {}
      topologyKey: rcs-msg-notify-prod
  • 含义:Pod 必须与集群中所有其他 Pod 部署在相同拓扑域(即具有相同 rcs-msg-notify-prod 标签值的节点上)

  • labelSelector: {} 匹配所有 Pod,因为没有指定具体标签

  • topologyKey: rcs-msg-notify-prod 表示使用节点的 rcs-msg-notify-prod 标签作为拓扑域

podAntiAffinity 部分

podAntiAffinity: {}
  • 这是一个空配置,表示没有 Pod 反亲和性规则

综合理解

这个配置的整体效果是:

  1. Pod 只能被调度到带有 rcs-msg-notify-prod=true 标签的节点上

  2. Pod 必须与所有其他 Pod 部署在相同拓扑域(即所有 Pod 都在具有相同 rcs-msg-notify-prod 标签值的节点上)

注意:这里的 podAffinity 配置有些特殊,因为它使用了空标签选择器匹配所有 Pod,这可能导致调度困难,除非集群中所有节点都有相同的 rcs-msg-notify-prod 标签值。

当前的设置并不能避免相同的 Pod 调度到同一个节点上。以下是详细分析:


为什么当前配置不能防止相同 Pod 调度到同一节点?

  1. 缺少 podAntiAffinity 规则
    您当前的 podAntiAffinity: {} 是空的,没有定义任何反亲和性规则。要阻止相同 Pod 调度到同一节点,必须明确配置反亲和性。

  2. podAffinity 的作用是共置(co-location),而非隔离
    当前的 podAffinity 只是强制 Pod 必须调度到具有相同 rcs-msg-notify-prod 标签值的节点,但不会阻止相同 Pod 部署到同一节点。

  3. topologyKey 在 podAffinity 中的用途

    • 它仅定义“拓扑域”(如节点、机架、区域等),而不是 Pod 之间的排斥规则。

    • 当前的 topologyKey: rcs-msg-notify-prod 仅确保 Pod 调度到具有相同 rcs-msg-notify-prod 标签值的节点,但不会限制同一节点上的副本数量。


如何修改配置以避免相同 Pod 调度到同一节点?

如果希望 相同的 Pod 不被调度到同一个节点(例如避免单点故障),需要配置 podAntiAffinity,例如:

方案 1:硬性反亲和性(不允许同一节点调度)
affinity:
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:  # 硬性要求
      - labelSelector:
          matchLabels:
            app: your-pod-label  # 替换为您的 Pod 标签
        topologyKey: kubernetes.io/hostname  # 以节点主机名为拓扑域
方案 2:软性反亲和性(尽量不调度到同一节点)
affinity:
  podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:  # 软性偏好
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchLabels:
              app: your-pod-label
          topologyKey: kubernetes.io/hostname

关键点说明

  1. topologyKey 的选择

    • 如果使用 kubernetes.io/hostname,则反亲和性针对单个节点(最严格)。

    • 如果使用其他标签(如 zone),则反亲和性会作用于更广的拓扑域(如整个可用区)。

  2. labelSelector 必须匹配 Pod 标签
    您需要确保 matchLabels 中的标签与您的 Pod 模板中定义的标签一致,例如:

    metadata:
      labels:
        app: your-pod-label  # 需与反亲和性规则匹配
  3. nodeAffinity 和 podAntiAffinity 可以共存
    您的原有 nodeAffinity 可以保留,只需补充 podAntiAffinity 即可。


最终建议配置

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
        - matchExpressions:
            - key: rcs-msg-notify-prod
              operator: In
              values:
                - "true"
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchLabels:
            app: your-pod-label  # 替换为您的实际 Pod 标签
        topologyKey: kubernetes.io/hostname  # 确保不调度到同一节点

这样既能满足节点亲和性要求,又能避免相同 Pod 调度到同一节点。