本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。

Kubernetes 1.31:PodAffinity 中的 MatchLabelKeys 进阶至 Beta

Kubernetes 1.29 在 podAffinitypodAntiAffinity 中引入了新的字段 matchLabelKeysmismatchLabelKeys

在 Kubernetes 1.31 中,此功能进入 Beta 阶段,并且相应的功能门控(MatchLabelKeysInPodAffinity)默认启用。

matchLabelKeys - 增强调度以实现灵活的滚动更新

在工作负载(例如 Deployment)滚动更新期间,集群中可能同时存在多个版本的 Pod。然而,调度器无法根据 podAffinitypodAntiAffinity 中指定的 labelSelector 来区分新旧版本。因此,它会不分版本地将 Pod 部署在一起或分散开来。

这可能导致不理想的调度结果,例如:

  • 新版本的 Pod 与旧版本的 Pod 部署在一起(podAffinity),而旧版本的 Pod 在滚动更新后最终会被移除。
  • 旧版本的 Pod 分布在所有可用的拓扑域中,导致新版本的 Pod 因为 podAntiAffinity 规则而找不到合适的节点。

matchLabelKeys 是一组 Pod 标签键,用于解决此问题。调度器会从新 Pod 的标签中查找这些键的值,并将它们与 labelSelector 结合起来,这样 podAffinity 就能匹配那些在标签中具有相同键值的 Pod。

通过在 matchLabelKeys 中使用标签 pod-template-hash,你可以确保只有相同版本的 Pod 会被用于 podAffinitypodAntiAffinity 的评估。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: application-server
...
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - database
        topologyKey: topology.kubernetes.io/zone
        matchLabelKeys:
        - pod-template-hash

上述 matchLabelKeys 在 Pod 中会被转换成类似下面的形式:

kind: Pod
metadata:
  name: application-server
  labels:
    pod-template-hash: xyz
...
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - database
          - key: pod-template-hash # Added from matchLabelKeys; Only Pods from the same replicaset will match this affinity.
            operator: In
            values:
            - xyz
        topologyKey: topology.kubernetes.io/zone
        matchLabelKeys:
        - pod-template-hash

mismatchLabelKeys - 服务隔离

mismatchLabelKeys 是一组 Pod 标签键,与 matchLabelKeys 类似,它会从新 Pod 的标签中查找这些键的值,并将其作为 key notin (value) 合并到 labelSelector 中,以便 podAffinity 规则*不*匹配那些在标签中具有相同键值的 Pod。

假设每个租户的所有 Pod 都通过控制器或像 Helm 这样的清单管理工具获得了 tenant 标签。

尽管在编写每个工作负载的清单时 tenant 标签的值是未知的,但集群管理员希望为租户隔离实现独占的 1:1 租户到域的放置。

mismatchLabelKeys 在这种用例中非常有效;通过使用 Mutating Webhook 全局应用以下亲和性规则,集群管理员可以确保来自同一租户的 Pod 将被独占地部署到同一个域中,这意味着其他租户的 Pod 不会部署到该域中。

affinity:
  podAffinity:      # ensures the pods of this tenant land on the same node pool
    requiredDuringSchedulingIgnoredDuringExecution:
    - matchLabelKeys:
        - tenant
      topologyKey: node-pool
  podAntiAffinity:  # ensures only Pods from this tenant lands on the same node pool
    requiredDuringSchedulingIgnoredDuringExecution:
    - mismatchLabelKeys:
        - tenant
      labelSelector:
        matchExpressions:
        - key: tenant
          operator: Exists
      topologyKey: node-pool

上述 matchLabelKeysmismatchLabelKeys 会被转换成类似下面的形式:

kind: Pod
metadata:
  name: application-server
  labels:
    tenant: service-a
spec: 
  affinity:
    podAffinity:      # ensures the pods of this tenant land on the same node pool
      requiredDuringSchedulingIgnoredDuringExecution:
      - matchLabelKeys:
          - tenant
        topologyKey: node-pool
        labelSelector:
          matchExpressions:
          - key: tenant
            operator: In
            values:
            - service-a 
    podAntiAffinity:  # ensures only Pods from this tenant lands on the same node pool
      requiredDuringSchedulingIgnoredDuringExecution:
      - mismatchLabelKeys:
          - tenant
        labelSelector:
          matchExpressions:
          - key: tenant
            operator: Exists
          - key: tenant
            operator: NotIn
            values:
            - service-a
        topologyKey: node-pool

参与进来

这些功能由 Kubernetes SIG Scheduling 管理。

请加入我们并分享你的反馈。我们期待你的回音!

我如何了解更多信息?