diff --git a/content/zh-cn/blog/_posts/2024-08-16-matchlabelkeys-podaffinity.md b/content/zh-cn/blog/_posts/2024-08-16-matchlabelkeys-podaffinity.md new file mode 100644 index 0000000000..a7a5e72339 --- /dev/null +++ b/content/zh-cn/blog/_posts/2024-08-16-matchlabelkeys-podaffinity.md @@ -0,0 +1,240 @@ +--- +layout: blog +title: 'Kubernetes 1.31:podAffinity 中的 matchLabelKeys 进阶至 Beta' +date: 2024-08-16 +slug: matchlabelkeys-podaffinity +author: > + Kensei Nakada (Tetrate) +--- + + + +Kubernetes 1.29 在 podAffinity 和 podAntiAffinity 中引入了新的字段 `matchLabelKeys` 和 `mismatchLabelKeys`。 + +在 Kubernetes 1.31 中,此特性进阶至 Beta,并且相应的特性门控(`MatchLabelKeysInPodAffinity`)默认启用。 + + +## `matchLabelKeys` - 为多样化滚动更新增强了调度 + +在工作负载(例如 Deployment)的滚动更新期间,集群中可能同时存在多个版本的 Pod。 +然而,调度器无法基于 podAffinity 或 podAntiAffinity 中指定的 `labelSelector` 区分新旧版本。 +结果,调度器将并置或分散调度 Pod,不会考虑这些 Pod 的版本。 + + +这可能导致次优的调度结果,例如: + +- 新版本的 Pod 与旧版本的 Pod(podAffinity)并置在一起,这些旧版本的 Pod 最终将在滚动更新后被移除。 +- 旧版本的 Pod 被分布在所有可用的拓扑中,导致新版本的 Pod 由于 podAntiAffinity 无法找到节点。 + + +`matchLabelKeys` 是一组 Pod 标签键,可以解决上述问题。 +调度器从新 Pod 的标签中查找这些键的值,并将其与 `labelSelector` 结合, +以便 podAffinity 匹配到具有相同标签键值的 Pod。 + +通过在 `matchLabelKeys` 中使用标签 +[pod-template-hash](/zh-cn/docs/concepts/workloads/controllers/deployment/#pod-template-hash-label), +你可以确保对 podAffinity 或 podAntiAffinity 进行评估时仅考虑相同版本的 Pod。 + +```yaml +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 +``` + + +上述 Pod 中的 `matchLabelKeys` 将被转换为: + + +```yaml +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 # 从 matchLabelKeys 添加; 只有来自同一 ReplicaSet 的 Pod 将与此亲和性匹配 + operator: In + values: + - xyz + topologyKey: topology.kubernetes.io/zone + matchLabelKeys: + - pod-template-hash +``` + + +## `mismatchLabelKeys` - 服务隔离 + +`mismatchLabelKeys` 是一组 Pod 标签键,类似于 `matchLabelKeys`, +它在新 Pod 的标签中查找这些键的值,并将其与 `labelSelector` 合并为 `key notin (value)`, +以便 podAffinity **不**会匹配到具有相同标签键值的 Pod。 + +假设每个租户的所有 Pod 通过控制器或像 Helm 这样的清单管理工具得到 `tenant` 标签。 + + +尽管在组合每个工作负载的清单时,`tenant` 标签的值是未知的, +但集群管理员希望实现租户与域之间形成排他性的 1:1 对应关系,以便隔离租户。 + +`mismatchLabelKeys` 适用于这一使用场景; +通过使用变更性质的 Webhook 在全局应用以下亲和性, +集群管理员可以确保来自同一租户的 Pod 将以独占方式落到同一域上, +这意味着来自其他租户的 Pod 不会落到同一域上。 + + +```yaml +affinity: + podAffinity: # 确保此租户的 Pod 落在同一节点池上 + requiredDuringSchedulingIgnoredDuringExecution: + - matchLabelKeys: + - tenant + topologyKey: node-pool + podAntiAffinity: # 确保只有此租户的 Pod 落在同一节点池上 + requiredDuringSchedulingIgnoredDuringExecution: + - mismatchLabelKeys: + - tenant + labelSelector: + matchExpressions: + - key: tenant + operator: Exists + topologyKey: node-pool +``` + + +上述的 `matchLabelKeys` 和 `mismatchLabelKeys` 将被转换为: + + +```yaml +kind: Pod +metadata: + name: application-server + labels: + tenant: service-a +spec: + affinity: + podAffinity: # 确保此租户的 Pod 落在同一节点池上 + requiredDuringSchedulingIgnoredDuringExecution: + - matchLabelKeys: + - tenant + topologyKey: node-pool + labelSelector: + matchExpressions: + - key: tenant + operator: In + values: + - service-a + podAntiAffinity: # 确保只有此租户的 Pod 落在同一节点池上 + requiredDuringSchedulingIgnoredDuringExecution: + - mismatchLabelKeys: + - tenant + labelSelector: + matchExpressions: + - key: tenant + operator: Exists + - key: tenant + operator: NotIn + values: + - service-a + topologyKey: node-pool +``` + + +## 参与其中 + +这些特性由 Kubernetes +[SIG Scheduling](https://github.com/kubernetes/community/tree/master/sig-scheduling) 管理。 + +请加入我们并分享你的反馈。我们期待听到你的声音! + + +## 了解更多 + +- [podAffinity 的官方文档](/zh-cn/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity) +- [KEP-3633:将 matchLabelKeys 和 mismatchLabelKeys 引入 podAffinity 和 podAntiAffinity](https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/3633-matchlabelkeys-to-podaffinity/README.md#story-2)