<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Kubernetes Blog</title><link>https://kubernetes.io/zh-cn/</link><description>The Kubernetes blog is used by the project to communicate new features, community reports, and any news that might be relevant to the Kubernetes community.</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><image><url>https://raw.githubusercontent.com/kubernetes/kubernetes/master/logo/logo.png</url><title>The Kubernetes project logo</title><link>https://kubernetes.io/zh-cn/</link></image><atom:link href="https://kubernetes.io/zh-cn/feed.xml" rel="self" type="application/rss+xml"/><item><title>Kubernetes v1.33 预览</title><link>https://kubernetes.io/zh-cn/blog/2025/03/26/kubernetes-v1-33-upcoming-changes/</link><pubDate>Wed, 26 Mar 2025 10:30:00 -0800</pubDate><guid>https://kubernetes.io/zh-cn/blog/2025/03/26/kubernetes-v1-33-upcoming-changes/</guid><description>
&lt;!--
layout: blog
title: 'Kubernetes v1.33 sneak peek'
date: 2025-03-26T10:30:00-08:00
slug: kubernetes-v1-33-upcoming-changes
author: >
Agustina Barbetta,
Aakanksha Bhende,
Udi Hofesh,
Ryota Sawada,
Sneha Yadav
-->
&lt;!--
As the release of Kubernetes v1.33 approaches, the Kubernetes project continues to evolve. Features may be deprecated, removed, or replaced to improve the overall health of the project. This blog post outlines some planned changes for the v1.33 release, which the release team believes you should be aware of to ensure the continued smooth operation of your Kubernetes environment and to keep you up-to-date with the latest developments. The information below is based on the current status of the v1.33 release and is subject to change before the final release date.
-->
&lt;p>随着 Kubernetes v1.33 版本的发布临近，Kubernetes 项目仍在不断发展。
为了提升项目的整体健康状况，某些特性可能会被弃用、移除或替换。
这篇博客文章概述了 v1.33 版本的一些计划变更，发布团队认为你有必要了解这些内容，
以确保 Kubernetes 环境的持续平稳运行，并让你掌握最新的发展动态。
以下信息基于 v1.33 版本的当前状态，在最终发布日期之前可能会有所变化。&lt;/p>
&lt;!--
## The Kubernetes API removal and deprecation process
The Kubernetes project has a well-documented [deprecation policy](/docs/reference/using-api/deprecation-policy/) for features. This policy states that stable APIs may only be deprecated when a newer, stable version of that same API is available and that APIs have a minimum lifetime for each stability level. A deprecated API has been marked for removal in a future Kubernetes release. It will continue to function until removal (at least one year from the deprecation), but usage will result in a warning being displayed. Removed APIs are no longer available in the current version, at which point you must migrate to using the replacement.
-->
&lt;h2 id="kubernetes-api-的移除与弃用流程">Kubernetes API 的移除与弃用流程&lt;/h2>
&lt;p>Kubernetes 项目针对特性的弃用有一套完善的&lt;a href="https://kubernetes.io/zh-cn/docs/reference/using-api/deprecation-policy/">弃用政策&lt;/a>。
该政策规定，只有在有更新的、稳定的同名 API 可用时，才能弃用稳定的 API，
并且每个稳定性级别的 API 都有最低的生命周期要求。被弃用的 API 已被标记为将在未来的
Kubernetes 版本中移除。在移除之前（自弃用起至少一年内），它仍然可以继续使用，
但使用时会显示警告信息。已被移除的 API 在当前版本中不再可用，届时你必须迁移到使用替代方案。&lt;/p>
&lt;!--
* Generally available (GA) or stable API versions may be marked as deprecated but must not be removed within a major version of Kubernetes.
* Beta or pre-release API versions must be supported for 3 releases after the deprecation.
* Alpha or experimental API versions may be removed in any release without prior deprecation notice; this process can become a withdrawal in cases where a different implementation for the same feature is already in place.
-->
&lt;ul>
&lt;li>
&lt;p>一般可用（GA）或稳定 API 版本可以被标记为已弃用，但在 Kubernetes
的一个主要版本内不得移除。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>测试版或预发布 API 版本在弃用后必须支持至少三个发行版本。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Alpha 或实验性 API 版本可以在任何版本中被移除，且无需事先发出弃用通知；
如果同一特性已经有了不同的实现，这个过程可能会变为撤回。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!--
Whether an API is removed as a result of a feature graduating from beta to stable, or because that API simply did not succeed, all removals comply with this deprecation policy. Whenever an API is removed, migration options are communicated in the [deprecation guide](/docs/reference/using-api/deprecation-guide/).
-->
&lt;p>无论是由于某个特性从测试阶段升级为稳定阶段而导致 API 被移除，还是因为该
API 未能成功，所有的移除操作都遵循此弃用政策。每当一个 API 被移除时，
迁移选项都会在&lt;a href="https://kubernetes.io/zh-cn/docs/reference/using-api/deprecation-guide/">弃用指南&lt;/a>中进行说明。&lt;/p>
&lt;!--
## Deprecations and removals for Kubernetes v1.33
### Deprecation of the stable Endpoints API
The [EndpointSlices](/docs/concepts/services-networking/endpoint-slices/) API has been stable since v1.21, which effectively replaced the original Endpoints API. While the original Endpoints API was simple and straightforward, it also posed some challenges when scaling to large numbers of network endpoints. The EndpointSlices API has introduced new features such as dual-stack networking, making the original Endpoints API ready for deprecation.
-->
&lt;h2 id="kubernetes-v1-33-的弃用与移除">Kubernetes v1.33 的弃用与移除&lt;/h2>
&lt;h3 id="稳定版-endpoints-api-的弃用">稳定版 Endpoints API 的弃用&lt;/h3>
&lt;p>&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/services-networking/endpoint-slices/">EndpointSlices&lt;/a> API
自 v1.21 起已稳定，实际上取代了原有的 Endpoints API。虽然原有的 Endpoints API 简单直接，
但在扩展到大量网络端点时也带来了一些挑战。EndpointSlices API 引入了诸如双栈网络等新特性，
使得原有的 Endpoints API 已准备好被弃用。&lt;/p>
&lt;!--
This deprecation only impacts those who use the Endpoints API directly from workloads or scripts; these users should migrate to use EndpointSlices instead. There will be a dedicated blog post with more details on the deprecation implications and migration plans in the coming weeks.
You can find more in [KEP-4974: Deprecate v1.Endpoints](https://kep.k8s.io/4974).
-->
&lt;p>此弃用仅影响那些直接在工作负载或脚本中使用 Endpoints API 的用户；
这些用户应迁移到使用 EndpointSlices。未来几周内将发布一篇专门的博客文章，
详细介绍弃用的影响和迁移计划。&lt;/p>
&lt;p>你可以在 &lt;a href="https://kep.k8s.io/4974">KEP-4974: Deprecate v1.Endpoints&lt;/a>
中找到更多信息。&lt;/p>
&lt;!--
### Removal of kube-proxy version information in node status
Following its deprecation in v1.31, as highlighted in the [release announcement](/blog/2024/07/19/kubernetes-1-31-upcoming-changes/#deprecation-of-status-nodeinfo-kubeproxyversion-field-for-nodes-kep-4004-https-github-com-kubernetes-enhancements-issues-4004), the `status.nodeInfo.kubeProxyVersion` field will be removed in v1.33. This field was set by kubelet, but its value was not consistently accurate. As it has been disabled by default since v1.31, the v1.33 release will remove this field entirely.
-->
&lt;h3 id="节点状态中-kube-proxy-版本信息的移除">节点状态中 kube-proxy 版本信息的移除&lt;/h3>
&lt;p>继在 v1.31 中被弃用，并在&lt;a href="https://kubernetes.io/blog/2024/07/19/kubernetes-1-31-upcoming-changes/#deprecation-of-status-nodeinfo-kubeproxyversion-field-for-nodes-kep-4004-https-github-com-kubernetes-enhancements-issues-4004">发布说明&lt;/a>中强调后，
&lt;code>status.nodeInfo.kubeProxyVersion&lt;/code> 字段将在 v1.33 中被移除。
此字段由 kubelet 设置，但其值并不总是准确的。由于自 v1.31
起该字段默认已被禁用，v1.33 发行版将完全移除此字段。&lt;/p>
&lt;!--
You can find more in [KEP-4004: Deprecate status.nodeInfo.kubeProxyVersion field](https://kep.k8s.io/4004).
### Removal of host network support for Windows pods
-->
&lt;p>你可以在 &lt;a href="https://kep.k8s.io/4004">KEP-4004: Deprecate status.nodeInfo.kubeProxyVersion field&lt;/a>
中找到更多信息。&lt;/p>
&lt;h3 id="移除对-windows-pod-的主机网络支持">移除对 Windows Pod 的主机网络支持&lt;/h3>
&lt;!--
Windows Pod networking aimed to achieve feature parity with Linux and provide better cluster density by allowing containers to use the Node’s networking namespace.
The original implementation landed as alpha with v1.26, but as it faced unexpected containerd behaviours,
and alternative solutions were available, the Kubernetes project has decided to withdraw the associated
KEP. We're expecting to see support fully removed in v1.33.
-->
&lt;p>Windows Pod 网络旨在通过允许容器使用节点的网络命名空间来实现与 Linux 的特性对等，
并提供更高的集群密度。最初的实现作为 Alpha 版本在 v1.26 中引入，但由于遇到了未预期的
containerd 行为，且存在替代方案，Kubernetes 项目决定撤回相关的 KEP。
我们预计在 v1.33 中完全移除对该特性的支持。&lt;/p>
&lt;!--
You can find more in [KEP-3503: Host network support for Windows pods](https://kep.k8s.io/3503).
## Featured improvement of Kubernetes v1.33
As authors of this article, we picked one improvement as the most significant change to call out!
-->
&lt;p>你可以在 &lt;a href="https://kep.k8s.io/3503">KEP-3503: Host network support for Windows pods&lt;/a>
中找到更多信息。&lt;/p>
&lt;h2 id="kubernetes-v1-33-的特色改进">Kubernetes v1.33 的特色改进&lt;/h2>
&lt;p>作为本文的作者，我们挑选了一项改进作为最重要的变更来特别提及！&lt;/p>
&lt;!--
### Support for user namespaces within Linux Pods
One of the oldest open KEPs today is [KEP-127](https://kep.k8s.io/127), Pod security improvement by using Linux [User namespaces](/docs/concepts/workloads/pods/user-namespaces/) for Pods. This KEP was first opened in late 2016, and after multiple iterations, had its alpha release in v1.25, initial beta in v1.30 (where it was disabled by default), and now is set to be a part of v1.33, where the feature is available by default.
-->
&lt;h3 id="linux-pods-中用户命名空间的支持">Linux Pods 中用户命名空间的支持&lt;/h3>
&lt;p>当前最古老的开放 KEP 之一是 &lt;a href="https://kep.k8s.io/127">KEP-127&lt;/a>，
通过使用 Linux &lt;a href="https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/user-namespaces/">用户命名空间&lt;/a>为
Pod 提供安全性改进。该 KEP 最初在 2016 年末提出，经过多次迭代，在 v1.25 中发布了 Alpha 版本，
在 v1.30 中首次进入 Beta 阶段（在此版本中默认禁用），现在它将成为 v1.33 的一部分，
默认情况下即可使用该特性。&lt;/p>
&lt;!--
This support will not impact existing Pods unless you manually specify `pod.spec.hostUsers` to opt in. As highlighted in the [v1.30 sneak peek blog](/blog/2024/03/12/kubernetes-1-30-upcoming-changes/), this is an important milestone for mitigating vulnerabilities.
You can find more in [KEP-127: Support User Namespaces in pods](https://kep.k8s.io/127).
-->
&lt;p>除非你手动指定 &lt;code>pod.spec.hostUsers&lt;/code> 以选择使用此特性，否则此支持不会影响现有的 Pod。
正如在 &lt;a href="https://kubernetes.io/blog/2024/03/12/kubernetes-1-30-upcoming-changes/">v1.30 预览博客&lt;/a>中强调的那样，
就缓解漏洞的影响而言，这是一个重要里程碑。&lt;/p>
&lt;p>你可以在 &lt;a href="https://kep.k8s.io/127">KEP-127: Support User Namespaces in pods&lt;/a>
中找到更多信息。&lt;/p>
&lt;!--
## Selected other Kubernetes v1.33 improvements
The following list of enhancements is likely to be included in the upcoming v1.33 release. This is not a commitment and the release content is subject to change.
-->
&lt;h2 id="精选的其他-kubernetes-v1-33-改进">精选的其他 Kubernetes v1.33 改进&lt;/h2>
&lt;p>以下列出的改进很可能会包含在即将到来的 v1.33 发行版中。
这些改进尚无法承诺，发行内容仍有可能发生变化。&lt;/p>
&lt;!--
### In-place resource resize for vertical scaling of Pods
When provisioning a Pod, you can use various resources such as Deployment, StatefulSet, etc. Scalability requirements may need horizontal scaling by updating the Pod replica count, or vertical scaling by updating resources allocated to Pod’s container(s). Before this enhancement, container resources defined in a Pod's `spec` were immutable, and updating any of these details within a Pod template would trigger Pod replacement.
-->
&lt;h3 id="pod-垂直扩展的就地资源调整">Pod 垂直扩展的就地资源调整&lt;/h3>
&lt;p>在制备某个 Pod 时，你可以使用诸如 Deployment、StatefulSet 等多种资源。
为了满足可扩缩性需求，可能需要通过更新 Pod 副本数量进行水平扩缩，或通过更新分配给
Pod 容器的资源进行垂直扩缩。在此增强特性之前，Pod 的 &lt;code>spec&lt;/code>
中定义的容器资源是不可变的，更新 Pod 模板中的这类细节会触发 Pod 的替换。&lt;/p>
&lt;!--
But what if you could dynamically update the resource configuration for your existing Pods without restarting them?
The [KEP-1287](https://kep.k8s.io/1287) is precisely to allow such in-place Pod updates. It opens up various possibilities of vertical scale-up for stateful processes without any downtime, seamless scale-down when the traffic is low, and even allocating larger resources during startup that is eventually reduced once the initial setup is complete. This was released as alpha in v1.27, and is expected to land as beta in v1.33.
-->
&lt;p>但是如果可以在不重启的情况下动态更新现有 Pod 的资源配置，那会怎样呢？&lt;/p>
&lt;p>&lt;a href="https://kep.k8s.io/1287">KEP-1287&lt;/a> 正是为了实现这种就地 Pod 更新而设计的。
它为无状态进程的垂直扩缩开辟了多种可能性，例如在不停机的情况下进行扩容、
在流量较低时无缝缩容，甚至在启动时分配更多资源，待初始设置完成后减少资源分配。
该特性在 v1.27 中以 Alpha 版本发布，并预计在 v1.33 中进入 beta 阶段。&lt;/p>
&lt;!--
You can find more in [KEP-1287: In-Place Update of Pod Resources](https://kep.k8s.io/1287).
### DRA’s ResourceClaim Device Status graduates to beta
-->
&lt;p>你可以在 &lt;a href="https://kep.k8s.io/1287">KEP-1287：Pod 资源的就地更新&lt;/a>中找到更多信息。&lt;/p>
&lt;h3 id="dra-的-resourceclaim-设备状态升级为-beta">DRA 的 ResourceClaim 设备状态升级为 Beta&lt;/h3>
&lt;!--
The `devices` field in ResourceClaim `status`, originally introduced in the v1.32 release, is likely to graduate to beta in v1.33. This field allows drivers to report device status data, improving both observability and troubleshooting capabilities.
-->
&lt;p>在 v1.32 版本中首次引入的 ResourceClaim &lt;code>status&lt;/code> 中的 &lt;code>devices&lt;/code> 字段，
预计将在 v1.33 中升级为 beta 阶段。此字段允许驱动程序报告设备状态数据，
从而提升可观测性和故障排查能力。&lt;/p>
&lt;!--
For example, reporting the interface name, MAC address, and IP addresses of network interfaces in the status of a ResourceClaim can significantly help in configuring and managing network services, as well as in debugging network related issues. You can read more about ResourceClaim Device Status in [Dynamic Resource Allocation: ResourceClaim Device Status](/docs/concepts/scheduling-eviction/dynamic-resource-allocation/#resourceclaim-device-status) document.
-->
&lt;p>例如，在 ResourceClaim 的状态中报告网络接口的接口名称、MAC 地址和 IP 地址，
可以显著帮助配置和管理网络服务，并且在调试网络相关问题时也非常有用。
你可以在&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/dynamic-resource-allocation/#resourceclaim-device-status">动态资源分配：ResourceClaim 设备状态&lt;/a>
文档中阅读关于 ResourceClaim 设备状态的更多信息。&lt;/p>
&lt;!--
Also, you can find more about the planned enhancement in [KEP-4817: DRA: Resource Claim Status with possible standardized network interface data](https://kep.k8s.io/4817).
-->
&lt;p>此外，你可以在
&lt;a href="https://kep.k8s.io/4817">KEP-4817: DRA: Resource Claim Status with possible standardized network interface data&lt;/a>
中找到更多关于此计划增强特性的信息。&lt;/p>
&lt;!--
### Ordered namespace deletion
This KEP introduces a more structured deletion process for Kubernetes namespaces to ensure secure and deterministic resource removal. The current semi-random deletion order can create security gaps or unintended behaviour, such as Pods persisting after their associated NetworkPolicies are deleted. By enforcing a structured deletion sequence that respects logical and security dependencies, this approach ensures Pods are removed before other resources. The design improves Kubernetes’s security and reliability by mitigating risks associated with non-deterministic deletions.
-->
&lt;h3 id="有序的命名空间删除">有序的命名空间删除&lt;/h3>
&lt;p>此 KEP 为 Kubernetes 命名空间引入了一种更为结构化的删除流程，
以确保更为安全且更为确定的资源移除。当前半随机的删除顺序可能会导致安全漏洞或意外行为，
例如在相关的 NetworkPolicy 被删除后，Pod 仍然存在。
通过强制执行尊重逻辑和安全依赖关系的结构化删除顺序，此方法确保在删除其他资源之前先删除 Pod。
这种设计通过减少与非确定性删除相关的风险，提升了 Kubernetes 的安全性和可靠性。&lt;/p>
&lt;!--
You can find more in [KEP-5080: Ordered namespace deletion](https://kep.k8s.io/5080).
-->
&lt;p>你可以在 &lt;a href="https://kep.k8s.io/5080">KEP-5080: Ordered namespace deletion&lt;/a>
中找到更多信息。&lt;/p>
&lt;!--
### Enhancements for indexed job management
These two KEPs are both set to graduate to GA to provide better reliability for job handling, specifically for indexed jobs. [KEP-3850](https://kep.k8s.io/3850) provides per-index backoff limits for indexed jobs, which allows each index to be fully independent of other indexes. Also, [KEP-3998](https://kep.k8s.io/3998) extends Job API to define conditions for making an indexed job as successfully completed when not all indexes are succeeded.
-->
&lt;h3 id="针对带索引作业-indexed-job-管理的增强">针对带索引作业（Indexed Job）管理的增强&lt;/h3>
&lt;p>这两个 KEP 都计划升级为 GA，以提供更好的作业处理可靠性，特别是针对索引作业。
&lt;a href="https://kep.k8s.io/3850">KEP-3850&lt;/a> 为索引作业中的不同索引分别支持独立的回退限制，
这使得每个索引可以完全独立于其他索引。此外，&lt;a href="https://kep.k8s.io/3998">KEP-3998&lt;/a>
扩展了 Job API，定义了在并非所有索引都成功的情况下将索引作业标记为成功完成的条件。&lt;/p>
&lt;!--
You can find more in [KEP-3850: Backoff Limit Per Index For Indexed Jobs](https://kep.k8s.io/3850) and [KEP-3998: Job success/completion policy](https://kep.k8s.io/3998).
-->
&lt;p>你可以在 &lt;a href="https://kep.k8s.io/3850">KEP-3850: Backoff Limit Per Index For Indexed Jobs&lt;/a> 和
&lt;a href="https://kep.k8s.io/3998">KEP-3998: Job success/completion policy&lt;/a> 中找到更多信息。&lt;/p>
&lt;!--
## Want to know more?
New features and deprecations are also announced in the Kubernetes release notes. We will formally announce what's new in [Kubernetes v1.33](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.33.md) as part of the CHANGELOG for that release.
-->
&lt;h2 id="想了解更多">想了解更多？&lt;/h2>
&lt;p>新特性和弃用也会在 Kubernetes 发行说明中宣布。我们将在该版本的
CHANGELOG 中正式宣布 &lt;a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.33.md">Kubernetes v1.33&lt;/a>
的新内容。&lt;/p>
&lt;!--
Kubernetes v1.33 release is planned for **Wednesday, 23rd April, 2025**. Stay tuned for updates!
You can also see the announcements of changes in the release notes for:
-->
&lt;p>Kubernetes v1.33 版本计划于 &lt;strong>2025年4月23日星期三&lt;/strong>发布。请持续关注以获取更新！&lt;/p>
&lt;p>你也可以在以下版本的发行说明中查看变更公告：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.32.md">Kubernetes v1.32&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.31.md">Kubernetes v1.31&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.30.md">Kubernetes v1.30&lt;/a>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!--
## Get involved
The simplest way to get involved with Kubernetes is by joining one of the many [Special Interest Groups](https://github.com/kubernetes/community/blob/master/sig-list.md) (SIGs) that align with your interests. Have something you’d like to broadcast to the Kubernetes community? Share your voice at our weekly [community meeting](https://github.com/kubernetes/community/tree/master/communication), and through the channels below. Thank you for your continued feedback and support.
-->
&lt;h2 id="参与进来">参与进来&lt;/h2>
&lt;p>参与 Kubernetes 最简单的方式是加入与你兴趣相符的众多&lt;a href="https://github.com/kubernetes/community/blob/master/sig-list.md">特别兴趣小组&lt;/a>（SIG）
之一。你有什么想向 Kubernetes 社区广播的内容吗？
通过我们每周的&lt;a href="https://github.com/kubernetes/community/tree/master/communication">社区会议&lt;/a>和以下渠道分享你的声音。
感谢你持续的反馈和支持。&lt;/p>
&lt;!--
- Follow us on Bluesky [@kubernetes.io](https://bsky.app/profile/kubernetes.io) for the latest updates
- Join the community discussion on [Discuss](https://discuss.kubernetes.io/)
- Join the community on [Slack](http://slack.k8s.io/)
- Post questions (or answer questions) on [Server Fault](https://serverfault.com/questions/tagged/kubernetes) or [Stack Overflow](http://stackoverflow.com/questions/tagged/kubernetes)
- Share your Kubernetes [story](https://docs.google.com/a/linuxfoundation.org/forms/d/e/1FAIpQLScuI7Ye3VQHQTwBASrgkjQDSS5TP0g3AXfFhwSM9YpHgxRKFA/viewform)
- Read more about what’s happening with Kubernetes on the [blog](https://kubernetes.io/blog/)
- Learn more about the [Kubernetes Release Team](https://github.com/kubernetes/sig-release/tree/master/release-team)
-->
&lt;ul>
&lt;li>在 Bluesky 上关注我们 &lt;a href="https://bsky.app/profile/kubernetes.io">@kubernetes.io&lt;/a> 以获取最新更新&lt;/li>
&lt;li>在 &lt;a href="https://discuss.kubernetes.io/">Discuss&lt;/a> 上参与社区讨论&lt;/li>
&lt;li>在 &lt;a href="http://slack.k8s.io/">Slack&lt;/a> 上加入社区&lt;/li>
&lt;li>在 &lt;a href="https://serverfault.com/questions/tagged/kubernetes">Server Fault&lt;/a> 或
&lt;a href="http://stackoverflow.com/questions/tagged/kubernetes">Stack Overflow&lt;/a> 上提问（或回答问题）&lt;/li>
&lt;li>分享你的 Kubernetes &lt;a href="https://docs.google.com/a/linuxfoundation.org/forms/d/e/1FAIpQLScuI7Ye3VQHQTwBASrgkjQDSS5TP0g3AXfFhwSM9YpHgxRKFA/viewform">故事&lt;/a>&lt;/li>
&lt;li>在&lt;a href="https://kubernetes.io/zh-cn/blog/">博客&lt;/a>上阅读更多关于 Kubernetes 最新动态的内容&lt;/li>
&lt;li>了解更多关于 &lt;a href="https://github.com/kubernetes/sig-release/tree/master/release-team">Kubernetes 发布团队&lt;/a>的信息&lt;/li>
&lt;/ul></description></item><item><title>ingress-nginx CVE-2025-1974 须知</title><link>https://kubernetes.io/zh-cn/blog/2025/03/24/ingress-nginx-cve-2025-1974/</link><pubDate>Mon, 24 Mar 2025 12:00:00 -0800</pubDate><guid>https://kubernetes.io/zh-cn/blog/2025/03/24/ingress-nginx-cve-2025-1974/</guid><description>
&lt;!--
layout: blog
title: "Ingress-nginx CVE-2025-1974: What You Need to Know"
date: 2025-03-24T12:00:00-08:00
slug: ingress-nginx-CVE-2025-1974
author: >
Tabitha Sable (Kubernetes Security Response Committee)
-->
&lt;!--
Today, the ingress-nginx maintainers have [released patches for a batch of critical vulnerabilities](https://github.com/kubernetes/ingress-nginx/releases) that could make it easy for attackers to take over your Kubernetes cluster. If you are among the over 40% of Kubernetes administrators using [ingress-nginx](https://github.com/kubernetes/ingress-nginx/), you should take action immediately to protect your users and data.
-->
&lt;p>今天，ingress-nginx 项目的维护者们&lt;a href="https://github.com/kubernetes/ingress-nginx/releases">发布了一批关键漏洞的修复补丁&lt;/a>，
这些漏洞可能让攻击者轻易接管你的 Kubernetes 集群。目前有 40% 以上的 Kubernetes 管理员正在使用
&lt;a href="https://github.com/kubernetes/ingress-nginx/">ingress-nginx&lt;/a>，
如果你是其中之一，请立即采取行动，保护你的用户和数据。&lt;/p>
&lt;!--
## Background
[Ingress](/docs/concepts/services-networking/ingress/) is the traditional Kubernetes feature for exposing your workload Pods to the world so that they can be useful. In an implementation-agnostic way, Kubernetes users can define how their applications should be made available on the network. Then, an [ingress controller](/docs/concepts/services-networking/ingress-controllers/) uses that definition to set up local or cloud resources as required for the user’s particular situation and needs.
-->
&lt;h2 id="background">背景 &lt;/h2>
&lt;p>&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/">Ingress&lt;/a>
是 Kubernetes 提供的一种传统特性，可以将你的工作负载 Pod 暴露给外部世界，方便外部用户使用。
Kubernetes 用户可以用与实现无关的方式来定义应用如何在网络上可用。
&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress-controllers/">Ingress 控制器&lt;/a>会根据定义，
配置所需的本地资源或云端资源，以满足用户的特定场景和需求。&lt;/p>
&lt;!--
Many different ingress controllers are available, to suit users of different cloud providers or brands of load balancers. Ingress-nginx is a software-only ingress controller provided by the Kubernetes project. Because of its versatility and ease of use, ingress-nginx is quite popular: it is deployed in over 40% of Kubernetes clusters\!
Ingress-nginx translates the requirements from Ingress objects into configuration for nginx, a powerful open source webserver daemon. Then, nginx uses that configuration to accept and route requests to the various applications running within a Kubernetes cluster. Proper handling of these nginx configuration parameters is crucial, because ingress-nginx needs to allow users significant flexibility while preventing them from accidentally or intentionally tricking nginx into doing things it shouldn’t.
-->
&lt;p>为了满足不同云厂商用户或负载均衡器产品的需求，目前有许多不同类型的 Ingress 控制器。
ingress-nginx 是 Kubernetes 项目提供的纯软件的 Ingress 控制器。
ingress-nginx 由于灵活易用，非常受用户欢迎。它已经被部署在超过 40% 的 Kubernetes 集群中！&lt;/p>
&lt;p>ingress-nginx 会将 Ingress 对象中的要求转换为 Nginx（一个强大的开源 Web 服务器守护进程）的配置。
Nginx 使用这些配置接受请求并将其路由到 Kubernetes 集群中运行的不同应用。
正确处理这些 Nginx 配置参数至关重要，因为 ingress-nginx 既要给予用户足够的灵活性，
又要防止用户无意或有意诱使 Nginx 执行其不应执行的操作。&lt;/p>
&lt;!--
## Vulnerabilities Patched Today
Four of today’s ingress-nginx vulnerabilities are improvements to how ingress-nginx handles particular bits of nginx config. Without these fixes, a specially-crafted Ingress object can cause nginx to misbehave in various ways, including revealing the values of [Secrets](/docs/concepts/configuration/secret/) that are accessible to ingress-nginx. By default, ingress-nginx has access to all Secrets cluster-wide, so this can often lead to complete cluster takeover by any user or entity that has permission to create an Ingress.
-->
&lt;h2 id="vulnerabilities-patched-today">今日修复的漏洞 &lt;/h2>
&lt;p>今天修复的四个 ingress-nginx 漏洞都是对 ingress-nginx 如何处理特定 Nginx 配置细节的改进。
如果不打这些修复补丁，一个精心构造的 Ingress 资源对象就可以让 Nginx 出现异常行为，
包括泄露 ingress-nginx 可访问的 &lt;a href="https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/">Secret&lt;/a>
的值。默认情况下，ingress-nginx 可以访问集群范围内的所有 Secret，因此这往往会导致任一有权限创建
Ingress 的用户或实体接管整个集群。&lt;/p>
&lt;!--
The most serious of today’s vulnerabilities, [CVE-2025-1974](https://github.com/kubernetes/kubernetes/issues/131009), rated [9.8 CVSS](https://www.first.org/cvss/calculator/3-1#CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H), allows anything on the Pod network to exploit configuration injection vulnerabilities via the Validating Admission Controller feature of ingress-nginx. This makes such vulnerabilities far more dangerous: ordinarily one would need to be able to create an Ingress object in the cluster, which is a fairly privileged action. When combined with today’s other vulnerabilities, **CVE-2025-1974 means that anything on the Pod network has a good chance of taking over your Kubernetes cluster, with no credentials or administrative access required**. In many common scenarios, the Pod network is accessible to all workloads in your cloud VPC, or even anyone connected to your corporate network\! This is a very serious situation.
-->
&lt;p>本次最严重的漏洞是 &lt;a href="https://github.com/kubernetes/kubernetes/issues/131009">CVE-2025-1974&lt;/a>，
CVSS 评分高达 &lt;a href="https://www.first.org/cvss/calculator/3-1#CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H">9.8&lt;/a>，
它允许 Pod 网络中的任意实体通过 ingress-nginx 的验证性准入控制器特性滥用配置注入漏洞。
这种机制使得这些漏洞会产生更危险的情形：攻击者通常需要能够在集群中创建 Ingress 对象（这是一种较高权限的操作）。
当结合使用今天修复的其他漏洞（比如 CVE-2025-1974），
&lt;strong>就意味着 Pod 网络中的任何实体都有极大可能接管你的 Kubernetes 集群，而不需要任何凭证或管理权限&lt;/strong>。
在许多常见场景下，Pod 网络可以访问云端 VPC 中的所有工作负载，甚至能访问连接到你公司内网的任何人的机器！
这是一个非常严重的安全风险。&lt;/p>
&lt;!--
Today, we have [released ingress-nginx v1.12.1 and v1.11.5](https://github.com/kubernetes/ingress-nginx/releases), which have fixes for all five of these vulnerabilities.
## Your next steps
First, determine if your clusters are using ingress-nginx. In most cases, you can check this by running `kubectl get pods --all-namespaces --selector app.kubernetes.io/name=ingress-nginx` with cluster administrator permissions.
-->
&lt;p>我们今天已经&lt;a href="https://github.com/kubernetes/ingress-nginx/releases">发布了 ingress-nginx v1.12.1 和 v1.11.5&lt;/a>，
这两个版本修复了所有这 5 个漏洞。&lt;/p>
&lt;h2 id="your-next-steps">你需要做什么 &lt;/h2>
&lt;p>首先，确定你的集群是否在使用 ingress-nginx。大多数情况下，你可以使用集群管理员权限运行以下命令进行检查：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>kubectl get pods --all-namespaces --selector app.kubernetes.io/name&lt;span style="color:#666">=&lt;/span>ingress-nginx
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
**If you are using ingress-nginx, make a plan to remediate these vulnerabilities immediately.**
**The best and easiest remedy is to [upgrade to the new patch release of ingress-nginx](https://kubernetes.github.io/ingress-nginx/deploy/upgrade/).** All five of today’s vulnerabilities are fixed by installing today’s patches.
If you can’t upgrade right away, you can significantly reduce your risk by turning off the Validating Admission Controller feature of ingress-nginx.
-->
&lt;p>&lt;strong>如果你在使用 ingress-nginx，请立即针对这些漏洞制定补救计划。&lt;/strong>&lt;/p>
&lt;p>&lt;strong>最简单且推荐的补救方案是&lt;a href="https://kubernetes.github.io/ingress-nginx/deploy/upgrade/">立即升级到最新补丁版本&lt;/a>。&lt;/strong>
安装今天的补丁，就能修复所有这 5 个漏洞。&lt;/p>
&lt;p>如果你暂时无法升级，可以通过关闭 ingress-nginx 的验证性准入控制器特性来显著降低风险。&lt;/p>
&lt;!--
* If you have installed ingress-nginx using Helm
* Reinstall, setting the Helm value `controller.admissionWebhooks.enabled=false`
* If you have installed ingress-nginx manually
* delete the ValidatingWebhookconfiguration called `ingress-nginx-admission`
* edit the `ingress-nginx-controller` Deployment or Daemonset, removing `--validating-webhook` from the controller container’s argument list
-->
&lt;ul>
&lt;li>如果你使用 Helm 安装了 ingress-nginx
&lt;ul>
&lt;li>重新安装，设置 Helm 参数 &lt;code>controller.admissionWebhooks.enabled=false&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>如果你是手动安装的
&lt;ul>
&lt;li>删除名为 &lt;code>ingress-nginx-admission&lt;/code> 的 ValidatingWebhookConfiguration&lt;/li>
&lt;li>编辑 &lt;code>ingress-nginx-controller&lt;/code> Deployment 或 DaemonSet，从控制器容器的参数列表中移除 &lt;code>--validating-webhook&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;!--
If you turn off the Validating Admission Controller feature as a mitigation for CVE-2025-1974, remember to turn it back on after you upgrade. This feature provides important quality of life improvements for your users, warning them about incorrect Ingress configurations before they can take effect.
-->
&lt;p>如果你为了缓解 CVE-2025-1974 造成的风险而关闭了验证性准入控制器特性，
请在升级完成后记得重新开启此特性。这个特性可以为你的用户提供重要的生命期帮助，
可以在错误的 Ingress 配置在生效之前及时提醒用户。&lt;/p>
&lt;!--
## Conclusion, thanks, and further reading
The ingress-nginx vulnerabilities announced today, including CVE-2025-1974, present a serious risk to many Kubernetes users and their data. If you use ingress-nginx, you should take action immediately to keep yourself safe.
Thanks go out to Nir Ohfeld, Sagi Tzadik, Ronen Shustin, and Hillai Ben-Sasson from Wiz for responsibly disclosing these vulnerabilities, and for working with the Kubernetes SRC members and ingress-nginx maintainers (Marco Ebert and James Strong) to ensure we fixed them effectively.
-->
&lt;h2 id="conclusion-thanks-and-further-reading">总结、致谢与更多参考 &lt;/h2>
&lt;p>今天公布的包括 CVE-2025-1974 在内的 ingress-nginx 漏洞对许多 Kubernetes 用户及其数据构成了严重风险。
如果你正在使用 ingress-nginx，请立即采取行动确保自身安全。&lt;/p>
&lt;p>我们要感谢来自 Wiz 的 Nir Ohfeld、Sagi Tzadik、Ronen Shustin 和 Hillai Ben-Sasson，
他们负责任地披露了这些漏洞，并与 Kubernetes 安全响应委员会成员以及 ingress-nginx
维护者（Marco Ebert 和 James Strong）协同合作，确保这些漏洞被有效修复。&lt;/p>
&lt;!--
For further information about the maintenance and future of ingress-nginx, please see this [GitHub issue](https://github.com/kubernetes/ingress-nginx/issues/13002) and/or attend [James and Marco’s KubeCon/CloudNativeCon EU 2025 presentation](https://kccnceu2025.sched.com/event/1tcyc/).
For further information about the specific vulnerabilities discussed in this article, please see the appropriate GitHub issue: [CVE-2025-24513](https://github.com/kubernetes/kubernetes/issues/131005), [CVE-2025-24514](https://github.com/kubernetes/kubernetes/issues/131006), [CVE-2025-1097](https://github.com/kubernetes/kubernetes/issues/131007), [CVE-2025-1098](https://github.com/kubernetes/kubernetes/issues/131008), or [CVE-2025-1974](https://github.com/kubernetes/kubernetes/issues/131009)
-->
&lt;p>有关 ingress-nginx 的维护和未来的更多信息，
请参阅&lt;a href="https://github.com/kubernetes/ingress-nginx/issues/13002">这个 GitHub Issue&lt;/a>，
或参与 &lt;a href="https://kccnceu2025.sched.com/event/1tcyc/">James 和 Marco 在 KubeCon/CloudNativeCon EU 2025 的演讲&lt;/a>。&lt;/p>
&lt;p>关于本文中提到的具体漏洞的信息，请参阅以下 GitHub Issue：&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/kubernetes/kubernetes/issues/131005">CVE-2025-24513&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes/kubernetes/issues/131006">CVE-2025-24514&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes/kubernetes/issues/131007">CVE-2025-1097&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes/kubernetes/issues/131008">CVE-2025-1098&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes/kubernetes/issues/131009">CVE-2025-1974&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>聚焦 SIG Apps</title><link>https://kubernetes.io/zh-cn/blog/2025/03/12/sig-apps-spotlight-2025/</link><pubDate>Wed, 12 Mar 2025 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2025/03/12/sig-apps-spotlight-2025/</guid><description>
&lt;!--
layout: blog
title: "Spotlight on SIG Apps"
slug: sig-apps-spotlight-2025
canonicalUrl: https://www.kubernetes.dev/blog/2025/03/12/sig-apps-spotlight-2025
date: 2025-03-12
author: "Sandipan Panda (DevZero)"
-->
&lt;!--
In our ongoing SIG Spotlight series, we dive into the heart of the Kubernetes project by talking to
the leaders of its various Special Interest Groups (SIGs). This time, we focus on
**[SIG Apps](https://github.com/kubernetes/community/tree/master/sig-apps#apps-special-interest-group)**,
the group responsible for everything related to developing, deploying, and operating applications on
Kubernetes. [Sandipan Panda](https://www.linkedin.com/in/sandipanpanda)
([DevZero](https://www.devzero.io/)) had the opportunity to interview [Maciej
Szulik](https://github.com/soltysh) ([Defense Unicorns](https://defenseunicorns.com/)) and [Janet
Kuo](https://github.com/janetkuo) ([Google](https://about.google/)), the chairs and tech leads of
SIG Apps. They shared their experiences, challenges, and visions for the future of application
management within the Kubernetes ecosystem.
-->
&lt;p>在我们正在进行的 SIG 聚焦系列中，我们通过与 Kubernetes 项目各个特别兴趣小组（SIG）的领导者对话，
深入探讨 Kubernetes 项目的核心。这一次，我们聚焦于
&lt;strong>&lt;a href="https://github.com/kubernetes/community/tree/master/sig-apps#apps-special-interest-group">SIG Apps&lt;/a>&lt;/strong>，
这个小组负责 Kubernetes 上与应用程序开发、部署和操作相关的所有内容。
&lt;a href="https://www.linkedin.com/in/sandipanpanda">Sandipan Panda&lt;/a>（[DevZero](&lt;a href="https://www.devzero.io/">https://www.devzero.io/&lt;/a>））
有机会采访了 SIG Apps 的主席和技术负责人
&lt;a href="https://github.com/soltysh">Maciej Szulik&lt;/a>（&lt;a href="https://defenseunicorns.com/">Defense Unicorns&lt;/a>）
以及 &lt;a href="https://github.com/janetkuo">Janet Kuo&lt;/a>（&lt;a href="https://about.google/">Google&lt;/a>）。
他们分享了在 Kubernetes 生态系统中关于应用管理的经验、挑战以及未来愿景。&lt;/p>
&lt;!--
## Introductions
**Sandipan: Hello, could you start by telling us a bit about yourself, your role, and your journey
within the Kubernetes community that led to your current roles in SIG Apps?**
**Maciej**: Hey, my name is Maciej, and I’m one of the leads for SIG Apps. Aside from this role, you
can also find me helping
[SIG CLI](https://github.com/kubernetes/community/tree/master/sig-cli#readme) and also being one of
the Steering Committee members. I’ve been contributing to Kubernetes since late 2014 in various
areas, including controllers, apiserver, and kubectl.
-->
&lt;h2 id="自我介绍">自我介绍&lt;/h2>
&lt;p>&lt;strong>Sandipan&lt;/strong>：你好，能否先简单介绍一下你自己、你的角色，以及你在
Kubernetes 社区中的经历，这些经历是如何引导你担任 SIG Apps 的当前角色的？&lt;/p>
&lt;p>&lt;strong>Maciej&lt;/strong>：嗨，我叫 Maciej，是 SIG Apps 的负责人之一。除了这个角色，
你还可以看到我在协助 &lt;a href="https://github.com/kubernetes/community/tree/master/sig-cli#readme">SIG CLI&lt;/a>
的工作，同时我也是指导委员会的成员之一。自 2014 年底以来，我一直为
Kubernetes 做出贡献，涉及的领域包括控制器、API 服务器以及 kubectl。&lt;/p>
&lt;!--
**Janet**: Certainly! I'm Janet, a Staff Software Engineer at Google, and I've been deeply involved
with the Kubernetes project since its early days, even before the 1.0 launch in 2015. It's been an
amazing journey!
My current role within the Kubernetes community is one of the chairs and tech leads of SIG Apps. My
journey with SIG Apps started organically. I started with building the Deployment API and adding
rolling update functionalities. I naturally gravitated towards SIG Apps and became increasingly
involved. Over time, I took on more responsibilities, culminating in my current leadership roles.
-->
&lt;p>&lt;strong>Janet&lt;/strong>：当然可以！我是 Janet，在 Google 担任资深软件工程师，
并且从 Kubernetes 项目早期（甚至在 2015 年 1.0 版本发布之前）就深度参与其中。
这是一段非常精彩的旅程！&lt;/p>
&lt;p>我在 Kubernetes 社区中的当前角色是 SIG Apps 的主席之一和技术负责人之一。
我与 SIG Apps 的结缘始于自然而然的过程。最初，我从构建 Deployment API
并添加滚动更新功能开始，逐渐对 SIG Apps 产生了浓厚的兴趣，并且参与度越来越高。
随着时间推移，我承担了更多的责任，最终走到了目前的领导岗位。&lt;/p>
&lt;!--
## About SIG Apps
*All following answers were jointly provided by Maciej and Janet.*
**Sandipan: For those unfamiliar, could you provide an overview of SIG Apps' mission and objectives?
What key problems does it aim to solve within the Kubernetes ecosystem?**
-->
&lt;h2 id="关于-sig-apps">关于 SIG Apps&lt;/h2>
&lt;p>&lt;strong>以下所有回答均由 Maciej 和 Janet 共同提供。&lt;/strong>&lt;/p>
&lt;p>&lt;strong>Sandipan&lt;/strong>：对于那些不熟悉的人，能否简要介绍一下 SIG Apps 的使命和目标？
它在 Kubernetes 生态系统中旨在解决哪些关键问题？&lt;/p>
&lt;!--
As described in our
[charter](https://github.com/kubernetes/community/blob/master/sig-apps/charter.md#scope), we cover a
broad area related to developing, deploying, and operating applications on Kubernetes. That, in
short, means we’re open to each and everyone showing up at our bi-weekly meetings and discussing the
ups and downs of writing and deploying various applications on Kubernetes.
**Sandipan: What are some of the most significant projects or initiatives currently being undertaken
by SIG Apps?**
-->
&lt;p>正如我们在&lt;a href="https://github.com/kubernetes/community/blob/master/sig-apps/charter.md#scope">章程&lt;/a>中所描述的那样，
我们涵盖了与在 Kubernetes 上开发、部署和操作应用程序相关的广泛领域。
简而言之，这意味着我们欢迎每个人参加我们的双周会议，讨论在 Kubernetes
上编写和部署各种应用程序的经验和挑战。&lt;/p>
&lt;p>&lt;strong>Sandipan&lt;/strong>：SIG Apps 目前正在进行的一些最重要项目或倡议有哪些？&lt;/p>
&lt;!--
At this point in time, the main factors driving the development of our controllers are the
challenges coming from running various AI-related workloads. It’s worth giving credit here to two
working groups we’ve sponsored over the past years:
-->
&lt;p>在当前阶段，推动我们控制器开发的主要因素是运行各种 AI 相关工作负载所带来的挑战。
在此值得一提的是，过去几年我们支持的两个工作组：&lt;/p>
&lt;!--
1. [The Batch Working Group](https://github.com/kubernetes/community/tree/master/wg-batch), which is
looking at running HPC, AI/ML, and data analytics jobs on top of Kubernetes.
2. [The Serving Working Group](https://github.com/kubernetes/community/tree/master/wg-serving), which
is focusing on hardware-accelerated AI/ML inference.
-->
&lt;ol>
&lt;li>&lt;a href="https://github.com/kubernetes/community/tree/master/wg-batch">Batch 工作组&lt;/a>，
该工作组致力于在 Kubernetes 上运行 HPC、AI/ML 和数据分析作业。&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes/community/tree/master/wg-serving">Serving 工作组&lt;/a>，
该工作组专注于硬件加速的 AI/ML 推理。&lt;/li>
&lt;/ol>
&lt;!---
## Best practices and challenges
**Sandipan: SIG Apps plays a crucial role in developing application management best practices for
Kubernetes. Can you share some of these best practices and how they help improve application
lifecycle management?**
-->
&lt;h2 id="最佳实践与挑战">最佳实践与挑战&lt;/h2>
&lt;p>&lt;strong>Sandipan&lt;/strong>：SIG Apps 在为 Kubernetes 开发应用程序管理最佳实践方面发挥着关键作用。
你能分享一些这些最佳实践吗？以及它们如何帮助改进应用程序生命周期管理？&lt;/p>
&lt;!--
1. Implementing [health checks and readiness probes](/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/)
ensures that your applications are healthy and ready to serve traffic, leading to improved
reliability and uptime. The above, combined with comprehensive logging, monitoring, and tracing
solutions, will provide insights into your application's behavior, enabling you to identify and
resolve issues quickly.
-->
&lt;ol>
&lt;li>实施&lt;a href="https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/">健康检查和就绪探针&lt;/a>
确保你的应用程序处于健康状态并准备好处理流量，从而提高可靠性和正常运行时间。
结合全面的日志记录、监控和跟踪解决方案，上述措施将为您提供应用程序行为的洞察，
使你能够快速识别并解决问题。&lt;/li>
&lt;/ol>
&lt;!--
2. [Auto-scale your application](/docs/concepts/workloads/autoscaling/) based
on resource utilization or custom metrics, optimizing resource usage and ensuring your
application can handle varying loads.
-->
&lt;ol start="2">
&lt;li>根据资源利用率或自定义指标&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/workloads/autoscaling/">自动扩缩你的应用&lt;/a>，
优化资源使用并确保您的应用程序能够处理不同的负载。&lt;/li>
&lt;/ol>
&lt;!--
3. Use Deployment for stateless applications, StatefulSet for stateful applications, Job
and CronJob for batch workloads, and DaemonSet for running a daemon on each node. Use
Operators and CRDs to extend the Kubernetes API to automate the deployment, management, and
lifecycle of complex applications, making them easier to operate and reducing manual
intervention.
-->
&lt;ol start="3">
&lt;li>对于无状态应用程序使用 Deployment，对于有状态应用程序使用 StatefulSet，
对于批处理工作负载使用 Job 和 CronJob，在每个节点上运行守护进程时使用
DaemonSet。使用 Operator 和 CRD 扩展 Kubernetes API 以自动化复杂应用程序的部署、
管理和生命周期，使其更易于操作并减少手动干预。&lt;/li>
&lt;/ol>
&lt;!--
**Sandipan: What are some of the common challenges SIG Apps faces, and how do you address them?**
The biggest challenge we’re facing all the time is the need to reject a lot of features, ideas, and
improvements. This requires a lot of discipline and patience to be able to explain the reasons
behind those decisions.
-->
&lt;p>&lt;strong>Sandipan&lt;/strong>：SIG Apps 面临的一些常见挑战是什么？你们是如何解决这些问题的？&lt;/p>
&lt;p>我们一直面临的最大挑战是需要拒绝许多功能、想法和改进。这需要大量的纪律性和耐心，
以便能够解释做出这些决定背后的原因。&lt;/p>
&lt;!--
**Sandipan: How has the evolution of Kubernetes influenced the work of SIG Apps? Are there any
recent changes or upcoming features in Kubernetes that you find particularly relevant or beneficial
for SIG Apps?**
The main benefit for both us and the whole community around SIG Apps is the ability to extend
kubernetes with [Custom Resource Definitions](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/)
and the fact that users can build their own custom controllers leveraging the built-in ones to
achieve whatever sophisticated use cases they might have and we, as the core maintainers, haven’t
considered or weren’t able to efficiently resolve inside Kubernetes.
-->
&lt;p>&lt;strong>Sandipan&lt;/strong>：Kubernetes 的演进如何影响了 SIG Apps 的工作？
Kubernetes 最近是否有任何变化或即将推出的功能，你认为对
SIG Apps 特别相关或有益？&lt;/p>
&lt;p>对我们以及围绕 SIG Apps 的整个社区而言，
最大的好处是能够通过&lt;a href="https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/">自定义资源定义（Custom Resource Definitions）&lt;/a>扩展
Kubernetes。用户可以利用内置控制器构建自己的自定义控制器，
以实现他们可能面对的各种复杂用例，而我们作为核心维护者，
可能没有考虑过这些用例，或者无法在 Kubernetes 内部高效解决。&lt;/p>
&lt;!--
## Contributing to SIG Apps
**Sandipan: What opportunities are available for new contributors who want to get involved with SIG
Apps, and what advice would you give them?**
-->
&lt;h2 id="贡献于-sig-apps">贡献于 SIG Apps&lt;/h2>
&lt;p>&lt;strong>Sandipan&lt;/strong>：对于想要参与 SIG Apps 的新贡献者，有哪些机会？
你会给他们什么建议？&lt;/p>
&lt;!--
We get the question, "What good first issue might you recommend we start with?" a lot :-) But
unfortunately, there’s no easy answer to it. We always tell everyone that the best option to start
contributing to core controllers is to find one you are willing to spend some time with. Read
through the code, then try running unit tests and integration tests focusing on that
controller. Once you grasp the general idea, try breaking it and the tests again to verify your
breakage. Once you start feeling confident you understand that particular controller, you may want
to search through open issues affecting that controller and either provide suggestions, explaining
the problem users have, or maybe attempt your first fix.
-->
&lt;p>我们经常被问道：“你们建议我们从哪个好的初始问题开始？” :-)
但遗憾的是，这个问题没有简单的答案。我们总是告诉大家，
为核心控制器做贡献的最佳方式是找到一个你愿意花时间研究的控制器。
阅读代码，然后尝试运行针对该控制器的单元测试和集成测试。一旦你掌握了大致的概念，
试着破坏它并再次运行测试以验证你的改动。当你开始有信心理解了这个特定的控制器后，
你可以搜索影响该控制器的待处理问题，提供一些建议，解释用户遇到的问题，
或者尝试提交你的第一个修复。&lt;/p>
&lt;!--
Like we said, there are no shortcuts on that road; you need to spend the time with the codebase to
understand all the edge cases we’ve slowly built up to get to the point where we are. Once you’re
successful with one controller, you’ll need to repeat that same process with others all over again.
**Sandipan: How does SIG Apps gather feedback from the community, and how is this feedback
integrated into your work?**
-->
&lt;p>正如我们所说，在这条道路上没有捷径可走；你需要花时间研究代码库，
以理解我们逐步积累的所有边缘情况，从而达到我们现在的位置。
一旦你在一个控制器上取得了成功，你就需要在其他控制器上重复同样的过程。&lt;/p>
&lt;p>&lt;strong>Sandipan&lt;/strong>：SIG Apps 如何从社区收集反馈，以及这些反馈是如何整合到你们的工作中的？&lt;/p>
&lt;!--
We always encourage everyone to show up and present their problems and solutions during our
bi-weekly [meetings](https://github.com/kubernetes/community/tree/master/sig-apps#meetings). As long
as you’re solving an interesting problem on top of Kubernetes and you can provide valuable feedback
about any of the core controllers, we’re always happy to hear from everyone.
-->
&lt;p>我们总是鼓励每个人参加我们的双周&lt;a href="https://github.com/kubernetes/community/tree/master/sig-apps#meetings">会议&lt;/a>，
并在会上提出他们的问题和解决方案。只要你是在 Kubernetes 上解决一个有趣的问题，
并且能够对任何核心控制器提供有价值的反馈，我们都非常乐意听取每个人的意见。&lt;/p>
&lt;!--
## Looking ahead
**Sandipan: Looking ahead, what are the key focus areas or upcoming trends in application management
within Kubernetes that SIG Apps is excited about? How is the SIG adapting to these trends?**
Definitely the current AI hype is the major driving factor; as mentioned above, we have two working
groups, each covering a different aspect of it.
-->
&lt;h2 id="展望未来">展望未来&lt;/h2>
&lt;p>&lt;strong>Sandipan&lt;/strong>：展望未来，Kubernetes 中应用程序管理的关键关注领域或即将到来的趋势有哪些是
SIG Apps 感到兴奋的？SIG 是如何适应这些趋势的？&lt;/p>
&lt;p>当前的 AI 热潮无疑是主要的驱动因素；如上所述，我们有两个工作组，
每个工作组都涵盖了它的一个不同方面。&lt;/p>
&lt;!--
**Sandipan: What are some of your favorite things about this SIG?**
Without a doubt, the people that participate in our meetings and on
[Slack](https://kubernetes.slack.com/messages/sig-apps), who tirelessly help triage issues, pull
requests and invest a lot of their time (very frequently their private time) into making kubernetes
great!
-->
&lt;p>&lt;strong>Sandipan&lt;/strong>：关于这个 SIG，你们最喜欢的事情有哪些？&lt;/p>
&lt;p>毫无疑问，参与我们会议和
&lt;a href="https://kubernetes.slack.com/messages/sig-apps">Slack&lt;/a> 频道的人们是最让我们感到欣慰的。
他们不知疲倦地帮助处理问题、拉取请求，并投入大量的时间（很多时候是他们的私人时间）来让
Kubernetes 变得更好！&lt;/p>
&lt;hr>
&lt;!--
SIG Apps is an essential part of the Kubernetes community, helping to shape how applications are
deployed and managed at scale. From its work on improving Kubernetes' workload APIs to driving
innovation in AI/ML application management, SIG Apps is continually adapting to meet the needs of
modern application developers and operators. Whether you’re a new contributor or an experienced
developer, there’s always an opportunity to get involved and make an impact.
-->
&lt;p>SIG Apps 是 Kubernetes 社区的重要组成部分，
帮助塑造了应用程序如何在大规模下部署和管理的方式。从改进 Kubernetes
的工作负载 API 到推动 AI/ML 应用程序管理的创新，SIG Apps
不断适应以满足现代应用程序开发者和操作人员的需求。无论你是新贡献者还是有经验的开发者，
都有机会参与其中并产生影响。&lt;/p>
&lt;!--
If you’re interested in learning more or contributing to SIG Apps, be sure to check out their [SIG
README](https://github.com/kubernetes/community/tree/master/sig-apps) and join their bi-weekly [meetings](https://github.com/kubernetes/community/tree/master/sig-apps#meetings).
- [SIG Apps Mailing List](https://groups.google.com/a/kubernetes.io/g/sig-apps)
- [SIG Apps on Slack](https://kubernetes.slack.com/messages/sig-apps)
-->
&lt;p>如果你有兴趣了解更多关于 SIG Apps 的信息或为其做出贡献，务必查看他们的
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-apps">SIG README&lt;/a>，
并加入他们的双周&lt;a href="https://github.com/kubernetes/community/tree/master/sig-apps#meetings">会议&lt;/a>。&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://groups.google.com/a/kubernetes.io/g/sig-apps">SIG Apps 邮件列表&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://kubernetes.slack.com/messages/sig-apps">SIG Apps 在 Slack 上&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>kube-proxy 的 NFTables 模式</title><link>https://kubernetes.io/zh-cn/blog/2025/02/28/nftables-kube-proxy/</link><pubDate>Fri, 28 Feb 2025 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2025/02/28/nftables-kube-proxy/</guid><description>
&lt;!--
layout: blog
title: "NFTables mode for kube-proxy"
date: 2025-02-28
slug: nftables-kube-proxy
author: >
Dan Winship (Red Hat)
-->
&lt;!--
A new nftables mode for kube-proxy was introduced as an alpha feature
in Kubernetes 1.29. Currently in beta, it is expected to be GA as of
1.33. The new mode fixes long-standing performance problems with the
iptables mode and all users running on systems with reasonably-recent
kernels are encouraged to try it out. (For compatibility reasons, even
once nftables becomes GA, iptables will still be the _default_.)
-->
&lt;p>Kubernetes 1.29 引入了一种新的 Alpha 特性：kube-proxy 的 nftables 模式。
目前该模式处于 Beta 阶段，并预计将在 1.33 版本中达到一般可用（GA）状态。
新模式解决了 iptables 模式长期存在的性能问题，建议所有运行在较新内核版本系统上的用户尝试使用。
出于兼容性原因，即使 nftables 成为 GA 功能，iptables 仍将是&lt;strong>默认&lt;/strong>模式。&lt;/p>
&lt;!--
## Why nftables? Part 1: data plane latency
The iptables API was designed for implementing simple firewalls, and
has problems scaling up to support Service proxying in a large
Kubernetes cluster with tens of thousands of Services.
In general, the ruleset generated by kube-proxy in iptables mode has a
number of iptables rules proportional to the sum of the number of
Services and the total number of endpoints. In particular, at the top
level of the ruleset, there is one rule to test each possible Service
IP (and port) that a packet might be addressed to:
-->
&lt;h2 id="为什么选择-nftables-第一部分-数据平面延迟">为什么选择 nftables？第一部分：数据平面延迟&lt;/h2>
&lt;p>iptables API 是被设计用于实现简单的防火墙功能，在扩展到支持大型 Kubernetes 集群中的 Service
代理时存在局限性，尤其是在包含数万个 Service 的集群中。&lt;/p>
&lt;p>通常，kube-proxy 在 iptables 模式下生成的规则集中的 iptables 规则数量与
Service 数量和总端点数量的总和成正比。
特别是，在规则集的顶层，针对数据包可能指向的每个可能的 Service IP（以及端口），
都有一条规则用于测试。&lt;/p>
&lt;!--
```
# If the packet is addressed to 172.30.0.41:80, then jump to the chain
# KUBE-SVC-XPGD46QRK7WJZT7O for further processing
-A KUBE-SERVICES -m comment --comment "namespace1/service1:p80 cluster IP" -m tcp -p tcp -d 172.30.0.41 --dport 80 -j KUBE-SVC-XPGD46QRK7WJZT7O
# If the packet is addressed to 172.30.0.42:443, then...
-A KUBE-SERVICES -m comment --comment "namespace2/service2:p443 cluster IP" -m tcp -p tcp -d 172.30.0.42 --dport 443 -j KUBE-SVC-GNZBNJ2PO5MGZ6GT
# etc...
-A KUBE-SERVICES -m comment --comment "namespace3/service3:p80 cluster IP" -m tcp -p tcp -d 172.30.0.43 --dport 80 -j KUBE-SVC-X27LE4BHSL4DOUIK
```
-->
&lt;pre tabindex="0">&lt;code># 如果数据包的目标地址是 172.30.0.41:80，则跳转到 KUBE-SVC-XPGD46QRK7WJZT7O 链进行进一步处理
-A KUBE-SERVICES -m comment --comment &amp;#34;namespace1/service1:p80 cluster IP&amp;#34; -m tcp -p tcp -d 172.30.0.41 --dport 80 -j KUBE-SVC-XPGD46QRK7WJZT7O
# 如果数据包的目标地址是 172.30.0.42:443，则...
-A KUBE-SERVICES -m comment --comment &amp;#34;namespace2/service2:p443 cluster IP&amp;#34; -m tcp -p tcp -d 172.30.0.42 --dport 443 -j KUBE-SVC-GNZBNJ2PO5MGZ6GT
# 等等...
-A KUBE-SERVICES -m comment --comment &amp;#34;namespace3/service3:p80 cluster IP&amp;#34; -m tcp -p tcp -d 172.30.0.43 --dport 80 -j KUBE-SVC-X27LE4BHSL4DOUIK
&lt;/code>&lt;/pre>&lt;!--
This means that when a packet comes in, the time it takes the kernel
to check it against all of the Service rules is **O(n)** in the number
of Services. As the number of Services increases, both the average and
the worst-case latency for the first packet of a new connection
increases (with the difference between best-case, average, and
worst-case being mostly determined by whether a given Service IP
address appears earlier or later in the `KUBE-SERVICES` chain).
&lt;figure>
&lt;img src="https://kubernetes.io/zh-cn/blog/2025/02/28/nftables-kube-proxy/iptables-only.svg"
alt="kube-proxy iptables first packet latency, at various percentiles, in clusters of various sizes"/>
&lt;/figure>
By contrast, with nftables, the normal way to write a ruleset like
this is to have a _single_ rule, using a "verdict map" to do the
dispatch:
-->
&lt;p>这意味着当数据包到达时，内核检查该数据包与所有 Service 规则所需的时间是 &lt;strong>O(n)&lt;/strong>，
其中 n 为 Service 的数量。随着 Service 数量的增加，新连接的第一个数据包的平均延迟和最坏情况下的延迟都会增加
（最佳情况、平均情况和最坏情况之间的差异主要取决于某个 Service IP 地址在 &lt;code>KUBE-SERVICES&lt;/code>
链中出现的顺序是靠前还是靠后）。&lt;/p>
&lt;figure>
&lt;img src="https://kubernetes.io/zh-cn/blog/2025/02/28/nftables-kube-proxy/iptables-only.svg"
alt="kube-proxy iptables 在不同规模集群中各百分位数下的第一个数据包延迟"/>
&lt;/figure>
&lt;p>相比之下，使用 nftables，编写此类规则集的常规方法是使用一个单一规则，
并通过&amp;quot;判决映射&amp;quot;（verdict map）来完成分发：&lt;/p>
&lt;!--
```
table ip kube-proxy {
# The service-ips verdict map indicates the action to take for each matching packet.
map service-ips {
type ipv4_addr . inet_proto . inet_service : verdict
comment "ClusterIP, ExternalIP and LoadBalancer IP traffic"
elements = { 172.30.0.41 . tcp . 80 : goto service-ULMVA6XW-namespace1/service1/tcp/p80,
172.30.0.42 . tcp . 443 : goto service-42NFTM6N-namespace2/service2/tcp/p443,
172.30.0.43 . tcp . 80 : goto service-4AT6LBPK-namespace3/service3/tcp/p80,
... }
}
# Now we just need a single rule to process all packets matching an
# element in the map. (This rule says, "construct a tuple from the
# destination IP address, layer 4 protocol, and destination port; look
# that tuple up in "service-ips"; and if there's a match, execute the
# associated verdict.)
chain services {
ip daddr . meta l4proto . th dport vmap @service-ips
}
...
}
```
-->
&lt;pre tabindex="0">&lt;code class="language-none" data-lang="none">table ip kube-proxy {
# service-ips 判决映射指示了对每个匹配数据包应采取的操作。
map service-ips {
type ipv4_addr . inet_proto . inet_service : verdict
comment &amp;#34;ClusterIP、ExternalIP 和 LoadBalancer IP 流量&amp;#34;
elements = { 172.30.0.41 . tcp . 80 : goto service-ULMVA6XW-namespace1/service1/tcp/p80,
172.30.0.42 . tcp . 443 : goto service-42NFTM6N-namespace2/service2/tcp/p443,
172.30.0.43 . tcp . 80 : goto service-4AT6LBPK-namespace3/service3/tcp/p80,
... }
}
# 现在我们只需要一条规则来处理所有与映射中元素匹配的数据包。
# （此规则表示：&amp;#34;根据目标 IP 地址、第 4 层协议和目标端口构建一个元组；
# 在 &amp;#39;service-ips&amp;#39; 中查找该元组；如果找到匹配项，则执行与之关联的判定。&amp;#34;）
chain services {
ip daddr . meta l4proto . th dport vmap @service-ips
}
...
}
&lt;/code>&lt;/pre>&lt;!--
Since there's only a single rule, with a roughly **O(1)** map lookup,
packet processing time is more or less constant regardless of cluster
size, and the best/average/worst cases are very similar:
&lt;figure>
&lt;img src="https://kubernetes.io/zh-cn/blog/2025/02/28/nftables-kube-proxy/nftables-only.svg"
alt="kube-proxy nftables first packet latency, at various percentiles, in clusters of various sizes"/>
&lt;/figure>
-->
&lt;p>由于只有一条规则，并且映射查找的时间复杂度大约为 &lt;strong>O(1)&lt;/strong>，因此数据包处理时间几乎与集群规模无关，
并且最佳、平均和最坏情况下的表现非常接近：&lt;/p>
&lt;figure>
&lt;img src="https://kubernetes.io/zh-cn/blog/2025/02/28/nftables-kube-proxy/nftables-only.svg"
alt="kube-proxy nftables 在不同规模集群中各百分位数下的第一个数据包延迟"/>
&lt;/figure>
&lt;!--
But note the huge difference in the vertical scale between the
iptables and nftables graphs! In the clusters with 5000 and 10,000
Services, the p50 (average) latency for nftables is about the same as
the p01 (approximately best-case) latency for iptables. In the 30,000
Service cluster, the p99 (approximately worst-case) latency for
nftables manages to beat out the p01 latency for iptables by a few
microseconds! Here's both sets of data together, but you may have to
squint to see the nftables results!:
&lt;figure>
&lt;img src="https://kubernetes.io/zh-cn/blog/2025/02/28/nftables-kube-proxy/iptables-vs-nftables.svg"
alt="kube-proxy iptables-vs-nftables first packet latency, at various percentiles, in clusters of various sizes"/>
&lt;/figure>
-->
&lt;p>但请注意图表中 iptables 和 nftables 之间在纵轴上的巨大差异！
在包含 5000 和 10,000 个 Service 的集群中，nftables 的 p50（平均）延迟与 iptables
的 p01（接近最佳情况）延迟大致相同。
在包含 30,000 个 Service 的集群中，nftables 的 p99（接近最坏情况）延迟比 iptables 的 p01 延迟快了几微秒！
以下是两组数据的对比图，但你可能需要仔细观察才能看到 nftables 的结果！&lt;/p>
&lt;figure>
&lt;img src="https://kubernetes.io/zh-cn/blog/2025/02/28/nftables-kube-proxy/iptables-vs-nftables.svg"
alt="kube-proxy iptables 与 nftables 在不同规模集群中各百分位数下的第一个数据包延迟对比"/>
&lt;/figure>
&lt;!--
## Why nftables? Part 2: control plane latency
While the improvements to data plane latency in large clusters are
great, there's another problem with iptables kube-proxy that often
keeps users from even being able to grow their clusters to that size:
the time it takes kube-proxy to program new iptables rules when
Services and their endpoints change.
-->
&lt;h2 id="为什么选择-nftables-第二部分-控制平面延迟">为什么选择 nftables？第二部分：控制平面延迟&lt;/h2>
&lt;p>虽然在大型集群中数据平面延迟的改进非常显著，但 iptables 模式的 kube-proxy 还存在另一个问题，
这往往使得用户无法将集群扩展到较大规模：那就是当 Service 及其端点发生变化时，kube-proxy
更新 iptables 规则所需的时间。&lt;/p>
&lt;!--
With both iptables and nftables, the total size of the ruleset as a
whole (actual rules, plus associated data) is **O(n)** in the combined
number of Services and their endpoints. Originally, the iptables
backend would rewrite every rule on every update, and with tens of
thousands of Services, this could grow to be hundreds of thousands of
iptables rules. Starting in Kubernetes 1.26, we began improving
kube-proxy so that it could skip updating _most_ of the unchanged
rules in each update, but the limitations of `iptables-restore` as an
API meant that it was still always necessary to send an update that's
**O(n)** in the number of Services (though with a noticeably smaller
constant than it used to be). Even with those optimizations, it can
still be necessary to make use of kube-proxy's `minSyncPeriod` config
option to ensure that it doesn't spend every waking second trying to
push iptables updates.
-->
&lt;p>对于 iptables 和 nftables，规则集的整体大小（实际规则加上相关数据）与 Service
及其端点的总数呈 &lt;strong>O(n)&lt;/strong> 关系。原来，iptables 后端在每次更新时都会重写所有规则，
当集群中存在数万个 Service 时，这可能导致规则数量增长至数十万条 iptables 规则。
从 Kubernetes 1.26 开始，我们开始优化 kube-proxy，使其能够在每次更新时跳过对大多数未更改规则的更新，
但由于 &lt;code>iptables-restore&lt;/code> API 的限制，仍然需要发送与 Service 数量呈 &lt;strong>O(n)&lt;/strong>
比例的更新（尽管常数因子比以前明显减小）。即使进行了这些优化，有时仍需使用 kube-proxy 的
&lt;code>minSyncPeriod&lt;/code> 配置选项，以确保它不会每秒钟都在尝试推送 iptables 更新。&lt;/p>
&lt;!--
The nftables APIs allow for doing much more incremental updates, and
when kube-proxy in nftables mode does an update, the size of the
update is only **O(n)** in the number of Services and endpoints that
have changed since the last sync, regardless of the total number of
Services and endpoints. The fact that the nftables API allows each
nftables-using component to have its own private table also means that
there is no global lock contention between components like with
iptables. As a result, kube-proxy's nftables updates can be done much
more efficiently than with iptables.
(Unfortunately I don't have cool graphs for this part.)
-->
&lt;p>nftables API 支持更为增量化的更新，当以 nftables 模式运行的 kube-proxy 执行更新时，
更新的规模仅与自上次同步以来发生变化的 Service 和端点数量呈 &lt;strong>O(n)&lt;/strong> 关系，而与总的 Service 和端点数量无关。
此外，由于 nftables API 允许每个使用 nftables 的组件拥有自己的私有表，因此不会像 iptables
那样在组件之间产生全局锁竞争。结果是，kube-proxy 在 nftables 模式下的更新可以比 iptables 模式下高效得多。&lt;/p>
&lt;p>（不幸的是，这部分我没有酷炫的图表。）&lt;/p>
&lt;!--
## Why _not_ nftables? {#why-not-nftables}
All that said, there are a few reasons why you might not want to jump
right into using the nftables backend for now.
First, the code is still fairly new. While it has plenty of unit
tests, performs correctly in our CI system, and has now been used in
the real world by multiple users, it has not seen anything close to as
much real-world usage as the iptables backend has, so we can't promise
that it is as stable and bug-free.
-->
&lt;h2 id="why-not-nftables">不选择 nftables 的理由有哪些？ &lt;/h2>
&lt;p>尽管如此，仍有几个原因可能让你目前不希望立即使用 nftables 后端。&lt;/p>
&lt;p>首先，该代码仍然相对较新。虽然它拥有大量的单元测试，在我们的 CI 系统中表现正确，
并且已经在现实世界中被多个用户使用，但其实际使用量远远不及 iptables 后端，
因此我们无法保证它同样稳定且无缺陷。&lt;/p>
&lt;!--
Second, the nftables mode will not work on older Linux distributions;
currently it requires a 5.13 or newer kernel. Additionally, because of
bugs in early versions of the `nft` command line tool, you should not
run kube-proxy in nftables mode on nodes that have an old (earlier
than 1.0.0) version of `nft` in the host filesystem (or else
kube-proxy's use of nftables may interfere with other uses of nftables
on the system).
-->
&lt;p>其次，nftables 模式无法在较旧的 Linux 发行版上工作；目前它需要 5.13 或更高版本的内核。
此外，由于早期版本的 &lt;code>nft&lt;/code> 命令行工具存在缺陷，不应在运行旧版本（早于 1.0.0）
&lt;code>nft&lt;/code> 的节点主机文件系统中上以 nftables 模式运行 kube-proxy（否则 kube-proxy
对 nftables 的使用可能会影响系统上其他程序对 nftables 的使用）。&lt;/p>
&lt;!--
Third, you may have other networking components in your cluster, such
as the pod network or NetworkPolicy implementation, that do not yet
support kube-proxy in nftables mode. You should consult the
documentation (or forums, bug tracker, etc.) for any such components
to see if they have problems with nftables mode. (In many cases they
will not; as long as they don't try to directly interact with or
override kube-proxy's iptables rules, they shouldn't care whether
kube-proxy is using iptables or nftables.) Additionally, observability
and monitoring tools that have not been updated may report less data
for kube-proxy in nftables mode than they do for kube-proxy in
iptables mode.
-->
&lt;p>第三，你的集群中可能还存在其他网络组件，例如 Pod 网络或 NetworkPolicy 实现，
这些组件可能尚不支持以 nftables 模式运行的 kube-proxy。你应查阅相关组件的文档（或论坛、问题跟踪系统等），
以确认它们是否与 nftables 模式存在兼容性问题。（在许多情况下，它们并不会受到影响；
只要它们不尝试直接操作或覆盖 kube-proxy 的 iptables 规则，就不在乎 kube-proxy
使用的是 iptables 还是 nftables。）
此外，相较于 iptables 模式下，尚未更新的可观测性和监控工具在 nftables
模式下可能会为 kube-proxy 提供更少的数据。&lt;/p>
&lt;!--
Finally, kube-proxy in nftables mode is intentionally not 100%
compatible with kube-proxy in iptables mode. There are a few old
kube-proxy features whose default behaviors are less secure, less
performant, or less intuitive than we'd like, but where we felt that
changing the default would be a compatibility break. Since the
nftables mode is opt-in, this gave us a chance to fix those bad
defaults without breaking users who weren't expecting changes. (In
particular, with nftables mode, NodePort Services are now only
reachable on their nodes' default IPs, as opposed to being reachable
on all IPs, including `127.0.0.1`, with iptables mode.) The
[kube-proxy documentation] has more information about this, including
information about metrics you can look at to determine if you are
relying on any of the changed functionality, and what configuration
options are available to get more backward-compatible behavior.
[kube-proxy documentation]: https://kubernetes.io/docs/reference/networking/virtual-ips/#migrating-from-iptables-mode-to-nftables
-->
&lt;p>最后，以 nftables 模式运行的 kube-proxy 有意不与以 iptables 模式运行的 kube-proxy 完全兼容。
有一些较旧的 kube-proxy 功能，默认行为不如我们期望的那样安全、高效或直观，但我们认为更改默认行为会导致兼容性问题。
由于 nftables 模式是可选的，这为我们提供了一个机会，在不影响期望稳定性的用户的情况下修复这些不良默认设置。
（特别是，在 nftables 模式下，NodePort 类型的 Service 现在仅在其节点的默认 IP 上可访问，而在 iptables 模式下，
它们在所有 IP 上均可访问，包括 &lt;code>127.0.0.1&lt;/code>。）&lt;a href="https://kubernetes.io/zh-cn/docs/reference/networking/virtual-ips/#migrating-from-iptables-mode-to-nftables">kube-proxy 文档&lt;/a> 提供了更多关于此方面的信息，
包括如何通过查看某些指标来判断你是否依赖于任何已更改的特性，以及有哪些配置选项可用于实现更向后兼容的行为。&lt;/p>
&lt;!--
## Trying out nftables mode
Ready to try it out? In Kubernetes 1.31 and later, you just need to
pass `--proxy-mode nftables` to kube-proxy (or set `mode: nftables` in
your kube-proxy config file).
If you are using kubeadm to set up your cluster, the kubeadm
documentation explains [how to pass a `KubeProxyConfiguration` to
`kubeadm init`]. You can also [deploy nftables-based clusters with
`kind`].
-->
&lt;h2 id="尝试使用-nftables-模式">尝试使用 nftables 模式&lt;/h2>
&lt;p>准备尝试了吗？在 Kubernetes 1.31 及更高版本中，你只需将 &lt;code>--proxy-mode nftables&lt;/code>
参数传递给 kube-proxy（或在 kube-proxy 配置文件中设置 &lt;code>mode: nftables&lt;/code>）。&lt;/p>
&lt;p>如果你使用 kubeadm 部署集群，kubeadm 文档解释了&lt;a href="https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-init/#config-file">如何向 &lt;code>kubeadm init&lt;/code> 传递 &lt;code>KubeProxyConfiguration&lt;/code>&lt;/a>。
你还可以&lt;a href="https://kind.sigs.k8s.io/docs/user/configuration/#kube-proxy-mode">通过 &lt;code>kind&lt;/code> 部署基于 nftables 的集群&lt;/a>。&lt;/p>
&lt;!--
You can also convert existing clusters from iptables (or ipvs) mode to
nftables by updating the kube-proxy configuration and restarting the
kube-proxy pods. (You do not need to reboot the nodes: when restarting
in nftables mode, kube-proxy will delete any existing iptables or ipvs
rules, and likewise, if you later revert back to iptables or ipvs
mode, it will delete any existing nftables rules.)
[how to pass a `KubeProxyConfiguration` to `kubeadm init`]: /docs/setup/production-environment/tools/kubeadm/control-plane-flags/#customizing-kube-proxy
[deploy nftables-based clusters with `kind`]: https://kind.sigs.k8s.io/docs/user/configuration/#kube-proxy-mode
-->
&lt;p>你还可以通过更新 kube-proxy 配置并重启 kube-proxy Pod，将现有集群从
iptables（或 ipvs）模式转换为 nftables 模式。（无需重启节点：
在以 nftables 模式重新启动时，kube-proxy 会删除现有的所有 iptables 或 ipvs 规则；
同样，如果你之后切换回 iptables 或 ipvs 模式，它将删除现有的所有 nftables 规则。）&lt;/p>
&lt;!--
## Future plans
As mentioned above, while nftables is now the _best_ kube-proxy mode,
it is not the _default_, and we do not yet have a plan for changing
that. We will continue to support the iptables mode for a long time.
The future of the IPVS mode of kube-proxy is less certain: its main
advantage over iptables was that it was faster, but certain aspects of
the IPVS architecture and APIs were awkward for kube-proxy's purposes
(for example, the fact that the `kube-ipvs0` device needs to have
_every_ Service IP address assigned to it), and some parts of
Kubernetes Service proxying semantics were difficult to implement
using IPVS (particularly the fact that some Services had to have
different endpoints depending on whether you connected to them from a
local or remote client). And now, the nftables mode has the same
performance as IPVS mode (actually, slightly better), without any of
the downsides:
-->
&lt;h2 id="未来计划">未来计划&lt;/h2>
&lt;p>如上所述，虽然 nftables 现在是的 kube-proxy 的最佳模式，但它还不是默认模式，
我们目前还没有更改这一设置的计划。我们将继续长期支持 iptables 模式。&lt;/p>
&lt;p>kube-proxy 的 IPVS 模式的未来则不太确定：它相对于 iptables 的主要优势在于速度更快，
但 IPVS 的架构和 API 在某些方面对 kube-proxy 来说不够理想（例如，&lt;code>kube-ipvs0&lt;/code>
设备需要被分配所有 Service IP 地址），
并且 Kubernetes Service 代理的部分语义使用 IPVS 难以实现（特别是某些
Service 根据连接的客户端是本地还是远程，需要有不同的端点）。
现在，nftables 模式的性能与 IPVS 模式相同（实际上略胜一筹），而且没有任何缺点：&lt;/p>
&lt;!--
&lt;figure>
&lt;img src="https://kubernetes.io/zh-cn/blog/2025/02/28/nftables-kube-proxy/ipvs-vs-nftables.svg"
alt="kube-proxy ipvs-vs-nftables first packet latency, at various percentiles, in clusters of various sizes"/>
&lt;/figure>
(In theory the IPVS mode also has the advantage of being able to use
various other IPVS functionality, like alternative "schedulers" for
balancing endpoints. In practice, this ended up not being very useful,
because kube-proxy runs independently on every node, and the IPVS
schedulers on each node had no way of sharing their state with the
proxies on other nodes, thus thwarting the effort to balance traffic
more cleverly.)
-->
&lt;figure>
&lt;img src="https://kubernetes.io/zh-cn/blog/2025/02/28/nftables-kube-proxy/ipvs-vs-nftables.svg"
alt="kube-proxy IPVS 与 nftables 在不同规模集群中各百分位数下的第一个数据包延迟对比"/>
&lt;/figure>
&lt;p>（理论上，IPVS 模式还具有可以使用其他 IPVS 功能的优势，例如使用替代的&amp;quot;调度器&amp;quot;来平衡端点。
但实际上，这并不太有用，因为 kube-proxy 在每个节点上独立运行，每个节点上的 IPVS
调度器无法与其他节点上的代理共享状态，从而无法实现更智能的流量均衡。）&lt;/p>
&lt;!--
While the Kubernetes project does not have an immediate plan to drop
the IPVS backend, it is probably doomed in the long run, and people
who are currently using IPVS mode should try out the nftables mode
instead (and file bugs if you think there is missing functionality in
nftables mode that you can't work around).
-->
&lt;p>虽然 Kubernetes 项目目前没有立即放弃 IPVS 后端的计划，但从长远来看，IPVS 可能难逃被淘汰的命运。
目前使用 IPVS 模式的用户应尝试使用 nftables 模式（如果发现 nftables 模式中缺少某些无法绕过的功能，
请提交问题报告）。&lt;/p>
&lt;!--
## Learn more
- "[KEP-3866: Add an nftables-based kube-proxy backend]" has the
history of the new feature.
- "[How the Tables Have Turned: Kubernetes Says Goodbye to IPTables]",
from KubeCon/CloudNativeCon North America 2024, talks about porting
kube-proxy and Calico from iptables to nftables.
- "[From Observability to Performance]", from KubeCon/CloudNativeCon
North America 2024. (This is where the kube-proxy latency data came
from; the [raw data for the charts] is also available.)
-->
&lt;h2 id="进一步了解">进一步了解&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>&amp;quot;&lt;a href="https://github.com/kubernetes/enhancements/blob/master/keps/sig-network/3866-nftables-proxy/README.md">KEP-3866: Add an nftables-based kube-proxy backend&lt;/a>&amp;quot; 记录了此新特性的历史。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&amp;quot;&lt;a href="https://youtu.be/yOGHb2HjslY?si=6O4PVJu7fGpReo1U">How the Tables Have Turned: Kubernetes Says Goodbye to IPTables&lt;/a>&amp;quot;，来自 2024 年
KubeCon/CloudNativeCon 北美大会，讨论了将 kube-proxy 和 Calico 从 iptables 迁移到 nftables 的过程。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&amp;quot;&lt;a href="https://youtu.be/uYo2O3jbJLk?si=py2AXzMJZ4PuhxNg">From Observability to Performance&lt;/a>&amp;quot;，同样来自 2024 年 KubeCon/CloudNativeCon 北美大会。
（kube-proxy 延迟数据来源于此；&lt;a href="https://docs.google.com/spreadsheets/d/1-ryDNc6gZocnMHEXC7mNtqknKSOv5uhXFKDx8Hu3AYA/edit">raw data for the charts&lt;/a> 也可用。）&lt;/p>
&lt;/li>
&lt;/ul></description></item><item><title>云控制器管理器（Cloud Controller Manager）'鸡与蛋'的问题</title><link>https://kubernetes.io/zh-cn/blog/2025/02/14/cloud-controller-manager-chicken-egg-problem/</link><pubDate>Fri, 14 Feb 2025 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2025/02/14/cloud-controller-manager-chicken-egg-problem/</guid><description>
&lt;!--
layout: blog
title: "The Cloud Controller Manager Chicken and Egg Problem"
date: 2025-02-14
slug: cloud-controller-manager-chicken-egg-problem
author: >
Antonio Ojea,
Michael McCune
-->
&lt;!--
Kubernetes 1.31
[completed the largest migration in Kubernetes history][migration-blog], removing the in-tree
cloud provider. While the component migration is now done, this leaves some additional
complexity for users and installer projects (for example, kOps or Cluster API) . We will go
over those additional steps and failure points and make recommendations for cluster owners.
This migration was complex and some logic had to be extracted from the core components,
building four new subsystems.
-->
&lt;p>Kubernetes 1.31&lt;br>
&lt;a href="https://kubernetes.io/zh-cn/blog/2024/05/20/completing-cloud-provider-migration/">完成了 Kubernetes 历史上最大的迁移&lt;/a>，移除了树内云驱动（in-tree cloud provider）。
虽然组件迁移已经完成，但这为用户和安装项目（例如 kOps 或 Cluster API）带来了一些额外的复杂性。
我们将回顾这些额外的步骤和可能的故障点，并为集群所有者提供改进建议。&lt;br>
此次迁移非常复杂，必须从核心组件中提取部分逻辑，构建四个新的子系统。&lt;/p>
&lt;!--
1. **Cloud controller manager** ([KEP-2392][kep2392])
2. **API server network proxy** ([KEP-1281][kep1281])
3. **kubelet credential provider plugins** ([KEP-2133][kep2133])
4. **Storage migration to use [CSI][csi]** ([KEP-625][kep625])
The [cloud controller manager is part of the control plane][ccm]. It is a critical component
that replaces some functionality that existed previously in the kube-controller-manager and the
kubelet.
-->
&lt;ol>
&lt;li>&lt;strong>云控制器管理器&lt;/strong> (&lt;a href="https://github.com/kubernetes/enhancements/blob/master/keps/sig-cloud-provider/2392-cloud-controller-manager/README.md">KEP-2392&lt;/a>)&lt;/li>
&lt;li>&lt;strong>API 服务器网络代理&lt;/strong> (&lt;a href="https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/1281-network-proxy">KEP-1281&lt;/a>)&lt;/li>
&lt;li>&lt;strong>kubelet 凭证提供程序插件&lt;/strong> (&lt;a href="https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2133-kubelet-credential-providers">KEP-2133&lt;/a>)&lt;/li>
&lt;li>&lt;strong>存储迁移到使用 &lt;a href="https://github.com/container-storage-interface/spec?tab=readme-ov-file#container-storage-interface-csi-specification-">CSI&lt;/a>&lt;/strong> (&lt;a href="https://github.com/kubernetes/enhancements/blob/master/keps/sig-storage/625-csi-migration/README.md">KEP-625&lt;/a>)&lt;/li>
&lt;/ol>
&lt;p>&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/architecture/cloud-controller/">云控制器管理器是控制平面的一部分&lt;/a>。这是一个关键组件，替换了之前存在于 kube-controller-manager
和 kubelet 中的某些特性。&lt;/p>
&lt;!--
&lt;figure>
&lt;img src="https://kubernetes.io/images/docs/components-of-kubernetes.svg"
alt="Components of Kubernetes"/> &lt;figcaption>
&lt;p>Components of Kubernetes&lt;/p>
&lt;/figcaption>
&lt;/figure>
-->
&lt;figure>
&lt;img src="https://kubernetes.io/zh-cn/docs/images/components-of-kubernetes.svg"
alt="Kubernetes 组件"/> &lt;figcaption>
&lt;p>Kubernetes 组件&lt;/p>
&lt;/figcaption>
&lt;/figure>
&lt;!--
One of the most critical functionalities of the cloud controller manager is the node controller,
which is responsible for the initialization of the nodes.
As you can see in the following diagram, when the **kubelet** starts, it registers the Node
object with the apiserver, Tainting the node so it can be processed first by the
cloud-controller-manager. The initial Node is missing the cloud-provider specific information,
like the Node Addresses and the Labels with the cloud provider specific information like the
Node, Region and Instance type information.
-->
&lt;p>云控制器管理器最重要的功能之一是节点控制器，它负责节点的初始化。&lt;/p>
&lt;p>从下图可以看出，当 &lt;strong>kubelet&lt;/strong> 启动时，它会向 apiserver 注册 Node 对象，并对节点设置污点，
以便云控制器管理器可以先处理该节点。初始的 Node 缺少与云提供商相关的信息，
例如节点地址和包含云提供商特定信息的标签，如节点、区域和实例类型信息。&lt;/p>
&lt;!--
&lt;figure class="diagram-medium ">
&lt;img src="https://kubernetes.io/zh-cn/blog/2025/02/14/cloud-controller-manager-chicken-egg-problem/ccm-chicken-egg-problem-sequence-diagram.svg"
alt="Chicken and egg problem sequence diagram"/> &lt;figcaption>
&lt;p>Chicken and egg problem sequence diagram&lt;/p>
&lt;/figcaption>
&lt;/figure>
-->
&lt;figure class="diagram-medium ">
&lt;img src="https://kubernetes.io/zh-cn/blog/2025/02/14/cloud-controller-manager-chicken-egg-problem/ccm-chicken-egg-problem-sequence-diagram.svg"
alt="鸡和蛋问题时序图"/> &lt;figcaption>
&lt;p>鸡和蛋问题时序图&lt;/p>
&lt;/figcaption>
&lt;/figure>
&lt;!--
This new initialization process adds some latency to the node readiness. Previously, the kubelet
was able to initialize the node at the same time it created the node. Since the logic has moved
to the cloud-controller-manager, this can cause a [chicken and egg problem][chicken-and-egg]
during the cluster bootstrapping for those Kubernetes architectures that do not deploy the
controller manager as the other components of the control plane, commonly as static pods,
standalone binaries or daemonsets/deployments with tolerations to the taints and using
`hostNetwork` (more on this below)
-->
&lt;p>这一新的初始化过程会增加节点就绪的延迟。以前，kubelet 可以在创建节点的同时初始化节点。
对于某些 Kubernetes 架构而言，其控制平面其他组件以静态 Pod、独立二进制文件或具有容忍污点功能的、
用 &lt;code>hostNetwork&lt;/code> DaemonSet/Deployment 部署，由于节点初始化逻辑已移至云控制管理器中，
如果不将控制器管理器作为控制平面的一部分，则可能会导致集群引导过程中出现&lt;a href="https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/running-cloud-controller/#chicken-and-egg">鸡和蛋问题&lt;/a>（更多内容见下文）。&lt;/p>
&lt;!--
## Examples of the dependency problem
As noted above, it is possible during bootstrapping for the cloud-controller-manager to be
unschedulable and as such the cluster will not initialize properly. The following are a few
concrete examples of how this problem can be expressed and the root causes for why they might
occur.
These examples assume you are running your cloud-controller-manager using a Kubernetes resource
(e.g. Deployment, DaemonSet, or similar) to control its lifecycle. Because these methods
rely on Kubernetes to schedule the cloud-controller-manager, care must be taken to ensure it
will schedule properly.
-->
&lt;h2 id="依赖问题的示例">依赖问题的示例&lt;/h2>
&lt;p>如上所述，在引导过程中，云控制器管理器可能无法被调度，
因此集群将无法正确初始化。以下几个具体示例说明此问题的可能表现形式及其根本原因。&lt;/p>
&lt;p>这些示例假设你使用 Kubernetes 资源（例如 Deployment、DaemonSet
或类似资源）来控制云控制器管理器的生命周期。由于这些方法依赖于 Kubernetes 来调度云控制器管理器，
因此必须确保其能够正确调度。&lt;/p>
&lt;!--
### Example: Cloud controller manager not scheduling due to uninitialized taint
As [noted in the Kubernetes documentation][kubedocs0], when the kubelet is started with the command line
flag `--cloud-provider=external`, its corresponding `Node` object will have a no schedule taint
named `node.cloudprovider.kubernetes.io/uninitialized` added. Because the cloud-controller-manager
is responsible for removing the no schedule taint, this can create a situation where a
cloud-controller-manager that is being managed by a Kubernetes resource, such as a `Deployment`
or `DaemonSet`, may not be able to schedule.
-->
&lt;h3 id="示例-由于未初始化的污点导致云控制器管理器无法调度">示例：由于未初始化的污点导致云控制器管理器无法调度&lt;/h3>
&lt;p>如 &lt;a href="https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/running-cloud-controller/#running-cloud-controller-manager">Kubernetes 文档中所述&lt;/a>，当 kubelet 使用命令行标志 &lt;code>--cloud-provider=external&lt;/code>
启动时，其对应的 &lt;code>Node&lt;/code> 对象将添加一个名为 &lt;code>node.cloudprovider.kubernetes.io/uninitialized&lt;/code>
的不可调度污点。由于云控制器管理器负责移除该不可调度污点，这可能会导致由某个 Kubernetes
资源（例如 &lt;code>Deployment&lt;/code> 或 &lt;code>DaemonSet&lt;/code>）管理的云控制器管理器无法被调度的情况。&lt;/p>
&lt;!--
If the cloud-controller-manager is not able to be scheduled during the initialization of the
control plane, then the resulting `Node` objects will all have the
`node.cloudprovider.kubernetes.io/uninitialized` no schedule taint. It also means that this taint
will not be removed as the cloud-controller-manager is responsible for its removal. If the no
schedule taint is not removed, then critical workloads, such as the container network interface
controllers, will not be able to schedule, and the cluster will be left in an unhealthy state.
-->
&lt;p>如果在控制平面初始化期间云控制器管理器无法被调度，那么生成的 &lt;code>Node&lt;/code> 对象将全部带有
&lt;code>node.cloudprovider.kubernetes.io/uninitialized&lt;/code> 不可调度污点。这也意味着该污点不会被移除，
因为云控制器管理器负责其移除工作。如果不可调度污点未被移除，关键工作负载（例如容器网络接口控制器）
将无法被调度，集群将处于不健康状态。&lt;/p>
&lt;!--
### Example: Cloud controller manager not scheduling due to not-ready taint
The next example would be possible in situations where the container network interface (CNI) is
waiting for IP address information from the cloud-controller-manager (CCM), and the CCM has not
tolerated the taint which would be removed by the CNI.
The [Kubernetes documentation describes][kubedocs1] the `node.kubernetes.io/not-ready` taint as follows:
> "The Node controller detects whether a Node is ready by monitoring its health and adds or removes this taint accordingly."
-->
&lt;h3 id="示例-由于未就绪污点导致云控制器管理器无法调度">示例：由于未就绪污点导致云控制器管理器无法调度&lt;/h3>
&lt;p>下一个示例可能出现在容器网络接口（CNI）正在等待来自云控制器管理器（CCM）的
IP 地址信息，而 CCM 未容忍将由 CNI 移除的污点的情况下。&lt;/p>
&lt;p>&lt;a href="https://kubernetes.io/zh-cn/docs/reference/labels-annotations-taints/#node-kubernetes-io-not-ready">Kubernetes 文档&lt;/a> 对 &lt;code>node.kubernetes.io/not-ready&lt;/code> 污点的描述如下：&lt;/p>
&lt;blockquote>
&lt;p>&amp;quot;节点控制器通过监控节点的健康状态来检测节点是否已准备好，并据此添加或移除此污点。&amp;quot;&lt;/p>
&lt;/blockquote>
&lt;!--
One of the conditions that can lead to a Node resource having this taint is when the container
network has not yet been initialized on that node. As the cloud-controller-manager is responsible
for adding the IP addresses to a Node resource, and the IP addresses are needed by the container
network controllers to properly configure the container network, it is possible in some
circumstances for a node to become stuck as not ready and uninitialized permanently.
This situation occurs for a similar reason as the first example, although in this case, the
`node.kubernetes.io/not-ready` taint is used with the no execute effect and thus will cause the
cloud-controller-manager not to run on the node with the taint. If the cloud-controller-manager is
not able to execute, then it will not initialize the node. It will cascade into the container
network controllers not being able to run properly, and the node will end up carrying both the
`node.cloudprovider.kubernetes.io/uninitialized` and `node.kubernetes.io/not-ready` taints,
leaving the cluster in an unhealthy state.
-->
&lt;p>当容器网络尚未在某节点上初始化时，可能导致 Node 资源具有此污点。由于云控制器管理器负责为
Node 资源添加 IP 地址，而容器网络控制器需要这些 IP 地址来正确配置容器网络，因此在某些情况下，
节点可能会永久处于未就绪且未初始化的状态。&lt;/p>
&lt;p>这种情况的发生原因与第一个示例类似，但在此情况下，&lt;code>node.kubernetes.io/not-ready&lt;/code>
污点使用了 NoExecute 效果，从而导致云控制器管理器无法在带有该污点的节点上运行。
如果云控制器管理器无法执行，则它将无法初始化节点。这将进一步导致容器网络控制器无法正常运行，
节点最终会同时携带 &lt;code>node.cloudprovider.kubernetes.io/uninitialized&lt;/code> 和
&lt;code>node.kubernetes.io/not-ready&lt;/code> 两个污点，从而使集群处于不健康状态。&lt;/p>
&lt;!--
## Our Recommendations
There is no one “correct way” to run a cloud-controller-manager. The details will depend on the
specific needs of the cluster administrators and users. When planning your clusters and the
lifecycle of the cloud-controller-managers please consider the following guidance:
For cloud-controller-managers running in the same cluster, they are managing.
-->
&lt;h2 id="我们的建议">我们的建议&lt;/h2>
&lt;p>运行云控制器管理器并没有唯一的“正确方式”。具体细节将取决于集群管理员和用户的特定需求。
在规划你的集群以及云控制器管理器的生命周期时，请考虑以下指导。&lt;/p>
&lt;p>对于在同一集群中运行的云控制器管理器，它们所管理的集群也是这一集群，需要特别注意。&lt;/p>
&lt;!--
1. Use host network mode, rather than the pod network: in most cases, a cloud controller manager
will need to communicate with an API service endpoint associated with the infrastructure.
Setting “hostNetwork” to true will ensure that the cloud controller is using the host
networking instead of the container network and, as such, will have the same network access as
the host operating system. It will also remove the dependency on the networking plugin. This
will ensure that the cloud controller has access to the infrastructure endpoint (always check
your networking configuration against your infrastructure provider’s instructions).
2. Use a scalable resource type. `Deployments` and `DaemonSets` are useful for controlling the
lifecycle of a cloud controller. They allow easy access to running multiple copies for redundancy
as well as using the Kubernetes scheduling to ensure proper placement in the cluster. When using
these primitives to control the lifecycle of your cloud controllers and running multiple
replicas, you must remember to enable leader election, or else your controllers will collide
with each other which could lead to nodes not being initialized in the cluster.
-->
&lt;ol>
&lt;li>使用主机网络模式，而不是 Pod 网络：在大多数情况下，云控制器管理器需要与基础设施相关的 API 服务端点进行通信。
将 &amp;quot;hostNetwork&amp;quot; 设置为 &lt;code>true&lt;/code> 可确保云控制器使用主机网络而非容器网络，从而拥有与主机操作系统相同的网络访问权限。
这还将消除对网络插件的依赖。这可以确保云控制器能够访问基础设施端点
（你应该始终检查网络配置是否与基础设施提供商所给的指导相符）。&lt;/li>
&lt;li>使用规模可扩缩的资源类型。&lt;code>Deployment&lt;/code> 和 &lt;code>DaemonSet&lt;/code> 对于控制云控制器的生命周期非常有用。
它们支持轻松地运行多个副本以实现冗余，并利用 Kubernetes 调度来确保在集群中的正确放置。
当使用这些原语控制云控制器的生命周期并运行多个副本时，请务必启用领导者选举，
否则控制器之间可能会发生冲突，导致集群中的节点无法初始化。&lt;/li>
&lt;/ol>
&lt;!--
3. Target the controller manager containers to the control plane. There might exist other
controllers which need to run outside the control plane (for example, Azure’s node manager
controller). Still, the controller managers themselves should be deployed to the control plane.
Use a node selector or affinity stanza to direct the scheduling of cloud controllers to the
control plane to ensure that they are running in a protected space. Cloud controllers are vital
to adding and removing nodes to a cluster as they form a link between Kubernetes and the
physical infrastructure. Running them on the control plane will help to ensure that they run
with a similar priority as other core cluster controllers and that they have some separation
from non-privileged user workloads.
1. It is worth noting that an anti-affinity stanza to prevent cloud controllers from running
on the same host is also very useful to ensure that a single node failure will not degrade
the cloud controller performance.
-->
&lt;ol start="3">
&lt;li>将控制器管理器容器定位到控制平面。可能存在一些需要在控制平面之外运行的其他控制器
（例如，Azure 的节点管理器控制器），但云控制器管理器本身应部署到控制平面。
使用节点选择算符或亲和性配置将云控制器管理器定向调度到控制平面节点，以确保它们运行在受保护的空间中。
云控制器管理器在集群中添加和移除节点时至关重要，因为它们构成了 Kubernetes 与物理基础设施之间的桥梁。
&lt;ol>
&lt;li>值得注意的是，使用反亲和性配置以防止多个云控制器管理器运行在同一主机上也非常有用，
这可以确保单个节点故障不会影响云控制器管理器的性能。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ol>
&lt;!--
4. Ensure that the tolerations allow operation. Use tolerations on the manifest for the cloud
controller container to ensure that it will schedule to the correct nodes and that it can run
in situations where a node is initializing. This means that cloud controllers should tolerate
the `node.cloudprovider.kubernetes.io/uninitialized` taint, and it should also tolerate any
taints associated with the control plane (for example, `node-role.kubernetes.io/control-plane`
or `node-role.kubernetes.io/master`). It can also be useful to tolerate the
`node.kubernetes.io/not-ready` taint to ensure that the cloud controller can run even when the
node is not yet available for health monitoring.
For cloud-controller-managers that will not be running on the cluster they manage (for example,
in a hosted control plane on a separate cluster), then the rules are much more constrained by the
dependencies of the environment of the cluster running the cloud-controller-manager. The advice
for running on a self-managed cluster may not be appropriate as the types of conflicts and network
constraints will be different. Please consult the architecture and requirements of your topology
for these scenarios.
-->
&lt;ol start="4">
&lt;li>确保污点容忍规则允许操作。在云控制器管理器容器的清单中使用污点容忍规则，以确保其能够被调度到正确的节点，
并能够在节点初始化时运行。这意味着云控制器应容忍 &lt;code>node.cloudprovider.kubernetes.io/uninitialized&lt;/code>
污点，还应容忍与控制平面相关的任何污点（例如，&lt;code>node-role.kubernetes.io/control-plane&lt;/code> 或
&lt;code>node-role.kubernetes.io/master&lt;/code>）。容忍 &lt;code>node.kubernetes.io/not-ready&lt;/code> 污点也可能很有用，
以确保即使节点尚未准备好进行健康监控时，云控制器仍能运行。&lt;/li>
&lt;/ol>
&lt;p>对于不在其所管理的集群上（例如，在其他集群上的托管控制平面上）运行的云控制器管理器，
其规则将更多地受限于运行云控制器管理器的集群环境的依赖项。针对自管集群的运行建议可能不适用，
因为冲突类型和网络约束会有所不同。请根据这些场景咨询你的拓扑结构的架构和需求。&lt;/p>
&lt;!--
### Example
This is an example of a Kubernetes Deployment highlighting the guidance shown above. It is
important to note that this is for demonstration purposes only, for production uses please
consult your cloud provider’s documentation.
-->
&lt;h3 id="示例">示例&lt;/h3>
&lt;p>这是一个 Kubernetes Deployment 的示例，突显了上述指导原则。需要注意的是，
此示例仅用于演示目的，对于生产环境的使用，请参考你的云提供商的文档。&lt;/p>
&lt;!--
```
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: cloud-controller-manager
name: cloud-controller-manager
namespace: kube-system
spec:
replicas: 2
selector:
matchLabels:
app.kubernetes.io/name: cloud-controller-manager
strategy:
type: Recreate
template:
metadata:
labels:
app.kubernetes.io/name: cloud-controller-manager
annotations:
kubernetes.io/description: Cloud controller manager for my infrastructure
spec:
containers: # the container details will depend on your specific cloud controller manager
- name: cloud-controller-manager
command:
- /bin/my-infrastructure-cloud-controller-manager
- --leader-elect=true
- -v=1
image: registry/my-infrastructure-cloud-controller-manager@latest
resources:
requests:
cpu: 200m
memory: 50Mi
hostNetwork: true # these Pods are part of the control plane
nodeSelector:
node-role.kubernetes.io/control-plane: ""
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: "kubernetes.io/hostname"
labelSelector:
matchLabels:
app.kubernetes.io/name: cloud-controller-manager
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/master
operator: Exists
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 120
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 120
- effect: NoSchedule
key: node.cloudprovider.kubernetes.io/uninitialized
operator: Exists
- effect: NoSchedule
key: node.kubernetes.io/not-ready
operator: Exists
```
-->
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>apps/v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Deployment&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">labels&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">app.kubernetes.io/name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>cloud-controller-manager&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>cloud-controller-manager&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">namespace&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>kube-system&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">replicas&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#666">2&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">selector&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">matchLabels&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">app.kubernetes.io/name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>cloud-controller-manager&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">strategy&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">type&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Recreate&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">template&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">labels&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">app.kubernetes.io/name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>cloud-controller-manager&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">annotations&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">kubernetes.io/description&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Cloud controller manager for my infrastructure&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">containers&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#080;font-style:italic"># 容器的详细信息将取决于你具体的云控制器管理器&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>cloud-controller-manager&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">command&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- /bin/my-infrastructure-cloud-controller-manager&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- --leader-elect=true&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- -v=1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">image&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>registry/my-infrastructure-cloud-controller-manager@latest&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">resources&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">requests&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">cpu&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>200m&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">memory&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>50Mi&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">hostNetwork&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#a2f;font-weight:bold">true&lt;/span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#080;font-style:italic"># 这些 Pod 是控制平面的一部分&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">nodeSelector&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">node-role.kubernetes.io/control-plane&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">affinity&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">podAntiAffinity&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">requiredDuringSchedulingIgnoredDuringExecution&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">topologyKey&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;kubernetes.io/hostname&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">labelSelector&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">matchLabels&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">app.kubernetes.io/name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>cloud-controller-manager&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">tolerations&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">effect&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>NoSchedule&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">key&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>node-role.kubernetes.io/master&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">operator&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Exists&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">effect&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>NoExecute&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">key&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>node.kubernetes.io/unreachable&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">operator&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Exists&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">tolerationSeconds&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#666">120&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">effect&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>NoExecute&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">key&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>node.kubernetes.io/not-ready&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">operator&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Exists&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">tolerationSeconds&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#666">120&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">effect&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>NoSchedule&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">key&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>node.cloudprovider.kubernetes.io/uninitialized&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">operator&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Exists&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">effect&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>NoSchedule&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">key&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>node.kubernetes.io/not-ready&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">operator&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Exists&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
When deciding how to deploy your cloud controller manager it is worth noting that
cluster-proportional, or resource-based, pod autoscaling is not recommended. Running multiple
replicas of a cloud controller manager is good practice for ensuring high-availability and
redundancy, but does not contribute to better performance. In general, only a single instance
of a cloud controller manager will be reconciling a cluster at any given time.
-->
&lt;p>在决定如何部署云控制器管理器时，需要注意的是，不建议使用与集群规模成比例的或基于资源的 Pod
自动规模扩缩。运行多个云控制器管理器副本是确保高可用性和冗余的良好实践，但这并不会提高性能。
通常情况下，任何时候只有一个云控制器管理器实例会负责协调集群。&lt;/p>
&lt;!--
[migration-blog]: /blog/2024/05/20/completing-cloud-provider-migration/
[kep2392]: https://github.com/kubernetes/enhancements/blob/master/keps/sig-cloud-provider/2392-cloud-controller-manager/README.md
[kep1281]: https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/1281-network-proxy
[kep2133]: https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2133-kubelet-credential-providers
[csi]: https://github.com/container-storage-interface/spec?tab=readme-ov-file#container-storage-interface-csi-specification-
[kep625]: https://github.com/kubernetes/enhancements/blob/master/keps/sig-storage/625-csi-migration/README.md
[ccm]: /docs/concepts/architecture/cloud-controller/
[chicken-and-egg]: /docs/tasks/administer-cluster/running-cloud-controller/#chicken-and-egg
[kubedocs0]: /docs/tasks/administer-cluster/running-cloud-controller/#running-cloud-controller-manager
[kubedocs1]: /docs/reference/labels-annotations-taints/#node-kubernetes-io-not-ready
--></description></item><item><title>聚焦 SIG Architecture: Enhancements</title><link>https://kubernetes.io/zh-cn/blog/2025/01/21/sig-architecture-enhancements/</link><pubDate>Tue, 21 Jan 2025 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2025/01/21/sig-architecture-enhancements/</guid><description>
&lt;!--
layout: blog
title: "Spotlight on SIG Architecture: Enhancements"
slug: sig-architecture-enhancements
canonicalUrl: https://www.kubernetes.dev/blog/2025/01/21/sig-architecture-enhancements
date: 2025-01-21
author: "Frederico Muñoz (SAS Institute)"
-->
&lt;!--
_This is the fourth interview of a SIG Architecture Spotlight series that will cover the different
subprojects, and we will be covering [SIG Architecture:
Enhancements](https://github.com/kubernetes/community/blob/master/sig-architecture/README.md#enhancements)._
In this SIG Architecture spotlight we talked with [Kirsten
Garrison](https://github.com/kikisdeliveryservice), lead of the Enhancements subproject.
-->
&lt;p>&lt;strong>这是 SIG Architecture 聚光灯系列的第四次采访，我们将介绍
&lt;a href="https://github.com/kubernetes/community/blob/master/sig-architecture/README.md#enhancements">SIG Architecture: Enhancements&lt;/a>。&lt;/strong>&lt;/p>
&lt;p>在本次 SIG Architecture 专题采访中，我们访谈了 Enhancements
子项目的负责人 &lt;a href="https://github.com/kikisdeliveryservice">Kirsten Garrison&lt;/a>。&lt;/p>
&lt;!--
## The Enhancements subproject
**Frederico (FSM): Hi Kirsten, very happy to have the opportunity to talk about the Enhancements
subproject. Let's start with some quick information about yourself and your role.**
-->
&lt;h2 id="enhancements-子项目">Enhancements 子项目&lt;/h2>
&lt;p>&lt;strong>Frederico (FSM)：你好 Kirsten，很高兴有机会讨论 Enhancements
子项目。开始请先介绍一下你自己和所承担的职责。&lt;/strong>&lt;/p>
&lt;!--
**Kirsten Garrison (KG)**: I’m a lead of the Enhancements subproject of SIG-Architecture and
currently work at Google. I first got involved by contributing to the service-catalog project with
the help of [Carolyn Van Slyck](https://github.com/carolynvs). With time, [I joined the Release
team](https://github.com/kubernetes/sig-release/blob/master/releases/release-1.17/release_team.md),
eventually becoming the Enhancements Lead and a Release Lead shadow. While on the release team, I
worked on some ideas to make the process better for the SIGs and Enhancements team (the opt-in
process) based on my team’s experiences. Eventually, I started attending Subproject meetings and
contributing to the Subproject’s work.
-->
&lt;p>&lt;strong>Kirsten Garrison (KG)&lt;/strong>：我是 SIG-Architecture 的 Enhancements 子项目的负责人，目前就职于 Google。
我最初在 &lt;a href="https://github.com/carolynvs">Carolyn Van Slyck&lt;/a> 的帮助下，为 service-catalog 项目贡献代码，
后来&lt;a href="https://github.com/kubernetes/sig-release/blob/master/releases/release-1.17/release_team.md">加入了 Release 团队&lt;/a>，
最终成为 Enhancements Lead 和 Release Lead 影子。
在发布团队工作期间，我根据团队的经验为 SIG 和 Enhancements 团队提出了一些改进流程的想法（如参与其中的流程）。
之后，我开始参加子项目会议，并为这个子项目的工作做贡献。&lt;/p>
&lt;!--
**FSM: You mentioned the Enhancements subproject: how would you describe its main goals and areas of
intervention?**
**KG**: The [Enhancements
Subproject](https://github.com/kubernetes/community/blob/master/sig-architecture/README.md#enhancements)
primarily concerns itself with the [Kubernetes Enhancement
Proposal](https://github.com/kubernetes/enhancements/blob/master/keps/sig-architecture/0000-kep-process/README.md)
(_KEP_ for short)—the "design" documents required for all features and significant changes
to the Kubernetes project.
-->
&lt;p>&lt;strong>FSM：你提到了 Enhancements 子项目，你如何描述它的主要目标和干预范围？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>KG&lt;/strong>：&lt;a href="https://github.com/kubernetes/community/blob/master/sig-architecture/README.md#enhancements">Enhancements 子项目&lt;/a>的核心是管理
&lt;a href="https://github.com/kubernetes/enhancements/blob/master/keps/sig-architecture/0000-kep-process/README.md">Kubernetes 增强提案（KEP）&lt;/a>，
这是 Kubernetes 项目所有特性和重大变更的“设计”文档。&lt;/p>
&lt;!--
## The KEP and its impact
**FSM: The improvement of the KEP process was (and is) one in which SIG Architecture was heavily
involved. Could you explain the process to those that aren’t aware of it?**
-->
&lt;h2 id="the-kep-and-its-impact">KEP 及其影响 &lt;/h2>
&lt;p>&lt;strong>FSM：KEP 流程的改进一直是 SIG Architecture 深度参与的工作之一。你能为不了解的人介绍一下这个流程吗？&lt;/strong>&lt;/p>
&lt;!--
**KG**: [Every release](https://kubernetes.io/releases/release/#the-release-cycle), the SIGs let the
Release Team know which features they intend to work on to be put into the release. As mentioned
above, the prerequisite for these changes is a KEP - a standardized design document that all authors
must fill out and approve in the first weeks of the release cycle. Most features [will move
through 3
phases](https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/#feature-stages):
alpha, beta and finally GA so approving a feature represents a significant commitment for the SIG.
-->
&lt;p>&lt;strong>KG&lt;/strong>：在&lt;a href="https://kubernetes.io/zh-cn/releases/release/#the-release-cycle">每次发布版本&lt;/a>时，各个
SIG 需要告知 Release Team 各自计划将哪些特性放到当前的版本发布中。
正如前面提到的，所有变更的前提是有一个 KEP，这是一种标准化的设计文档，
所有 KEP 的作者必须在发布周期的最初几周内填写完并获得批准。
大多数特性&lt;a href="https://kubernetes.io/zh-cn/docs/reference/command-line-tools-reference/feature-gates/#feature-stages">会经历三个阶段&lt;/a>：
Alpha、Beta，最终进入 GA，因此批准一个特性对 SIG 来说是一项重大承诺。&lt;/p>
&lt;!--
The KEP serves as the full source of truth of a feature. The [KEP
template](https://github.com/kubernetes/enhancements/blob/master/keps/NNNN-kep-template/README.md)
has different requirements based on what stage a feature is in, but it generally requires a detailed
discussion of the design and the impact as well as providing artifacts of stability and
performance. The KEP takes quite a bit of iterative work between authors, SIG reviewers, api review
team and the Production Readiness Review team[^1] before it is approved. Each set of reviewers is
looking to make sure that the proposal meets their standards in order to have a stable and
performant Kubernetes release. Only after all approvals are secured, can an author go forth and
merge their feature in the Kubernetes code base.
-->
&lt;p>KEP 作为某个特性真实、完整的信息来源。
&lt;a href="https://github.com/kubernetes/enhancements/blob/master/keps/NNNN-kep-template/README.md">KEP 模板&lt;/a>
对处于不同阶段的特性具有不同的要求，但通常需要详细讨论其设计、影响，并提供稳定性和性能的证明材料。
KEP 通常会在作者、SIG 审查人员、API 审查团队和 Production Readiness Review 团队&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>之间进行多轮迭代后才能获批。
每组审查者都会确保提案符合其标准，以保证 Kubernetes 版本的稳定性和性能。
只有在所有审批完成后，作者才能将其特性合并到 Kubernetes 代码库。&lt;/p>
&lt;!--
**FSM: I see, quite a bit of additional structure was added. Looking back, what were the most
significant improvements of that approach?**
**KG**: In general, I think that the improvements with the most impact had to do with focusing on
the core intent of the KEP. KEPs exist not just to memorialize designs, but provide a structured way
to discuss and come to an agreement about different facets of the change. At the core of the KEP
process is communication and consideration.
-->
&lt;p>&lt;strong>FSM：我懂了，新增了一些结构。回顾来看，你认为这种流程方法最重要的改进是什么？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>KG&lt;/strong>：总体而言，我认为最有影响力的改进在于聚焦 KEP 的核心意图。
KEP 不仅仅是设计的存档文件，更是提供了一种结构化的方式来讨论和达成共识。
KEP 流程的核心是沟通和审慎考虑。&lt;/p>
&lt;!--
To that end, some of the significant changes revolve around a more detailed and accessible KEP
template. A significant amount of work was put in over time to get the
[k/enhancements](https://github.com/kubernetes/enhancements) repo into its current form -- a
directory structure organized by SIG with the contours of the modern KEP template (with
Proposal/Motivation/Design Details subsections). We might take that basic structure for granted
today, but it really represents the work of many people trying to get the foundation of this process
in place over time.
-->
&lt;p>为此，一些重要的改进围绕着更详细且更易于访问的 KEP 模板展开。
我们投入了大量时间，使 &lt;a href="https://github.com/kubernetes/enhancements">k/enhancements&lt;/a>
仓库发展成当前的形式：目录结构按 SIG 小组划分，附带现代 KEP 模板文件，
其中包含 Proposal/Motivation/Design Details（提案/动机/设计细节）等小节。
我们今天可能认为这种基本结构是理所当然的，但它实际上代表付出了许多人力和时间努力工作才奠定了这一流程基础。&lt;/p>
&lt;!--
As Kubernetes matures, we’ve needed to think about more than just the end goal of getting a single
feature merged. We need to think about things like: stability, performance, setting and meeting user
expectations. And as we’ve thought about those things the template has grown more detailed. The
addition of the Production Readiness Review was major as well as the enhanced testing requirements
(varying at different stages of a KEP’s lifecycle).
-->
&lt;p>随着 Kubernetes 的发展和成熟，我们需要考虑的不仅仅是如何合并单个特性，还需要关注稳定性、性能、设置和用户期望等问题。
因此随着我们的思考深入，KEP 模板变得更详细。例如增加了 Production Readiness Review 机制，同时对测试要求进行了强化
（这些要求会随着 KEP 生命周期的不同阶段动态调整）。&lt;/p>
&lt;!--
## Current areas of focus
**FSM: Speaking of maturing, we’ve [recently released Kubernetes
v1.31](https://kubernetes.io/blog/2024/08/13/kubernetes-v1-31-release/), and work on v1.32 [has
started](https://github.com/fsmunoz/sig-release/tree/release-1.32/releases/release-1.32). Are there
any areas that the Enhancements sub-project is currently addressing that might change the way things
are done?**
-->
&lt;h2 id="current-areas-of-focus">当前关注领域 &lt;/h2>
&lt;p>&lt;strong>FSM：说到发展，我们&lt;a href="https://kubernetes.io/zh-cn/blog/2024/08/13/kubernetes-v1-31-release/">最近发布了 Kubernetes v1.31&lt;/a>，
而 v1.32 版本的开发工作&lt;a href="https://github.com/fsmunoz/sig-release/tree/release-1.32/releases/release-1.32">已经开始&lt;/a>。
Enhancements 子项目目前有哪些领域正在推进以改进这个流程？&lt;/strong>&lt;/p>
&lt;!--
**KG**: We’re currently working on two things:
1) _Creating a Process KEP template._ Sometimes people want to harness the KEP process for
significant changes that are more process oriented rather than feature oriented. We want to
support this because memorializing changes is important and giving people a better tool to do so
will only encourage more discussion and transparency.
2) _KEP versioning._ While our template changes aim to be as non-disruptive as possible, we
believe that it will be easier to track and communicate those changes to the community better with
a versioned KEP template and the policies that go alongside such versioning.
-->
&lt;p>&lt;strong>KG&lt;/strong>：我们目前正在进行两项工作：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>创建一个 Process KEP 模板&lt;/strong>。有时，人们希望使用 KEP 流程来记录重要的流程变更，而不是特性变更。
我们希望支持这一点，因为记录变更很重要，为此提供更好的工具将鼓励更多的讨论和更透明。&lt;/li>
&lt;li>&lt;strong>KEP 版本化&lt;/strong>。虽然我们的模板变更旨在尽量减少破坏性影响，但我们认为引入 KEP 版本化及相应的策略，
可以让变更更易于追踪并更好地与社区沟通。&lt;/li>
&lt;/ol>
&lt;!--
Both features will take some time to get right and fully roll out (just like a KEP feature) but we
believe that they will both provide improvements that will benefit the community at large.
**FSM: You mentioned improvements: I remember when project boards for Enhancement tracking were
introduced in recent releases, to great effect and unanimous applause from release team members. Was
this a particular area of focus for the subproject?**
-->
&lt;p>这两项改进都需要时间来完善和推广（就像 KEP 特性本身一样），但我们相信它们最终会给社区带来很大的好处。&lt;/p>
&lt;p>&lt;strong>FSM：你提到了改进：我记得最近的发布引入了用于 Enhancement 追踪的项目看板（Project Board），
发布团队成员对此表示一致好评。这是 Enhancements 子项目的一个重点方向吗？&lt;/strong>&lt;/p>
&lt;!--
**KG**: The Subproject provided support to the Release Team’s Enhancement team in the migration away
from using the spreadsheet to a project board. The collection and tracking of enhancements has
always been a logistical challenge. During my time on the Release Team, I helped with the transition
to an opt-in system of enhancements, whereby the SIG leads "opt-in" KEPs for release tracking. This
helped to enhance communication between authors and SIGs before any significant work was undertaken
on a KEP and removed toil from the Enhancements team. This change used the existing tools to avoid
introducing too many changes at once to the community. Later, the Release Team approached the
Subproject with an idea of leveraging GitHub Project Boards to further improve the collection
process. This was to be a move away from the use of complicated spreadsheets to using repo-native
labels on [k/enhancement](https://github.com/kubernetes/enhancements) issues and project boards.
-->
&lt;p>&lt;strong>KG&lt;/strong>：Enhancements 子项目为 Release Team 的 Enhancement 团队提供支持，从使用电子表格迁移到一个项目看板。
增强提案的收集和跟踪一直是后勤支持的一项挑战。在我担任 Release Team 成员期间，我帮助推动了增强的“选择加入”机制，
即 SIG 负责人需要主动“选择加入” KEP 进行发布追踪。
这有助于在对 KEP 实施重大工作之前，加强作者与 SIG 之间的沟通，并减少 Enhancements 团队的重复工作。
这一变更利用了现有工具，以避免一次性向社区引入过多变化。
后来，Release Team 向子项目提出了利用 GitHub 项目看板进一步改进收集流程的想法。
这一举措旨在从使用复杂的电子表格转为使用 &lt;a href="https://github.com/kubernetes/enhancements">k/enhancement&lt;/a>
Issues 和项目看板上的原生仓库标签。&lt;/p>
&lt;!--
**FSM: That surely adds an impact on simplifying the workflow...**
**KG**: Removing sources of friction and promoting clear communication is very important to the
Enhancements Subproject. At the same time, it’s important to give careful consideration to
decisions that impact the community as a whole. We want to make sure that changes are balanced to
give an upside and while not causing any regressions and pain in the rollout. We supported the
Release Team in ideation as well as through the actual migration to the project boards. It was a
great success and exciting to see the team make high impact changes that helped everyone involved in
the KEP process!
-->
&lt;p>&lt;strong>FSM：这无疑简化了工作流程...&lt;/strong>&lt;/p>
&lt;p>&lt;strong>KG&lt;/strong>：减少摩擦来源、促进清晰沟通对 Enhancements 子项目至关重要。同时，我们也需要谨慎考虑影响整个社区的决策。
我们希望确保变更既带来好处，又不会在推广过程中造成回归或额外负担。
我们支持 Release Team 进行头脑风暴，并协助完成迁移到项目看板的工作。
这次变更取得了巨大成功，很高兴看到团队做出了高影响力的改进，使所有参与 KEP 流程的每个人受益！&lt;/p>
&lt;!--
## Getting involved
**FSM: For those reading that might be curious and interested in helping, how would you describe the
required skills for participating in the sub-project?**
**KG**: Familiarity with KEPs either via experience or taking time to look through the
kubernetes/enhancements repo is helpful. All are welcome to participate if interested - we can take
it from there.
-->
&lt;h2 id="getting-involved">如何参与 &lt;/h2>
&lt;p>&lt;strong>FSM：如果有人想要参与 Enhancements 子项目，你认为需要具备哪些技能？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>KG&lt;/strong>：熟悉 KEP 机制，无论是通过体验，还是花时间阅读
&lt;a href="https://github.com/kubernetes/enhancements">kubernetes/enhancements&lt;/a> 仓库都会有所帮助。
我们欢迎所有感兴趣的人参与，我们可以一步步引导他们。&lt;/p>
&lt;!--
**FSM: Excellent! Many thanks for your time and insight -- any final comments you would like to
share with our readers?**
**KG**: The Enhancements process is one of the most important parts of Kubernetes and requires
enormous amounts of coordination and collaboration of people and teams across the project to make it
successful. I’m thankful and inspired by everyone’s continued hard work and dedication to making the
project great. This is truly a wonderful community.
-->
&lt;p>&lt;strong>FSM：太棒了！非常感谢你的时间和分享——最后你有什么想对读者们说的吗？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>KG&lt;/strong>：Enhancements 流程是 Kubernetes 生态中最重要组成部分之一，需要各个团队的密切协作才能成功。
我很感激并敬佩大家持续不断的努力工作和奉献，让这个项目越来越好。这真是一个很棒的社区。&lt;/p>
&lt;!--
[^1]: For more information, check the [Production Readiness Review spotlight
interview](https://kubernetes.io/blog/2023/11/02/sig-architecture-production-readiness-spotlight-2023/)
in this series.
-->
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>更多信息参考 &lt;a href="https://kubernetes.io/blog/2023/11/02/sig-architecture-production-readiness-spotlight-2023/">Production Readiness Review 专题采访&lt;/a>。&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>使用 API 流式传输来增强 Kubernetes API 服务器效率</title><link>https://kubernetes.io/zh-cn/blog/2024/12/17/kube-apiserver-api-streaming/</link><pubDate>Tue, 17 Dec 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/12/17/kube-apiserver-api-streaming/</guid><description>
&lt;!--
layout: blog
title: 'Enhancing Kubernetes API Server Efficiency with API Streaming'
date: 2024-12-17
slug: kube-apiserver-api-streaming
author: >
Stefan Schimanski (Upbound),
Wojciech Tyczynski (Google),
Lukasz Szaszkiewicz (Red Hat)
-->
&lt;!--
Managing Kubernetes clusters efficiently is critical, especially as their size is growing.
A significant challenge with large clusters is the memory overhead caused by **list** requests.
-->
&lt;p>高效管理 Kubernetes 集群至关重要，特别是在集群规模不断增长的情况下更是如此。
大型集群面临的一个重大挑战是 &lt;strong>list&lt;/strong> 请求所造成的内存开销。&lt;/p>
&lt;!--
In the existing implementation, the kube-apiserver processes **list** requests by assembling the entire response in-memory before transmitting any data to the client.
But what if the response body is substantial, say hundreds of megabytes? Additionally, imagine a scenario where multiple **list** requests flood in simultaneously, perhaps after a brief network outage.
While [API Priority and Fairness](/docs/concepts/cluster-administration/flow-control) has proven to reasonably protect kube-apiserver from CPU overload, its impact is visibly smaller for memory protection.
This can be explained by the differing nature of resource consumption by a single API request - the CPU usage at any given time is capped by a constant, whereas memory, being uncompressible, can grow proportionally with the number of processed objects and is unbounded.
This situation poses a genuine risk, potentially overwhelming and crashing any kube-apiserver within seconds due to out-of-memory (OOM) conditions. To better visualize the issue, let's consider the below graph.
-->
&lt;p>在现有的实现中，kube-apiserver 在处理 &lt;strong>list&lt;/strong> 请求时，先在内存中组装整个响应，再将所有数据传输给客户端。
但如果响应体非常庞大，比如数百兆字节呢？另外再想象这样一种场景，有多个 &lt;strong>list&lt;/strong> 请求同时涌入，可能是在短暂的网络中断后涌入。
虽然 &lt;a href="https://kubernetes.io/zh-cn/docs/concepts/cluster-administration/flow-control">API 优先级和公平性&lt;/a>已经证明可以合理地保护
kube-apiserver 免受 CPU 过载，但其对内存保护的影响却明显较弱。这可以解释为各个 API 请求的资源消耗性质有所不同。
在任何给定时间，CPU 使用量都会受到某个常量的限制，而内存由于不可压缩，会随着处理对象数量的增加而成比例增长，且没有上限。
这种情况会带来真正的风险，kube-apiserver 可能会在几秒钟内因内存不足（OOM）状况而淹没和崩溃。
为了更直观地查验这个问题，我们看看下面的图表。&lt;/p>
&lt;!--
&lt;figure>
&lt;img src="https://kubernetes.io/zh-cn/blog/2024/12/17/kube-apiserver-api-streaming/kube-apiserver-memory_usage.png"
alt="Monitoring graph showing kube-apiserver memory usage"/>
&lt;/figure>
-->
&lt;figure>
&lt;img src="https://kubernetes.io/zh-cn/blog/2024/12/17/kube-apiserver-api-streaming/kube-apiserver-memory_usage.png"
alt="显示 kube-apiserver 内存使用量的监控图表"/>
&lt;/figure>
&lt;!--
The graph shows the memory usage of a kube-apiserver during a synthetic test.
(see the [synthetic test](#the-synthetic-test) section for more details).
The results clearly show that increasing the number of informers significantly boosts the server's memory consumption.
Notably, at approximately 16:40, the server crashed when serving only 16 informers.
-->
&lt;p>以上图表显示了 kube-apiserver 在一次模拟测试中的内存使用情况。
（有关更多细节，参见&lt;a href="#the-synthetic-test">模拟测试&lt;/a>一节）。
结果清楚地表明，增加 informer 的数量显著提高了服务器的内存消耗量。
值得注意的是，在大约 16:40 时，服务器在仅提供了 16 个 informer 时就崩溃了。&lt;/p>
&lt;!--
## Why does kube-apiserver allocate so much memory for list requests?
Our investigation revealed that this substantial memory allocation occurs because the server before sending the first byte to the client must:
* fetch data from the database,
* deserialize the data from its stored format,
* and finally construct the final response by converting and serializing the data into a client requested format
-->
&lt;h2 id="why-does-kube-apiserver-allocates-so-much-memory-for-list-requests">为什么 kube-apiserver 为 list 请求分配这么多内存？ &lt;/h2>
&lt;p>我们的调查显示，这种大量内存分配的发生是因为在向客户端发送第一个字节之前，服务器必须：&lt;/p>
&lt;ul>
&lt;li>从数据库中获取数据&lt;/li>
&lt;li>对数据执行从其存储格式的反序列化&lt;/li>
&lt;li>最后通过将数据转换和序列化为客户端所请求的格式来构造最终的响应。&lt;/li>
&lt;/ul>
&lt;!--
This sequence results in significant temporary memory consumption.
The actual usage depends on many factors like the page size, applied filters (e.g. label selectors), query parameters, and sizes of individual objects.
Unfortunately, neither [API Priority and Fairness](/docs/concepts/cluster-administration/flow-control) nor Golang's garbage collection or Golang memory limits can prevent the system from exhausting memory under these conditions.
The memory is allocated suddenly and rapidly, and just a few requests can quickly deplete the available memory, leading to resource exhaustion.
-->
&lt;p>这个序列导致了显著的临时内存消耗。实际使用量取决于许多因素，
比如分页大小、所施加的过滤器（例如标签选择算符）、查询参数和单个对象的体量。&lt;/p>
&lt;p>不巧的是，无论是 &lt;a href="https://kubernetes.io/zh-cn/docs/concepts/cluster-administration/flow-control">API 优先级和公平性&lt;/a>，
还是 Golang 的垃圾收集或 Golang 的内存限制，都无法在这些状况下防止系统耗尽内存。
内存是被突然且快速分配的，仅仅几个请求就可能迅速耗尽可用内存，导致资源耗尽。&lt;/p>
&lt;!--
Depending on how the API server is run on the node, it might either be killed through OOM by the kernel when exceeding the configured memory limits during these uncontrolled spikes, or if limits are not configured it might have even worse impact on the control plane node.
And worst, after the first API server failure, the same requests will likely hit another control plane node in an HA setup with probably the same impact.
Potentially a situation that is hard to diagnose and hard to recover from.
-->
&lt;p>取决于 API 服务器在节点上的运行方式，API 服务器可能在这些不受控制的峰值期间因为超过所配置的内存限制而被内核通过 OOM 杀死，
或者如果没有为服务器配置限制值，则其可能对控制平面节点产生更糟糕的影响。最糟糕的是，
在第一个 API 服务器出现故障后，相同的请求将很可能会影响高可用（HA）部署中的另一个控制平面节点，
并可能产生相同的影响。这可能是一个难以诊断和难以恢复的情况。&lt;/p>
&lt;!--
## Streaming list requests
Today, we're excited to announce a major improvement.
With the graduation of the _watch list_ feature to beta in Kubernetes 1.32, client-go users can opt-in (after explicitly enabling `WatchListClient` feature gate)
to streaming lists by switching from **list** to (a special kind of) **watch** requests.
-->
&lt;h2 id="streaming-list-requests">流式处理 list 请求 &lt;/h2>
&lt;p>今天，我们很高兴地宣布一项重大改进。随着 Kubernetes 1.32 中 &lt;em>watch list&lt;/em> 特性进阶至 Beta，
client-go 用户可以选择（在显式启用 &lt;code>WatchListClient&lt;/code> 特性门控后）通过将 &lt;strong>list&lt;/strong> 请求切换为（某种特殊类别的）
&lt;strong>watch&lt;/strong> 请求来进行流式处理。&lt;/p>
&lt;!--
**Watch** requests are served from the _watch cache_, an in-memory cache designed to improve scalability of read operations.
By streaming each item individually instead of returning the entire collection, the new method maintains constant memory overhead.
The API server is bound by the maximum allowed size of an object in etcd plus a few additional allocations.
This approach drastically reduces the temporary memory usage compared to traditional **list** requests, ensuring a more efficient and stable system,
especially in clusters with a large number of objects of a given type or large average object sizes where despite paging memory consumption used to be high.
-->
&lt;p>&lt;strong>watch&lt;/strong> 请求使用 &lt;strong>监视缓存（watch cache）&lt;/strong> 提供服务，监视缓存是设计来提高读操作扩缩容能力的一个内存缓存。
通过逐个流式传输每一项，而不是返回整个集合，这种新方法保持了恒定的内存开销。
API 服务器受限于 etcd 中对象的最大允许体量加上少量额外分配的内存。
与传统的 &lt;strong>list&lt;/strong> 请求相比，尤其是在分页情况下内存消耗仍较高的、具有大量特定类别的对象或对象体量平均较大的集群中，
这种方法大幅降低了临时内存使用量，确保了系统更高效和更稳定。&lt;/p>
&lt;!--
Building on the insight gained from the synthetic test (see the [synthetic test](#the-synthetic-test), we developed an automated performance test to systematically evaluate the impact of the _watch list_ feature.
This test replicates the same scenario, generating a large number of Secrets with a large payload, and scaling the number of informers to simulate heavy **list** request patterns.
The automated test is executed periodically to monitor memory usage of the server with the feature enabled and disabled.
-->
&lt;p>基于模拟测试所了解的情况（参见&lt;a href="#the-synthetic-test">模拟测试&lt;/a>），我们开发了一种自动化的性能测试，
以系统地评估 &lt;em>watch list&lt;/em> 特性的影响。此测试能够重现相同的场景，生成大量载荷较大的 Secret，
并扩缩容 informer 的数量以模拟高频率的 &lt;strong>list&lt;/strong> 请求模式。
这种自动化测试被定期执行，以监控启用和禁用此特性后服务器的内存使用情况。&lt;/p>
&lt;!--
The results showed significant improvements with the _watch list_ feature enabled.
With the feature turned on, the kube-apiserver’s memory consumption stabilized at approximately **2 GB**.
By contrast, with the feature disabled, memory usage increased to approximately **20GB**, a **10x** increase!
These results confirm the effectiveness of the new streaming API, which reduces the temporary memory footprint.
-->
&lt;p>结果表明，启用 &lt;em>watch list&lt;/em> 特性后有显著改善。
启用此特性时，kube-apiserver 的内存消耗稳定在大约 &lt;strong>2 GB&lt;/strong>。
相比之下，禁用此特性时，内存使用量增加到约 &lt;strong>20 GB&lt;/strong>，增长了 &lt;strong>10 倍&lt;/strong>！
这些结果证实了新的流式 API 的有效性，减少了临时内存占用。&lt;/p>
&lt;!--
## Enabling API Streaming for your component
Upgrade to Kubernetes 1.32. Make sure your cluster uses etcd in version 3.4.31+ or 3.5.13+.
Change your client software to use watch lists. If your client code is written in Golang, you'll want to enable `WatchListClient` for client-go.
For details on enabling that feature, read [Introducing Feature Gates to Client-Go: Enhancing Flexibility and Control](/blog/2024/08/12/feature-gates-in-client-go).
-->
&lt;h2 id="enabling-api-streaming-for-your-component">为你的组件启用 API 流式传输 &lt;/h2>
&lt;p>升级到 Kubernetes 1.32。确保你的集群使用 etcd v3.4.31+ 或 v3.5.13+。将你的客户端软件更改为使用 watch list。
如果你的客户端代码是用 Golang 编写的，你将需要为 client-go 启用 &lt;code>WatchListClient&lt;/code>。有关启用该特性的细节，
参阅&lt;a href="https://kubernetes.io/zh-cn/blog/2024/08/12/feature-gates-in-client-go">为 client-go 引入特性门控：增强灵活性和控制&lt;/a>。&lt;/p>
&lt;!--
## What's next?
In Kubernetes 1.32, the feature is enabled in kube-controller-manager by default despite its beta state.
This will eventually be expanded to other core components like kube-scheduler or kubelet; once the feature becomes generally available, if not earlier.
Other 3rd-party components are encouraged to opt-in to the feature during the beta phase, especially when they are at risk of accessing a large number of resources or kinds with potentially large object sizes.
-->
&lt;h2 id="whats-next">接下来 &lt;/h2>
&lt;p>在 Kubernetes 1.32 中，尽管此特性处于 Beta 状态，但在 kube-controller-manager 中默认被启用。
一旦此特性进阶至正式发布（GA），或许更早，此特性最终将被扩展到 kube-scheduler 或 kubelet 这类其他核心组件。
我们鼓励其他第三方组件在此特性处于 Beta 阶段时选择使用此特性，特别是这些组件在有可能访问大量资源或对象体量较大的情况下。&lt;/p>
&lt;!--
For the time being, [API Priority and Fairness](/docs/concepts/cluster-administration/flow-control) assigns a reasonable small cost to **list** requests.
This is necessary to allow enough parallelism for the average case where **list** requests are cheap enough.
But it does not match the spiky exceptional situation of many and large objects.
Once the majority of the Kubernetes ecosystem has switched to _watch list_, the **list** cost estimation can be changed to larger values without risking degraded performance in the average case,
and with that increasing the protection against this kind of requests that can still hit the API server in the future.
-->
&lt;p>目前，&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/cluster-administration/flow-control">API 优先级和公平性&lt;/a>为
&lt;strong>list&lt;/strong> 请求带来了少量但合理的开销。这是必要的，以允许在通常 &lt;strong>list&lt;/strong> 请求开销足够低的情况下实现足够的并行性。
但这并不适用于对象数量众多、体量巨大的峰值异常情形。一旦大多数 Kubernetes 生态体系切换到 &lt;em>watch list&lt;/em> ，
就可以将 &lt;strong>list&lt;/strong> 开销估算调整为更大的值，而不必担心在平均情况下出现性能下降，
从而提高对未来可能仍会影响 API 服务器的此类请求的保护。&lt;/p>
&lt;!--
## The synthetic test
In order to reproduce the issue, we conducted a manual test to understand the impact of **list** requests on kube-apiserver memory usage.
In the test, we created 400 Secrets, each containing 1 MB of data, and used informers to retrieve all Secrets.
-->
&lt;h2 id="the-synthetic-test">模拟测试 &lt;/h2>
&lt;p>为了重现此问题，我们实施了手动测试，以了解 &lt;strong>list&lt;/strong> 请求对 kube-apiserver 内存使用量的影响。
在测试中，我们创建了 400 个 Secret，每个 Secret 包含 1 MB 的数据，并使用 informer 检索所有 Secret。&lt;/p>
&lt;!--
The results were alarming, only 16 informers were needed to cause the test server to run out of memory and crash, demonstrating how quickly memory consumption can grow under such conditions.
Special shout out to [@deads2k](https://github.com/deads2k) for his help in shaping this feature.
-->
&lt;p>结果令人担忧，仅需 16 个 informer 就足以导致测试服务器内存耗尽并崩溃，展示了在这些状况下内存消耗快速增长的方式。&lt;/p>
&lt;p>特别感谢 &lt;a href="https://github.com/deads2k">@deads2k&lt;/a> 在构造此特性所提供的帮助。&lt;/p></description></item><item><title>Kubernetes v1.32 增加了新的 CPU Manager 静态策略选项用于严格 CPU 预留</title><link>https://kubernetes.io/zh-cn/blog/2024/12/16/cpumanager-strict-cpu-reservation/</link><pubDate>Mon, 16 Dec 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/12/16/cpumanager-strict-cpu-reservation/</guid><description>
&lt;!--
layout: blog
title: 'Kubernetes v1.32 Adds A New CPU Manager Static Policy Option For Strict CPU Reservation'
date: 2024-12-16
slug: cpumanager-strict-cpu-reservation
author: >
[Jing Zhang](https://github.com/jingczhang) (Nokia)
-->
&lt;!--
In Kubernetes v1.32, after years of community discussion, we are excited to introduce a
`strict-cpu-reservation` option for the [CPU Manager static policy](/docs/tasks/administer-cluster/cpu-management-policies/#static-policy-options).
This feature is currently in alpha, with the associated policy hidden by default. You can only use the
policy if you explicitly enable the alpha behavior in your cluster.
-->
&lt;p>在 Kubernetes v1.32 中，经过社区多年的讨论，我们很高兴地引入了
&lt;a href="https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/cpu-management-policies/#static-policy-options">CPU Manager 静态策略&lt;/a>的
&lt;code>strict-cpu-reservation&lt;/code> 选项。此特性当前处于 Alpha 阶段，默认情况下关联的策略是隐藏的。
只有在你的集群中明确启用了此 Alpha 行为后，才能使用此策略。&lt;/p>
&lt;!--
## Understanding the feature
The CPU Manager static policy is used to reduce latency or improve performance. The `reservedSystemCPUs` defines an explicit CPU set for OS system daemons and kubernetes system daemons. This option is designed for Telco/NFV type use cases where uncontrolled interrupts/timers may impact the workload performance. you can use this option to define the explicit cpuset for the system/kubernetes daemons as well as the interrupts/timers, so the rest CPUs on the system can be used exclusively for workloads, with less impact from uncontrolled interrupts/timers. More details of this parameter can be found on the [Explicitly Reserved CPU List](/docs/tasks/administer-cluster/reserve-compute-resources/#explicitly-reserved-cpu-list) page.
If you want to protect your system daemons and interrupt processing, the obvious way is to use the `reservedSystemCPUs` option.
-->
&lt;h2 id="理解此特性">理解此特性&lt;/h2>
&lt;p>CPU Manager 静态策略用于减少延迟或提高性能。&lt;code>reservedSystemCPUs&lt;/code>
定义了一个明确的 CPU 集合，供操作系统系统守护进程和 Kubernetes 系统守护进程使用。
此选项专为 Telco/NFV 类型的使用场景设计，在这些场景中，不受控制的中断/计时器可能会影响工作负载的性能。
你可以使用此选项为系统/Kubernetes 守护进程以及中断/计时器定义明确的 CPU 集合，
从而使系统上的其余 CPU 可以专用于工作负载，并减少不受控制的中断/计时器带来的影响。
有关此参数的更多详细信息，请参阅
&lt;a href="https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/reserve-compute-resources/#explicitly-reserved-cpu-list">显式预留的 CPU 列表&lt;/a>
页面。&lt;/p>
&lt;p>如果你希望保护系统守护进程和中断处理，显而易见的方法是使用 &lt;code>reservedSystemCPUs&lt;/code> 选项。&lt;/p>
&lt;!--
However, until the Kubernetes v1.32 release, this isolation was only implemented for guaranteed
pods that made requests for a whole number of CPUs. At pod admission time, the kubelet only
compares the CPU _requests_ against the allocatable CPUs. In Kubernetes, limits can be higher than
the requests; the previous implementation allowed burstable and best-effort pods to use up
the capacity of `reservedSystemCPUs`, which could then starve host OS services of CPU - and we
know that people saw this in real life deployments.
The existing behavior also made benchmarking (for both infrastructure and workloads) results inaccurate.
When this new `strict-cpu-reservation` policy option is enabled, the CPU Manager static policy will not allow any workload to use the reserved system CPU cores.
-->
&lt;p>然而，在 Kubernetes v1.32 发布之前，这种隔离仅针对请求整数个 CPU
的 Guaranteed 类型 Pod 实现。在 Pod 准入时，kubelet 仅将 CPU
&lt;strong>请求量&lt;/strong>与可分配的 CPU 进行比较。在 Kubernetes 中，限制值可以高于请求值；
之前的实现允许 Burstable 和 BestEffort 类型的 Pod 使用 &lt;code>reservedSystemCPUs&lt;/code> 的容量，
这可能导致主机操作系统服务缺乏足够的 CPU 资源 —— 并且我们已经知道在实际部署中确实发生过这种情况。
现有的行为还导致基础设施和工作负载的基准测试结果不准确。&lt;/p>
&lt;p>当启用这个新的 &lt;code>strict-cpu-reservation&lt;/code> 策略选项后，CPU Manager
静态策略将不允许任何工作负载使用预留的系统 CPU 核心。&lt;/p>
&lt;!--
## Enabling the feature
To enable this feature, you need to turn on both the `CPUManagerPolicyAlphaOptions` feature gate and the `strict-cpu-reservation` policy option. And you need to remove the `/var/lib/kubelet/cpu_manager_state` file if it exists and restart kubelet.
With the following kubelet configuration:
-->
&lt;h2 id="启用此特性">启用此特性&lt;/h2>
&lt;p>要启用此特性，你需要同时开启 &lt;code>CPUManagerPolicyAlphaOptions&lt;/code> 特性门控和
&lt;code>strict-cpu-reservation&lt;/code> 策略选项。并且如果存在 &lt;code>/var/lib/kubelet/cpu_manager_state&lt;/code>
文件，则需要删除该文件并重启 kubelet。&lt;/p>
&lt;p>使用以下 kubelet 配置：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>KubeletConfiguration&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>kubelet.config.k8s.io/v1beta1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">featureGates&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>...&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">CPUManagerPolicyOptions&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#a2f;font-weight:bold">true&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">CPUManagerPolicyAlphaOptions&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#a2f;font-weight:bold">true&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">cpuManagerPolicy&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>static&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">cpuManagerPolicyOptions&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">strict-cpu-reservation&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;true&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">reservedSystemCPUs&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;0,32,1,33,16,48&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#00f;font-weight:bold">...&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
When `strict-cpu-reservation` is not set or set to false:
-->
&lt;p>当未设置 &lt;code>strict-cpu-reservation&lt;/code> 或将其设置为 false 时：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000080;font-weight:bold">#&lt;/span> cat /var/lib/kubelet/cpu_manager_state
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888">{&amp;#34;policyName&amp;#34;:&amp;#34;static&amp;#34;,&amp;#34;defaultCpuSet&amp;#34;:&amp;#34;0-63&amp;#34;,&amp;#34;checksum&amp;#34;:1058907510}
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
When `strict-cpu-reservation` is set to true:
-->
&lt;p>当 &lt;code>strict-cpu-reservation&lt;/code> 设置为 true 时：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000080;font-weight:bold">#&lt;/span> cat /var/lib/kubelet/cpu_manager_state
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888">{&amp;#34;policyName&amp;#34;:&amp;#34;static&amp;#34;,&amp;#34;defaultCpuSet&amp;#34;:&amp;#34;2-15,17-31,34-47,49-63&amp;#34;,&amp;#34;checksum&amp;#34;:4141502832}
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
## Monitoring the feature
You can monitor the feature impact by checking the following CPU Manager counters:
- `cpu_manager_shared_pool_size_millicores`: report shared pool size, in millicores (e.g. 13500m)
- `cpu_manager_exclusive_cpu_allocation_count`: report exclusively allocated cores, counting full cores (e.g. 16)
-->
&lt;h2 id="监控此特性">监控此特性&lt;/h2>
&lt;p>你可以通过检查以下 CPU Manager 计数器来监控该特性的影响：&lt;/p>
&lt;ul>
&lt;li>&lt;code>cpu_manager_shared_pool_size_millicores&lt;/code>：报告共享池大小，以毫核为单位（例如 13500m）&lt;/li>
&lt;li>&lt;code>cpu_manager_exclusive_cpu_allocation_count&lt;/code>：报告独占分配的核心数，按完整核心计数（例如 16）&lt;/li>
&lt;/ul>
&lt;!--
Your best-effort workloads may starve if the `cpu_manager_shared_pool_size_millicores` count is zero for prolonged time.
We believe any pod that is required for operational purpose like a log forwarder should not run as best-effort, but you can review and adjust the amount of CPU cores reserved as needed.
-->
&lt;p>如果 &lt;code>cpu_manager_shared_pool_size_millicores&lt;/code> 计数在长时间内为零，
你的 BestEffort 类型工作负载可能会因资源匮乏而受到影响。&lt;/p>
&lt;p>我们建议，任何用于操作目的的 Pod（如日志转发器）都不应以 BestEffort 方式运行，
但你可以根据需要审查并调整预留的 CPU 核心数量。&lt;/p>
&lt;!--
## Conclusion
Strict CPU reservation is critical for Telco/NFV use cases. It is also a prerequisite for enabling the all-in-one type of deployments where workloads are placed on nodes serving combined control+worker+storage roles.
We want you to start using the feature and looking forward to your feedback.
-->
&lt;h2 id="总结">总结&lt;/h2>
&lt;p>严格的 CPU 预留对于 Telco/NFV 使用场景至关重要。
它也是启用一体化部署类型（其中工作负载被放置在同时担任控制面节点、工作节点和存储角色的节点上）的前提条件。&lt;/p>
&lt;p>我们希望你开始使用该特性，并期待你的反馈。&lt;/p>
&lt;!--
## Further reading
Please check out the [Control CPU Management Policies on the Node](/docs/tasks/administer-cluster/cpu-management-policies/)
task page to learn more about the CPU Manager, and how it fits in relation to the other node-level resource managers.
-->
&lt;h2 id="进一步阅读">进一步阅读&lt;/h2>
&lt;p>请查看&lt;a href="https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/cpu-management-policies/">节点上的控制 CPU 管理策略&lt;/a>任务页面，
以了解更多关于 CPU Manager 的信息，以及它如何与其他节点级资源管理器相关联。&lt;/p>
&lt;!--
## Getting involved
This feature is driven by the [SIG Node](https://github.com/Kubernetes/community/blob/master/sig-node/README.md). If you are interested in helping develop this feature, sharing feedback, or participating in any other ongoing SIG Node projects, please attend the SIG Node meeting for more details.
-->
&lt;h2 id="参与其中">参与其中&lt;/h2>
&lt;p>此特性由 &lt;a href="https://github.com/kubernetes/community/blob/master/sig-node/README.md">SIG Node&lt;/a>
推动。如果你有兴趣帮助开发此特性、分享反馈或参与任何其他正在进行的 SIG Node 项目，
请参加 SIG Node 会议以获取更多详情。&lt;/p></description></item><item><title>Kubernetes v1.32：内存管理器进阶至 GA</title><link>https://kubernetes.io/zh-cn/blog/2024/12/13/memory-manager-goes-ga/</link><pubDate>Fri, 13 Dec 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/12/13/memory-manager-goes-ga/</guid><description>
&lt;!--
layout: blog
title: "Kubernetes v1.32: Memory Manager Goes GA"
date: 2024-12-13
slug: memory-manager-goes-ga
author: >
[Talor Itzhak](https://github.com/Tal-or) (Red Hat)
-->
&lt;!--
With Kubernetes 1.32, the memory manager has officially graduated to General Availability (GA),
marking a significant milestone in the journey toward efficient and predictable memory allocation for containerized applications.
Since Kubernetes v1.22, where it graduated to beta, the memory manager has proved itself reliable, stable and a good complementary feature for the
[CPU Manager](/docs/tasks/administer-cluster/cpu-management-policies/).
-->
&lt;p>随着 Kubernetes 1.32 的发布，内存管理器已进阶至正式发布（GA），
这标志着在为容器化应用实现高效和可预测的内存分配的旅程中迈出了重要的一步。
内存管理器自 Kubernetes v1.22 进阶至 Beta 后，其可靠性、稳定性已得到证实，
是 &lt;a href="https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/cpu-management-policies/">CPU 管理器&lt;/a>的一个良好补充特性。&lt;/p>
&lt;!--
As part of kubelet's workload admission process,
the memory manager provides topology hints
to optimize memory allocation and alignment.
This enables users to allocate exclusive
memory for Pods in the [Guaranteed](/docs/concepts/workloads/pods/pod-qos/#guaranteed) QoS class.
More details about the process can be found in the memory manager goes to beta [blog](/blog/2021/08/11/kubernetes-1-22-feature-memory-manager-moves-to-beta/).
-->
&lt;p>作为 kubelet 的工作负载准入过程的一部分，内存管理器提供拓扑提示以优化内存分配和对齐。这使得用户能够为
&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/pod-qos/#guaranteed">Guaranteed&lt;/a> QoS 类的 Pod 分配独占的内存。
有关此过程的细节，参见博客：&lt;a href="https://kubernetes.io/blog/2021/08/11/kubernetes-1-22-feature-memory-manager-moves-to-beta/">内存管理器进阶至 Beta&lt;/a>。&lt;/p>
&lt;!--
Most of the changes introduced since the Beta are bug fixes, internal refactoring and
observability improvements, such as metrics and better logging.
-->
&lt;p>自 Beta 以来引入的大部分变更是修复 Bug、内部重构以及改进可观测性（例如优化指标和日志）。&lt;/p>
&lt;!--
## Observability improvements
As part of the effort
to increase the observability of memory manager, new metrics have been added
to provide some statistics on memory allocation patterns.
-->
&lt;h2 id="observability-improvements">改进可观测性 &lt;/h2>
&lt;p>作为提高内存管理器可观测性工作的一部分，新增了一些指标以提供关于内存分配模式的某些统计信息。&lt;/p>
&lt;!--
* **memory_manager_pinning_requests_total** -
tracks the number of times the pod spec required the memory manager to pin memory pages.
* **memory_manager_pinning_errors_total** -
tracks the number of times the pod spec required the memory manager
to pin memory pages, but the allocation failed.
-->
&lt;ul>
&lt;li>
&lt;p>&lt;strong>memory_manager_pinning_requests_total&lt;/strong> -
跟踪 Pod 规约要求内存管理器锁定内存页的次数。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>memory_manager_pinning_errors_total&lt;/strong> -
跟踪 Pod 规约要求内存管理器锁定内存页但分配失败的次数。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!--
## Improving memory manager reliability and consistency
The kubelet does not guarantee pod ordering
when admitting pods after a restart or reboot.
In certain edge cases, this behavior could cause
the memory manager to reject some pods,
and in more extreme cases, it may cause kubelet to fail upon restart.
-->
&lt;h2 id="improving-memory-manager-reliability-and-consistency">提高内存管理器可靠性和一致性 &lt;/h2>
&lt;p>kubelet 不保证在 Pod 重启或重新引导后准入 Pod 的顺序。&lt;/p>
&lt;p>在某些边缘情况下，这种行为可能导致内存管理器拒绝某些 Pod，
在更极端的情况下，可能导致 kubelet 在重启时失败。&lt;/p>
&lt;!--
Previously, the beta implementation lacked certain checks and logic to prevent
these issues.
To stabilize the memory manager for general availability (GA) readiness,
small but critical refinements have been
made to the algorithm, improving its robustness and handling of edge cases.
-->
&lt;p>以前，Beta 实现缺乏某些检查和逻辑来防止这些问题的发生。&lt;/p>
&lt;p>为了使内存管理器更为稳定，以便为进阶至正式发布（GA）做好准备，
我们对算法进行了小而美的改进，提高了其稳健性和对边缘场景的处理能力。&lt;/p>
&lt;!--
## Future development
There is more to come for the future of Topology Manager in general,
and memory manager in particular.
Notably, ongoing efforts are underway
to extend [memory manager support to Windows](https://github.com/kubernetes/kubernetes/pull/128560),
enabling CPU and memory affinity on a Windows operating system.
-->
&lt;h2 id="future-development">未来发展 &lt;/h2>
&lt;p>总体而言，未来对拓扑管理器（Topology Manager），特别是内存管理器，会有更多特性推出。
值得一提的是，目前的工作重心是将&lt;a href="https://github.com/kubernetes/kubernetes/pull/128560">内存管理器支持扩展到 Windows&lt;/a>，
使得在 Windows 操作系统上实现 CPU 和内存亲和性成为可能。&lt;/p>
&lt;!--
## Getting involved
This feature is driven by the [SIG Node](https://github.com/Kubernetes/community/blob/master/sig-node/README.md) community.
Please join us to connect with the community
and share your ideas and feedback around the above feature and
beyond.
We look forward to hearing from you!
-->
&lt;h2 id="getting-involved">参与其中 &lt;/h2>
&lt;p>此特性由 &lt;a href="https://github.com/Kubernetes/community/blob/master/sig-node/README.md">SIG Node&lt;/a>
社区推动。请加入我们，与社区建立联系，分享你对上述特性及其他方面的想法和反馈。
我们期待听到你的声音！&lt;/p></description></item><item><title>Kubernetes v1.32：QueueingHint 为优化 Pod 调度带来了新的可能</title><link>https://kubernetes.io/zh-cn/blog/2024/12/12/scheduler-queueinghint/</link><pubDate>Thu, 12 Dec 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/12/12/scheduler-queueinghint/</guid><description>
&lt;!--
layout: blog
title: "Kubernetes v1.32: QueueingHint Brings a New Possibility to Optimize Pod Scheduling"
date: 2024-12-12
slug: scheduler-queueinghint
Author: >
[Kensei Nakada](https://github.com/sanposhiho) (Tetrate.io)
-->
&lt;!--
The Kubernetes [scheduler](/docs/concepts/scheduling-eviction/kube-scheduler/) is the core
component that selects the nodes on which new Pods run. The scheduler processes
these new Pods **one by one**. Therefore, the larger your clusters, the more important
the throughput of the scheduler becomes.
Over the years, Kubernetes SIG Scheduling has improved the throughput
of the scheduler in multiple enhancements. This blog post describes a major improvement to the
scheduler in Kubernetes v1.32: a
[scheduling context element](/docs/concepts/scheduling-eviction/scheduling-framework/#extension-points)
named _QueueingHint_. This page provides background knowledge of the scheduler and explains how
QueueingHint improves scheduling throughput.
-->
&lt;p>Kubernetes &lt;a href="https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/kube-scheduler/">调度器&lt;/a>是为新
Pod 选择运行节点的核心组件，调度器会&lt;strong>逐一&lt;/strong>处理这些新 Pod。
因此，集群规模越大，调度器的吞吐量就越重要。&lt;/p>
&lt;p>多年来，Kubernetes SIG Scheduling 通过多次增强改进了调度器的吞吐量。
本博客文章描述了 Kubernetes v1.32 中对调度器的一项重大改进：
一个名为 &lt;strong>QueueingHint&lt;/strong> 的&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/scheduling-framework/#extension-points">调度上下文元素&lt;/a>。
本页面提供了关于调度器的背景知识，并解释了 QueueingHint 如何提升调度吞吐量。&lt;/p>
&lt;!--
## Scheduling queue
The scheduler stores all unscheduled Pods in an internal component called the _scheduling queue_.
The scheduling queue consists of the following data structures:
- **ActiveQ**: holds newly created Pods or Pods that are ready to be retried for scheduling.
- **BackoffQ**: holds Pods that are ready to be retried but are waiting for a backoff period to end. The
backoff period depends on the number of unsuccessful scheduling attempts performed by the scheduler on that Pod.
- **Unschedulable Pod Pool**: holds Pods that the scheduler won't attempt to schedule for one of the
following reasons:
- The scheduler previously attempted and was unable to schedule the Pods. Since that attempt, the cluster
hasn't changed in a way that could make those Pods schedulable.
- The Pods are blocked from entering the scheduling cycles by PreEnqueue Plugins,
for example, they have a [scheduling gate](/docs/concepts/scheduling-eviction/pod-scheduling-readiness/#configuring-pod-schedulinggates),
and get blocked by the scheduling gate plugin.
-->
&lt;h2 id="调度队列">调度队列&lt;/h2>
&lt;p>调度器将所有未调度的 Pod 存储在一个名为&lt;strong>调度队列&lt;/strong>的内部组件中。&lt;/p>
&lt;p>调度队列由以下数据结构组成：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>ActiveQ&lt;/strong>：保存新创建的 Pod 或准备重试调度的 Pod。&lt;/li>
&lt;li>&lt;strong>BackoffQ&lt;/strong>：保存准备重试但正在等待退避期结束的 Pod。退避期取决于调度器对该 Pod 执行的不成功调度尝试次数。&lt;/li>
&lt;li>&lt;strong>无法调度的 Pod 池&lt;/strong>：保存调度器不会尝试调度的 Pod，原因可能包括以下几点：
&lt;ul>
&lt;li>调度器之前尝试调度这些 Pod 但未能成功。自那次尝试以来，集群没有发生任何使得这些 Pod 可以被调度的变化。&lt;/li>
&lt;li>这些 Pod 被 &lt;a href="https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/pod-scheduling-readiness/#configuring-pod-schedulinggates">PreEnqueue 插件&lt;/a>阻止进入调度周期，
例如，它们具有一个&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/pod-scheduling-readiness/#configuring-pod-schedulinggates">调度门控&lt;/a>，并被调度门控插件阻止。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;!--
## Scheduling framework and plugins
The Kubernetes scheduler is implemented following the Kubernetes
[scheduling framework](/docs/concepts/scheduling-eviction/scheduling-framework/).
And, all scheduling features are implemented as plugins
(e.g., [Pod affinity](/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity)
is implemented in the `InterPodAffinity` plugin.)
-->
&lt;h2 id="调度框架和插件">调度框架和插件&lt;/h2>
&lt;p>Kubernetes 调度器的实现遵循 Kubernetes 的&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/scheduling-framework/">调度框架&lt;/a>。&lt;/p>
&lt;p>并且，所有的调度特性都是以插件的形式实现的
（例如，&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity">Pod 亲和性&lt;/a>是在
&lt;code>InterPodAffinity&lt;/code> 插件中实现的。）&lt;/p>
&lt;!--
The scheduler processes pending Pods in phases called _cycles_ as follows:
1. **Scheduling cycle**: the scheduler takes pending Pods from the activeQ component of the scheduling
queue _one by one_. For each Pod, the scheduler runs the filtering/scoring logic from every scheduling plugin. The
scheduler then decides on the best node for the Pod, or decides that the Pod can't be scheduled at that time.
If the scheduler decides that a Pod can't be scheduled, that Pod enters the Unschedulable Pod Pool
component of the scheduling queue. However, if the scheduler decides to place the Pod on a node,
the Pod goes to the binding cycle.
1. **Binding cycle**: the scheduler communicates the node placement decision to the Kubernetes API
server. This operation bounds the Pod to the selected node.
-->
&lt;p>调度器按照称为&lt;strong>周期&lt;/strong>的阶段来处理待调度的 Pod，具体如下：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>调度周期（Scheduling cycle）&lt;/strong>：调度器从调度队列的 activeQ 组件中&lt;strong>逐一&lt;/strong>取出待调度的 Pod。
对于每个 Pod，调度器会运行来自每个调度插件的过滤/评分逻辑。然后，调度器决定最适合该 Pod 的节点，
或者决定当前无法调度该 Pod。&lt;/p>
&lt;p>如果调度器决定一个 Pod 无法被调度，该 Pod 将进入调度队列的无法调度的 Pod
池（Unschedulable Pod Pool）组件。然而，如果调度器决定将 Pod 放置到某个节点上，
该 Pod 将进入绑定周期（Binding cycle）。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>绑定周期（Binding cycle）&lt;/strong>：调度器将节点分配决策传达给 Kubernetes API 服务器。
这一操作将 Pod 绑定到选定的节点。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;!--
Aside from some exceptions, most unscheduled Pods enter the unschedulable pod pool after each scheduling
cycle. The Unschedulable Pod Pool component is crucial because of how the scheduling cycle processes Pods one by one. If the scheduler had to constantly retry placing unschedulable Pods, instead of offloading those
Pods to the Unschedulable Pod Pool, multiple scheduling cycles would be wasted on those Pods.
-->
&lt;p>除了少数例外情况，大多数未调度的 Pod 在每次调度周期后都会进入无法调度的 Pod 池。
无法调度的 Pod 池组件至关重要，因为调度周期是逐个处理 Pod 的。
如果调度器需要不断重试放置那些无法调度的 Pod，而不是将这些 Pod 分载到无法调度的 Pod 池中，
将会在这些 Pod 上浪费很多调度周期。&lt;/p>
&lt;!--
## Improvements to retrying Pod scheduling with QueuingHint
Unschedulable Pods only move back into the ActiveQ or BackoffQ components of the scheduling
queue if changes in the cluster might allow the scheduler to place those Pods on nodes.
Prior to v1.32, each plugin registered which cluster changes could solve their failures, an object creation, update, or deletion in the cluster (called _cluster events_),
with `EnqueueExtensions` (`EventsToRegister`),
and the scheduling queue retries a pod with an event that is registered by a plugin that rejected the pod in a previous scheduling cycle.
Additionally, we had an internal feature called `preCheck`, which helped further filtering of events for efficiency, based on Kubernetes core scheduling constraints;
For example, `preCheck` could filter out node-related events when the node status is `NotReady`.
-->
&lt;h2 id="使用-queueinghint-改进-pod-调度重试">使用 QueueingHint 改进 Pod 调度重试&lt;/h2>
&lt;p>无法调度的 Pod 仅在集群发生可能允许调度器将这些 Pod 放置到节点上的变化时，
才会重新移入调度队列的 ActiveQ 或 BackoffQ 组件。&lt;/p>
&lt;p>在 v1.32 之前，每个插件通过 &lt;code>EnqueueExtensions&lt;/code>（&lt;code>EventsToRegister&lt;/code>）注册哪些集群变化
（称为&lt;strong>集群事件&lt;/strong>，即集群中的对象创建、更新或删除）可以解决其失败情况。当某个插件在之前的调度周期中拒绝了某个 Pod 后，
调度队列会在出现该插件注册的事件时重试该 Pod 的调度。&lt;/p>
&lt;p>此外，我们还拥有一个名为 &lt;code>preCheck&lt;/code> 的内部特性，它基于 Kubernetes 核心调度约束进一步过滤事件以提高效率；
例如，&lt;code>preCheck&lt;/code> 可以在节点状态为 &lt;code>NotReady&lt;/code> 时过滤掉与节点相关的事件。&lt;/p>
&lt;!--
However, we had two issues for those approaches:
- Requeueing with events was too broad, could lead to scheduling retries for no reason.
- A new scheduled Pod _might_ solve the `InterPodAffinity`'s failure, but not all of them do.
For example, if a new Pod is created, but without a label matching `InterPodAffinity` of the unschedulable pod, the pod wouldn't be schedulable.
- `preCheck` relied on the logic of in-tree plugins and was not extensible to custom plugins,
like in issue [#110175](https://github.com/kubernetes/kubernetes/issues/110175).
-->
&lt;p>然而，这些方法存在两个问题：&lt;/p>
&lt;ul>
&lt;li>基于事件的重新排队过于宽泛，可能会导致毫无来由的调度重试。
&lt;ul>
&lt;li>新调度的 Pod &lt;strong>可能&lt;/strong>解决 &lt;code>InterPodAffinity&lt;/code> 失败的问题，但并非所有新 Pod 都能做到。
例如，如果创建了一个新的 Pod，但该 Pod 没有与无法调度的 Pod 的 &lt;code>InterPodAffinity&lt;/code> 匹配的标签，
则该 Pod 仍然无法被调度。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;code>preCheck&lt;/code> 依赖于 in-tree 插件的逻辑，并且不适用于自定义插件，如在问题
&lt;a href="https://github.com/kubernetes/kubernetes/issues/110175">#110175&lt;/a> 中所述。&lt;/li>
&lt;/ul>
&lt;!--
Here QueueingHints come into play;
a QueueingHint subscribes to a particular kind of cluster event, and make a decision about whether each incoming event could make the Pod schedulable.
For example, consider a Pod named `pod-a` that has a required Pod affinity. `pod-a` was rejected in
the scheduling cycle by the `InterPodAffinity` plugin because no node had an existing Pod that matched
the Pod affinity specification for `pod-a`.
-->
&lt;p>在这里，QueueingHints 发挥了作用；QueueingHint 订阅特定类型的集群事件，并决定每个传入的事件是否可以使 Pod 变得可调度。&lt;/p>
&lt;p>例如，考虑一个名为 &lt;code>pod-a&lt;/code> 的 Pod，它具有必需的 Pod 亲和性。&lt;code>pod-a&lt;/code> 在调度周期中被
&lt;code>InterPodAffinity&lt;/code> 插件拒绝，因为没有节点上有现有的 Pod 符合 &lt;code>pod-a&lt;/code> 的 Pod 亲和性规约。&lt;/p>
&lt;!--
&lt;figure>
&lt;img src="https://kubernetes.io/zh-cn/blog/2024/12/12/scheduler-queueinghint/queueinghint1.svg"
alt="A diagram showing the scheduling queue and pod-a rejected by InterPodAffinity plugin"/> &lt;figcaption>
&lt;p>A diagram showing the scheduling queue and pod-a rejected by InterPodAffinity plugin&lt;/p>
&lt;/figcaption>
&lt;/figure>
`pod-a` moves into the Unschedulable Pod Pool. The scheduling queue records which plugin caused
the scheduling failure for the Pod. For `pod-a`, the scheduling queue records that the `InterPodAffinity`
plugin rejected the Pod.
-->
&lt;figure>
&lt;img src="https://kubernetes.io/zh-cn/blog/2024/12/12/scheduler-queueinghint/queueinghint1.svg"
alt="显示调度队列和被 InterPodAffinity 插件拒绝的 pod-a 的图示"/> &lt;figcaption>
&lt;p>显示调度队列和被 InterPodAffinity 插件拒绝的 pod-a 的图示&lt;/p>
&lt;/figcaption>
&lt;/figure>
&lt;p>&lt;code>pod-a&lt;/code> 移入无法调度的 Pod 池 (Unschedulable Pod Pool)。调度队列记录了导致 Pod
调度失败的插件。对于 &lt;code>pod-a&lt;/code>，调度队列记录了 &lt;code>InterPodAffinity&lt;/code> 插件拒绝了该 Pod。&lt;/p>
&lt;!--
`pod-a` will never be schedulable until the InterPodAffinity failure is resolved.
There're some scenarios that the failure could be resolved, one example is an existing running pod gets a label update and becomes matching a Pod affinity.
For this scenario, the `InterPodAffinity` plugin's `QueuingHint` callback function checks every Pod label update that occurs in the cluster.
Then, if a Pod gets a label update that matches the Pod affinity requirement of `pod-a`, the `InterPodAffinity`,
plugin's `QueuingHint` prompts the scheduling queue to move `pod-a` back into the ActiveQ or
the BackoffQ component.
&lt;figure>
&lt;img src="https://kubernetes.io/zh-cn/blog/2024/12/12/scheduler-queueinghint/queueinghint2.svg"
alt="A diagram showing the scheduling queue and pod-a being moved by InterPodAffinity QueueingHint"/> &lt;figcaption>
&lt;p>A diagram showing the scheduling queue and pod-a being moved by InterPodAffinity QueueingHint&lt;/p>
&lt;/figcaption>
&lt;/figure>
-->
&lt;p>&lt;code>pod-a&lt;/code> 在 &lt;code>InterPodAffinity&lt;/code> 失败被解决之前将永远不会被调度。
有一些情景可以解决这一失败，例如，一个现有的运行中的 Pod 获取了标签更新并符合 Pod 亲和性要求。
在这种情况下，&lt;code>InterPodAffinity&lt;/code> 插件的 &lt;code>QueuingHint&lt;/code> 回调函数会检查集群中发生的每一个 Pod 标签更新。
然后，如果一个 Pod 的标签更新符合 &lt;code>pod-a&lt;/code> 的 Pod 亲和性要求，&lt;code>InterPodAffinity&lt;/code> 插件的
&lt;code>QueuingHint&lt;/code> 会提示调度队列将 &lt;code>pod-a&lt;/code> 重新移入 ActiveQ 或 BackoffQ 组件。&lt;/p>
&lt;figure>
&lt;img src="https://kubernetes.io/zh-cn/blog/2024/12/12/scheduler-queueinghint/queueinghint2.svg"
alt="显示调度队列和由 InterPodAffinity QueuingHint 移动的 pod-a 的图示"/> &lt;figcaption>
&lt;p>显示调度队列和由 InterPodAffinity QueuingHint 移动的 pod-a 的图示&lt;/p>
&lt;/figcaption>
&lt;/figure>
&lt;!--
## QueueingHint's history and what's new in v1.32
At SIG Scheduling, we have been working on the development of QueueingHint since
Kubernetes v1.28.
While QueuingHint isn't user-facing, we implemented the `SchedulerQueueingHints` feature gate as a
safety measure when we originally added this feature. In v1.28, we implemented QueueingHints with a
few in-tree plugins experimentally, and made the feature gate enabled by default.
-->
&lt;h2 id="queueinghint-的历史及-v1-32-中的新变化">QueueingHint 的历史及 v1.32 中的新变化&lt;/h2>
&lt;p>在 SIG Scheduling，我们自 Kubernetes v1.28 开始就致力于 QueueingHint 的开发。&lt;/p>
&lt;p>尽管 QueueingHint 并不是面向用户的特性，我们在最初添加此特性时还是实现了 &lt;code>SchedulerQueueingHints&lt;/code>
特性门控作为安全措施。在 v1.28 中，我们实验性地为几个 in-tree 插件实现了 QueueingHints，并将该特性门控默认启用。&lt;/p>
&lt;!--
However, users reported a memory leak, and consequently we disabled the feature gate in a
patch release of v1.28. From v1.28 until v1.31, we kept working on the QueueingHint implementation
within the rest of the in-tree plugins and fixing bugs.
In v1.32, we made this feature enabled by default again. We finished implementing QueueingHints
in all plugins and also identified the cause of the memory leak!
We thank all the contributors who participated in the development of this feature and those who reported and investigated the earlier issues.
-->
&lt;p>然而，用户报告了一个内存泄漏问题，因此我们在 v1.28 的一个补丁版本中禁用了该特性门控。从 v1.28 到 v1.31，
我们一直在其余的 in-tree 插件中继续开发 QueueingHint，并修复相关 bug。&lt;/p>
&lt;p>在 v1.32 中，我们再次默认启用了这一特性。我们完成了所有插件中 QueueingHints 的实现，并且找到了内存泄漏的原因！&lt;/p>
&lt;p>我们感谢所有参与此特性开发的贡献者，以及那些报告和调查早期问题的用户。&lt;/p>
&lt;!--
## Getting involved
These features are managed by Kubernetes [SIG Scheduling](https://github.com/kubernetes/community/tree/master/sig-scheduling).
Please join us and share your feedback.
-->
&lt;h2 id="参与其中">参与其中&lt;/h2>
&lt;p>这些特性由 Kubernetes &lt;a href="https://github.com/kubernetes/community/tree/master/sig-scheduling">SIG Scheduling&lt;/a> 管理。&lt;/p>
&lt;p>请加入我们并分享你的反馈。&lt;/p>
&lt;!--
## How can I learn more?
- [KEP-4247: Per-plugin callback functions for efficient requeueing in the scheduling queue](https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/4247-queueinghint/README.md)
-->
&lt;h2 id="如何了解更多">如何了解更多？&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/4247-queueinghint/README.md">KEP-4247：为调度队列中的高效重新排队实现每插件回调函数&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Kubernetes v1.32 预览</title><link>https://kubernetes.io/zh-cn/blog/2024/11/08/kubernetes-1-32-upcoming-changes/</link><pubDate>Fri, 08 Nov 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/11/08/kubernetes-1-32-upcoming-changes/</guid><description>
&lt;!--
layout: blog
title: 'Kubernetes v1.32 sneak peek'
date: 2024-11-08
slug: kubernetes-1-32-upcoming-changes
author: >
Matteo Bianchi,
Edith Puclla,
William Rizzo,
Ryota Sawada,
Rashan Smith
-->
&lt;!--
As we get closer to the release date for Kubernetes v1.32, the project develops and matures.
Features may be deprecated, removed, or replaced with better ones for the project's overall health.
This blog outlines some of the planned changes for the Kubernetes v1.32 release,
that the release team feels you should be aware of, for the continued maintenance
of your Kubernetes environment and keeping up to date with the latest changes.
Information listed below is based on the current status of the v1.32 release
and may change before the actual release date.
-->
&lt;p>随着 Kubernetes v1.32 发布日期的临近，Kubernetes 项目继续发展和成熟。
在这个过程中，某些特性可能会被弃用、移除或被更好的特性取代，以确保项目的整体健康与发展。&lt;/p>
&lt;p>本文概述了 Kubernetes v1.32 发布的一些计划变更，发布团队认为你应该了解这些变更，
以确保你的 Kubernetes 环境得以持续维护并跟上最新的变化。以下信息基于 v1.32
发布的当前状态，实际发布日期前可能会有所变动。&lt;/p>
&lt;!--
### The Kubernetes API removal and deprecation process
The Kubernetes project has a well-documented [deprecation policy](/docs/reference/using-api/deprecation-policy/)
for features. This policy states that stable APIs may only be deprecated when a newer,
stable version of that API is available and that APIs have a minimum lifetime for each stability level.
A deprecated API has been marked for removal in a future Kubernetes release will continue to function until
removal (at least one year from the deprecation). Its usage will result in a warning being displayed.
Removed APIs are no longer available in the current version, so you must migrate to use the replacement instead.
-->
&lt;h3 id="kubernetes-api-的移除和弃用流程">Kubernetes API 的移除和弃用流程&lt;/h3>
&lt;p>Kubernetes 项目对功能特性有一个文档完备的&lt;a href="https://kubernetes.io/zh-cn/docs/reference/using-api/deprecation-policy/">弃用策略&lt;/a>。
该策略规定，只有当较新的、稳定的相同 API 可用时，原有的稳定 API 才可能被弃用，每个稳定级别的 API 都有一个最短的生命周期。
弃用的 API 指的是已标记为将在后续发行某个 Kubernetes 版本时移除的 API；
移除之前该 API 将继续发挥作用（从弃用起至少一年时间），但使用时会显示一条警告。
移除的 API 将在当前版本中不再可用，此时你必须迁移以使用替换的 API。&lt;/p>
&lt;!--
* Generally available (GA) or stable API versions may be marked as deprecated but must not be removed within a major version of Kubernetes.
* Beta or pre-release API versions must be supported for 3 releases after the deprecation.
* Alpha or experimental API versions may be removed in any release without prior deprecation notice;
this process can become a withdrawal in cases where a different implementation for the same feature is already in place.
-->
&lt;ul>
&lt;li>
&lt;p>正式发布的（GA）或稳定的 API 版本可被标记为已弃用，但不得在 Kubernetes 主要版本未变时删除。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Beta 或预发布 API 版本，必须保持在被弃用后 3 个发布版本中仍然可用。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Alpha 或实验性 API 版本可以在任何版本中删除，不必提前通知；
如果同一特性已有不同实施方案，则此过程可能会成为撤销。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!--
Whether an API is removed due to a feature graduating from beta to stable or because that API did not succeed,
all removals comply with this deprecation policy. Whenever an API is removed,
migration options are communicated in the [deprecation guide](/docs/reference/using-api/deprecation-guide/).
-->
&lt;p>无论 API 是因为特性从 Beta 升级到稳定状态还是因为未能成功而被移除，
所有移除操作都遵守此弃用策略。每当 API 被移除时，
迁移选项都会在&lt;a href="https://kubernetes.io/zh-cn/docs/reference/using-api/deprecation-guide/">弃用指南&lt;/a>中进行说明。&lt;/p>
&lt;!--
## Note on the withdrawal of the old DRA implementation
The enhancement [#3063](https://github.com/kubernetes/enhancements/issues/3063)
introduced Dynamic Resource Allocation (DRA) in Kubernetes 1.26.
-->
&lt;h2 id="关于撤回-dra-的旧的实现的说明">关于撤回 DRA 的旧的实现的说明&lt;/h2>
&lt;p>增强特性 &lt;a href="https://github.com/kubernetes/enhancements/issues/3063">#3063&lt;/a> 在 Kubernetes 1.26
中引入了动态资源分配（DRA）。&lt;/p>
&lt;!--
However, in Kubernetes v1.32, this approach to DRA will be significantly changed.
Code related to the original implementation will be removed, leaving KEP
[#4381](https://github.com/kubernetes/enhancements/issues/4381) as the "new" base functionality.
-->
&lt;p>然而，在 Kubernetes v1.32 中，这种 DRA 的实现方法将发生重大变化。与原来实现相关的代码将被删除，
只留下 KEP &lt;a href="https://github.com/kubernetes/enhancements/issues/4381">#4381&lt;/a> 作为&amp;quot;新&amp;quot;的基础特性。&lt;/p>
&lt;!--
The decision to change the existing approach originated from its incompatibility with cluster autoscaling
as resource availability was non-transparent, complicating decision-making for both Cluster Autoscaler and controllers.
The newly added Structured Parameter model substitutes the functionality.
-->
&lt;p>改变现有方法的决定源于其与集群自动伸缩的不兼容性，因为资源可用性是不透明的，
这使得 Cluster Autoscaler 和控制器的决策变得复杂。
新增的结构化参数模型替换了原有特性。&lt;/p>
&lt;!--
This removal will allow Kubernetes to handle new hardware requirements and resource claims more predictably,
bypassing the complexities of back and forth API calls to the kube-apiserver.
Please also see the enhancement issue [#3063](https://github.com/kubernetes/enhancements/issues/3063) to find out more.
-->
&lt;p>这次移除将使 Kubernetes 能够更可预测地处理新的硬件需求和资源声明，
避免了与 kube-apiserver 之间复杂的来回 API 调用。&lt;/p>
&lt;p>请参阅增强问题 &lt;a href="https://github.com/kubernetes/enhancements/issues/3063">#3063&lt;/a> 以了解更多信息。&lt;/p>
&lt;!--
## API removal
There is only a single API removal planned for [Kubernetes v1.32](/docs/reference/using-api/deprecation-guide/#v1-32):
-->
&lt;h2 id="api-移除">API 移除&lt;/h2>
&lt;p>在 &lt;a href="https://kubernetes.io/zh-cn/docs/reference/using-api/deprecation-guide/#v1-32">Kubernetes v1.32&lt;/a> 中，计划仅移除一个 API：&lt;/p>
&lt;!--
* The `flowcontrol.apiserver.k8s.io/v1beta3` API version of FlowSchema and PriorityLevelConfiguration has been removed.
To prepare for this, you can edit your existing manifests and rewrite client software to use the
`flowcontrol.apiserver.k8s.io/v1 API` version, available since v1.29.
All existing persisted objects are accessible via the new API. Notable changes in `flowcontrol.apiserver.k8s.io/v1beta3`
include that the PriorityLevelConfiguration `spec.limited.nominalConcurrencyShares` field only defaults to 30 when unspecified,
and an explicit value of 0 is not changed to 30.
For more information, please refer to the [API deprecation guide](/docs/reference/using-api/deprecation-guide/#v1-32).
-->
&lt;ul>
&lt;li>
&lt;p>&lt;code>flowcontrol.apiserver.k8s.io/v1beta3&lt;/code> 版本的 FlowSchema 和 PriorityLevelConfiguration 已被移除。
为了对此做好准备，你可以编辑现有的清单文件并重写客户端软件，使用自 v1.29 起可用的 &lt;code>flowcontrol.apiserver.k8s.io/v1&lt;/code> API 版本。
所有现有的持久化对象都可以通过新 API 访问。&lt;code>flowcontrol.apiserver.k8s.io/v1beta3&lt;/code> 中的重要变化包括：
当未指定时，PriorityLevelConfiguration 的 &lt;code>spec.limited.nominalConcurrencyShares&lt;/code>
字段仅默认为 30，而显式设置的 0 值不会被更改为此默认值。&lt;/p>
&lt;p>有关更多信息，请参阅 &lt;a href="https://kubernetes.io/zh-cn/docs/reference/using-api/deprecation-guide/#v1-32">API 弃用指南&lt;/a>。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!--
## Sneak peek of Kubernetes v1.32
The following list of enhancements is likely to be included in the v1.32 release.
This is not a commitment and the release content is subject to change.
-->
&lt;h2 id="kubernetes-v1-32-的抢先预览">Kubernetes v1.32 的抢先预览&lt;/h2>
&lt;p>以下增强特性有可能会被包含在 v1.32 发布版本中。请注意，这并不是最终承诺，发布内容可能会发生变化。&lt;/p>
&lt;!--
### Even more DRA enhancements!
In this release, like the previous one, the Kubernetes project continues proposing a number
of enhancements to the Dynamic Resource Allocation (DRA), a key component of the Kubernetes resource management system.
These enhancements aim to improve the flexibility and efficiency of resource allocation for workloads that require specialized hardware,
such as GPUs, FPGAs and network adapters. This release introduces improvements,
including the addition of resource health status in the Pod status, as outlined in
KEP [#4680](https://github.com/kubernetes/enhancements/issues/4680).
-->
&lt;h3 id="更多-dra-增强特性">更多 DRA 增强特性！&lt;/h3>
&lt;p>在此次发布中，就像上一次一样，Kubernetes 项目继续提出多项对动态资源分配（DRA）的增强。
DRA 是 Kubernetes 资源管理系统的关键组件，这些增强旨在提高对需要专用硬件（如 GPU、FPGA 和网络适配器）
的工作负载进行资源分配的灵活性和效率。此次发布引入了多项改进，包括在 Pod 状态中添加资源健康状态，
具体内容详见 KEP &lt;a href="https://github.com/kubernetes/enhancements/issues/4680">#4680&lt;/a>。&lt;/p>
&lt;!--
#### Add resource health status to the Pod status
It isn't easy to know when a Pod uses a device that has failed or is temporarily unhealthy.
KEP [#4680](https://github.com/kubernetes/enhancements/issues/4680) proposes exposing device
health via Pod `status`, making troubleshooting of Pod crashes easier.
-->
&lt;h4 id="在-pod-状态中添加资源健康状态">在 Pod 状态中添加资源健康状态&lt;/h4>
&lt;p>当 Pod 使用的设备出现故障或暂时不健康时，很难及时发现。
KEP &lt;a href="https://github.com/kubernetes/enhancements/issues/4680">#4680&lt;/a>
提议通过 Pod 的 &lt;code>status&lt;/code> 暴露设备健康状态，从而使 Pod 崩溃的故障排除更加容易。&lt;/p>
&lt;!--
### Windows strikes back!
KEP [#4802](https://github.com/kubernetes/enhancements/issues/4802) adds support
for graceful shutdowns of Windows nodes in Kubernetes clusters.
Before this release, Kubernetes provided graceful node shutdown functionality for
Linux nodes but lacked equivalent support for Windows.
This enhancement enables the kubelet on Windows nodes to handle system shutdown events properly.
Doing so, it ensures that Pods running on Windows nodes are gracefully terminated,
allowing workloads to be rescheduled without disruption.
This improvement enhances the reliability and stability of clusters that include Windows nodes,
especially during a planned maintenance or any system updates.
-->
&lt;h3 id="windows-工作继续">Windows 工作继续&lt;/h3>
&lt;p>KEP &lt;a href="https://github.com/kubernetes/enhancements/issues/4802">#4802&lt;/a> 为
Kubernetes 集群中的 Windows 节点添加了体面关机支持。
在此之前，Kubernetes 为 Linux 节点提供了体面关机特性，但缺乏对 Windows 节点的同等支持。
这一增强特性使 Windows 节点上的 kubelet 能够正确处理系统关机事件，确保在 Windows 节点上运行的 Pod 能够体面终止，
从而允许工作负载在不受干扰的情况下重新调度。这一改进提高了包含 Windows 节点的集群的可靠性和稳定性，
特别是在计划维护或系统更新期间。&lt;/p>
&lt;!--
### Allow special characters in environment variables
With the graduation of this [enhancement](https://github.com/kubernetes/enhancements/issues/4369) to beta,
Kubernetes now allows almost all printable ASCII characters (excluding "=") to be used as environment variable names.
This change addresses the limitations previously imposed on variable naming, facilitating a broader adoption of
Kubernetes by accommodating various application needs. The relaxed validation will be enabled by default via the
`RelaxedEnvironmentVariableValidation` feature gate, ensuring that users can easily utilize environment
variables without strict constraints, enhancing flexibility for developers working with applications like
.NET Core that require special characters in their configurations.
-->
&lt;h3 id="允许环境变量中使用特殊字符">允许环境变量中使用特殊字符&lt;/h3>
&lt;p>随着这一&lt;a href="https://github.com/kubernetes/enhancements/issues/4369">增强特性&lt;/a>升级到 Beta 阶段，
Kubernetes 现在允许几乎所有的可打印 ASCII 字符（不包括 &lt;code>=&lt;/code>）作为环境变量名称。
这一变化解决了此前对变量命名的限制，通过适应各种应用需求，促进了 Kubernetes 的更广泛采用。
放宽的验证将通过 &lt;code>RelaxedEnvironmentVariableValidation&lt;/code> 特性门控默认启用，
确保用户可以轻松使用环境变量而不受严格限制，增强了开发者在处理需要特殊字符配置的应用（如 .NET Core）时的灵活性。&lt;/p>
&lt;!--
### Make Kubernetes aware of the LoadBalancer behavior
KEP [#1860](https://github.com/kubernetes/enhancements/issues/1860) graduates to GA,
introducing the `ipMode` field for a Service of `type: LoadBalancer`, which can be set to either
`"VIP"` or `"Proxy"`. This enhancement is aimed at improving how cloud providers load balancers
interact with kube-proxy and it is a change transparent to the end user.
The existing behavior of kube-proxy is preserved when using `"VIP"`, where kube-proxy handles the load balancing.
Using `"Proxy"` results in traffic sent directly to the load balancer,
providing cloud providers greater control over relying on kube-proxy;
this means that you could see an improvement in the performance of your load balancer for some cloud providers.
-->
&lt;h3 id="使-kubernetes-感知到-loadbalancer-的行为">使 Kubernetes 感知到 LoadBalancer 的行为&lt;/h3>
&lt;p>KEP &lt;a href="https://github.com/kubernetes/enhancements/issues/1860">#1860&lt;/a> 升级到 GA 阶段，
为 &lt;code>type: LoadBalancer&lt;/code> 类型的 Service 引入了 &lt;code>ipMode&lt;/code> 字段，该字段可以设置为 &lt;code>&amp;quot;VIP&amp;quot;&lt;/code> 或 &lt;code>&amp;quot;Proxy&amp;quot;&lt;/code>。
这一增强旨在改善云提供商负载均衡器与 kube-proxy 的交互方式，对最终用户来说是透明的。
使用 &lt;code>&amp;quot;VIP&amp;quot;&lt;/code> 时，kube-proxy 会继续处理负载均衡，保持现有的行为。使用 &lt;code>&amp;quot;Proxy&amp;quot;&lt;/code> 时，
流量将直接发送到负载均衡器，提供云提供商对依赖 kube-proxy 的更大控制权；
这意味着对于某些云提供商，你可能会看到负载均衡器性能的提升。&lt;/p>
&lt;!--
### Retry generate name for resources
This [enhancement](https://github.com/kubernetes/enhancements/issues/4420)
improves how name conflicts are handled for Kubernetes resources created with the `generateName` field.
Previously, if a name conflict occurred, the API server returned a 409 HTTP Conflict error and clients
had to manually retry the request. With this update, the API server automatically retries generating
a new name up to seven times in case of a conflict. This significantly reduces the chances of collision,
ensuring smooth generation of up to 1 million names with less than a 0.1% probability of a conflict,
providing more resilience for large-scale workloads.
-->
&lt;h3 id="为资源生成名称时重试">为资源生成名称时重试&lt;/h3>
&lt;p>这一&lt;a href="https://github.com/kubernetes/enhancements/issues/4420">增强特性&lt;/a>改进了使用
&lt;code>generateName&lt;/code> 字段创建 Kubernetes 资源时的名称冲突处理。此前，如果发生名称冲突，
API 服务器会返回 409 HTTP 冲突错误，客户端需要手动重试请求。通过此次更新，
API 服务器在发生冲突时会自动重试生成新名称，最多重试七次。这显著降低了冲突的可能性，
确保生成多达 100 万个名称时冲突的概率低于 0.1%，为大规模工作负载提供了更高的弹性。&lt;/p>
&lt;!--
## Want to know more?
New features and deprecations are also announced in the Kubernetes release notes.
We will formally announce what's new in
[Kubernetes v1.32](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.32.md)
as part of the CHANGELOG for this release.
You can see the announcements of changes in the release notes for:
-->
&lt;h2 id="想了解更多">想了解更多？&lt;/h2>
&lt;p>新特性和弃用特性也会在 Kubernetes 发布说明中宣布。我们将在此次发布的
&lt;a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.32.md">Kubernetes v1.32&lt;/a>
的 CHANGELOG 中正式宣布新内容。&lt;/p>
&lt;p>你可以在以下版本的发布说明中查看变更公告：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.31.md">Kubernetes v1.31&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.30.md">Kubernetes v1.30&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.29.md">Kubernetes v1.29&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.28.md">Kubernetes v1.28&lt;/a>&lt;/p>
&lt;/li>
&lt;/ul></description></item><item><title>关于日本的 Kubernetes 上游培训的特别报道</title><link>https://kubernetes.io/zh-cn/blog/2024/10/28/k8s-upstream-training-japan-spotlight/</link><pubDate>Mon, 28 Oct 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/10/28/k8s-upstream-training-japan-spotlight/</guid><description>
&lt;!--
layout: blog
title: "Spotlight on Kubernetes Upstream Training in Japan"
slug: k8s-upstream-training-japan-spotlight
date: 2024-10-28
canonicalUrl: https://www.k8s.dev/blog/2024/10/28/k8s-upstream-training-japan-spotlight/
author: >
[Junya Okabe](https://github.com/Okabe-Junya) (University of Tsukuba) /
Organizing team of Kubernetes Upstream Training in Japan
-->
&lt;!--
We are organizers of [Kubernetes Upstream Training in Japan](https://github.com/kubernetes-sigs/contributor-playground/tree/master/japan).
Our team is composed of members who actively contribute to Kubernetes, including individuals who hold roles such as member, reviewer, approver, and chair.
-->
&lt;p>我们是&lt;a href="https://github.com/kubernetes-sigs/contributor-playground/tree/master/japan">日本 Kubernetes 上游培训&lt;/a>的组织者。
我们的团队由积极向 Kubernetes 做贡献的成员组成，他们在社区中担任了 Member、Reviewer、Approver 和 Chair 等角色。&lt;/p>
&lt;!--
Our goal is to increase the number of Kubernetes contributors and foster the growth of the community.
While Kubernetes community is friendly and collaborative, newcomers may find the first step of contributing to be a bit challenging.
Our training program aims to lower that barrier and create an environment where even beginners can participate smoothly.
-->
&lt;p>我们的目标是增加 Kubernetes 贡献者的数量，并促进社区的成长。
虽然 Kubernetes 社区友好协作，但新手可能会发现迈出贡献的第一步有些困难。
我们的培训项目旨在降低壁垒，创造一个即使是初学者也能顺利参与的环境。&lt;/p>
&lt;!--
## What is Kubernetes upstream training in Japan?
![Upstream Training in 2022](ood-2022-01.png)
Our training started in 2019 and is held 1 to 2 times a year.
Initially, Kubernetes Upstream Training was conducted as a co-located event of KubeCon (Kubernetes Contributor Summit),
but we launched Kubernetes Upstream Training in Japan with the aim of increasing Japanese contributors by hosting a similar event in Japan.
-->
&lt;h2 id="what-is-kubernetes-upstream-training-in-japan">日本 Kubernetes 上游培训是什么？ &lt;/h2>
&lt;p>&lt;img alt="2022 年上游培训" src="https://kubernetes.io/zh-cn/blog/2024/10/28/k8s-upstream-training-japan-spotlight/ood-2022-01.png">&lt;/p>
&lt;p>我们的培训始于 2019 年，每年举办 1 到 2 次。
最初，Kubernetes 上游培训曾作为 KubeCon（Kubernetes 贡献者峰会）的同场地活动进行，
后来我们在日本推出了 Kubernetes 上游培训，目的是通过在日本举办类似活动来增加日本的贡献者。&lt;/p>
&lt;!--
Before the pandemic, the training was held in person, but since 2020, it has been conducted online.
The training offers the following content for those who have not yet contributed to Kubernetes:
* Introduction to Kubernetes community
* Overview of Kubernetes codebase and how to create your first PR
* Tips and encouragement to lower participation barriers, such as language
* How to set up the development environment
* Hands-on session using [kubernetes-sigs/contributor-playground](https://github.com/kubernetes-sigs/contributor-playground)
-->
&lt;p>在疫情之前，培训是面对面进行的，但自 2020 年以来，我们已转为在线上进行。
培训为尚未参与过 Kubernetes 贡献的学员提供以下内容：&lt;/p>
&lt;ul>
&lt;li>Kubernetes 社区简介&lt;/li>
&lt;li>Kubernetes 代码库概述以及如何创建你的第一个 PR&lt;/li>
&lt;li>各种降低参与壁垒（如语言）的提示和鼓励&lt;/li>
&lt;li>如何搭建开发环境&lt;/li>
&lt;li>使用 &lt;a href="https://github.com/kubernetes-sigs/contributor-playground">kubernetes-sigs/contributor-playground&lt;/a>
开展实践课程&lt;/li>
&lt;/ul>
&lt;!--
At the beginning of the program, we explain why contributing to Kubernetes is important and who can contribute.
We emphasize that contributing to Kubernetes allows you to make a global impact and that Kubernetes community is looking forward to your contributions!
We also explain Kubernetes community, SIGs, and Working Groups.
Next, we explain the roles and responsibilities of Member, Reviewer, Approver, Tech Lead, and Chair.
Additionally, we introduce the communication tools we primarily use, such as Slack, GitHub, and mailing lists.
Some Japanese speakers may feel that communicating in English is a barrier.
Additionally, those who are new to the community need to understand where and how communication takes place.
We emphasize the importance of taking that first step, which is the most important aspect we focus on in our training!
-->
&lt;p>在培训开始时，我们讲解为什么贡献 Kubernetes 很重要以及谁可以做贡献。
我们强调，贡献 Kubernetes 可以让你产生全球影响，而 Kubernetes 社区期待着你的贡献！&lt;/p>
&lt;p>我们还讲解 Kubernetes 社区、SIG（特别兴趣小组）和 WG（工作组）。
接下来，我们讲解 Member、Reviewer、Approver、Tech Lead 和 Chair 的角色与职责。
此外，我们介绍大家所使用的主要沟通工具，如 Slack、GitHub 和邮件列表。
一些讲日语的人可能会觉得用英语沟通是一个障碍。
此外，社区的新人需要理解在哪儿以及如何与人交流。
我们强调迈出第一步的重要性，这是我们培训中最关注的方面！&lt;/p>
&lt;!--
We then go over the structure of Kubernetes codebase, the main repositories, how to create a PR, and the CI/CD process using [Prow](https://docs.prow.k8s.io/).
We explain in detail the process from creating a PR to getting it merged.
After several lectures, participants get to experience hands-on work using [kubernetes-sigs/contributor-playground](https://github.com/kubernetes-sigs/contributor-playground), where they can create a simple PR.
The goal is for participants to get a feel for the process of contributing to Kubernetes.
At the end of the program, we also provide a detailed explanation of setting up the development environment for contributing to the `kubernetes/kubernetes` repository,
including building code locally, running tests efficiently, and setting up clusters.
-->
&lt;p>然后，我们讲解 Kubernetes 代码库的结构、主要的仓库、如何创建 PR 以及使用
&lt;a href="https://docs.prow.k8s.io/">Prow&lt;/a> 的 CI/CD 流程。
我们详细讲解从创建 PR 到合并 PR 的过程。&lt;/p>
&lt;p>经过几节课后，参与者将体验使用
&lt;a href="https://github.com/kubernetes-sigs/contributor-playground">kubernetes-sigs/contributor-playground&lt;/a>
开展实践工作，在那里他们可以创建一个简单的 PR。
目标是让参与者体验贡献 Kubernetes 的过程。&lt;/p>
&lt;p>在项目结束时，我们还提供关于为贡献 &lt;code>kubernetes/kubernetes&lt;/code> 仓库搭建开发环境的详细说明，
包括如何在本地构建代码、如何高效运行测试以及如何搭建集群。&lt;/p>
&lt;!--
## Interview with participants
We conducted interviews with those who participated in our training program.
We asked them about their reasons for joining, their impressions, and their future goals.
-->
&lt;h2 id="interview-with-participants">与参与者的访谈 &lt;/h2>
&lt;p>我们对参与我们培训项目的人进行了访谈。
我们询问了他们参加的原因、印象和未来目标。&lt;/p>
&lt;!--
### [Keita Mochizuki](https://github.com/mochizuki875) ([NTT DATA Group Corporation](https://www.nttdata.com/global/en/about-us/profile))
Keita Mochizuki is a contributor who consistently contributes to Kubernetes and related projects.
Keita is also a professional in container security and has recently published a book.
Additionally, he has made available a [Roadmap for New Contributors](https://github.com/mochizuki875/KubernetesFirstContributionRoadMap), which is highly beneficial for those new to contributing.
**Junya:** Why did you decide to participate in Kubernetes Upstream Training?
-->
&lt;h3 id="keita-mochizuki-https-github-com-mochizuki875-ntt-data-集团公司-https-www-nttdata-com-global-en-about-us-profile">&lt;a href="https://github.com/mochizuki875">Keita Mochizuki&lt;/a>（&lt;a href="https://www.nttdata.com/global/en/about-us/profile">NTT DATA 集团公司&lt;/a>）&lt;/h3>
&lt;p>Keita Mochizuki 是一位持续为 Kubernetes 及相关项目做贡献的贡献者。
他还是容器安全领域的专业人士，他最近出版了一本书。此外，
他还发布了一份&lt;a href="https://github.com/mochizuki875/KubernetesFirstContributionRoadMap">新贡献者路线图&lt;/a>，
对新贡献者非常有帮助。&lt;/p>
&lt;p>&lt;strong>Junya：&lt;/strong> 你为什么决定参加 Kubernetes 上游培训？&lt;/p>
&lt;!--
**Keita:** Actually, I participated twice, in 2020 and 2022.
In 2020, I had just started learning about Kubernetes and wanted to try getting involved in activities outside of work, so I signed up after seeing the event on Twitter by chance.
However, I didn't have much knowledge at the time, and contributing to OSS felt like something beyond my reach.
As a result, my understanding after the training was shallow, and I left with more of a "hmm, okay" feeling.
In 2022, I participated again when I was at a stage where I was seriously considering starting contributions.
This time, I did prior research and was able to resolve my questions during the lectures, making it a very productive experience.
-->
&lt;p>&lt;strong>Keita：&lt;/strong> 实际上，我分别在 2020 年和 2022 年参加过两次培训。
在 2020 年，我刚开始学习 Kubernetes，想尝试参与工作以外的活动，
所以在 Twitter 上偶然看到活动后报了名参加了活动。
然而，那时我的知识积累还不多，贡献 OSS 感觉超出了我的能力。
因此，在培训后的理解比较肤浅，离开时更多是“嗯，好吧”的感觉。&lt;/p>
&lt;p>在 2022 年，我再次参加，那时我认真考虑开始贡献。
我事先进行了研究，并能够在讲座中解决我的问题，那次经历非常有成效。&lt;/p>
&lt;!--
**Junya:** How did you feel after participating?
**Keita:** I felt that the significance of this training greatly depends on the participant's mindset.
The training itself consists of general explanations and simple hands-on exercises, but it doesn't mean that attending the training will immediately lead to contributions.
**Junya:** What is your purpose for contributing?
**Keita:** My initial motivation was to "gain a deep understanding of Kubernetes and build a track record," meaning "contributing itself was the goal."
Nowadays, I also contribute to address bugs or constraints I discover during my work.
Additionally, through contributing, I've become less hesitant to analyze undocumented features directly from the source code.
-->
&lt;p>&lt;strong>Junya：&lt;/strong> 参加后你有什么感受？&lt;/p>
&lt;p>&lt;strong>Keita：&lt;/strong> 我觉得培训的意义很大程度上取决于参与者的心态。
培训本身包括常规的讲解和简单的实践练习，但这并不意味着参加培训就会立即会去做贡献。&lt;/p>
&lt;p>&lt;strong>Junya：&lt;/strong> 你贡献的目的是什么？&lt;/p>
&lt;p>&lt;strong>Keita：&lt;/strong> 我最初的动机是“深入理解 Kubernetes 并生成成绩记录”，也就是说“贡献本身就是目标”。
如今，我还会通过贡献来解决我在工作中发现的 Bug 或约束。
此外，通过贡献，我变得不再那么犹豫，会去直接基于源代码分析了解没有文档记录的特性。&lt;/p>
&lt;!--
**Junya:** What has been challenging about contributing?
**Keita:** The most difficult part was taking the first step. Contributing to OSS requires a certain level of knowledge, and leveraging resources like this training and support from others was essential.
One phrase that stuck with me was, "Once you take the first step, it becomes easier to move forward."
Also, in terms of continuing contributions as part of my job, the most challenging aspect is presenting the outcomes as achievements.
To keep contributing over time, it's important to align it with business goals and strategies, but upstream contributions don't always lead to immediate results that can be directly tied to performance.
Therefore, it's crucial to ensure mutual understanding with managers and gain their support.
-->
&lt;p>&lt;strong>Junya：&lt;/strong> 贡献中遇到的挑战是什么？&lt;/p>
&lt;p>&lt;strong>Keita：&lt;/strong> 最困难的部分是迈出第一步。贡献 OSS 需要一定的知识水平，利用像这样的培训和他人的支持至关重要。
一句让我印象深刻的话是，“一旦你迈出第一步，后续就会变得更容易。”&lt;br>
此外，在作为工作的一部分继续贡献时，最具挑战性的是将输出的结果变为成就感。
要保持长期贡献，将贡献与业务目标和策略对齐非常重要，但上游贡献并不总是能直接产生与表现相关的即时结果。
因此，确保与管理人员的相互理解并获得他们的支持至关重要。&lt;/p>
&lt;!--
**Junya:** What are your future goals?
**Keita:** My goal is to contribute to areas with a larger impact.
So far, I've mainly contributed by fixing smaller bugs as my primary focus was building a track record,
but moving forward, I'd like to challenge myself with contributions that have a greater impact on Kubernetes users or that address issues related to my work.
Recently, I've also been working on reflecting the changes I've made to the codebase into the official documentation,
and I see this as a step toward achieving my goals.
**Junya:** Thank you very much!
-->
&lt;p>&lt;strong>Junya：&lt;/strong> 你未来的目标是什么？&lt;/p>
&lt;p>&lt;strong>Keita：&lt;/strong> 我的目标是对影响更大的领域做出贡献。
到目前为止，我主要通过修复较小的 Bug 来做贡献，因为我的主要关注是生成一份成绩单，
但未来，我希望挑战自己对 Kubernetes 用户产生更大影响的贡献，或解决与我工作相关的问题。
最近，我还在努力将我对代码库所做的更改反映到官方文档中，
我将这视为实现我目标的一步。&lt;/p>
&lt;p>&lt;strong>Junya：&lt;/strong> 非常感谢！&lt;/p>
&lt;!--
### [Yoshiki Fujikane](https://github.com/ffjlabo) ([CyberAgent, Inc.](https://www.cyberagent.co.jp/en/))
Yoshiki Fujikane is one of the maintainers of [PipeCD](https://pipecd.dev/), a CNCF Sandbox project.
In addition to developing new features for Kubernetes support in PipeCD,
Yoshiki actively participates in community management and speaks at various technical conferences.
-->
&lt;h3 id="yoshiki-fujikane-https-github-com-ffjlabo-cyberagent-inc-https-www-cyberagent-co-jp-en">&lt;a href="https://github.com/ffjlabo">Yoshiki Fujikane&lt;/a>（&lt;a href="https://www.cyberagent.co.jp/en/">CyberAgent, Inc.&lt;/a>）&lt;/h3>
&lt;p>Yoshiki Fujikane 是 CNCF 沙盒项目 &lt;a href="https://pipecd.dev/">PipeCD&lt;/a> 的维护者之一。
除了在 PipeCD 中开发对 Kubernetes 支持的新特性外，
Yoshiki 还积极参与社区管理，并在各种技术会议上发言。&lt;/p>
&lt;!--
**Junya:** Why did you decide to participate in the Kubernetes Upstream Training?
**Yoshiki:** At the time I participated, I was still a student.
I had only briefly worked with EKS, but I thought Kubernetes seemed complex yet cool, and I was casually interested in it.
Back then, OSS felt like something out of reach, and upstream development for Kubernetes seemed incredibly daunting.
While I had always been interested in OSS, I didn't know where to start.
It was during this time that I learned about the Kubernetes Upstream Training and decided to take the challenge of contributing to Kubernetes.
-->
&lt;p>&lt;strong>Junya：&lt;/strong> 你为什么决定参加 Kubernetes 上游培训？&lt;/p>
&lt;p>&lt;strong>Yoshiki：&lt;/strong> 当我参与培训时，我还是一名学生。
我只简短地接触过 EKS，我觉得 Kubernetes 看起来复杂但很酷，我对此有一种随意的兴趣。
当时，OSS 对我来说感觉像是遥不可及，而 Kubernetes 的上游开发似乎非常令人生畏。
虽然我一直对 OSS 感兴趣，但我不知道从哪里开始。
也就在那个时候，我了解到 Kubernetes 上游培训，并决定挑战自己为 Kubernetes 做贡献。&lt;/p>
&lt;!--
**Junya:** What were your impressions after participating?
**Yoshiki:** I found it extremely valuable as a way to understand what it's like to be part of an OSS community.
At the time, my English skills weren't very strong, so accessing primary sources of information felt like a big hurdle for me.
Kubernetes is a very large project, and I didn't have a clear understanding of the overall structure, let alone what was necessary for contributing.
The upstream training provided a Japanese explanation of the community structure and allowed me to gain hands-on experience with actual contributions.
Thanks to the guidance I received, I was able to learn how to approach primary sources and use them as entry points for further investigation, which was incredibly helpful.
This experience made me realize the importance of organizing and reviewing primary sources, and now I often dive into GitHub issues and documentation when something piques my interest.
As a result, while I am no longer contributing to Kubernetes itself, the experience has been a great foundation for contributing to other projects.
-->
&lt;p>&lt;strong>Junya：&lt;/strong> 参加后你的印象是什么？&lt;/p>
&lt;p>&lt;strong>Yoshiki：&lt;/strong> 我发现对于了解如何成为 OSS 社区的一部分，这种培训是一种非常有价值的方式。
当时，我的英语水平不是很好，所以获取主要信息源对我来说是一个很大的障碍。
Kubernetes 是一个非常大的项目，我对整体结构没有清晰的理解，更不用说贡献所需的内容了。
上游培训提供了对社区结构的日文解释，并让我获得了实际贡献的实践经验。
得益于我所得到的指导，我学会了如何接触主要信息源，并将其作为进一步研究的切入点，这对我帮助很大。
这次经历让我意识到组织和评审主要信息源的重要性，现在我经常在 GitHub Issue 和文档中深入研究我感兴趣的内容。
因此，虽然我不再直接向 Kubernetes 做贡献，但这次经历为我在其他项目中做贡献奠定了很好的基础。&lt;/p>
&lt;!--
**Junya:** What areas are you currently contributing to, and what are the other projects you're involved in?
**Yoshiki:** Right now, I'm no longer working with Kubernetes, but instead, I'm a maintainer of PipeCD, a CNCF Sandbox project.
PipeCD is a CD tool that supports GitOps-style deployments for various application platforms.
The tool originally started as an internal project at CyberAgent.
With different teams adopting different platforms, PipeCD was developed to provide a unified CD platform with a consistent user experience.
Currently, it supports Kubernetes, AWS ECS, Lambda, Cloud Run, and Terraform.
-->
&lt;p>&lt;strong>Junya：&lt;/strong> 你目前在哪些领域做贡献？你参与了哪些其他项目？&lt;/p>
&lt;p>&lt;strong>Yoshiki：&lt;/strong> 目前，我不再从事 Kubernetes 的工作，而是担任 CNCF 沙盒项目 PipeCD 的维护者。
PipeCD 是一个支持各种应用平台的 GitOps 式部署的 CD 工具。
此工具最初作为 CyberAgent 的内部项目启动。
随着不同团队采用不同的平台，PipeCD 设计为提供一个统一的 CD 平台，确保用户体验一致。
目前，它支持 Kubernetes、AWS ECS、Lambda、Cloud Run 和 Terraform。&lt;/p>
&lt;!--
**Junya:** What role do you play within the PipeCD team?
**Yoshiki:** I work full-time on improving and developing Kubernetes-related features within the team.
Since we provide PipeCD as a SaaS internally, my main focus is on adding new features and improving existing ones as part of that support.
In addition to code contributions, I also contribute by giving talks at various events and managing community meetings to help grow the PipeCD community.
-->
&lt;p>&lt;strong>Junya：&lt;/strong> 你在 PipeCD 团队中扮演什么角色？&lt;/p>
&lt;p>&lt;strong>Yoshiki：&lt;/strong> 我全职负责团队中与 Kubernetes 相关特性的改进和开发。
由于我们将 PipeCD 作为内部 SaaS 提供，我的主要关注点是添加新特性和改进现有特性，
确保 PipeCD 能够持续良好支持 Kubernetes 等平台。
除了代码贡献外，我还通过在各种活动上发言和管理社区会议来帮助发展 PipeCD 社区。&lt;/p>
&lt;!--
**Junya:** Could you explain what kind of improvements or developments you are working on with regards to Kubernetes?
**Yoshiki:** PipeCD supports GitOps and Progressive Delivery for Kubernetes, so I'm involved in the development of those features.
Recently, I've been working on features that streamline deployments across multiple clusters.
-->
&lt;p>&lt;strong>Junya：&lt;/strong> 你能讲解一下你对于 Kubernetes 正在进行哪些改进或开发吗？&lt;/p>
&lt;p>&lt;strong>Yoshiki：&lt;/strong> PipeCD 支持 Kubernetes 的 GitOps 和渐进式交付，因此我参与这些特性的开发。
最近，我一直在开发简化跨多个集群部署的特性。&lt;/p>
&lt;!--
**Junya:** Have you encountered any challenges while contributing to OSS?
**Yoshiki:** One challenge is developing features that maintain generality while meeting user use cases.
When we receive feature requests while operating the internal SaaS, we first consider adding features to solve those issues.
At the same time, we want PipeCD to be used by a broader audience as an OSS tool.
So, I always think about whether a feature designed for one use case could be applied to another, ensuring the software remains flexible and widely usable.
-->
&lt;p>&lt;strong>Junya：&lt;/strong> 在贡献 OSS 的过程中，你遇到过哪些挑战？&lt;/p>
&lt;p>&lt;strong>Yoshiki：&lt;/strong> 一个挑战是开发在满足用户用例的同时保持通用性的特性。
当我们在运营内部 SaaS 期间收到特性请求时，我们首先考虑添加特性来解决这些问题。
与此同时，我们希望 PipeCD 作为一个 OSS 工具被更广泛的受众使用。
因此，我总是思考为一个用例设计的特性是否可以应用于其他用例，以确保 PipeCD 这个软件保持灵活且广泛可用。&lt;/p>
&lt;!--
**Junya:** What are your goals moving forward?
**Yoshiki:** I want to focus on expanding PipeCD's functionality.
Currently, we are developing PipeCD under the slogan "One CD for All."
As I mentioned earlier, it supports Kubernetes, AWS ECS, Lambda, Cloud Run, and Terraform, but there are many other platforms out there, and new platforms may emerge in the future.
For this reason, we are currently developing a plugin system that will allow users to extend PipeCD on their own, and I want to push this effort forward.
I'm also working on features for multi-cluster deployments in Kubernetes, and I aim to continue making impactful contributions.
**Junya:** Thank you very much!
-->
&lt;p>&lt;strong>Junya：&lt;/strong> 你未来的目标是什么？&lt;/p>
&lt;p>&lt;strong>Yoshiki：&lt;/strong> 我希望专注于扩展 PipeCD 的功能。
目前，我们正在以“普遍可用的持续交付”（One CD for All）的口号开发 PipeCD。
正如我之前提到的，它支持 Kubernetes、AWS ECS、Lambda、Cloud Run 和 Terraform，
但还有许多其他平台，以及未来可能会出现的新平台。
因此，我们目前正在开发一个插件系统，允许用户自行扩展 PipeCD，我希望将这一努力向前推进。
我也在处理 Kubernetes 的多集群部署特性，目标是继续做出有影响力的贡献。&lt;/p>
&lt;p>&lt;strong>Junya：&lt;/strong> 非常感谢！&lt;/p>
&lt;!--
## Future of Kubernetes upstream training
We plan to continue hosting Kubernetes Upstream Training in Japan and look forward to welcoming many new contributors.
Our next session is scheduled to take place at the end of November during [CloudNative Days Winter 2024](https://event.cloudnativedays.jp/cndw2024).
-->
&lt;h2 id="future-of-kubernetes-upstream-training">Kubernetes 上游培训的未来 &lt;/h2>
&lt;p>我们计划继续在日本举办 Kubernetes 上游培训，并期待欢迎更多的新贡献者。
我们的下一次培训定于 11 月底在
&lt;a href="https://event.cloudnativedays.jp/cndw2024">CloudNative Days Winter 2024&lt;/a> 期间举行。&lt;/p>
&lt;!--
Moreover, our goal is to expand these training programs not only in Japan but also around the world.
[Kubernetes celebrated its 10th anniversary](https://kubernetes.io/blog/2024/06/06/10-years-of-kubernetes/) this year, and for the community to become even more active, it's crucial for people across the globe to continue contributing.
While Upstream Training is already held in several regions, we aim to bring it to even more places.
We hope that as more people join Kubernetes community and contribute, our community will become even more vibrant!
-->
&lt;p>此外，我们的目标不仅是在日本推广这些培训项目，还希望推广到全球。
今年的 &lt;a href="https://kubernetes.io/zh-cn/blog/2024/06/06/10-years-of-kubernetes/">Kubernetes 十周年庆&lt;/a>，
以及为了使社区更加活跃，让全球各地的人们持续贡献至关重要。
虽然上游培训已经在多个地区举行，但我们希望将其带到更多地方。&lt;/p>
&lt;p>我们希望随着越来越多的人加入 Kubernetes 社区并做出贡献，我们的社区将变得更加生机勃勃！&lt;/p></description></item><item><title>公布 2024 年指导委员会选举结果</title><link>https://kubernetes.io/zh-cn/blog/2024/10/02/steering-committee-results-2024/</link><pubDate>Wed, 02 Oct 2024 15:10:00 -0500</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/10/02/steering-committee-results-2024/</guid><description>
&lt;!--
layout: blog
title: "Announcing the 2024 Steering Committee Election Results"
slug: steering-committee-results-2024
canonicalUrl: https://www.kubernetes.dev/blog/2024/10/02/steering-committee-results-2024
date: 2024-10-02T15:10:00-05:00
author: >
Bridget Kromhout
-->
&lt;!--
The [2024 Steering Committee Election](https://github.com/kubernetes/community/tree/master/elections/steering/2024) is now complete. The Kubernetes Steering Committee consists of 7 seats, 3 of which were up for election in 2024. Incoming committee members serve a term of 2 years, and all members are elected by the Kubernetes Community.
This community body is significant since it oversees the governance of the entire Kubernetes project. With that great power comes great responsibility. You can learn more about the steering committee’s role in their [charter](https://github.com/kubernetes/steering/blob/master/charter.md).
Thank you to everyone who voted in the election; your participation helps support the community’s continued health and success.
-->
&lt;p>&lt;a href="https://github.com/kubernetes/community/tree/master/elections/steering/2024">2024 年指导委员会选举&lt;/a>现已完成。
Kubernetes 指导委员会由 7 个席位组成，其中 3 个席位于 2024 年进行选举。
新任委员会成员的任期为 2 年，所有成员均由 Kubernetes 社区选举产生。&lt;/p>
&lt;p>这个社区机构非常重要，因为它负责监督整个 Kubernetes 项目的治理。
权力越大责任越大，你可以在其
&lt;a href="https://github.com/kubernetes/steering/blob/master/charter.md">章程&lt;/a>中了解有关指导委员会角色的更多信息。&lt;/p>
&lt;p>感谢所有在选举中投票的人；你们的参与有助于支持社区的持续健康和成功。&lt;/p>
&lt;!--
## Results
Congratulations to the elected committee members whose two year terms begin immediately (listed in alphabetical order by GitHub handle):
-->
&lt;h2 id="结果">结果&lt;/h2>
&lt;p>祝贺当选的委员会成员，其两年任期立即开始（按 GitHub 句柄按字母顺序列出）：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Antonio Ojea (&lt;a href="https://github.com/aojea">@aojea&lt;/a>), Google&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Benjamin Elder (&lt;a href="https://github.com/bentheelder">@BenTheElder&lt;/a>), Google&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Sascha Grunert (&lt;a href="https://github.com/saschagrunert">@saschagrunert&lt;/a>), Red Hat&lt;/strong>&lt;/li>
&lt;/ul>
&lt;!--
They join continuing members:
-->
&lt;p>他们将与以下连任成员一起工作：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Stephen Augustus (&lt;a href="https://github.com/justaugustus">@justaugustus&lt;/a>), Cisco&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Paco Xu 徐俊杰 (&lt;a href="https://github.com/pacoxu">@pacoxu&lt;/a>), DaoCloud&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Patrick Ohly (&lt;a href="https://github.com/pohly">@pohly&lt;/a>), Intel&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Maciej Szulik (&lt;a href="https://github.com/soltysh">@soltysh&lt;/a>), Defense Unicorns&lt;/strong>&lt;/li>
&lt;/ul>
&lt;!--
Benjamin Elder is a returning Steering Committee Member.
-->
&lt;p>Benjamin Elder 是一位回归的指导委员会成员。&lt;/p>
&lt;!--
## Big Thanks!
Thank you and congratulations on a successful election to this round’s election officers:
-->
&lt;h2 id="十分感谢">十分感谢！&lt;/h2>
&lt;p>感谢并祝贺本轮选举官员成功完成选举工作：&lt;/p>
&lt;ul>
&lt;li>Bridget Kromhout (&lt;a href="https://github.com/bridgetkromhout">@bridgetkromhout&lt;/a>)&lt;/li>
&lt;li>Christoph Blecker (&lt;a href="https://github.com/cblecker">@cblecker&lt;/a>)&lt;/li>
&lt;li>Priyanka Saggu (&lt;a href="https://github.com/Priyankasaggu11929">@Priyankasaggu11929&lt;/a>)&lt;/li>
&lt;/ul>
&lt;!--
Thanks to the Emeritus Steering Committee Members. Your service is appreciated by the community:
-->
&lt;p>感谢名誉指导委员会成员，你们的服务受到社区的赞赏：&lt;/p>
&lt;ul>
&lt;li>Bob Killen (&lt;a href="https://github.com/mrbobbytables">@mrbobbytables&lt;/a>)&lt;/li>
&lt;li>Nabarun Pal (&lt;a href="https://github.com/palnabarun">@palnabarun&lt;/a>)&lt;/li>
&lt;/ul>
&lt;!--
And thank you to all the candidates who came forward to run for election.
-->
&lt;p>感谢所有前来竞选的候选人。&lt;/p>
&lt;!--
## Get involved with the Steering Committee
This governing body, like all of Kubernetes, is open to all. You can follow along with Steering Committee [meeting notes](https://bit.ly/k8s-steering-wd) and weigh in by filing an issue or creating a PR against their [repo](https://github.com/kubernetes/steering). They have an open meeting on [the first Monday at 8am PT of every month](https://github.com/kubernetes/steering). They can also be contacted at their public mailing list steering@kubernetes.io.
-->
&lt;h2 id="参与指导委员会">参与指导委员会&lt;/h2>
&lt;p>这个管理机构与所有 Kubernetes 一样，向所有人开放。
你可以关注指导委员会&lt;a href="https://github.com/orgs/kubernetes/projects/40">会议记录&lt;/a>，
并通过提交 Issue 或针对其 &lt;a href="https://github.com/kubernetes/steering">repo&lt;/a> 创建 PR 来参与。
他们在&lt;a href="https://github.com/kubernetes/steering">太平洋时间每月第一个周一上午 8:00&lt;/a> 举行开放的会议。
你还可以通过其公共邮件列表 &lt;a href="mailto:steering@kubernetes.io">steering@kubernetes.io&lt;/a> 与他们联系。&lt;/p>
&lt;!--
You can see what the Steering Committee meetings are all about by watching past meetings on the [YouTube Playlist](https://www.youtube.com/playlist?list=PL69nYSiGNLP1yP1B_nd9-drjoxp0Q14qM).
If you want to meet some of the newly elected Steering Committee members, join us for the [Steering AMA](https://www.kubernetes.dev/events/2024/kcsna/schedule/#steering-ama) at the Kubernetes Contributor Summit North America 2024 in Salt Lake City.
-->
&lt;p>你可以通过在 &lt;a href="https://www.youtube.com/playlist?list=PL69nYSiGNLP1yP1B_nd9-drjoxp0Q14qM">YouTube 播放列表&lt;/a>上观看过去的会议来了解指导委员会会议的全部内容。&lt;/p>
&lt;p>如果你想认识一些新当选的指导委员会成员，
欢迎参加在盐湖城举行的 2024 年北美 Kubernetes 贡献者峰会上的
&lt;a href="https://www.kubernetes.dev/events/2024/kcsna/schedule/#steering-ama">Steering AMA&lt;/a>。&lt;/p>
&lt;hr>
&lt;!--
_This post was adapted from one written by the [Contributor Comms Subproject](https://github.com/kubernetes/community/tree/master/communication/contributor-comms). If you want to write stories about the Kubernetes community, learn more about us._
-->
&lt;p>&lt;strong>这篇文章是由&lt;a href="https://github.com/kubernetes/community/tree/master/communication/contributor-comms">贡献者通信子项目&lt;/a>撰写的。
如果你想撰写有关 Kubernetes 社区的故事，请了解有关我们的更多信息。&lt;/strong>&lt;/p></description></item><item><title>SIG Scheduling 访谈</title><link>https://kubernetes.io/zh-cn/blog/2024/09/24/sig-scheduling-spotlight-2024/</link><pubDate>Tue, 24 Sep 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/09/24/sig-scheduling-spotlight-2024/</guid><description>
&lt;!--
layout: blog
title: "Spotlight on SIG Scheduling"
slug: sig-scheduling-spotlight-2024
canonicalUrl: https://www.kubernetes.dev/blog/2024/09/24/sig-scheduling-spotlight-2024
date: 2024-09-24
author: "Arvind Parekh"
-->
&lt;!--
In this SIG Scheduling spotlight we talked with [Kensei Nakada](https://github.com/sanposhiho/), an
approver in SIG Scheduling.
## Introductions
**Arvind:** **Hello, thank you for the opportunity to learn more about SIG Scheduling! Would you
like to introduce yourself and tell us a bit about your role, and how you got involved with
Kubernetes?**
-->
&lt;p>在本次 SIG Scheduling 的访谈中，我们与 &lt;a href="https://github.com/sanposhiho/">Kensei Nakada&lt;/a>
进行了交流，他是 SIG Scheduling 的一名 Approver。&lt;/p>
&lt;h2 id="介绍">介绍&lt;/h2>
&lt;p>&lt;strong>Arvind:&lt;/strong> &lt;strong>你好，感谢你让我们有机会了解 SIG Scheduling！
你能介绍一下自己，告诉我们你的角色以及你是如何参与 Kubernetes 的吗？&lt;/strong>&lt;/p>
&lt;!--
**Kensei**: Hi, thanks for the opportunity! I’m Kensei Nakada
([@sanposhiho](https://github.com/sanposhiho/)), a software engineer at
[Tetrate.io](https://tetrate.io/). I have been contributing to Kubernetes in my free time for more
than 3 years, and now I’m an approver of SIG Scheduling in Kubernetes. Also, I’m a founder/owner of
two SIG subprojects,
[kube-scheduler-simulator](https://github.com/kubernetes-sigs/kube-scheduler-simulator) and
[kube-scheduler-wasm-extension](https://github.com/kubernetes-sigs/kube-scheduler-wasm-extension).
-->
&lt;p>&lt;strong>Kensei&lt;/strong>: 嗨，感谢你给我这个机会！我是 Kensei Nakada
(&lt;a href="https://github.com/sanposhiho/">@sanposhiho&lt;/a>)，是来自 &lt;a href="https://tetrate.io/">Tetrate.io&lt;/a> 的一名软件工程师。
我在业余时间为 Kubernetes 贡献了超过 3 年的时间，现在我是 Kubernetes 中 SIG Scheduling 的一名 Approver。
同时，我还是两个 SIG 子项目的创始人/负责人：
&lt;a href="https://github.com/kubernetes-sigs/kube-scheduler-simulator">kube-scheduler-simulator&lt;/a> 和
&lt;a href="https://github.com/kubernetes-sigs/kube-scheduler-wasm-extension">kube-scheduler-wasm-extension&lt;/a>。&lt;/p>
&lt;!--
## About SIG Scheduling
**AP: That's awesome! You've been involved with the project since a long time. Can you provide a
brief overview of SIG Scheduling and explain its role within the Kubernetes ecosystem?**
**KN**: As the name implies, our responsibility is to enhance scheduling within
Kubernetes. Specifically, we develop the components that determine which Node is the best place for
each Pod. In Kubernetes, our main focus is on maintaining the
[kube-scheduler](/docs/concepts/scheduling-eviction/kube-scheduler/), along
with other scheduling-related components as part of our SIG subprojects.
-->
&lt;h2 id="关于-sig-scheduling">关于 SIG Scheduling&lt;/h2>
&lt;p>&lt;strong>AP: 太棒了！你参与这个项目已经很久了。你能简要概述一下 SIG Scheduling，并说明它在 Kubernetes 生态系统中的角色吗？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>KN&lt;/strong>: 正如名字所示，我们的责任是增强 Kubernetes 中的调度特性。
具体来说，我们开发了一些组件，将每个 Pod 调度到最合适的 Node。
在 Kubernetes 中，我们的主要关注点是维护
&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/kube-scheduler/">kube-scheduler&lt;/a>，
以及其他调度相关的组件，这些组件是 SIG Scheduling 的子项目。&lt;/p>
&lt;!--
**AP: I see, got it! That makes me curious--what recent innovations or developments has SIG
Scheduling introduced to Kubernetes scheduling?**
**KN**: From a feature perspective, there have been
[several enhancements](/blog/2023/04/17/fine-grained-pod-topology-spread-features-beta/)
to `PodTopologySpread` recently. `PodTopologySpread` is a relatively new feature in the scheduler,
and we are still in the process of gathering feedback and making improvements.
-->
&lt;p>&lt;strong>AP: 明白了！我有点好奇，SIG Scheduling 最近为 Kubernetes 调度引入了哪些创新或发展？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>KN&lt;/strong>: 从特性的角度来看，最近对 &lt;code>PodTopologySpread&lt;/code>
进行了&lt;a href="https://kubernetes.io/zh-cn/blog/2023/04/17/fine-grained-pod-topology-spread-features-beta/">几项增强&lt;/a>。
&lt;code>PodTopologySpread&lt;/code> 是调度器中一个相对较新的特性，我们仍在收集反馈并进行改进。&lt;/p>
&lt;!--
Most recently, we have been focusing on a new internal enhancement called
[QueueingHint](https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/4247-queueinghint/README.md)
which aims to enhance scheduling throughput. Throughput is one of our crucial metrics in
scheduling. Traditionally, we have primarily focused on optimizing the latency of each scheduling
cycle. QueueingHint takes a different approach, optimizing when to retry scheduling, thereby
reducing the likelihood of wasting scheduling cycles.
-->
&lt;p>最近，我们专注于一个内部增强特性，称为
&lt;a href="https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/4247-queueinghint/README.md">QueueingHint&lt;/a>，
这个特性旨在提高调度的吞吐量。吞吐量是我们调度中的关键指标之一。传统上，我们主要关注优化每个调度周期的延迟。
而 QueueingHint 采取了一种不同的方法，它可以优化何时重试调度，从而减少浪费调度周期的可能性。&lt;/p>
&lt;!--
**A: That sounds interesting! Are there any other interesting topics or projects you are currently
working on within SIG Scheduling?**
**KN**: I’m leading the development of `QueueingHint` which I just shared. Given that it’s a big new
challenge for us, we’ve been facing many unexpected challenges, especially around the scalability,
and we’re trying to solve each of them to eventually enable it by default.
-->
&lt;p>&lt;strong>A: 听起来很有趣！你目前在 SIG Scheduling 中还有其他有趣的主题或项目吗？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>KN&lt;/strong>: 我正在牵头刚刚提到的 &lt;code>QueueingHint&lt;/code> 的开发。考虑到这是我们面临的一项重大新挑战，
我们遇到了许多意想不到的问题，特别是在可扩展性方面，我们正在努力解决每一个问题，使这项特性最终能够默认启用。&lt;/p>
&lt;!--
And also, I believe
[kube-scheduler-wasm-extension](https://github.com/kubernetes-sigs/kube-scheduler-wasm-extension)
(a SIG subproject) that I started last year would be interesting to many people. Kubernetes has
various extensions from many components. Traditionally, extensions are provided via webhooks
([extender](https://github.com/kubernetes/design-proposals-archive/blob/main/scheduling/scheduler_extender.md)
in the scheduler) or Go SDK ([Scheduling Framework](/docs/concepts/scheduling-eviction/scheduling-framework/)
in the scheduler). However, these come with drawbacks - performance issues with webhooks and the need to
rebuild and replace schedulers with Go SDK, posing difficulties for those seeking to extend the
scheduler but lacking familiarity with it. The project is trying to introduce a new solution to
this general challenge - a [WebAssembly](https://webassembly.org/) based extension. Wasm allows
users to build plugins easily, without worrying about recompiling or replacing their scheduler, and
sidestepping performance concerns.
-->
&lt;p>此外，我认为我去年启动的
&lt;a href="https://github.com/kubernetes-sigs/kube-scheduler-wasm-extension">kube-scheduler-wasm-extension&lt;/a>（SIG 子项目）
对许多人来说也会很有趣。Kubernetes 有各种扩展来自许多组件。传统上，扩展通过 Webhook
（调度器中的 &lt;a href="https://github.com/kubernetes/design-proposals-archive/blob/main/scheduling/scheduler_extender.md">extender&lt;/a>）或
Go SDK（调度器中的&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/scheduling-framework/">调度框架&lt;/a>）提供。
然而，这些方法存在缺点，首先是 Webhook 的性能问题以及需要重建和替换调度器的 Go SDK，这就给那些希望扩展调度器但对其不熟悉的人带来了困难。
此项目尝试引入一种新的解决方案来应对这一普遍挑战，即基于 &lt;a href="https://webassembly.org/">WebAssembly&lt;/a> 的扩展。
Wasm 允许用户轻松构建插件，而无需担心重新编译或替换调度器，还能规避性能问题。&lt;/p>
&lt;!--
Through this project, SIG Scheduling has been learning valuable insights about WebAssembly's
interaction with large Kubernetes objects. And I believe the experience that we’re gaining should be
useful broadly within the community, beyond SIG Scheduling.
**A: Definitely! Now, there are 8 subprojects inside SIG Scheduling. Would you like to
talk about them? Are there some interesting contributions by those teams you want to highlight?**
**KN**: Let me pick up three subprojects: Kueue, KWOK and descheduler.
-->
&lt;p>通过这个项目，SIG Scheduling 正在积累 WebAssembly 与大型 Kubernetes 对象交互的宝贵洞察。
我相信我们所获得的经验应该对整个社区都很有用，而不仅限于 SIG Scheduling 的范围。&lt;/p>
&lt;p>&lt;strong>A: 当然！目前 SIG Scheduling 有 8 个子项目。你想谈谈它们吗？有没有一些你想强调的有趣贡献？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>KN&lt;/strong>: 让我挑选三个子项目：Kueue、KWOK 和 Descheduler。&lt;/p>
&lt;!--
[Kueue](https://github.com/kubernetes-sigs/kueue)
: Recently, many people have been trying to manage batch workloads with Kubernetes, and in 2022,
Kubernetes community founded
[WG-Batch](https://github.com/kubernetes/community/blob/master/wg-batch/README.md) for better
support for such batch workloads in Kubernetes. [Kueue](https://github.com/kubernetes-sigs/kueue)
is a project that takes a crucial role for it. It’s a job queueing controller, deciding when a job
should wait, when a job should be admitted to start, and when a job should be preempted. Kueue aims
to be installed on a vanilla Kubernetes cluster while cooperating with existing matured controllers
(scheduler, cluster-autoscaler, kube-controller-manager, etc).
-->
&lt;dl>
&lt;dt>&lt;a href="https://github.com/kubernetes-sigs/kueue">Kueue&lt;/a>:&lt;/dt>
&lt;dd>最近，许多人尝试使用 Kubernetes 管理批处理工作负载，2022 年，Kubernetes 社区成立了
&lt;a href="https://github.com/kubernetes/community/blob/master/wg-batch/README.md">WG-Batch&lt;/a>，
以更好地支持 Kubernetes 中的此类批处理工作负载。
&lt;a href="https://github.com/kubernetes-sigs/kueue">Kueue&lt;/a> 是一个在其中扮演关键角色的项目。
它是一个作业队列控制器，决定何时一个作业应该等待，何时一个作业应该被准许启动，以及何时一个作业应该被抢占。
Kueue 旨在安装在一个普通的 Kubernetes 集群上，
同时与现有的成熟控制器（调度器、cluster-autoscaler、kube-controller-manager 等）协作。&lt;/dd>
&lt;/dl>
&lt;!--
[KWOK](https://github.com/kubernetes-sigs/kwok)
: KWOK is a component in which you can create a cluster of thousands of Nodes in seconds. It’s
mostly useful for simulation/testing as a lightweight cluster, and actually another SIG sub
project [kube-scheduler-simulator](https://github.com/kubernetes-sigs/kube-scheduler-simulator)
uses KWOK background.
[descheduler](https://github.com/kubernetes-sigs/descheduler)
: Descheduler is a component recreating pods that are running on undesired Nodes. In Kubernetes,
scheduling constraints (`PodAffinity`, `NodeAffinity`, `PodTopologySpread`, etc) are honored only at
Pod schedule, but it’s not guaranteed that the contrtaints are kept being satisfied afterwards.
Descheduler evicts Pods violating their scheduling constraints (or other undesired conditions) so
that they’re recreated and rescheduled.
-->
&lt;dl>
&lt;dt>&lt;a href="https://github.com/kubernetes-sigs/kwok">KWOK&lt;/a>&lt;/dt>
&lt;dd>KWOK 这个组件可以在几秒钟内创建一个包含数千个节点的集群。它主要用于模拟/测试轻量级集群，实际上另一个 SIG 子项目
&lt;a href="https://github.com/kubernetes-sigs/kube-scheduler-simulator">kube-scheduler-simulator&lt;/a> 就在后端使用了 KWOK。&lt;/dd>
&lt;dt>&lt;a href="https://github.com/kubernetes-sigs/descheduler">Descheduler&lt;/a>&lt;/dt>
&lt;dd>Descheduler 这个组件可以将运行在不理想的节点上的 Pod 重新创建。
在 Kubernetes 中，调度约束（&lt;code>PodAffinity&lt;/code>、&lt;code>NodeAffinity&lt;/code>、&lt;code>PodTopologySpread&lt;/code> 等）仅在 Pod 调度时被考虑，
但不能保证这些约束在之后仍然被满足。Descheduler 会驱逐违反其调度约束（或其他不符合预期状况）的 Pod，
以便这些 Pod 被重新创建和重新调度。&lt;/dd>
&lt;/dl>
&lt;!--
[Descheduling Framework](https://github.com/kubernetes-sigs/descheduler/blob/master/keps/753-descheduling-framework/README.md)
: One very interesting on-going project, similar to
[Scheduling Framework](/docs/concepts/scheduling-eviction/scheduling-framework/) in the
scheduler, aiming to make descheduling logic extensible and allow maintainers to focus on building
a core engine of descheduler.
-->
&lt;dl>
&lt;dt>&lt;a href="https://github.com/kubernetes-sigs/descheduler/blob/master/keps/753-descheduling-framework/README.md">Descheduling Framework&lt;/a>:&lt;/dt>
&lt;dd>一个非常有趣的正在进行的项目，类似于调度器中的&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/scheduling-framework/">调度框架&lt;/a>，
旨在使去调度逻辑可扩展，并允许维护者们专注于构建 Descheduler 的核心引擎。&lt;/dd>
&lt;/dl>
&lt;!--
**AP: Thank you for letting us know! And I have to ask, what are some of your favorite things about
this SIG?**
**KN**: What I really like about this SIG is how actively engaged everyone is. We come from various
companies and industries, bringing diverse perspectives to the table. Instead of these differences
causing division, they actually generate a wealth of opinions. Each view is respected, and this
makes our discussions both rich and productive.
I really appreciate this collaborative atmosphere, and I believe it has been key to continuously
improving our components over the years.
-->
&lt;p>&lt;strong>AP: 感谢你告诉我们这些！我想问一下，你最喜欢这个 SIG 的哪些方面？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>KN&lt;/strong>: 我真正喜欢这个 SIG 的地方在于每个人都积极参与。
我们来自不同的公司和行业，带来了多样的视角。
这些差异并没有造成分歧，实际上产生了丰富的观点。
每种观点都会受到尊重，这使我们的讨论既丰富又富有成效。&lt;/p>
&lt;p>我非常欣赏这种协作氛围，我相信这对我们多年来不断改进组件至关重要。&lt;/p>
&lt;!--
## Contributing to SIG Scheduling
**AP: Kubernetes is a community-driven project. Any recommendations for new contributors or
beginners looking to get involved and contribute to SIG scheduling? Where should they start?**
**KN**: Let me start with a general recommendation for contributing to any SIG: a common approach is to look for
[good-first-issue](https://github.com/kubernetes/kubernetes/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22).
However, you'll soon realize that many people worldwide are trying to contribute to the Kubernetes
repository.
-->
&lt;h2 id="给-sig-scheduling-做贡献">给 SIG Scheduling 做贡献&lt;/h2>
&lt;p>&lt;strong>AP: Kubernetes 是一个社区驱动的项目。你对新贡献者或希望参与并为
SIG Scheduling 做出贡献的初学者有什么建议？他们应该从哪里开始？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>KN&lt;/strong>: 让我先给出一个关于为任何 SIG 贡献的通用建议：一种常见的方法是寻找
&lt;a href="https://github.com/kubernetes/kubernetes/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22">good-first-issue&lt;/a>。
然而，你很快就会意识到，世界各地有很多人正在尝试为 Kubernetes 仓库做贡献。&lt;/p>
&lt;!--
I suggest starting by examining the implementation of a component that interests you. If you have
any questions about it, ask in the corresponding Slack channel (e.g., #sig-scheduling for the
scheduler, #sig-node for kubelet, etc). Once you have a rough understanding of the implementation,
look at issues within the SIG (e.g.,
[sig-scheduling](https://github.com/kubernetes/kubernetes/issues?q=is%3Aopen+is%3Aissue+label%3Asig%2Fscheduling)),
where you'll find more unassigned issues compared to good-first-issue ones. You may also want to
filter issues with the
[kind/cleanup](https://github.com/kubernetes/kubernetes/issues?q=is%3Aopen+is%3Aissue++label%3Akind%2Fcleanup+)
label, which often indicates lower-priority tasks and can be starting points.
-->
&lt;p>我建议先查看你感兴趣的某个组件的实现。如果你对该组件有任何疑问，可以在相应的
Slack 频道中提问（例如，调度器的 #sig-scheduling，kubelet 的 #sig-node 等）。
一旦你对实现有了大致了解，就可以查看 SIG 中的 Issue
（例如，&lt;a href="https://github.com/kubernetes/kubernetes/issues?q=is%3Aopen+is%3Aissue+label%3Asig%2Fscheduling">sig-scheduling&lt;/a>），
相比 good-first-issue，在这里你会发现更多未分配的 Issue。你可能还想过滤带有
&lt;a href="https://github.com/kubernetes/kubernetes/issues?q=is%3Aopen+is%3Aissue++label%3Akind%2Fcleanup+">kind/cleanup&lt;/a>
标签的 Issue，这通常表示较低优先级的任务，可以作为起点。&lt;/p>
&lt;!--
Specifically for SIG Scheduling, you should first understand the
[Scheduling Framework](/docs/concepts/scheduling-eviction/scheduling-framework/), which is
the fundamental architecture of kube-scheduler. Most of the implementation is found in
[pkg/scheduler](https://github.com/kubernetes/kubernetes/tree/master/pkg/scheduler).
I suggest starting with
[ScheduleOne](https://github.com/kubernetes/kubernetes/blob/0590bb1ac495ae8af2a573f879408e48800da2c5/pkg/scheduler/schedule_one.go#L66)
function and then exploring deeper from there.
Additionally, apart from the main kubernetes/kubernetes repository, consider looking into
sub-projects. These typically have fewer maintainers and offer more opportunities to make a
significant impact. Despite being called "sub" projects, many have a large number of users and a
considerable impact on the community.
-->
&lt;p>具体对于 SIG Scheduling 而言，你应该先了解&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/scheduling-framework/">调度框架&lt;/a>，
这是 kube-scheduler 的基本架构。大多数实现都可以在
&lt;a href="https://github.com/kubernetes/kubernetes/tree/master/pkg/scheduler">pkg/scheduler&lt;/a>中找到。我建议从
&lt;a href="https://github.com/kubernetes/kubernetes/blob/0590bb1ac495ae8af2a573f879408e48800da2c5/pkg/scheduler/schedule_one.go#L66">ScheduleOne&lt;/a>
函数开始，然后再深入探索。&lt;/p>
&lt;p>此外，除了 kubernetes/kubernetes 主仓库外，还可以考虑查看一些子项目。
这些子项目的维护者通常比较少，你有更多的机会来对其产生重大影响。尽管被称为“子”项目，
但许多项目实际上有大量用户，并对社区产生了相当大的影响。&lt;/p>
&lt;!--
And last but not least, remember contributing to the community isn’t just about code. While I
talked a lot about the implementation contribution, there are many ways to contribute, and each one
is valuable. One comment to an issue, one feedback to an existing feature, one review comment in PR,
one clarification on the documentation; every small contribution helps drive the Kubernetes
ecosystem forward.
**AP: Those are some pretty useful tips! And if I may ask, how do you assist new contributors in
getting started, and what skills are contributors likely to learn by participating in SIG Scheduling?**
-->
&lt;p>最后但同样重要的是，记住为社区做贡献不仅仅是编写代码。
虽然我谈到了很多关于实现的贡献，但还有许多其他方式可以做贡献，每一种都很有价值。
对某个 Issue 的一条评论，对现有特性的一个反馈，对 PR 的一个审查建议，对文档的一个说明阐述；
每一个小贡献都有助于推动 Kubernetes 生态系统向前发展。&lt;/p>
&lt;p>&lt;strong>AP: 这些建议非常有用！冒昧问一下，你是如何帮助新贡献者入门的，参与 SIG Scheduling 的贡献者可能会学习到哪些技能？&lt;/strong>&lt;/p>
&lt;!--
**KN**: Our maintainers are available to answer your questions in the #sig-scheduling Slack
channel. By participating, you'll gain a deeper understanding of Kubernetes scheduling and have the
opportunity to collaborate and network with maintainers from diverse backgrounds. You'll learn not
just how to write code, but also how to maintain a large project, design and discuss new features,
address bugs, and much more.
## Future Directions
**AP: What are some Kubernetes-specific challenges in terms of scheduling? Are there any particular
pain points?**
-->
&lt;p>&lt;strong>KN&lt;/strong>: 我们的维护者在 #sig-scheduling Slack 频道中随时可以回答你的问题。
多多参与，你将深入了解 Kubernetes 的调度，并有机会与来自不同背景的维护者合作和建立联系。
你将学习到的不仅仅是如何编写代码，还有如何维护大型项目、设计和讨论新特性、解决 Bug 等等。&lt;/p>
&lt;h2 id="未来方向">未来方向&lt;/h2>
&lt;p>&lt;strong>AP: 在调度方面，Kubernetes 特有的挑战有哪些？有没有特别的痛点？&lt;/strong>&lt;/p>
&lt;!--
**KN**: Scheduling in Kubernetes can be quite challenging because of the diverse needs of different
organizations with different business requirements. Supporting all possible use cases in
kube-scheduler is impossible. Therefore, extensibility is a key focus for us. A few years ago, we
rearchitected kube-scheduler with [Scheduling Framework](/docs/concepts/scheduling-eviction/scheduling-framework/),
which offers flexible extensibility for users to implement various scheduling needs through plugins. This
allows maintainers to focus on the core scheduling features and the framework runtime.
-->
&lt;p>&lt;strong>KN&lt;/strong>: 在 Kubernetes 中进行调度可能相当具有挑战性，因为不同组织有不同的业务要求。
在 kube-scheduler 中支持所有可能的使用场景是不可能的。因此，可扩展性是我们关注的核心焦点。
几年前，我们使用&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/scheduling-framework/">调度框架&lt;/a>为
kube-scheduler 重新设计了架构，为用户通过插件实现各种调度需求提供了灵活的可扩展性。
这使得维护者们能够专注于核心调度特性和框架运行时。&lt;/p>
&lt;!--
Another major issue is maintaining sufficient scheduling throughput. Typically, a Kubernetes cluster
has only one kube-scheduler, so its throughput directly affects the overall scheduling scalability
and, consequently, the cluster's scalability. Although we have an internal performance test
([scheduler_perf](https://github.com/kubernetes/kubernetes/tree/master/test/integration/scheduler_perf)),
unfortunately, we sometimes overlook performance degradation in less common scenarios. It’s
difficult as even small changes, which look irrelevant to performance, can lead to degradation.
-->
&lt;p>另一个主要问题是保持足够的调度吞吐量。通常，一个 Kubernetes 集群只有一个 kube-scheduler，
因此其吞吐量直接影响整体调度的可扩展性，从而影响集群的可扩展性。尽管我们有一个内部性能测试
(&lt;a href="https://github.com/kubernetes/kubernetes/tree/master/test/integration/scheduler_perf">scheduler_perf&lt;/a>)，
但不巧的是，我们有时会忽视在不常见场景下的性能下降。即使是与性能无关的小改动也有难度，可能导致性能下降。&lt;/p>
&lt;!--
**AP: What are some upcoming goals or initiatives for SIG Scheduling? How do you envision the SIG evolving in the future?**
**KN**: Our primary goal is always to build and maintain _extensible_ and _stable_ scheduling
runtime, and I bet this goal will remain unchanged forever.
As already mentioned, extensibility is key to solving the challenge of the diverse needs of
scheduling. Rather than trying to support every different use case directly in kube-scheduler, we
will continue to focus on enhancing extensibility so that it can accommodate various use
cases. [kube-scheduler-wasm-extension](https://github.com/kubernetes-sigs/kube-scheduler-wasm-extension)
that I mentioned is also part of this initiative.
-->
&lt;p>&lt;strong>AP: 接下来 SIG Scheduling 有哪些即将实现的目标或计划？你如何看待 SIG 的未来发展？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>KN&lt;/strong>: 我们的主要目标始终是构建和维护&lt;strong>可扩展的&lt;/strong>和&lt;strong>稳定的&lt;/strong>调度运行时，我敢打赌这个目标将永远不会改变。&lt;/p>
&lt;p>正如之前所提到的，可扩展性是解决调度多样化需求挑战的关键。我们不会尝试直接在 kube-scheduler 中支持每种不同的使用场景，
而是将继续专注于增强可扩展性，以便能够适应各种用例。我提到的
&lt;a href="https://github.com/kubernetes-sigs/kube-scheduler-wasm-extension">kube-scheduler-wasm-extension&lt;/a>
也是这一计划的一部分。&lt;/p>
&lt;!--
Regarding stability, introducing new optimizations like QueueHint is one of our
strategies. Additionally, maintaining throughput is also a crucial goal towards the future. We’re
planning to enhance our throughput monitoring
([ref](https://github.com/kubernetes/kubernetes/issues/124774)), so that we can notice degradation
as much as possible on our own before releasing. But, realistically, we can't cover every possible
scenario. We highly appreciate any attention the community can give to scheduling throughput and
encourage feedback and alerts regarding performance issues!
-->
&lt;p>关于稳定性，引入 QueueHint 这类新的优化是我们的一项策略。
此外，保持吞吐量也是面向未来的关键目标。我们计划增强我们的吞吐量监控
(&lt;a href="https://github.com/kubernetes/kubernetes/issues/124774">参考&lt;/a>)，
以便在发布之前尽可能多地发现性能下降问题。但实际上，我们无法覆盖每个可能的场景。
我们非常感谢社区对调度吞吐量的关注，鼓励大家提出反馈，就性能问题提出警示！&lt;/p>
&lt;!--
## Closing Remarks
**AP: Finally, what message would you like to convey to those who are interested in learning more
about SIG Scheduling?**
**KN**: Scheduling is one of the most complicated areas in Kubernetes, and you may find it difficult
at first. But, as I shared earlier, you can find many opportunities for contributions, and many
maintainers are willing to help you understand things. We know your unique perspective and skills
are what makes our open source so powerful 😊
-->
&lt;h2 id="结束语">结束语&lt;/h2>
&lt;p>&lt;strong>AP: 最后，你想对那些有兴趣了解 SIG Scheduling 的人说些什么？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>KN&lt;/strong>: 调度是 Kubernetes 中最复杂的领域之一，你可能一开始会觉得很困难。但正如我之前分享的，
你可以找到许多贡献的机会，许多维护者愿意帮助你理解各事项。
我们知道你独特的视角和技能是我们的开源项目能够如此强大的源泉 😊&lt;/p>
&lt;!--
Feel free to reach out to us in Slack
([#sig-scheduling](https://kubernetes.slack.com/archives/C09TP78DV)) or
[meetings](https://github.com/kubernetes/community/blob/master/sig-scheduling/README.md#meetings).
I hope this article interests everyone and we can see new contributors!
**AP: Thank you so much for taking the time to do this! I'm confident that many will find this
information invaluable for understanding more about SIG Scheduling and for contributing to the SIG.**
-->
&lt;p>随时可以通过 Slack (&lt;a href="https://kubernetes.slack.com/archives/C09TP78DV">#sig-scheduling&lt;/a>)
或&lt;a href="https://github.com/kubernetes/community/blob/master/sig-scheduling/README.md#meetings">会议&lt;/a>联系我们。
我希望这篇文章能引起大家的兴趣，希望能吸引到新的贡献者！&lt;/p>
&lt;p>&lt;strong>AP: 非常感谢你抽出时间进行这次访谈！我相信很多人会发现这些信息对理解 SIG Scheduling 和参与 SIG 的贡献非常有价值。&lt;/strong>&lt;/p></description></item><item><title>Kubernetes v1.31：kubeadm v1beta4</title><link>https://kubernetes.io/zh-cn/blog/2024/08/23/kubernetes-1-31-kubeadm-v1beta4/</link><pubDate>Fri, 23 Aug 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/08/23/kubernetes-1-31-kubeadm-v1beta4/</guid><description>
&lt;!--
layout: blog
title: 'Kubernetes v1.31: kubeadm v1beta4'
date: 2024-08-23
slug: kubernetes-1-31-kubeadm-v1beta4
author: >
Paco Xu (DaoCloud)
-->
&lt;!--
As part of the Kubernetes v1.31 release, [`kubeadm`](/docs/reference/setup-tools/kubeadm/) is
adopting a new ([v1beta4](/docs/reference/config-api/kubeadm-config.v1beta4/)) version of
its configuration file format. Configuration in the previous v1beta3 format is now formally
deprecated, which means it's supported but you should migrate to v1beta4 and stop using
the deprecated format.
Support for v1beta3 configuration will be removed after a minimum of 3 Kubernetes minor releases.
-->
&lt;p>作为 Kubernetes v1.31 发布的一部分，&lt;a href="https://kubernetes.io/zh-cn/docs/reference/setup-tools/kubeadm/">&lt;code>kubeadm&lt;/code>&lt;/a>
采用了全新版本（&lt;a href="https://kubernetes.io/zh-cn/docs/reference/config-api/kubeadm-config.v1beta4/">v1beta4&lt;/a>）的配置文件格式。
之前 v1beta3 格式的配置现已正式弃用，这意味着尽管之前的格式仍然受支持，但你应迁移到 v1beta4 并停止使用已弃用的格式。
对 v1beta3 配置的支持将在至少 3 次 Kubernetes 次要版本发布后被移除。&lt;/p>
&lt;!--
In this article, I'll walk you through key changes;
I'll explain about the kubeadm v1beta4 configuration format,
and how to migrate from v1beta3 to v1beta4.
You can read the reference for the v1beta4 configuration format:
[kubeadm Configuration (v1beta4)](/docs/reference/config-api/kubeadm-config.v1beta4/).
-->
&lt;p>在本文中，我将介绍关键的变更；我将解释 kubeadm v1beta4 配置格式，以及如何从 v1beta3 迁移到 v1beta4。&lt;/p>
&lt;p>你可以参阅 v1beta4 配置格式的参考文档：
&lt;a href="https://kubernetes.io/zh-cn/docs/reference/config-api/kubeadm-config.v1beta4/">kubeadm 配置 (v1beta4)&lt;/a>。&lt;/p>
&lt;!--
### A list of changes since v1beta3
This version improves on the [v1beta3](/docs/reference/config-api/kubeadm-config.v1beta3/)
format by fixing some minor issues and adding a few new fields.
To put it simply,
-->
&lt;h3 id="自-v1beta3-以来的变更列表">自 v1beta3 以来的变更列表&lt;/h3>
&lt;p>此版本通过修复一些小问题并添加一些新字段来改进
&lt;a href="https://kubernetes.io/zh-cn/docs/reference/config-api/kubeadm-config.v1beta3/">v1beta3&lt;/a> 格式。&lt;/p>
&lt;p>简单而言，&lt;/p>
&lt;!--
- Two new configuration elements: ResetConfiguration and UpgradeConfiguration
- For InitConfiguration and JoinConfiguration, `dryRun` mode and `nodeRegistration.imagePullSerial` are supported
- For ClusterConfiguration, there are new fields including `certificateValidityPeriod`,
`caCertificateValidityPeriod`, `encryptionAlgorithm`, `dns.disabled` and `proxy.disabled`.
- Support `extraEnvs` for all control plan components
- `extraArgs` changed from a map to structured extra arguments for duplicates
- Add a `timeouts` structure for init, join, upgrade and reset.
-->
&lt;ul>
&lt;li>增加了两个新的配置元素：ResetConfiguration 和 UpgradeConfiguration&lt;/li>
&lt;li>对于 InitConfiguration 和 JoinConfiguration，支持 &lt;code>dryRun&lt;/code> 模式和 &lt;code>nodeRegistration.imagePullSerial&lt;/code>&lt;/li>
&lt;li>对于 ClusterConfiguration，新增字段包括 &lt;code>certificateValidityPeriod&lt;/code>、&lt;code>caCertificateValidityPeriod&lt;/code>、
&lt;code>encryptionAlgorithm&lt;/code>、&lt;code>dns.disabled&lt;/code> 和 &lt;code>proxy.disabled&lt;/code>&lt;/li>
&lt;li>所有控制平面组件支持 &lt;code>extraEnvs&lt;/code>&lt;/li>
&lt;li>&lt;code>extraArgs&lt;/code> 从映射变更为支持重复的结构化额外参数&lt;/li>
&lt;li>为 init、join、upgrade 和 reset 添加了 &lt;code>timeouts&lt;/code> 结构&lt;/li>
&lt;/ul>
&lt;!--
For details, you can see the [official document](/docs/reference/config-api/kubeadm-config.v1beta4/) below:
- Support custom environment variables in control plane components under `ClusterConfiguration`.
Use `apiServer.extraEnvs`, `controllerManager.extraEnvs`, `scheduler.extraEnvs`, `etcd.local.extraEnvs`.
- The ResetConfiguration API type is now supported in v1beta4. Users are able to reset a node by passing
a `--config` file to `kubeadm reset`.
- `dryRun` mode is now configurable in InitConfiguration and JoinConfiguration.
-->
&lt;p>有关细节请参阅以下&lt;a href="https://kubernetes.io/zh-cn/docs/reference/config-api/kubeadm-config.v1beta4/">官方文档&lt;/a>：&lt;/p>
&lt;ul>
&lt;li>在 &lt;code>ClusterConfiguration&lt;/code> 下支持控制平面组件的自定义环境变量。
可以使用 &lt;code>apiServer.extraEnvs&lt;/code>、&lt;code>controllerManager.extraEnvs&lt;/code>、&lt;code>scheduler.extraEnvs&lt;/code>、&lt;code>etcd.local.extraEnvs&lt;/code>。&lt;/li>
&lt;li>ResetConfiguration API 类型现在在 v1beta4 中得到支持。用户可以通过将 &lt;code>--config&lt;/code> 文件传递给 &lt;code>kubeadm reset&lt;/code> 来重置节点。&lt;/li>
&lt;li>&lt;code>dryRun&lt;/code> 模式现在在 InitConfiguration 和 JoinConfiguration 中可配置。&lt;/li>
&lt;/ul>
&lt;!--
- Replace the existing string/string extra argument maps with structured extra arguments that support duplicates.
The change applies to `ClusterConfiguration` - `apiServer.extraArgs`, `controllerManager.extraArgs`,
`scheduler.extraArgs`, `etcd.local.extraArgs`. Also to `nodeRegistrationOptions.kubeletExtraArgs`.
- Added `ClusterConfiguration.encryptionAlgorithm` that can be used to set the asymmetric encryption
algorithm used for this cluster's keys and certificates. Can be one of "RSA-2048" (default), "RSA-3072",
"RSA-4096" or "ECDSA-P256".
- Added `ClusterConfiguration.dns.disabled` and `ClusterConfiguration.proxy.disabled` that can be used
to disable the CoreDNS and kube-proxy addons during cluster initialization.
Skipping the related addons phases, during cluster creation will set the same fields to `true`.
-->
&lt;ul>
&lt;li>用支持重复的结构化额外参数替换现有的 string/string 额外参数映射。
此变更适用于 &lt;code>ClusterConfiguration&lt;/code> - &lt;code>apiServer.extraArgs&lt;/code>、&lt;code>controllerManager.extraArgs&lt;/code>、
&lt;code>scheduler.extraArgs&lt;/code>、&lt;code>etcd.local.extraArgs&lt;/code>。也适用于 &lt;code>nodeRegistrationOptions.kubeletExtraArgs&lt;/code>。&lt;/li>
&lt;li>添加了 &lt;code>ClusterConfiguration.encryptionAlgorithm&lt;/code>，可用于设置此集群的密钥和证书所使用的非对称加密算法。
可以是 &amp;quot;RSA-2048&amp;quot;（默认）、&amp;quot;RSA-3072&amp;quot;、&amp;quot;RSA-4096&amp;quot; 或 &amp;quot;ECDSA-P256&amp;quot; 之一。&lt;/li>
&lt;li>添加了 &lt;code>ClusterConfiguration.dns.disabled&lt;/code> 和 &lt;code>ClusterConfiguration.proxy.disabled&lt;/code>，
可用于在集群初始化期间禁用 CoreDNS 和 kube-proxy 插件。
在集群创建期间跳过相关插件阶段将把相同的字段设置为 &lt;code>true&lt;/code>。&lt;/li>
&lt;/ul>
&lt;!--
- Added the `nodeRegistration.imagePullSerial` field in `InitConfiguration` and `JoinConfiguration`,
which can be used to control if kubeadm pulls images serially or in parallel.
- The UpgradeConfiguration kubeadm API is now supported in v1beta4 when passing `--config` to
`kubeadm upgrade` subcommands.
For upgrade subcommands, the usage of component configuration for kubelet and kube-proxy, as well as
InitConfiguration and ClusterConfiguration, is now deprecated and will be ignored when passing `--config`.
- Added a `timeouts` structure to `InitConfiguration`, `JoinConfiguration`, `ResetConfiguration` and
`UpgradeConfiguration` that can be used to configure various timeouts.
The `ClusterConfiguration.timeoutForControlPlane` field is replaced by `timeouts.controlPlaneComponentHealthCheck`.
The `JoinConfiguration.discovery.timeout` is replaced by `timeouts.discovery`.
-->
&lt;ul>
&lt;li>在 &lt;code>InitConfiguration&lt;/code> 和 &lt;code>JoinConfiguration&lt;/code> 中添加了 &lt;code>nodeRegistration.imagePullSerial&lt;/code> 字段，
可用于控制 kubeadm 是顺序拉取镜像还是并行拉取镜像。&lt;/li>
&lt;li>当将 &lt;code>--config&lt;/code> 传递给 &lt;code>kubeadm upgrade&lt;/code> 子命令时，现已在 v1beta4 中支持 UpgradeConfiguration kubeadm API。
对于升级子命令，kubelet 和 kube-proxy 的组件配置以及 InitConfiguration 和 ClusterConfiguration 的用法现已弃用，
并将在传递 &lt;code>--config&lt;/code> 时被忽略。&lt;/li>
&lt;li>在 &lt;code>InitConfiguration&lt;/code>、&lt;code>JoinConfiguration&lt;/code>、&lt;code>ResetConfiguration&lt;/code> 和 &lt;code>UpgradeConfiguration&lt;/code>
中添加了 &lt;code>timeouts&lt;/code> 结构，可用于配置各种超时。
&lt;code>ClusterConfiguration.timeoutForControlPlane&lt;/code> 字段被 &lt;code>timeouts.controlPlaneComponentHealthCheck&lt;/code> 替换。
&lt;code>JoinConfiguration.discovery.timeout&lt;/code> 被 &lt;code>timeouts.discovery&lt;/code> 替换。&lt;/li>
&lt;/ul>
&lt;!--
- Added a `certificateValidityPeriod` and `caCertificateValidityPeriod` fields to `ClusterConfiguration`.
These fields can be used to control the validity period of certificates generated by kubeadm during
sub-commands such as `init`, `join`, `upgrade` and `certs`.
Default values continue to be 1 year for non-CA certificates and 10 years for CA certificates.
Also note that only non-CA certificates are renewable by `kubeadm certs renew`.
These changes simplify the configuration of tools that use kubeadm
and improve the extensibility of kubeadm itself.
-->
&lt;ul>
&lt;li>向 &lt;code>ClusterConfiguration&lt;/code> 添加了 &lt;code>certificateValidityPeriod&lt;/code> 和 &lt;code>caCertificateValidityPeriod&lt;/code> 字段。
这些字段可用于控制 kubeadm 在 &lt;code>init&lt;/code>、&lt;code>join&lt;/code>、&lt;code>upgrade&lt;/code> 和 &lt;code>certs&lt;/code> 等子命令中生成的证书的有效期。
默认值继续为非 CA 证书 1 年和 CA 证书 10 年。另请注意，只有非 CA 证书可以通过 &lt;code>kubeadm certs renew&lt;/code> 进行续期。&lt;/li>
&lt;/ul>
&lt;p>这些变更简化了使用 kubeadm 的工具的配置，并提高了 kubeadm 本身的可扩展性。&lt;/p>
&lt;!--
### How to migrate v1beta3 configuration to v1beta4?
If your configuration is not using the latest version, it is recommended that you migrate using
the [kubeadm config migrate](/docs/reference/setup-tools/kubeadm/kubeadm-config/#cmd-config-migrate) command.
This command reads an existing configuration file that uses the old format, and writes a new
file that uses the current format.
-->
&lt;h3 id="如何将-v1beta3-配置迁移到-v1beta4">如何将 v1beta3 配置迁移到 v1beta4？&lt;/h3>
&lt;p>如果你的配置未使用最新版本，建议你使用
&lt;a href="https://kubernetes.io/zh-cn/docs/reference/setup-tools/kubeadm/kubeadm-config/#cmd-config-migrate">kubeadm config migrate&lt;/a>
命令进行迁移。&lt;/p>
&lt;p>此命令读取使用旧格式的现有配置文件，并写入一个使用当前格式的新文件。&lt;/p>
&lt;!--
#### Example {#example-kubeadm-config-migrate}
Using kubeadm v1.31, run `kubeadm config migrate --old-config old-v1beta3.yaml --new-config new-v1beta4.yaml`
## How do I get involved?
Huge thanks to all the contributors who helped with the design, implementation,
and review of this feature:
-->
&lt;h4 id="example-kubeadm-config-migrate">示例&lt;/h4>
&lt;p>使用 kubeadm v1.31，运行 &lt;code>kubeadm config migrate --old-config old-v1beta3.yaml --new-config new-v1beta4.yaml&lt;/code>&lt;/p>
&lt;h2 id="我该如何参与">我该如何参与？&lt;/h2>
&lt;p>衷心感谢在此特性的设计、实现和评审中提供帮助的所有贡献者：&lt;/p>
&lt;!--
- Lubomir I. Ivanov ([neolit123](https://github.com/neolit123))
- Dave Chen([chendave](https://github.com/chendave))
- Paco Xu ([pacoxu](https://github.com/pacoxu))
- Sata Qiu([sataqiu](https://github.com/sataqiu))
- Baofa Fan([carlory](https://github.com/carlory))
- Calvin Chen([calvin0327](https://github.com/calvin0327))
- Ruquan Zhao([ruquanzhao](https://github.com/ruquanzhao))
-->
&lt;ul>
&lt;li>Lubomir I. Ivanov (&lt;a href="https://github.com/neolit123">neolit123&lt;/a>)&lt;/li>
&lt;li>Dave Chen (&lt;a href="https://github.com/chendave">chendave&lt;/a>)&lt;/li>
&lt;li>Paco Xu (&lt;a href="https://github.com/pacoxu">pacoxu&lt;/a>)&lt;/li>
&lt;li>Sata Qiu (&lt;a href="https://github.com/sataqiu">sataqiu&lt;/a>)&lt;/li>
&lt;li>Baofa Fan (&lt;a href="https://github.com/carlory">carlory&lt;/a>)&lt;/li>
&lt;li>Calvin Chen (&lt;a href="https://github.com/calvin0327">calvin0327&lt;/a>)&lt;/li>
&lt;li>Ruquan Zhao (&lt;a href="https://github.com/ruquanzhao">ruquanzhao&lt;/a>)&lt;/li>
&lt;/ul>
&lt;!--
For those interested in getting involved in future discussions on kubeadm configuration,
you can reach out kubeadm or [SIG-cluster-lifecycle](https://github.com/kubernetes/community/blob/master/sig-cluster-lifecycle/README.md) by several means:
- v1beta4 related items are tracked in [kubeadm issue #2890](https://github.com/kubernetes/kubeadm/issues/2890).
- Slack: [#kubeadm](https://kubernetes.slack.com/messages/kubeadm) or [#sig-cluster-lifecycle](https://kubernetes.slack.com/messages/sig-cluster-lifecycle)
- [Mailing list](https://groups.google.com/forum/#!forum/kubernetes-sig-cluster-lifecycle)
-->
&lt;p>如果你有兴趣参与 kubeadm 配置的后续讨论，可以通过多种方式与 kubeadm 或
&lt;a href="https://github.com/kubernetes/community/blob/master/sig-cluster-lifecycle/README.md">SIG-cluster-lifecycle&lt;/a> 联系：&lt;/p>
&lt;ul>
&lt;li>v1beta4 相关事项在 &lt;a href="https://github.com/kubernetes/kubeadm/issues/2890">kubeadm issue #2890&lt;/a> 中跟踪。&lt;/li>
&lt;li>Slack: &lt;a href="https://kubernetes.slack.com/messages/kubeadm">#kubeadm&lt;/a> 或
&lt;a href="https://kubernetes.slack.com/messages/sig-cluster-lifecycle">#sig-cluster-lifecycle&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://groups.google.com/forum/#!forum/kubernetes-sig-cluster-lifecycle">邮件列表&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Kubernetes 1.31：kubectl debug 中的自定义模板化配置特性已进入 Beta 阶段</title><link>https://kubernetes.io/zh-cn/blog/2024/08/22/kubernetes-1-31-custom-profiling-kubectl-debug/</link><pubDate>Thu, 22 Aug 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/08/22/kubernetes-1-31-custom-profiling-kubectl-debug/</guid><description>
&lt;!--
layout: blog
title: "Kubernetes 1.31: Custom Profiling in Kubectl Debug Graduates to Beta"
date: 2024-08-22
slug: kubernetes-1-31-custom-profiling-kubectl-debug
author: >
Arda Güçlü (Red Hat)
-->
&lt;!--
There are many ways of troubleshooting the pods and nodes in the cluster. However, `kubectl debug` is one of the easiest, highly used and most prominent ones. It
provides a set of static profiles and each profile serves for a different kind of role. For instance, from the network administrator's point of view,
debugging the node should be as easy as this:
-->
&lt;p>有很多方法可以对集群中的 Pod 和节点进行故障排查，而 &lt;code>kubectl debug&lt;/code> 是最简单、使用最广泛、最突出的方法之一。
它提供了一组静态配置，每个配置适用于不同类型的角色。
例如，从网络管理员的视角来看，调试节点应该像这样简单：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ kubectl debug node/mynode -it --image&lt;span style="color:#666">=&lt;/span>busybox --profile&lt;span style="color:#666">=&lt;/span>netadmin
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
On the other hand, static profiles also bring about inherent rigidity, which has some implications for some pods contrary to their ease of use.
Because there are various kinds of pods (or nodes) that all have their specific
necessities, and unfortunately, some can't be debugged by only using the static profiles.
Take an instance of a simple pod consisting of a container whose healthiness relies on an environment variable:
-->
&lt;p>另一方面，静态配置也存在固有的刚性，对某些 Pod 所产生的影响与其易用性是相悖的。
因为各种类型的 Pod（或节点）都有其特定的需求，不幸的是，有些问题仅通过静态配置是无法调试的。&lt;/p>
&lt;p>以一个简单的 Pod 为例，此 Pod 由一个容器组成，其健康状况依赖于环境变量：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Pod&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>example-pod&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">containers&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>example-container&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">image&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>customapp:latest&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">env&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>REQUIRED_ENV_VAR&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">value&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;value1&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
Currently, copying the pod is the sole mechanism that supports debugging this pod in kubectl debug. Furthermore, what if user needs to modify the `REQUIRED_ENV_VAR` to something different
for advanced troubleshooting?. There is no mechanism to achieve this.
-->
&lt;p>目前，复制 Pod 是使用 &lt;code>kubectl debug&lt;/code> 命令调试此 Pod 的唯一机制。
此外，如果用户需要将 &lt;code>REQUIRED_ENV_VAR&lt;/code> 环境变量修改为其他不同值来进行高级故障排查，
当前并没有机制能够实现这一需求。&lt;/p>
&lt;!--
## Custom Profiling
Custom profiling is a new functionality available under `--custom` flag, introduced in kubectl debug to provide extensibility. It expects partial `Container` spec in either YAML or JSON format.
In order to debug the example-container above by creating an ephemeral container, we simply have to define this YAML:
-->
&lt;h2 id="自定义模板化配置">自定义模板化配置&lt;/h2>
&lt;p>自定义模板化配置使用 &lt;code>--custom&lt;/code> 标志提供的一项新特性，在 &lt;code>kubectl debug&lt;/code> 中引入以提供可扩展性。
它需要以 YAML 或 JSON 格式的内容填充 &lt;code>container&lt;/code> 规约，
为了通过创建临时容器来调试上面的示例容器，我们只需定义此 YAML：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#080;font-style:italic"># partial_container.yaml&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">env&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>REQUIRED_ENV_VAR&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">value&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>value2&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
and execute:
-->
&lt;p>并且执行：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>kubectl debug example-pod -it --image&lt;span style="color:#666">=&lt;/span>customapp --custom&lt;span style="color:#666">=&lt;/span>partial_container.yaml
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
Here is another example that modifies multiple fields at once (change port number, add resource limits, modify environment variable) in JSON:
-->
&lt;p>下面是另一个在 JSON 中一次修改多个字段（更改端口号、添加资源限制、修改环境变量）的示例：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#008000;font-weight:bold">&amp;#34;ports&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#008000;font-weight:bold">&amp;#34;containerPort&amp;#34;&lt;/span>: &lt;span style="color:#666">80&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#008000;font-weight:bold">&amp;#34;resources&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#008000;font-weight:bold">&amp;#34;limits&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#008000;font-weight:bold">&amp;#34;cpu&amp;#34;&lt;/span>: &lt;span style="color:#b44">&amp;#34;0.5&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#008000;font-weight:bold">&amp;#34;memory&amp;#34;&lt;/span>: &lt;span style="color:#b44">&amp;#34;512Mi&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#008000;font-weight:bold">&amp;#34;requests&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#008000;font-weight:bold">&amp;#34;cpu&amp;#34;&lt;/span>: &lt;span style="color:#b44">&amp;#34;0.2&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#008000;font-weight:bold">&amp;#34;memory&amp;#34;&lt;/span>: &lt;span style="color:#b44">&amp;#34;256Mi&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#008000;font-weight:bold">&amp;#34;env&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#008000;font-weight:bold">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#b44">&amp;#34;REQUIRED_ENV_VAR&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#008000;font-weight:bold">&amp;#34;value&amp;#34;&lt;/span>: &lt;span style="color:#b44">&amp;#34;value2&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
## Constraints
Uncontrolled extensibility hurts the usability. So that, custom profiling is not allowed for certain fields such as command, image, lifecycle, volume devices and container name.
In the future, more fields can be added to the disallowed list if required.
-->
&lt;h2 id="约束">约束&lt;/h2>
&lt;p>不受控制的扩展性会损害可用性。因此，某些字段（例如命令、镜像、生命周期、卷设备和容器名称）不允许进行自定义模版化配置。
将来如果需要，可以将更多字段添加到禁止列表中。&lt;/p>
&lt;!--
## Limitations
The `kubectl debug` command has 3 aspects: Debugging with ephemeral containers, pod copying, and node debugging. The largest intersection set of these aspects is the container spec within a Pod
That's why, custom profiling only supports the modification of the fields that are defined with `containers`. This leads to a limitation that if user needs to modify the other fields in the Pod spec, it is not supported.
-->
&lt;h2 id="限制">限制&lt;/h2>
&lt;p>&lt;code>kubectl debug&lt;/code> 命令有 3 个方面：使用临时容器进行调试、Pod 复制和节点调试。
这些方面最大的交集是 Pod 内的容器规约，因此自定义模版化配置仅支持修改使用 &lt;code>containers&lt;/code> 下定义的字段。
这导致了一个限制，如果用户需要修改 Pod 规约中的其他字段，则不受支持。&lt;/p>
&lt;!--
## Acknowledgments
Special thanks to all the contributors who reviewed and commented on this feature, from the initial conception to its actual implementation (alphabetical order):
-->
&lt;h2 id="致谢">致谢&lt;/h2>
&lt;p>特别感谢所有审查和评论此特性（从最初的概念到实际实施）的贡献者（按字母顺序排列）：&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/eddiezane">Eddie Zaneski&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/soltysh">Maciej Szulik&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/verb">Lee Verberne&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Kubernetes 1.31：细粒度的 SupplementalGroups 控制</title><link>https://kubernetes.io/zh-cn/blog/2024/08/22/fine-grained-supplementalgroups-control/</link><pubDate>Thu, 22 Aug 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/08/22/fine-grained-supplementalgroups-control/</guid><description>
&lt;!--
layout: blog
title: 'Kubernetes 1.31: Fine-grained SupplementalGroups control'
date: 2024-08-22
slug: fine-grained-supplementalgroups-control
author: >
Shingo Omura (Woven By Toyota)
-->
&lt;!--
This blog discusses a new feature in Kubernetes 1.31 to improve the handling of supplementary groups in containers within Pods.
-->
&lt;p>本博客讨论了 Kubernetes 1.31 中的一项新特性，目的是改善处理 Pod 中容器内的附加组。&lt;/p>
&lt;!--
## Motivation: Implicit group memberships defined in `/etc/group` in the container image
Although this behavior may not be popular with many Kubernetes cluster users/admins, kubernetes, by default, _merges_ group information from the Pod with information defined in `/etc/group` in the container image.
Let's see an example, below Pod specifies `runAsUser=1000`, `runAsGroup=3000` and `supplementalGroups=4000` in the Pod's security context.
-->
&lt;h2 id="动机-容器镜像中-etc-group-中定义的隐式组成员关系">动机：容器镜像中 &lt;code>/etc/group&lt;/code> 中定义的隐式组成员关系&lt;/h2>
&lt;p>尽管这种行为可能并不受许多 Kubernetes 集群用户/管理员的欢迎，
但 Kubernetes 默认情况下会将 Pod 中的组信息与容器镜像中 &lt;code>/etc/group&lt;/code> 中定义的信息进行&lt;strong>合并&lt;/strong>。&lt;/p>
&lt;p>让我们看一个例子，以下 Pod 在 Pod 的安全上下文中指定了
&lt;code>runAsUser=1000&lt;/code>、&lt;code>runAsGroup=3000&lt;/code> 和 &lt;code>supplementalGroups=4000&lt;/code>。&lt;/p>
&lt;div class="highlight code-sample">
&lt;div class="copy-code-icon">
&lt;a href="https://raw.githubusercontent.com/kubernetes/website/release-1.32/content/zh-cn/examples/implicit-groups.yaml" download="implicit-groups.yaml">&lt;code>implicit-groups.yaml&lt;/code>
&lt;/a>&lt;img src="https://kubernetes.io/images/copycode.svg" class="icon-copycode" onclick="copyCode('implicit-groups-yaml')" title="复制 implicit-groups.yaml 到剪贴板">&lt;/img>&lt;/div>
&lt;div class="includecode" id="implicit-groups-yaml">&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Pod&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>implicit-groups&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">securityContext&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">runAsUser&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#666">1000&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">runAsGroup&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#666">3000&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">supplementalGroups&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>[&lt;span style="color:#666">4000&lt;/span>]&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">containers&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ctr&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">image&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>registry.k8s.io/e2e-test-images/agnhost:2.45&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">command&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>[&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;sh&amp;#34;&lt;/span>,&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;-c&amp;#34;&lt;/span>,&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;sleep 1h&amp;#34;&lt;/span>&lt;span style="color:#bbb"> &lt;/span>]&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">securityContext&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">allowPrivilegeEscalation&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#a2f;font-weight:bold">false&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/div>
&lt;/div>
&lt;!--
What is the result of `id` command in the `ctr` container?
```console
# Create the Pod:
$ kubectl apply -f https://k8s.io/blog/2024-08-22-Fine-grained-SupplementalGroups-control/implicit-groups.yaml
# Verify that the Pod's Container is running:
$ kubectl get pod implicit-groups
# Check the id command
$ kubectl exec implicit-groups -- id
```
-->
&lt;p>在 &lt;code>ctr&lt;/code> 容器中执行 &lt;code>id&lt;/code> 命令的结果是什么？&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000080;font-weight:bold">#&lt;/span> 创建 Pod：
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000080;font-weight:bold">$&lt;/span> kubectl apply -f https://k8s.io/blog/2024-08-22-Fine-grained-SupplementalGroups-control/implicit-groups.yaml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="">&lt;/span>&lt;span style="color:#000080;font-weight:bold">#&lt;/span> 验证 Pod 的容器正在运行：
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000080;font-weight:bold">$&lt;/span> kubectl get pod implicit-groups
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="">&lt;/span>&lt;span style="color:#000080;font-weight:bold">#&lt;/span> 检查 id 命令
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000080;font-weight:bold">$&lt;/span> kubectl &lt;span style="color:#a2f">exec&lt;/span> implicit-groups -- id
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
Then, output should be similar to this:
-->
&lt;p>输出应类似于：&lt;/p>
&lt;pre tabindex="0">&lt;code class="language-none" data-lang="none">uid=1000 gid=3000 groups=3000,4000,50000
&lt;/code>&lt;/pre>&lt;!--
Where does group ID `50000` in supplementary groups (`groups` field) come from, even though `50000` is not defined in the Pod's manifest at all? The answer is `/etc/group` file in the container image.
Checking the contents of `/etc/group` in the container image should show below:
-->
&lt;p>尽管 &lt;code>50000&lt;/code> 根本没有在 Pod 的清单中被定义，但附加组中的组 ID &lt;code>50000&lt;/code>（&lt;code>groups&lt;/code> 字段）是从哪里来的呢？
答案是容器镜像中的 &lt;code>/etc/group&lt;/code> 文件。&lt;/p>
&lt;p>检查容器镜像中 &lt;code>/etc/group&lt;/code> 的内容应如下所示：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000080;font-weight:bold">$&lt;/span> kubectl &lt;span style="color:#a2f">exec&lt;/span> implicit-groups -- cat /etc/group
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888">...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888">user-defined-in-image:x:1000:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888">group-defined-in-image:x:50000:user-defined-in-image
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
Aha! The container's primary user `1000` belongs to the group `50000` in the last entry.
Thus, the group membership defined in `/etc/group` in the container image for the container's primary user is _implicitly_ merged to the information from the Pod. Please note that this was a design decision the current CRI implementations inherited from Docker, and the community never really reconsidered it until now.
-->
&lt;p>原来如此！容器的主要用户 &lt;code>1000&lt;/code> 属于最后一个条目中的组 &lt;code>50000&lt;/code>。&lt;/p>
&lt;p>因此，容器镜像中为容器的主要用户定义的组成员关系会被&lt;strong>隐式&lt;/strong>合并到 Pod 的信息中。
请注意，这是当前 CRI 实现从 Docker 继承的设计决策，而社区直到现在才重新考虑这个问题。&lt;/p>
&lt;!--
### What's wrong with it?
The _implicitly_ merged group information from `/etc/group` in the container image may cause some concerns particularly in accessing volumes (see [kubernetes/kubernetes#112879](https://issue.k8s.io/112879) for details) because file permission is controlled by uid/gid in Linux. Even worse, the implicit gids from `/etc/group` can not be detected/validated by any policy engines because there is no clue for the implicit group information in the manifest. This can also be a concern for Kubernetes security.
-->
&lt;h3 id="这有什么问题">这有什么问题？&lt;/h3>
&lt;p>从容器镜像中的 &lt;code>/etc/group&lt;/code> &lt;strong>隐式&lt;/strong>合并的组信息可能会引起一些担忧，特别是在访问卷时
（有关细节参见 &lt;a href="https://issue.k8s.io/112879">kubernetes/kubernetes#112879&lt;/a>），
因为在 Linux 中文件权限是通过 uid/gid 进行控制的。
更糟糕的是，隐式的 gid 无法被任何策略引擎所检测/验证，因为在清单中没有隐式组信息的线索。
这对 Kubernetes 的安全性也可能构成隐患。&lt;/p>
&lt;!--
## Fine-grained SupplementalGroups control in a Pod: `SupplementaryGroupsPolicy`
To tackle the above problem, Kubernetes 1.31 introduces new field `supplementalGroupsPolicy` in Pod's `.spec.securityContext`.
This field provies a way to control how to calculate supplementary groups for the container processes in a Pod. The available policy is below:
-->
&lt;h2 id="pod-中的细粒度-supplementalgroups-控制-supplementarygroupspolicy">Pod 中的细粒度 SupplementalGroups 控制：&lt;code>SupplementaryGroupsPolicy&lt;/code>&lt;/h2>
&lt;p>为了解决上述问题，Kubernetes 1.31 在 Pod 的 &lt;code>.spec.securityContext&lt;/code>
中引入了新的字段 &lt;code>supplementalGroupsPolicy&lt;/code>。&lt;/p>
&lt;p>此字段提供了一种控制 Pod 中容器进程如何计算附加组的方法。可用的策略如下：&lt;/p>
&lt;!--
* _Merge_: The group membership defined in `/etc/group` for the container's primary user will be merged. If not specified, this policy will be applied (i.e. as-is behavior for backword compatibility).
* _Strict_: it only attaches specified group IDs in `fsGroup`, `supplementalGroups`, or `runAsGroup` fields as the supplementary groups of the container processes. This means no group membership defined in `/etc/group` for the container's primary user will be merged.
Let's see how `Strict` policy works.
-->
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Merge&lt;/strong>：将容器的主要用户在 &lt;code>/etc/group&lt;/code> 中定义的组成员关系进行合并。
如果不指定，则应用此策略（即为了向后兼容性而保持的原有行为）。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Strict&lt;/strong>：仅将 &lt;code>fsGroup&lt;/code>、&lt;code>supplementalGroups&lt;/code> 或 &lt;code>runAsGroup&lt;/code>
字段中指定的组 ID 挂接为容器进程的附加组。这意味着容器的主要用户在 &lt;code>/etc/group&lt;/code> 中定义的任何组成员关系都不会被合并。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>让我们看看 &lt;code>Strict&lt;/code> 策略是如何工作的。&lt;/p>
&lt;div class="highlight code-sample">
&lt;div class="copy-code-icon">
&lt;a href="https://raw.githubusercontent.com/kubernetes/website/release-1.32/content/zh-cn/examples/strict-supplementalgroups-policy.yaml" download="strict-supplementalgroups-policy.yaml">&lt;code>strict-supplementalgroups-policy.yaml&lt;/code>
&lt;/a>&lt;img src="https://kubernetes.io/images/copycode.svg" class="icon-copycode" onclick="copyCode('strict-supplementalgroups-policy-yaml')" title="复制 strict-supplementalgroups-policy.yaml 到剪贴板">&lt;/img>&lt;/div>
&lt;div class="includecode" id="strict-supplementalgroups-policy-yaml">&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Pod&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>strict-supplementalgroups-policy&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">securityContext&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">runAsUser&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#666">1000&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">runAsGroup&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#666">3000&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">supplementalGroups&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>[&lt;span style="color:#666">4000&lt;/span>]&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">supplementalGroupsPolicy&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Strict&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">containers&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ctr&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">image&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>registry.k8s.io/e2e-test-images/agnhost:2.45&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">command&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>[&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;sh&amp;#34;&lt;/span>,&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;-c&amp;#34;&lt;/span>,&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;sleep 1h&amp;#34;&lt;/span>&lt;span style="color:#bbb"> &lt;/span>]&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">securityContext&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">allowPrivilegeEscalation&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#a2f;font-weight:bold">false&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/div>
&lt;/div>
&lt;!--
```console
# Create the Pod:
$ kubectl apply -f https://k8s.io/blog/2024-08-22-Fine-grained-SupplementalGroups-control/strict-supplementalgroups-policy.yaml
# Verify that the Pod's Container is running:
$ kubectl get pod strict-supplementalgroups-policy
# Check the process identity:
kubectl exec -it strict-supplementalgroups-policy -- id
```
-->
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000080;font-weight:bold">#&lt;/span> 创建 Pod：
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000080;font-weight:bold">$&lt;/span> kubectl apply -f https://k8s.io/blog/2024-08-22-Fine-grained-SupplementalGroups-control/strict-supplementalgroups-policy.yaml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="">&lt;/span>&lt;span style="color:#000080;font-weight:bold">#&lt;/span> 验证 Pod 的容器正在运行：
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000080;font-weight:bold">$&lt;/span> kubectl get pod strict-supplementalgroups-policy
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="">&lt;/span>&lt;span style="color:#000080;font-weight:bold">#&lt;/span> 检查进程身份：
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888">kubectl exec -it strict-supplementalgroups-policy -- id
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
The output should be similar to this:
-->
&lt;p>输出应类似于：&lt;/p>
&lt;pre tabindex="0">&lt;code class="language-none" data-lang="none">uid=1000 gid=3000 groups=3000,4000
&lt;/code>&lt;/pre>&lt;!--
You can see `Strict` policy can exclude group `50000` from `groups`!
Thus, ensuring `supplementalGroupsPolicy: Strict` (enforced by some policy mechanism) helps prevent the implicit supplementary groups in a Pod.
-->
&lt;p>你可以看到 &lt;code>Strict&lt;/code> 策略可以将组 &lt;code>50000&lt;/code> 从 &lt;code>groups&lt;/code> 中排除出去！&lt;/p>
&lt;p>因此，确保（通过某些策略机制强制执行的）&lt;code>supplementalGroupsPolicy: Strict&lt;/code> 有助于防止 Pod 中的隐式附加组。&lt;/p>
&lt;div class="alert alert-info" role="alert">&lt;h4 class="alert-heading">说明：&lt;/h4>&lt;!--
Actually, this is not enough because container with sufficient privileges / capability can change its process identity. Please see the following section for details.
-->
&lt;p>实际上，这还不够，因为具有足够权限/能力的容器可以更改其进程身份。
有关细节参见以下章节。&lt;/p>&lt;/div>
&lt;!--
## Attached process identity in Pod status
This feature also exposes the process identity attached to the first container process of the container
via `.status.containerStatuses[].user.linux` field. It would be helpful to see if implicit group IDs are attached.
-->
&lt;h2 id="pod-状态中挂接的进程身份">Pod 状态中挂接的进程身份&lt;/h2>
&lt;p>此特性还通过 &lt;code>.status.containerStatuses[].user.linux&lt;/code>
字段公开挂接到容器的第一个容器进程的进程身份。这将有助于查看隐式组 ID 是否被挂接。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#00f;font-weight:bold">...&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">status&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">containerStatuses&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ctr&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">user&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">linux&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">gid&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#666">3000&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">supplementalGroups&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#666">3000&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#666">4000&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">uid&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#666">1000&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#00f;font-weight:bold">...&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;div class="alert alert-info" role="alert">&lt;h4 class="alert-heading">说明：&lt;/h4>&lt;!--
Please note that the values in `status.containerStatuses[].user.linux` field is _the firstly attached_
process identity to the first container process in the container. If the container has sufficient privilege
to call system calls related to process identity (e.g. [`setuid(2)`](https://man7.org/linux/man-pages/man2/setuid.2.html), [`setgid(2)`](https://man7.org/linux/man-pages/man2/setgid.2.html) or [`setgroups(2)`](https://man7.org/linux/man-pages/man2/setgroups.2.html), etc.), the container process can change its identity. Thus, the _actual_ process identity will be dynamic.
-->
&lt;p>请注意，&lt;code>status.containerStatuses[].user.linux&lt;/code> 字段中的值是&lt;strong>首次挂接&lt;/strong>到容器中第一个容器进程的进程身份。
如果容器具有足够的权限调用与进程身份相关的系统调用（例如
&lt;a href="https://man7.org/linux/man-pages/man2/setuid.2.html">&lt;code>setuid(2)&lt;/code>&lt;/a>、
&lt;a href="https://man7.org/linux/man-pages/man2/setgid.2.html">&lt;code>setgid(2)&lt;/code>&lt;/a> 或
&lt;a href="https://man7.org/linux/man-pages/man2/setgroups.2.html">&lt;code>setgroups(2)&lt;/code>&lt;/a> 等），
则容器进程可以更改其身份。因此，&lt;strong>实际&lt;/strong>的进程身份将是动态的。&lt;/p>&lt;/div>
&lt;!--
## Feature availability
To enable `supplementalGroupsPolicy` field, the following components have to be used:
-->
&lt;h2 id="特性可用性">特性可用性&lt;/h2>
&lt;p>要启用 &lt;code>supplementalGroupsPolicy&lt;/code> 字段，必须使用以下组件：&lt;/p>
&lt;!--
- Kubernetes: v1.31 or later, with the `SupplementalGroupsPolicy` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) enabled. As of v1.31, the gate is marked as alpha.
- CRI runtime:
- containerd: v2.0 or later
- CRI-O: v1.31 or later
You can see if the feature is supported in the Node's `.status.features.supplementalGroupsPolicy` field.
-->
&lt;ul>
&lt;li>Kubernetes：v1.31 或更高版本，启用 &lt;code>SupplementalGroupsPolicy&lt;/code>
&lt;a href="https://kubernetes.io/zh-cn/docs/reference/command-line-tools-reference/feature-gates/">特性门控&lt;/a>。
截至 v1.31，此门控标记为 Alpha。&lt;/li>
&lt;li>CRI 运行时：
&lt;ul>
&lt;li>containerd：v2.0 或更高版本&lt;/li>
&lt;li>CRI-O：v1.31 或更高版本&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>你可以在 Node 的 &lt;code>.status.features.supplementalGroupsPolicy&lt;/code> 字段中查看此特性是否受支持。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Node&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#00f;font-weight:bold">...&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">status&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">features&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">supplementalGroupsPolicy&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#a2f;font-weight:bold">true&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
## What's next?
Kubernetes SIG Node hope - and expect - that the feature will be promoted to beta and eventually
general availability (GA) in future releases of Kubernetes, so that users no longer need to enable
the feature gate manually.
`Merge` policy is applied when `supplementalGroupsPolicy` is not specified, for backwards compatibility.
-->
&lt;h2 id="接下来">接下来&lt;/h2>
&lt;p>Kubernetes SIG Node 希望并期待此特性将在 Kubernetes 后续版本中进阶至 Beta，
并最终进阶至正式发布（GA），以便用户不再需要手动启用特性门控。&lt;/p>
&lt;p>当 &lt;code>supplementalGroupsPolicy&lt;/code> 未被指定时，将应用 &lt;code>Merge&lt;/code> 策略，以保持向后兼容性。&lt;/p>
&lt;!--
## How can I learn more?
-->
&lt;h2 id="我如何了解更多">我如何了解更多？&lt;/h2>
&lt;!-- https://github.com/kubernetes/website/pull/46920 -->
&lt;!--
- [Configure a Security Context for a Pod or Container](/docs/tasks/configure-pod-container/security-context/)
for the further details of `supplementalGroupsPolicy`
- [KEP-3619: Fine-grained SupplementalGroups control](https://github.com/kubernetes/enhancements/issues/3619)
-->
&lt;ul>
&lt;li>&lt;a href="https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/security-context/">为 Pod 或容器配置安全上下文&lt;/a>以获取有关
&lt;code>supplementalGroupsPolicy&lt;/code> 的更多细节&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes/enhancements/issues/3619">KEP-3619：细粒度 SupplementalGroups 控制&lt;/a>&lt;/li>
&lt;/ul>
&lt;!--
## How to get involved?
This feature is driven by the SIG Node community. Please join us to connect with
the community and share your ideas and feedback around the above feature and
beyond. We look forward to hearing from you!
-->
&lt;h2 id="如何参与">如何参与？&lt;/h2>
&lt;p>此特性由 SIG Node 社区推动。请加入我们，与社区保持联系，
分享你对上述特性及其他方面的想法和反馈。我们期待听到你的声音！&lt;/p></description></item><item><title>Kubernetes v1.31：全新的 Kubernetes CPUManager 静态策略：跨核分发 CPU</title><link>https://kubernetes.io/zh-cn/blog/2024/08/22/cpumanager-static-policy-distributed-cpu-across-cores/</link><pubDate>Thu, 22 Aug 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/08/22/cpumanager-static-policy-distributed-cpu-across-cores/</guid><description>
&lt;!--
layout: blog
title: 'Kubernetes v1.31: New Kubernetes CPUManager Static Policy: Distribute CPUs Across Cores'
date: 2024-08-22
slug: cpumanager-static-policy-distributed-cpu-across-cores
author: >
[Jiaxin Shan](https://github.com/Jeffwan) (Bytedance)
-->
&lt;!--
In Kubernetes v1.31, we are excited to introduce a significant enhancement to CPU management capabilities: the `distribute-cpus-across-cores` option for the [CPUManager static policy](/docs/tasks/administer-cluster/cpu-management-policies/#static-policy-options). This feature is currently in alpha and hidden by default, marking a strategic shift aimed at optimizing CPU utilization and improving system performance across multi-core processors.
-->
&lt;p>在 Kubernetes v1.31 中，我们很高兴引入了对 CPU 管理能力的重大增强：针对
&lt;a href="https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/cpu-management-policies/#static-policy-options">CPUManager 静态策略&lt;/a>的
&lt;code>distribute-cpus-across-cores&lt;/code> 选项。此特性目前处于 Alpha 阶段，
默认被隐藏，标志着旨在优化 CPU 利用率和改善多核处理器系统性能的战略转变。&lt;/p>
&lt;!--
## Understanding the feature
Traditionally, Kubernetes' CPUManager tends to allocate CPUs as compactly as possible, typically packing them onto the fewest number of physical cores. However, allocation strategy matters, CPUs on the same physical host still share some resources of the physical core, such as the cache and execution units, etc.
-->
&lt;h2 id="understanding-the-feature">理解这一特性 &lt;/h2>
&lt;p>传统上，Kubernetes 的 CPUManager 倾向于尽可能紧凑地分配 CPU，通常将这些 CPU 打包到尽可能少的物理核上。
然而，分配策略很重要，因为同一物理主机上的 CPU 仍然共享一些物理核的资源，例如缓存和执行单元等。&lt;/p>
&lt;figure>
&lt;img src="https://kubernetes.io/zh-cn/blog/2024/08/22/cpumanager-static-policy-distributed-cpu-across-cores/cpu-cache-architecture.png"
alt="cpu-cache-architecture"/>
&lt;/figure>
&lt;!--
While default approach minimizes inter-core communication and can be beneficial under certain scenarios, it also poses a challenge. CPUs sharing a physical core can lead to resource contention, which in turn may cause performance bottlenecks, particularly noticeable in CPU-intensive applications.
-->
&lt;p>虽然默认方法可以最小化核间通信，并在某些情况下是有益的，但也带来了挑战。
在同一物理核上共享的 CPU 可能导致资源竞争，从而可能造成性能瓶颈，这在 CPU 密集型应用中尤为明显。&lt;/p>
&lt;!--
The new `distribute-cpus-across-cores` feature addresses this issue by modifying the allocation strategy. When enabled, this policy option instructs the CPUManager to spread out the CPUs (hardware threads) across as many physical cores as possible. This distribution is designed to minimize contention among CPUs sharing the same physical core, potentially enhancing the performance of applications by providing them dedicated core resources.
Technically, within this static policy, the free CPU list is reordered in the manner depicted in the diagram, aiming to allocate CPUs from separate physical cores.
-->
&lt;p>全新的 &lt;code>distribute-cpus-across-cores&lt;/code> 特性通过修改分配策略来解决这个问题。
当此特性被启用时，此策略选项指示 CPUManager 尽可能将 CPU（硬件线程）分发到尽可能多的物理核上。
这种分发旨在最小化共享同一物理核的 CPU 之间的争用，从而通过为应用提供专用的核资源来潜在提高性能。&lt;/p>
&lt;p>从技术上讲，在这个静态策略中，可用的 CPU 列表按照图示的方式重新排序，旨在从不同的物理核分配 CPU。&lt;/p>
&lt;figure>
&lt;img src="https://kubernetes.io/zh-cn/blog/2024/08/22/cpumanager-static-policy-distributed-cpu-across-cores/cpu-ordering.png"
alt="cpu-ordering"/>
&lt;/figure>
&lt;!--
## Enabling the feature
To enable this feature, users firstly need to add `--cpu-manager-policy=static` kubelet flag or the `cpuManagerPolicy: static` field in KubeletConfiuration. Then user can add `--cpu-manager-policy-options distribute-cpus-across-cores=true` or `distribute-cpus-across-cores=true` to their CPUManager policy options in the Kubernetes configuration or. This setting directs the CPUManager to adopt the new distribution strategy. It is important to note that this policy option cannot currently be used in conjunction with `full-pcpus-only` or `distribute-cpus-across-numa` options.
-->
&lt;h2 id="enabling-the-feature">启用此特性 &lt;/h2>
&lt;p>要启用此特性，用户首先需要在 kubelet 配置中添加 &lt;code>--cpu-manager-policy=static&lt;/code> kubelet 标志或 &lt;code>cpuManagerPolicy: static&lt;/code> 字段。
然后用户可以在 Kubernetes 配置中添加 &lt;code>--cpu-manager-policy-options distribute-cpus-across-cores=true&lt;/code> 或
&lt;code>distribute-cpus-across-cores=true&lt;/code> 到自己的 CPUManager 策略选项中。此设置指示 CPUManager 采用新的分发策略。
需要注意的是，目前此策略选项无法与 &lt;code>full-pcpus-only&lt;/code> 或 &lt;code>distribute-cpus-across-numa&lt;/code> 选项一起使用。&lt;/p>
&lt;!--
## Current limitations and future directions
As with any new feature, especially one in alpha, there are limitations and areas for future improvement. One significant current limitation is that `distribute-cpus-across-cores` cannot be combined with other policy options that might conflict in terms of CPU allocation strategies. This restriction can affect compatibility with certain workloads and deployment scenarios that rely on more specialized resource management.
-->
&lt;h2 id="current-limitations-and-future-directions">当前限制和未来方向 &lt;/h2>
&lt;p>与所有新特性一样，尤其是处于 Alpha 阶段的特性，此特性也存在一些限制，很多方面还有待后续改进。
当前一个显著的限制是 &lt;code>distribute-cpus-across-cores&lt;/code> 不能与可能在 CPU 分配策略上存在冲突的其他策略选项结合使用。
这一限制可能会影响与（依赖于更专业的资源管理的）某些工作负载和部署场景的兼容性。&lt;/p>
&lt;!--
Looking forward, we are committed to enhancing the compatibility and functionality of the `distribute-cpus-across-cores` option. Future updates will focus on resolving these compatibility issues, allowing this policy to be combined with other CPUManager policies seamlessly. Our goal is to provide a more flexible and robust CPU allocation framework that can adapt to a variety of workloads and performance demands.
-->
&lt;p>展望未来，我们将致力于增强 &lt;code>distribute-cpus-across-cores&lt;/code> 选项的兼容性和特性。
未来的更新将专注于解决这些兼容性问题，使此策略能够与其他 CPUManager 策略无缝结合。
我们的目标是提供一个更灵活和强大的 CPU 分配框架，能够适应各种工作负载和性能需求。&lt;/p>
&lt;!--
## Conclusion
The introduction of the `distribute-cpus-across-cores` policy in Kubernetes CPUManager is a step forward in our ongoing efforts to refine resource management and improve application performance. By reducing the contention on physical cores, this feature offers a more balanced approach to CPU resource allocation, particularly beneficial for environments running heterogeneous workloads. We encourage Kubernetes users to test this new feature and provide feedback, which will be invaluable in shaping its future development.
This draft aims to clearly explain the new feature while setting expectations for its current stage and future improvements.
-->
&lt;h2 id="conclusion">结论 &lt;/h2>
&lt;p>在 Kubernetes CPUManager 中引入 &lt;code>distribute-cpus-across-cores&lt;/code> 策略是我们持续努力改进资源管理和提升应用性能而向前迈出的一步。
通过减少物理核上的争用，此特性提供了更加平衡的 CPU 资源分配方法，特别有利于运行异构工作负载的环境。
我们鼓励 Kubernetes 用户测试这一新特性并提供反馈，这将对其未来发展至关重要。&lt;/p>
&lt;p>本文旨在清晰地解释这一新特性，同时设定对其当前阶段和未来改进的期望。&lt;/p>
&lt;!--
## Further reading
Please check out the [Control CPU Management Policies on the Node](/docs/tasks/administer-cluster/cpu-management-policies/)
task page to learn more about the CPU Manager, and how it fits in relation to the other node-level resource managers.
-->
&lt;h2 id="further-reading">进一步阅读 &lt;/h2>
&lt;p>请查阅&lt;a href="https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/cpu-management-policies/">节点上的 CPU 管理策略&lt;/a>任务页面，
以了解有关 CPU 管理器的更多信息，以及 CPU 管理器与其他节点级资源管理器的关系。&lt;/p>
&lt;!--
## Getting involved
This feature is driven by the [SIG Node](https://github.com/Kubernetes/community/blob/master/sig-node/README.md). If you are interested in helping develop this feature, sharing feedback, or participating in any other ongoing SIG Node projects, please attend the SIG Node meeting for more details.
-->
&lt;h2 id="getting-involved">参与其中 &lt;/h2>
&lt;p>此特性由 &lt;a href="https://github.com/Kubernetes/community/blob/master/sig-node/README.md">SIG Node&lt;/a> 推动。
如果你有兴趣帮助开发此特性、分享反馈或参与其他目前 SIG Node 项目的工作，请参加 SIG Node 会议了解更多细节。&lt;/p></description></item><item><title>Kubernetes 1.31: 节点 Cgroup 驱动程序的自动配置 (beta)</title><link>https://kubernetes.io/zh-cn/blog/2024/08/21/cri-cgroup-driver-lookup-now-beta/</link><pubDate>Wed, 21 Aug 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/08/21/cri-cgroup-driver-lookup-now-beta/</guid><description>
&lt;!--
layout: blog
title: "Kubernetes 1.31: Autoconfiguration For Node Cgroup Driver (beta)"
date: 2024-08-21
slug: cri-cgroup-driver-lookup-now-beta
author: >
Peter Hunt (Red Hat)
-->
&lt;!--
Historically, configuring the correct cgroup driver has been a pain point for users running new
Kubernetes clusters. On Linux systems, there are two different cgroup drivers:
`cgroupfs` and `systemd`. In the past, both the [kubelet](/docs/reference/command-line-tools-reference/kubelet/)
and CRI implementation (like CRI-O or containerd) needed to be configured to use
the same cgroup driver, or else the kubelet would exit with an error. This was a
source of headaches for many cluster admins. However, there is light at the end of the tunnel!
-->
&lt;p>一直以来，为新运行的 Kubernetes 集群配置正确的 cgroup 驱动程序是用户的一个痛点。
在 Linux 系统中，存在两种不同的 cgroup 驱动程序：&lt;code>cgroupfs&lt;/code> 和 &lt;code>systemd&lt;/code>。
过去，&lt;a href="https://kubernetes.io/zh-cn/docs/reference/command-line-tools-reference/kubelet/">kubelet&lt;/a> 和 CRI
实现（如 CRI-O 或 containerd）需要配置为使用相同的 cgroup 驱动程序， 否则 kubelet 会报错并退出。
这让许多集群管理员头疼不已。不过，现在曙光乍现！&lt;/p>
&lt;!--
## Automated cgroup driver detection
In v1.28.0, the SIG Node community introduced the feature gate
`KubeletCgroupDriverFromCRI`, which instructs the kubelet to ask the CRI
implementation which cgroup driver to use. A few minor releases of Kubernetes
happened whilst we waited for support to land in the major two CRI implementations
(containerd and CRI-O), but as of v1.31.0, this feature is now beta!
-->
&lt;h2 id="自动检测-cgroup-驱动程序">自动检测 cgroup 驱动程序&lt;/h2>
&lt;p>在 v1.28.0 版本中，SIG Node 社区引入了 &lt;code>KubeletCgroupDriverFromCRI&lt;/code> 特性门控，
它指示 kubelet 向 CRI 实现询问使用哪个 cgroup 驱动程序。在两个主要的 CRI 实现（containerd
和 CRI-O）增加对该功能的支持这段期间，Kubernetes 经历了几次小版本发布，但从 v1.31.0 版本开始，此功能现已进入 beta 阶段！&lt;/p>
&lt;!--
In addition to setting the feature gate, a cluster admin needs to ensure their
CRI implementation is new enough:
- containerd: Support was added in v2.0.0
- CRI-O: Support was added in v1.28.0
-->
&lt;p>除了设置特性门控之外，集群管理员还需要确保 CRI 实现版本足够新：&lt;/p>
&lt;ul>
&lt;li>containerd：v2.0.0 版本开始支持&lt;/li>
&lt;li>CRI-O：v1.28.0 版本开始支持&lt;/li>
&lt;/ul>
&lt;!--
Then, they should ensure their CRI implementation is configured to the
cgroup_driver they would like to use.
-->
&lt;p>然后，他们应该确保配置其 CRI 实现使用他们想要的 cgroup 驱动程序。&lt;/p>
&lt;!--
## Future work
Eventually, support for the kubelet's `cgroupDriver` configuration field will be
dropped, and the kubelet will fail to start if the CRI implementation isn't new
enough to have support for this feature.
-->
&lt;h2 id="未来工作">未来工作&lt;/h2>
&lt;p>最终，kubelet 对 &lt;code>cgroupDriver&lt;/code> 配置字段的支持将会被移除，如果 CRI 实现的版本不够新，无法支持此功能，kubelet 将无法启动。&lt;/p></description></item><item><title>Kubernetes 1.31：流式传输从 SPDY 转换为 WebSocket</title><link>https://kubernetes.io/zh-cn/blog/2024/08/20/websockets-transition/</link><pubDate>Tue, 20 Aug 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/08/20/websockets-transition/</guid><description>
&lt;!--
layout: blog
title: 'Kubernetes 1.31: Streaming Transitions from SPDY to WebSockets'
date: 2024-08-20
slug: websockets-transition
author: >
[Sean Sullivan](https://github.com/seans3) (Google)
[Shannon Kularathna](https://github.com/shannonxtreme) (Google)
-->
&lt;!--
In Kubernetes 1.31, by default kubectl now uses the WebSocket protocol
instead of SPDY for streaming.
This post describes what these changes mean for you and why these streaming APIs
matter.
-->
&lt;p>在 Kubernetes 1.31 中，kubectl 现在默认使用 WebSocket 协议而不是 SPDY 进行流式传输。&lt;/p>
&lt;p>这篇文章介绍了这些变化对你意味着什么以及这些流式传输 API 的重要性。&lt;/p>
&lt;!--
## Streaming APIs in Kubernetes
In Kubernetes, specific endpoints that are exposed as an HTTP or RESTful
interface are upgraded to streaming connections, which require a streaming
protocol. Unlike HTTP, which is a request-response protocol, a streaming
protocol provides a persistent connection that's bi-directional, low-latency,
and lets you interact in real-time. Streaming protocols support reading and
writing data between your client and the server, in both directions, over the
same connection. This type of connection is useful, for example, when you create
a shell in a running container from your local workstation and run commands in
the container.
-->
&lt;h2 id="kubernetes-中的流式-api">Kubernetes 中的流式 API&lt;/h2>
&lt;p>在 Kubernetes 中，某些以 HTTP 或 RESTful 接口公开的某些端点会被升级为流式连接，因而需要使用流式协议。
与 HTTP 这种请求-响应协议不同，流式协议提供了一种持久的双向连接，具有低延迟的特点，并允许实时交互。
流式协议支持在客户端与服务器之间通过同一个连接进行双向的数据读写。
这种类型的连接非常有用，例如，当你从本地工作站在某个运行中的容器内创建 shell 并在该容器中运行命令时。&lt;/p>
&lt;!--
## Why change the streaming protocol?
Before the v1.31 release, Kubernetes used the SPDY/3.1 protocol by default when
upgrading streaming connections. SPDY/3.1 has been deprecated for eight years,
and it was never standardized. Many modern proxies, gateways, and load balancers
no longer support the protocol. As a result, you might notice that commands like
`kubectl cp`, `kubectl attach`, `kubectl exec`, and `kubectl port-forward`
stop working when you try to access your cluster through a proxy or gateway.
-->
&lt;h2 id="为什么要改变流式传输协议">为什么要改变流式传输协议？&lt;/h2>
&lt;p>在 v1.31 版本发布之前，Kubernetes 默认使用 SPDY/3.1 协议来升级流式连接。
但是 SPDY/3.1 已经被废弃了八年之久，并且从未被标准化，许多现代代理、网关和负载均衡器已经不再支持该协议。
因此，当你尝试通过代理或网关访问集群时，可能会发现像 &lt;code>kubectl cp&lt;/code>、&lt;code>kubectl attach&lt;/code>、&lt;code>kubectl exec&lt;/code>
和 &lt;code>kubectl port-forward&lt;/code> 这样的命令无法正常工作。&lt;/p>
&lt;!--
As of Kubernetes v1.31, SIG API Machinery has modified the streaming
protocol that a Kubernetes client (such as `kubectl`) uses for these commands
to the more modern [WebSocket streaming protocol](https://datatracker.ietf.org/doc/html/rfc6455).
The WebSocket protocol is a currently supported standardized streaming protocol
that guarantees compatibility and interoperability with different components and
programming languages. The WebSocket protocol is more widely supported by modern
proxies and gateways than SPDY.
-->
&lt;p>从 Kubernetes v1.31 版本开始，SIG API Machinery 修改了 Kubernetes
客户端（如 &lt;code>kubectl&lt;/code>）中用于这些命令的流式传输协议，将其改为更现代化的
&lt;a href="https://datatracker.ietf.org/doc/html/rfc6455">WebSocket 流式传输协议&lt;/a>。
WebSocket 协议是一种当前得到支持的标准流式传输协议，
它可以确保与不同组件及编程语言之间的兼容性和互操作性。
相较于 SPDY，WebSocket 协议更为广泛地被现代代理和网关所支持。&lt;/p>
&lt;!--
## How streaming APIs work
Kubernetes upgrades HTTP connections to streaming connections by adding
specific upgrade headers to the originating HTTP request. For example, an HTTP
upgrade request for running the `date` command on an `nginx` container within
a cluster is similar to the following:
-->
&lt;h2 id="流式-api-的工作原理">流式 API 的工作原理&lt;/h2>
&lt;p>Kubernetes 通过在原始的 HTTP 请求中添加特定的升级头字段来将 HTTP 连接升级为流式连接。
例如，在集群内的 &lt;code>nginx&lt;/code> 容器上运行 &lt;code>date&lt;/code> 命令的 HTTP 升级请求类似于以下内容：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000080;font-weight:bold">$&lt;/span> kubectl &lt;span style="color:#a2f">exec&lt;/span> -v&lt;span style="color:#666">=&lt;/span>&lt;span style="color:#666">8&lt;/span> nginx -- date
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888">GET https://127.0.0.1:43251/api/v1/namespaces/default/pods/nginx/exec?command=date…
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888">Request Headers:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888"> Connection: Upgrade
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888"> Upgrade: websocket
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888"> Sec-Websocket-Protocol: v5.channel.k8s.io
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888"> User-Agent: kubectl/v1.31.0 (linux/amd64) kubernetes/6911225
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
If the container runtime supports the WebSocket streaming protocol and at least
one of the subprotocol versions (e.g. `v5.channel.k8s.io`), the server responds
with a successful `101 Switching Protocols` status, along with the negotiated
subprotocol version:
-->
&lt;p>如果容器运行时支持 WebSocket 流式协议及其至少一个子协议版本（例如 &lt;code>v5.channel.k8s.io&lt;/code>），
服务器会以代表成功的 &lt;code>101 Switching Protocols&lt;/code> 状态码进行响应，并附带协商后的子协议版本：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888">Response Status: 101 Switching Protocols in 3 milliseconds
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888">Response Headers:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888"> Upgrade: websocket
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888"> Connection: Upgrade
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888"> Sec-Websocket-Accept: j0/jHW9RpaUoGsUAv97EcKw8jFM=
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888"> Sec-Websocket-Protocol: v5.channel.k8s.io
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
At this point the TCP connection used for the HTTP protocol has changed to a
streaming connection. Subsequent STDIN, STDOUT, and STDERR data (as well as
terminal resizing data and process exit code data) for this shell interaction is
then streamed over this upgraded connection.
-->
&lt;p>此时，原本用于 HTTP 协议的 TCP 连接已转换为流式连接。
随后，此 Shell 交互中的标准输入（STDIN）、标准输出（STDOUT）和标准错误输出（STDERR）数据
（以及终端重置大小数据和进程退出码数据）会通过这个升级后的连接进行流式传输。&lt;/p>
&lt;!--
## How to use the new WebSocket streaming protocol
If your cluster and kubectl are on version 1.29 or later, there are two
control plane feature gates and two kubectl environment variables that
govern the use of the WebSockets rather than SPDY. In Kubernetes 1.31,
all of the following feature gates are in beta and are enabled by
default:
-->
&lt;h2 id="如何使用新的-websocket-流式协议">如何使用新的 WebSocket 流式协议&lt;/h2>
&lt;p>如果你的集群和 kubectl 版本为 1.29 及以上版本，有两个控制面特性门控以及两个
kubectl 环境变量用来控制启用 WebSocket 而不是 SPDY 作为流式协议。
在 Kubernetes 1.31 中，以下所有特性门控均处于 Beta 阶段，并且默认被启用：&lt;/p>
&lt;!--
- [Feature gates](/docs/reference/command-line-tools-reference/feature-gates/)
- `TranslateStreamCloseWebsocketRequests`
- `.../exec`
- `.../attach`
- `PortForwardWebsockets`
- `.../port-forward`
- kubectl feature control environment variables
- `KUBECTL_REMOTE_COMMAND_WEBSOCKETS`
- `kubectl exec`
- `kubectl cp`
- `kubectl attach`
- `KUBECTL_PORT_FORWARD_WEBSOCKETS`
- `kubectl port-forward`
-->
&lt;ul>
&lt;li>&lt;a href="https://kubernetes.io/zh-cn/docs/reference/command-line-tools-reference/feature-gates/">特性门控&lt;/a>
&lt;ul>
&lt;li>&lt;code>TranslateStreamCloseWebsocketRequests&lt;/code>
&lt;ul>
&lt;li>&lt;code>.../exec&lt;/code>&lt;/li>
&lt;li>&lt;code>.../attach&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;code>PortForwardWebsockets&lt;/code>
&lt;ul>
&lt;li>&lt;code>.../port-forward&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>kubectl 特性控制环境变量
&lt;ul>
&lt;li>&lt;code>KUBECTL_REMOTE_COMMAND_WEBSOCKETS&lt;/code>
&lt;ul>
&lt;li>&lt;code>kubectl exec&lt;/code>&lt;/li>
&lt;li>&lt;code>kubectl cp&lt;/code>&lt;/li>
&lt;li>&lt;code>kubectl attach&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;code>KUBECTL_PORT_FORWARD_WEBSOCKETS&lt;/code>
&lt;ul>
&lt;li>&lt;code>kubectl port-forward&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;!--
If you're connecting to an older cluster but can manage the feature gate
settings, turn on both `TranslateStreamCloseWebsocketRequests` (added in
Kubernetes v1.29) and `PortForwardWebsockets` (added in Kubernetes
v1.30) to try this new behavior. Version 1.31 of `kubectl` can automatically use
the new behavior, but you do need to connect to a cluster where the server-side
features are explicitly enabled.
-->
&lt;p>如果你正在使用一个较旧的集群但可以管理其特性门控设置，
那么可以通过开启 &lt;code>TranslateStreamCloseWebsocketRequests&lt;/code>（在 Kubernetes v1.29 中添加）
和 &lt;code>PortForwardWebsockets&lt;/code>（在 Kubernetes v1.30 中添加）来尝试启用 Websocket 作为流式传输协议。
版本为 1.31 的 kubectl 可以自动使用新的行为，但你需要连接到明确启用了服务器端特性的集群。&lt;/p>
&lt;!--
## Learn more about streaming APIs
- [KEP 4006 - Transitioning from SPDY to WebSockets](https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/4006-transition-spdy-to-websockets)
- [RFC 6455 - The WebSockets Protocol](https://datatracker.ietf.org/doc/html/rfc6455)
- [Container Runtime Interface streaming explained](https://kubernetes.io/blog/2024/05/01/cri-streaming-explained/)
-->
&lt;h2 id="了解有关流式-api-的更多信息">了解有关流式 API 的更多信息&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/4006-transition-spdy-to-websockets">KEP 4006 - Transitioning from SPDY to WebSockets（英文）&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://datatracker.ietf.org/doc/html/rfc6455">RFC 6455 - The WebSockets Protocol（英文）&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://kubernetes.io/blog/2024/05/01/cri-streaming-explained/">Container Runtime Interface streaming explained（英文）&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Kubernetes 1.31：针对 Job 的 Pod 失效策略进阶至 GA</title><link>https://kubernetes.io/zh-cn/blog/2024/08/19/kubernetes-1-31-pod-failure-policy-for-jobs-goes-ga/</link><pubDate>Mon, 19 Aug 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/08/19/kubernetes-1-31-pod-failure-policy-for-jobs-goes-ga/</guid><description>
&lt;!--
layout: blog
title: "Kubernetes 1.31: Pod Failure Policy for Jobs Goes GA"
date: 2024-08-19
slug: kubernetes-1-31-pod-failure-policy-for-jobs-goes-ga
author: >
[Michał Woźniak](https://github.com/mimowo) (Google),
[Shannon Kularathna](https://github.com/shannonxtreme) (Google)
-->
&lt;!--
This post describes _Pod failure policy_, which graduates to stable in Kubernetes
1.31, and how to use it in your Jobs.
-->
&lt;p>这篇博文阐述在 Kubernetes 1.31 中进阶至 Stable 的 &lt;strong>Pod 失效策略&lt;/strong>，还介绍如何在你的 Job 中使用此策略。&lt;/p>
&lt;!--
## About Pod failure policy
When you run workloads on Kubernetes, Pods might fail for a variety of reasons.
Ideally, workloads like Jobs should be able to ignore transient, retriable
failures and continue running to completion.
-->
&lt;h2 id="关于-pod-失效策略">关于 Pod 失效策略&lt;/h2>
&lt;p>当你在 Kubernetes 上运行工作负载时，Pod 可能因各种原因而失效。
理想情况下，像 Job 这样的工作负载应该能够忽略瞬时的、可重试的失效，并继续运行直到完成。&lt;/p>
&lt;!--
To allow for these transient failures, Kubernetes Jobs include the `backoffLimit`
field, which lets you specify a number of Pod failures that you're willing to tolerate
during Job execution. However, if you set a large value for the `backoffLimit` field
and rely solely on this field, you might notice unnecessary increases in operating
costs as Pods restart excessively until the backoffLimit is met.
-->
&lt;p>要允许这些瞬时的失效，Kubernetes Job 需包含 &lt;code>backoffLimit&lt;/code> 字段，
此字段允许你指定在 Job 执行期间你愿意容忍的 Pod 失效次数。然而，
如果你为 &lt;code>backoffLimit&lt;/code> 字段设置了一个较大的值，并完全依赖这个字段，
你可能会发现，由于在满足 backoffLimit 条件之前 Pod 重启次数太多，导致运营成本发生不必要的增加。&lt;/p>
&lt;!--
This becomes particularly problematic when running large-scale Jobs with
thousands of long-running Pods across thousands of nodes.
The Pod failure policy extends the backoff limit mechanism to help you reduce
costs in the following ways:
- Gives you control to fail the Job as soon as a non-retriable Pod failure occurs.
- Allows you to ignore retriable errors without increasing the `backoffLimit` field.
-->
&lt;p>在运行大规模的、包含跨数千节点且长时间运行的 Pod 的 Job 时，这个问题尤其严重。&lt;/p>
&lt;p>Pod 失效策略扩展了回退限制机制，帮助你通过以下方式降低成本：&lt;/p>
&lt;ul>
&lt;li>让你在出现不可重试的 Pod 失效时控制 Job 失败。&lt;/li>
&lt;li>允许你忽略可重试的错误，而不增加 &lt;code>backoffLimit&lt;/code> 字段。&lt;/li>
&lt;/ul>
&lt;!--
For example, you can use a Pod failure policy to run your workload on more affordable spot machines
by ignoring Pod failures caused by
[graceful node shutdown](/docs/concepts/cluster-administration/node-shutdown/#graceful-node-shutdown).
The policy allows you to distinguish between retriable and non-retriable Pod
failures based on container exit codes or Pod conditions in a failed Pod.
-->
&lt;p>例如，通过忽略由&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/cluster-administration/node-shutdown/#graceful-node-shutdown">节点体面关闭&lt;/a>引起的
Pod 失效，你可以使用 Pod 失效策略在更实惠的临时机器上运行你的工作负载。&lt;/p>
&lt;p>此策略允许你基于失效 Pod 中的容器退出码或 Pod 状况来区分可重试和不可重试的 Pod 失效。&lt;/p>
&lt;!--
## How it works
You specify a Pod failure policy in the Job specification, represented as a list
of rules.
For each rule you define _match requirements_ based on one of the following properties:
- Container exit codes: the `onExitCodes` property.
- Pod conditions: the `onPodConditions` property.
-->
&lt;h2 id="它是如何工作的">它是如何工作的&lt;/h2>
&lt;p>你在 Job 规约中指定的 Pod 失效策略是一个规则的列表。&lt;/p>
&lt;p>对于每个规则，你基于以下属性之一来定义&lt;strong>匹配条件&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>容器退出码：&lt;code>onExitCodes&lt;/code> 属性。&lt;/li>
&lt;li>Pod 状况：&lt;code>onPodConditions&lt;/code> 属性。&lt;/li>
&lt;/ul>
&lt;!--
Additionally, for each rule, you specify one of the following actions to take
when a Pod matches the rule:
- `Ignore`: Do not count the failure towards the `backoffLimit` or `backoffLimitPerIndex`.
- `FailJob`: Fail the entire Job and terminate all running Pods.
- `FailIndex`: Fail the index corresponding to the failed Pod.
This action works with the [Backoff limit per index](/docs/concepts/workloads/controllers/job/#backoff-limit-per-index) feature.
- `Count`: Count the failure towards the `backoffLimit` or `backoffLimitPerIndex`.
This is the default behavior.
-->
&lt;p>此外，对于每个规则，你要指定在 Pod 与此规则匹配时应采取的动作，可选动作为以下之一：&lt;/p>
&lt;ul>
&lt;li>&lt;code>Ignore&lt;/code>：不将失效计入 &lt;code>backoffLimit&lt;/code> 或 &lt;code>backoffLimitPerIndex&lt;/code>。&lt;/li>
&lt;li>&lt;code>FailJob&lt;/code>：让整个 Job 失败并终止所有运行的 Pod。&lt;/li>
&lt;li>&lt;code>FailIndex&lt;/code>：与失效 Pod 对应的索引失效。&lt;br>
此动作与&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/job/#backoff-limit-per-index">逐索引回退限制&lt;/a>特性一起使用。&lt;/li>
&lt;li>&lt;code>Count&lt;/code>：将失效计入 &lt;code>backoffLimit&lt;/code> 或 &lt;code>backoffLimitPerIndex&lt;/code>。这是默认行为。&lt;/li>
&lt;/ul>
&lt;!--
When Pod failures occur in a running Job, Kubernetes matches the
failed Pod status against the list of Pod failure policy rules, in the specified
order, and takes the corresponding actions for the first matched rule.
Note that when specifying the Pod failure policy, you must also set the Job's
Pod template with `restartPolicy: Never`. This prevents race conditions between
the kubelet and the Job controller when counting Pod failures.
-->
&lt;p>当在运行的 Job 中发生 Pod 失效时，Kubernetes 按所给的顺序将失效 Pod 的状态与
Pod 失效策略规则的列表进行匹配，并根据匹配的第一个规则采取相应的动作。&lt;/p>
&lt;p>请注意，在指定 Pod 失效策略时，你还必须在 Job 的 Pod 模板中设置 &lt;code>restartPolicy: Never&lt;/code>。
此字段可以防止在对 Pod 失效计数时在 kubelet 和 Job 控制器之间出现竞争条件。&lt;/p>
&lt;!--
### Kubernetes-initiated Pod disruptions
To allow matching Pod failure policy rules against failures caused by
disruptions initiated by Kubernetes, this feature introduces the `DisruptionTarget`
Pod condition.
Kubernetes adds this condition to any Pod, regardless of whether it's managed by
a Job controller, that fails because of a retriable
[disruption scenario](/docs/concepts/workloads/pods/disruptions/#pod-disruption-conditions).
The `DisruptionTarget` condition contains one of the following reasons that
corresponds to these disruption scenarios:
-->
&lt;h3 id="kubernetes-发起的-pod-干扰">Kubernetes 发起的 Pod 干扰&lt;/h3>
&lt;p>为了允许将 Pod 失效策略规则与由 Kubernetes 引发的干扰所导致的失效进行匹配，
此特性引入了 &lt;code>DisruptionTarget&lt;/code> Pod 状况。&lt;/p>
&lt;p>Kubernetes 会将此状况添加到因可重试的&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/disruptions/#pod-disruption-conditions">干扰场景&lt;/a>而失效的所有
Pod，无论其是否由 Job 控制器管理。其中 &lt;code>DisruptionTarget&lt;/code> 状况包含与这些干扰场景对应的以下原因之一：&lt;/p>
&lt;!--
- `PreemptionByKubeScheduler`: [Preemption](/docs/concepts/scheduling-eviction/pod-priority-preemption)
by `kube-scheduler` to accommodate a new Pod that has a higher priority.
- `DeletionByTaintManager` - the Pod is due to be deleted by
`kube-controller-manager` due to a `NoExecute` [taint](/docs/concepts/scheduling-eviction/taint-and-toleration/)
that the Pod doesn't tolerate.
- `EvictionByEvictionAPI` - the Pod is due to be deleted by an
[API-initiated eviction](/docs/concepts/scheduling-eviction/api-eviction/).
- `DeletionByPodGC` - the Pod is bound to a node that no longer exists, and is due to
be deleted by [Pod garbage collection](/docs/concepts/workloads/pods/pod-lifecycle/#pod-garbage-collection).
- `TerminationByKubelet` - the Pod was terminated by
[graceful node shutdown](/docs/concepts/cluster-administration/node-shutdown/#graceful-node-shutdown),
[node pressure eviction](/docs/concepts/scheduling-eviction/node-pressure-eviction/)
or preemption for [system critical pods](/docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods/).
-->
&lt;ul>
&lt;li>&lt;code>PreemptionByKubeScheduler&lt;/code>：由 &lt;code>kube-scheduler&lt;/code>
&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/pod-priority-preemption">抢占&lt;/a>以接纳更高优先级的新 Pod。&lt;/li>
&lt;li>&lt;code>DeletionByTaintManager&lt;/code> - Pod 因其不容忍的 &lt;code>NoExecute&lt;/code>
&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/taint-and-toleration/">污点&lt;/a>而被 &lt;code>kube-controller-manager&lt;/code> 删除。&lt;/li>
&lt;li>&lt;code>EvictionByEvictionAPI&lt;/code> - Pod 因为 &lt;a href="https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/api-eviction/">API 发起的驱逐&lt;/a>而被删除。&lt;/li>
&lt;li>&lt;code>DeletionByPodGC&lt;/code> - Pod 被绑定到一个不再存在的节点，并将通过
&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/pod-lifecycle/#pod-garbage-collection">Pod 垃圾收集&lt;/a>而被删除。&lt;/li>
&lt;li>&lt;code>TerminationByKubelet&lt;/code> - Pod 因&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/cluster-administration/node-shutdown/#graceful-node-shutdown">节点体面关闭&lt;/a>、
&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/node-pressure-eviction/">节点压力驱逐&lt;/a>或被&lt;a href="https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods/">系统关键 Pod&lt;/a>抢占&lt;/li>
&lt;/ul>
&lt;!--
In all other disruption scenarios, like eviction due to exceeding
[Pod container limits](/docs/concepts/configuration/manage-resources-containers/),
Pods don't receive the `DisruptionTarget` condition because the disruptions were
likely caused by the Pod and would reoccur on retry.
### Example
The Pod failure policy snippet below demonstrates an example use:
-->
&lt;p>在所有其他干扰场景中，例如因超过
&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/configuration/manage-resources-containers/">Pod 容器限制&lt;/a>而驱逐，
Pod 不会收到 &lt;code>DisruptionTarget&lt;/code> 状况，因为干扰可能是由 Pod 引起的，并且在重试时会再次发生干扰。&lt;/p>
&lt;h3 id="示例">示例&lt;/h3>
&lt;p>下面的 Pod 失效策略片段演示了一种用法：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">podFailurePolicy&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">rules&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">action&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Ignore&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">onPodConditions&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">type&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>DisruptionTarget&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">action&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>FailJob&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">onPodConditions&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">type&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ConfigIssue&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">action&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>FailJob&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">onExitCodes&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">operator&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>In&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">values&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>[&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#666">42&lt;/span>&lt;span style="color:#bbb"> &lt;/span>]&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
In this example, the Pod failure policy does the following:
- Ignores any failed Pods that have the built-in `DisruptionTarget`
condition. These Pods don't count towards Job backoff limits.
- Fails the Job if any failed Pods have the custom user-supplied
`ConfigIssue` condition, which was added either by a custom controller or webhook.
- Fails the Job if any containers exited with the exit code 42.
- Counts all other Pod failures towards the default `backoffLimit` (or
`backoffLimitPerIndex` if used).
-->
&lt;p>在这个例子中，Pod 失效策略执行以下操作：&lt;/p>
&lt;ul>
&lt;li>忽略任何具有内置 &lt;code>DisruptionTarget&lt;/code> 状况的失效 Pod。这些 Pod 不计入 Job 回退限制。&lt;/li>
&lt;li>如果任何失效的 Pod 具有用户自定义的、由自定义控制器或 Webhook 添加的 &lt;code>ConfigIssue&lt;/code>
状况，则让 Job 失败。&lt;/li>
&lt;li>如果任何容器以退出码 42 退出，则让 Job 失败。&lt;/li>
&lt;li>将所有其他 Pod 失效计入默认的 &lt;code>backoffLimit&lt;/code>（在合适的情况下，计入 &lt;code>backoffLimitPerIndex&lt;/code>）。&lt;/li>
&lt;/ul>
&lt;!--
## Learn more
- For a hands-on guide to using Pod failure policy, see
[Handling retriable and non-retriable pod failures with Pod failure policy](/docs/tasks/job/pod-failure-policy/)
- Read the documentation for
[Pod failure policy](/docs/concepts/workloads/controllers/job/#pod-failure-policy) and
[Backoff limit per index](/docs/concepts/workloads/controllers/job/#backoff-limit-per-index)
- Read the documentation for
[Pod disruption conditions](/docs/concepts/workloads/pods/disruptions/#pod-disruption-conditions)
- Read the KEP for [Pod failure policy](https://github.com/kubernetes/enhancements/tree/master/keps/sig-apps/3329-retriable-and-non-retriable-failures)
-->
&lt;h2 id="进一步了解">进一步了解&lt;/h2>
&lt;ul>
&lt;li>有关使用 Pod 失效策略的实践指南，
参见&lt;a href="https://kubernetes.io/zh-cn/docs/tasks/job/pod-failure-policy/">使用 Pod 失效策略处理可重试和不可重试的 Pod 失效&lt;/a>&lt;/li>
&lt;li>阅读文档：&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/job/#pod-failure-policy">Pod 失效策略&lt;/a>和&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/job/#backoff-limit-per-index">逐索引回退限制&lt;/a>&lt;/li>
&lt;li>阅读文档：&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/disruptions/#pod-disruption-conditions">Pod 干扰状况&lt;/a>&lt;/li>
&lt;li>阅读 KEP：&lt;a href="https://github.com/kubernetes/enhancements/tree/master/keps/sig-apps/3329-retriable-and-non-retriable-failures">Pod 失效策略&lt;/a>&lt;/li>
&lt;/ul>
&lt;!--
## Related work
Based on the concepts introduced by Pod failure policy, the following additional work is in progress:
- JobSet integration: [Configurable Failure Policy API](https://github.com/kubernetes-sigs/jobset/issues/262)
- [Pod failure policy extension to add more granular failure reasons](https://github.com/kubernetes/enhancements/issues/4443)
- Support for Pod failure policy via JobSet in [Kubeflow Training v2](https://github.com/kubeflow/training-operator/pull/2171)
- Proposal: [Disrupted Pods should be removed from endpoints](https://docs.google.com/document/d/1t25jgO_-LRHhjRXf4KJ5xY_t8BZYdapv7MDAxVGY6R8)
-->
&lt;h2 id="相关工作">相关工作&lt;/h2>
&lt;p>基于 Pod 失效策略所引入的概念，正在进行中的进一步工作如下：&lt;/p>
&lt;ul>
&lt;li>JobSet 集成：&lt;a href="https://github.com/kubernetes-sigs/jobset/issues/262">可配置的失效策略 API&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes/enhancements/issues/4443">扩展 Pod 失效策略以添加更细粒度的失效原因&lt;/a>&lt;/li>
&lt;li>通过 JobSet 在 &lt;a href="https://github.com/kubeflow/training-operator/pull/2171">Kubeflow Training v2&lt;/a>
中支持 Pod 失效策略&lt;/li>
&lt;li>提案：&lt;a href="https://docs.google.com/document/d/1t25jgO_-LRHhjRXf4KJ5xY_t8BZYdapv7MDAxVGY6R8">受干扰的 Pod 应从端点中移除&lt;/a>&lt;/li>
&lt;/ul>
&lt;!--
## Get involved
This work was sponsored by
[batch working group](https://github.com/kubernetes/community/tree/master/wg-batch)
in close collaboration with the
[SIG Apps](https://github.com/kubernetes/community/tree/master/sig-apps),
and [SIG Node](https://github.com/kubernetes/community/tree/master/sig-node),
and [SIG Scheduling](https://github.com/kubernetes/community/tree/master/sig-scheduling)
communities.
-->
&lt;h2 id="参与其中">参与其中&lt;/h2>
&lt;p>这项工作由 &lt;a href="https://github.com/kubernetes/community/tree/master/wg-batch">Batch Working Group（批处理工作组）&lt;/a> 发起，
与 &lt;a href="https://github.com/kubernetes/community/tree/master/sig-apps">SIG Apps&lt;/a>、
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-node">SIG Node&lt;/a>
和 &lt;a href="https://github.com/kubernetes/community/tree/master/sig-scheduling">SIG Scheduling&lt;/a>
社区密切合作。&lt;/p>
&lt;!--
If you are interested in working on new features in the space we recommend
subscribing to our [Slack](https://kubernetes.slack.com/messages/wg-batch)
channel and attending the regular community meetings.
## Acknowledgments
I would love to thank everyone who was involved in this project over the years -
it's been a journey and a joint community effort! The list below is
my best-effort attempt to remember and recognize people who made an impact.
Thank you!
-->
&lt;p>如果你有兴趣处理这个领域中的新特性，建议你订阅我们的
&lt;a href="https://kubernetes.slack.com/messages/wg-batch">Slack&lt;/a> 频道，并参加定期的社区会议。&lt;/p>
&lt;h2 id="感谢">感谢&lt;/h2>
&lt;p>我想感谢在这些年里参与过这个项目的每个人。
这是一段旅程，也是一个社区共同努力的见证！
以下名单是我尽力记住并对此特性产生过影响的人。感谢大家！&lt;/p>
&lt;!--
- [Aldo Culquicondor](https://github.com/alculquicondor/) for guidance and reviews throughout the process
- [Jordan Liggitt](https://github.com/liggitt) for KEP and API reviews
- [David Eads](https://github.com/deads2k) for API reviews
- [Maciej Szulik](https://github.com/soltysh) for KEP reviews from SIG Apps PoV
- [Clayton Coleman](https://github.com/smarterclayton) for guidance and SIG Node reviews
- [Sergey Kanzhelev](https://github.com/SergeyKanzhelev) for KEP reviews from SIG Node PoV
- [Dawn Chen](https://github.com/dchen1107) for KEP reviews from SIG Node PoV
- [Daniel Smith](https://github.com/lavalamp) for reviews from SIG API machinery PoV
- [Antoine Pelisse](https://github.com/apelisse) for reviews from SIG API machinery PoV
- [John Belamaric](https://github.com/johnbelamaric) for PRR reviews
- [Filip Křepinský](https://github.com/atiratree) for thorough reviews from SIG Apps PoV and bug-fixing
- [David Porter](https://github.com/bobbypage) for thorough reviews from SIG Node PoV
- [Jensen Lo](https://github.com/jensentanlo) for early requirements discussions, testing and reporting issues
- [Daniel Vega-Myhre](https://github.com/danielvegamyhre) for advancing JobSet integration and reporting issues
- [Abdullah Gharaibeh](https://github.com/ahg-g) for early design discussions and guidance
- [Antonio Ojea](https://github.com/aojea) for test reviews
- [Yuki Iwai](https://github.com/tenzen-y) for reviews and aligning implementation of the closely related Job features
- [Kevin Hannon](https://github.com/kannon92) for reviews and aligning implementation of the closely related Job features
- [Tim Bannister](https://github.com/sftim) for docs reviews
- [Shannon Kularathna](https://github.com/shannonxtreme) for docs reviews
- [Paola Cortés](https://github.com/cortespao) for docs reviews
-->
&lt;ul>
&lt;li>&lt;a href="https://github.com/alculquicondor/">Aldo Culquicondor&lt;/a> 在整个过程中提供指导和审查&lt;/li>
&lt;li>&lt;a href="https://github.com/liggitt">Jordan Liggitt&lt;/a> 审查 KEP 和 API&lt;/li>
&lt;li>&lt;a href="https://github.com/deads2k">David Eads&lt;/a> 审查 API&lt;/li>
&lt;li>&lt;a href="https://github.com/soltysh">Maciej Szulik&lt;/a> 从 SIG Apps 角度审查 KEP&lt;/li>
&lt;li>&lt;a href="https://github.com/smarterclayton">Clayton Coleman&lt;/a> 提供指导和 SIG Node 审查&lt;/li>
&lt;li>&lt;a href="https://github.com/SergeyKanzhelev">Sergey Kanzhelev&lt;/a> 从 SIG Node 角度审查 KEP&lt;/li>
&lt;li>&lt;a href="https://github.com/dchen1107">Dawn Chen&lt;/a> 从 SIG Node 角度审查 KEP&lt;/li>
&lt;li>&lt;a href="https://github.com/lavalamp">Daniel Smith&lt;/a> 从 SIG API Machinery 角度进行审查&lt;/li>
&lt;li>&lt;a href="https://github.com/apelisse">Antoine Pelisse&lt;/a> 从 SIG API Machinery 角度进行审查&lt;/li>
&lt;li>&lt;a href="https://github.com/johnbelamaric">John Belamaric&lt;/a> 审查 PRR&lt;/li>
&lt;li>&lt;a href="https://github.com/atiratree">Filip Křepinský&lt;/a> 从 SIG Apps 角度进行全面审查并修复 Bug&lt;/li>
&lt;li>&lt;a href="https://github.com/bobbypage">David Porter&lt;/a> 从 SIG Node 角度进行全面审查&lt;/li>
&lt;li>&lt;a href="https://github.com/jensentanlo">Jensen Lo&lt;/a> 进行早期需求讨论、测试和报告问题&lt;/li>
&lt;li>&lt;a href="https://github.com/danielvegamyhre">Daniel Vega-Myhre&lt;/a> 推进 JobSet 集成并报告问题&lt;/li>
&lt;li>&lt;a href="https://github.com/ahg-g">Abdullah Gharaibeh&lt;/a> 进行早期设计讨论和指导&lt;/li>
&lt;li>&lt;a href="https://github.com/aojea">Antonio Ojea&lt;/a> 审查测试&lt;/li>
&lt;li>&lt;a href="https://github.com/tenzen-y">Yuki Iwai&lt;/a> 审查并协调相关 Job 特性的实现&lt;/li>
&lt;li>&lt;a href="https://github.com/kannon92">Kevin Hannon&lt;/a> 审查并协调相关 Job 特性的实现&lt;/li>
&lt;li>&lt;a href="https://github.com/sftim">Tim Bannister&lt;/a> 审查文档&lt;/li>
&lt;li>&lt;a href="https://github.com/shannonxtreme">Shannon Kularathna&lt;/a> 审查文档&lt;/li>
&lt;li>&lt;a href="https://github.com/cortespao">Paola Cortés&lt;/a> 审查文档&lt;/li>
&lt;/ul></description></item><item><title>Kubernetes 1.31：podAffinity 中的 matchLabelKeys 进阶至 Beta</title><link>https://kubernetes.io/zh-cn/blog/2024/08/16/matchlabelkeys-podaffinity/</link><pubDate>Fri, 16 Aug 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/08/16/matchlabelkeys-podaffinity/</guid><description>
&lt;!--
layout: blog
title: 'Kubernetes 1.31: MatchLabelKeys in PodAffinity graduates to beta'
date: 2024-08-16
slug: matchlabelkeys-podaffinity
author: >
Kensei Nakada (Tetrate)
-->
&lt;!--
Kubernetes 1.29 introduced new fields `matchLabelKeys` and `mismatchLabelKeys` in `podAffinity` and `podAntiAffinity`.
In Kubernetes 1.31, this feature moves to beta and the corresponding feature gate (`MatchLabelKeysInPodAffinity`) gets enabled by default.
-->
&lt;p>Kubernetes 1.29 在 &lt;code>podAffinity&lt;/code> 和 &lt;code>podAntiAffinity&lt;/code> 中引入了新的字段 &lt;code>matchLabelKeys&lt;/code> 和 &lt;code>mismatchLabelKeys&lt;/code>。&lt;/p>
&lt;p>在 Kubernetes 1.31 中，此特性进阶至 Beta，并且相应的特性门控（&lt;code>MatchLabelKeysInPodAffinity&lt;/code>）默认启用。&lt;/p>
&lt;!--
## `matchLabelKeys` - Enhanced scheduling for versatile rolling updates
During a workload's (e.g., Deployment) rolling update, a cluster may have Pods from multiple versions at the same time.
However, the scheduler cannot distinguish between old and new versions based on the `labelSelector` specified in `podAffinity` or `podAntiAffinity`. As a result, it will co-locate or disperse Pods regardless of their versions.
-->
&lt;h2 id="matchlabelkeys-为多样化滚动更新增强了调度">&lt;code>matchLabelKeys&lt;/code> - 为多样化滚动更新增强了调度&lt;/h2>
&lt;p>在工作负载（例如 Deployment）的滚动更新期间，集群中可能同时存在多个版本的 Pod。&lt;br>
然而，调度器无法基于 &lt;code>podAffinity&lt;/code> 或 &lt;code>podAntiAffinity&lt;/code> 中指定的 &lt;code>labelSelector&lt;/code> 区分新旧版本。
结果，调度器将并置或分散调度 Pod，不会考虑这些 Pod 的版本。&lt;/p>
&lt;!--
This can lead to sub-optimal scheduling outcome, for example:
- New version Pods are co-located with old version Pods (`podAffinity`), which will eventually be removed after rolling updates.
- Old version Pods are distributed across all available topologies, preventing new version Pods from finding nodes due to `podAntiAffinity`.
-->
&lt;p>这可能导致次优的调度结果，例如：&lt;/p>
&lt;ul>
&lt;li>新版本的 Pod 与旧版本的 Pod（&lt;code>podAffinity&lt;/code>）并置在一起，这些旧版本的 Pod 最终将在滚动更新后被移除。&lt;/li>
&lt;li>旧版本的 Pod 被分布在所有可用的拓扑中，导致新版本的 Pod 由于 &lt;code>podAntiAffinity&lt;/code> 无法找到节点。&lt;/li>
&lt;/ul>
&lt;!--
`matchLabelKeys` is a set of Pod label keys and addresses this problem.
The scheduler looks up the values of these keys from the new Pod's labels and combines them with `labelSelector`
so that podAffinity matches Pods that have the same key-value in labels.
By using label [pod-template-hash](/docs/concepts/workloads/controllers/deployment/#pod-template-hash-label) in `matchLabelKeys`,
you can ensure that only Pods of the same version are evaluated for `podAffinity` or `podAntiAffinity`.
-->
&lt;p>&lt;code>matchLabelKeys&lt;/code> 是一组 Pod 标签键，可以解决上述问题。&lt;br>
调度器从新 Pod 的标签中查找这些键的值，并将其与 &lt;code>labelSelector&lt;/code> 结合，
以便 &lt;code>podAffinity&lt;/code> 匹配到具有相同标签键值的 Pod。&lt;/p>
&lt;p>通过在 &lt;code>matchLabelKeys&lt;/code> 中使用标签
&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/deployment/#pod-template-hash-label">pod-template-hash&lt;/a>，&lt;br>
你可以确保对 &lt;code>podAffinity&lt;/code> 或 &lt;code>podAntiAffinity&lt;/code> 进行评估时仅考虑相同版本的 Pod。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>apps/v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Deployment&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>application-server&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#00f;font-weight:bold">...&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">affinity&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">podAffinity&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">requiredDuringSchedulingIgnoredDuringExecution&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">labelSelector&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">matchExpressions&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">key&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>app&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">operator&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>In&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">values&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- database&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">topologyKey&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>topology.kubernetes.io/zone&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">matchLabelKeys&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- pod-template-hash&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
The above `matchLabelKeys` will be translated in Pods like:
-->
&lt;p>上述 Pod 中的 &lt;code>matchLabelKeys&lt;/code> 将被转换为：&lt;/p>
&lt;!--
# Added from matchLabelKeys; Only Pods from the same replicaset will match this affinity.
-->
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Pod&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>application-server&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">labels&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">pod-template-hash&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>xyz&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#00f;font-weight:bold">...&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">affinity&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">podAffinity&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">requiredDuringSchedulingIgnoredDuringExecution&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">labelSelector&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">matchExpressions&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">key&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>app&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">operator&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>In&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">values&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- database&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">key&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>pod-template-hash&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#080;font-style:italic"># 从 matchLabelKeys 添加; 只有来自同一 ReplicaSet 的 Pod 将与此亲和性匹配&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">operator&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>In&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">values&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- xyz &lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">topologyKey&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>topology.kubernetes.io/zone&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">matchLabelKeys&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- pod-template-hash&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
## `mismatchLabelKeys` - Service isolation
`mismatchLabelKeys` is a set of Pod label keys, like `matchLabelKeys`,
which looks up the values of these keys from the new Pod's labels, and merge them with `labelSelector` as `key notin (value)`
so that `podAffinity` does _not_ match Pods that have the same key-value in labels.
Suppose all Pods for each tenant get `tenant` label via a controller or a manifest management tool like Helm.
-->
&lt;h2 id="mismatchlabelkeys-服务隔离">&lt;code>mismatchLabelKeys&lt;/code> - 服务隔离&lt;/h2>
&lt;p>&lt;code>mismatchLabelKeys&lt;/code> 是一组 Pod 标签键，类似于 &lt;code>matchLabelKeys&lt;/code>，&lt;br>
它在新 Pod 的标签中查找这些键的值，并将其与 &lt;code>labelSelector&lt;/code> 合并为 &lt;code>key notin (value)&lt;/code>，
以便 &lt;code>podAffinity&lt;/code> &lt;strong>不&lt;/strong>会匹配到具有相同标签键值的 Pod。&lt;/p>
&lt;p>假设每个租户的所有 Pod 通过控制器或像 Helm 这样的清单管理工具得到 &lt;code>tenant&lt;/code> 标签。&lt;/p>
&lt;!--
Although the value of `tenant` label is unknown when composing each workload's manifest,
the cluster admin wants to achieve exclusive 1:1 tenant to domain placement for a tenant isolation.
`mismatchLabelKeys` works for this usecase;
By applying the following affinity globally using a mutating webhook,
the cluster admin can ensure that the Pods from the same tenant will land on the same domain exclusively,
meaning Pods from other tenants won't land on the same domain.
-->
&lt;p>尽管在组合每个工作负载的清单时，&lt;code>tenant&lt;/code> 标签的值是未知的，&lt;br>
但集群管理员希望实现租户与域之间形成排他性的 1:1 对应关系，以便隔离租户。&lt;/p>
&lt;p>&lt;code>mismatchLabelKeys&lt;/code> 适用于这一使用场景；&lt;br>
通过使用变更性质的 Webhook 在全局应用以下亲和性，
集群管理员可以确保来自同一租户的 Pod 将以独占方式落到同一域上，&lt;br>
这意味着来自其他租户的 Pod 不会落到同一域上。&lt;/p>
&lt;!--
```yaml
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
```
-->
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">affinity&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">podAffinity&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#080;font-style:italic"># 确保此租户的 Pod 落在同一节点池上&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">requiredDuringSchedulingIgnoredDuringExecution&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">matchLabelKeys&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- tenant&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">topologyKey&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>node-pool&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">podAntiAffinity&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#080;font-style:italic"># 确保只有此租户的 Pod 落在同一节点池上&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">requiredDuringSchedulingIgnoredDuringExecution&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">mismatchLabelKeys&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- tenant&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">labelSelector&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">matchExpressions&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">key&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>tenant&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">operator&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Exists&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">topologyKey&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>node-pool&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
The above `matchLabelKeys` and `mismatchLabelKeys` will be translated to like:
-->
&lt;p>上述的 &lt;code>matchLabelKeys&lt;/code> 和 &lt;code>mismatchLabelKeys&lt;/code> 将被转换为：&lt;/p>
&lt;!--
```yaml
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
```
-->
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Pod&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>application-server&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">labels&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">tenant&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>service-a&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">affinity&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">podAffinity&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#080;font-style:italic"># 确保此租户的 Pod 落在同一节点池上&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">requiredDuringSchedulingIgnoredDuringExecution&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">matchLabelKeys&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- tenant&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">topologyKey&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>node-pool&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">labelSelector&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">matchExpressions&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">key&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>tenant&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">operator&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>In&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">values&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- service-a &lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">podAntiAffinity&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#080;font-style:italic"># 确保只有此租户的 Pod 落在同一节点池上&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">requiredDuringSchedulingIgnoredDuringExecution&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">mismatchLabelKeys&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- tenant&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">labelSelector&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">matchExpressions&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">key&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>tenant&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">operator&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Exists&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">key&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>tenant&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">operator&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>NotIn&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">values&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- service-a &lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">topologyKey&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>node-pool&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
## Getting involved
These features are managed by Kubernetes [SIG Scheduling](https://github.com/kubernetes/community/tree/master/sig-scheduling).
Please join us and share your feedback. We look forward to hearing from you!
-->
&lt;h2 id="参与其中">参与其中&lt;/h2>
&lt;p>这些特性由 Kubernetes
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-scheduling">SIG Scheduling&lt;/a> 管理。&lt;/p>
&lt;p>请加入我们并分享你的反馈。我们期待听到你的声音！&lt;/p>
&lt;!--
## How can I learn more?
- [The official document of podAffinity](/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity)
- [KEP-3633: Introduce matchLabelKeys and mismatchLabelKeys to podAffinity and podAntiAffinity](https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/3633-matchlabelkeys-to-podaffinity/README.md#story-2)
-->
&lt;h2 id="了解更多">了解更多&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity">podAffinity 的官方文档&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/3633-matchlabelkeys-to-podaffinity/README.md#story-2">KEP-3633：将 matchLabelKeys 和 mismatchLabelKeys 引入 podAffinity 和 podAntiAffinity&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Kubernetes 1.31：防止无序删除时 PersistentVolume 泄漏</title><link>https://kubernetes.io/zh-cn/blog/2024/08/16/kubernetes-1-31-prevent-persistentvolume-leaks-when-deleting-out-of-order/</link><pubDate>Fri, 16 Aug 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/08/16/kubernetes-1-31-prevent-persistentvolume-leaks-when-deleting-out-of-order/</guid><description>
&lt;!--
layout: blog
title: 'Kubernetes 1.31: Prevent PersistentVolume Leaks When Deleting out of Order'
date: 2024-08-16
slug: kubernetes-1-31-prevent-persistentvolume-leaks-when-deleting-out-of-order
author: >
Deepak Kinni (Broadcom)
-->
&lt;!--
[PersistentVolume](/docs/concepts/storage/persistent-volumes/) (or PVs for short) are
associated with [Reclaim Policy](/docs/concepts/storage/persistent-volumes/#reclaim-policy).
The reclaim policy is used to determine the actions that need to be taken by the storage
backend on deletion of the PVC Bound to a PV.
When the reclaim policy is `Delete`, the expectation is that the storage backend
releases the storage resource allocated for the PV. In essence, the reclaim
policy needs to be honored on PV deletion.
With the recent Kubernetes v1.31 release, a beta feature lets you configure your
cluster to behave that way and honor the configured reclaim policy.
-->
&lt;p>&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/">PersistentVolume&lt;/a>（简称 PV）
具有与之关联的&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/#reclaim-policy">回收策略&lt;/a>。
回收策略用于确定在删除绑定到 PV 的 PVC 时存储后端需要采取的操作。当回收策略为 &lt;code>Delete&lt;/code> 时，
期望存储后端释放为 PV 所分配的存储资源。实际上，在 PV 被删除时就需要执行此回收策略。&lt;/p>
&lt;p>在最近发布的 Kubernetes v1.31 版本中，一个 Beta 特性允许你配置集群以这种方式运行并执行你配置的回收策略。&lt;/p>
&lt;!--
## How did reclaim work in previous Kubernetes releases?
[PersistentVolumeClaim](/docs/concepts/storage/persistent-volumes/#Introduction) (or PVC for short) is
a user's request for storage. A PV and PVC are considered [Bound](/docs/concepts/storage/persistent-volumes/#Binding)
if a newly created PV or a matching PV is found. The PVs themselves are
backed by volumes allocated by the storage backend.
-->
&lt;h2 id="在以前的-kubernetes-版本中回收是如何工作的">在以前的 Kubernetes 版本中回收是如何工作的？&lt;/h2>
&lt;p>&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/#Introduction">PersistentVolumeClaim&lt;/a>
（简称 PVC）是用户对存储的请求。如果新创建了 PV 或找到了匹配的 PV，那么此 PV 和此 PVC
被视为&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/#Binding">已绑定&lt;/a>。
PV 本身是由存储后端所分配的卷支持的。&lt;/p>
&lt;!--
Normally, if the volume is to be deleted, then the expectation is to delete the
PVC for a bound PV-PVC pair. However, there are no restrictions on deleting a PV
before deleting a PVC.
First, I'll demonstrate the behavior for clusters running an older version of Kubernetes.
#### Retrieve a PVC that is bound to a PV
Retrieve an existing PVC `example-vanilla-block-pvc`
-->
&lt;p>通常，如果卷要被删除，对应的预期是为一个已绑定的 PV-PVC 对删除其中的 PVC。
不过，对于在删除 PVC 之前可否删除 PV 并没有限制。&lt;/p>
&lt;p>首先，我将演示运行旧版本 Kubernetes 的集群的行为。&lt;/p>
&lt;h4 id="检索绑定到-pv-的-pvc">检索绑定到 PV 的 PVC&lt;/h4>
&lt;p>检索现有的 PVC &lt;code>example-vanilla-block-pvc&lt;/code>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>kubectl get pvc example-vanilla-block-pvc
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
The following output shows the PVC and its bound PV; the PV is shown under the `VOLUME` column:
-->
&lt;p>以下输出显示了 PVC 及其绑定的 PV；此 PV 显示在 &lt;code>VOLUME&lt;/code> 列下：&lt;/p>
&lt;pre tabindex="0">&lt;code>NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
example-vanilla-block-pvc Bound pvc-6791fdd4-5fad-438e-a7fb-16410363e3da 5Gi RWO example-vanilla-block-sc 19s
&lt;/code>&lt;/pre>&lt;!--
#### Delete PV
When I try to delete a bound PV, the kubectl session blocks and the `kubectl`
tool does not return back control to the shell; for example:
-->
&lt;h4 id="删除-pv">删除 PV&lt;/h4>
&lt;p>当我尝试删除已绑定的 PV 时，kubectl 会话被阻塞，
且 &lt;code>kubectl&lt;/code> 工具不会将控制权返回给 Shell；例如：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>kubectl delete pv pvc-6791fdd4-5fad-438e-a7fb-16410363e3da
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;pre tabindex="0">&lt;code>persistentvolume &amp;#34;pvc-6791fdd4-5fad-438e-a7fb-16410363e3da&amp;#34; deleted
^C
&lt;/code>&lt;/pre>&lt;!--
#### Retrieving the PV
-->
&lt;h4 id="检索-pv">检索 PV&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>kubectl get pv pvc-6791fdd4-5fad-438e-a7fb-16410363e3da
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
It can be observed that the PV is in a `Terminating` state
-->
&lt;p>你可以观察到 PV 处于 &lt;code>Terminating&lt;/code> 状态：&lt;/p>
&lt;pre tabindex="0">&lt;code>NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-6791fdd4-5fad-438e-a7fb-16410363e3da 5Gi RWO Delete Terminating default/example-vanilla-block-pvc example-vanilla-block-sc 2m23s
&lt;/code>&lt;/pre>&lt;!--
#### Delete PVC
-->
&lt;h4 id="删除-pvc">删除 PVC&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>kubectl delete pvc example-vanilla-block-pvc
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
The following output is seen if the PVC gets successfully deleted:
-->
&lt;p>如果 PVC 被成功删除，则会看到以下输出：&lt;/p>
&lt;pre tabindex="0">&lt;code>persistentvolumeclaim &amp;#34;example-vanilla-block-pvc&amp;#34; deleted
&lt;/code>&lt;/pre>&lt;!--
The PV object from the cluster also gets deleted. When attempting to retrieve the PV
it will be observed that the PV is no longer found:
-->
&lt;p>集群中的 PV 对象也被删除。当尝试检索 PV 时，你会观察到该 PV 已不再存在：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>kubectl get pv pvc-6791fdd4-5fad-438e-a7fb-16410363e3da
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;pre tabindex="0">&lt;code>Error from server (NotFound): persistentvolumes &amp;#34;pvc-6791fdd4-5fad-438e-a7fb-16410363e3da&amp;#34; not found
&lt;/code>&lt;/pre>&lt;!--
Although the PV is deleted, the underlying storage resource is not deleted and
needs to be removed manually.
To sum up, the reclaim policy associated with the PersistentVolume is currently
ignored under certain circumstances. For a `Bound` PV-PVC pair, the ordering of PV-PVC
deletion determines whether the PV reclaim policy is honored. The reclaim policy
is honored if the PVC is deleted first; however, if the PV is deleted prior to
deleting the PVC, then the reclaim policy is not exercised. As a result of this behavior,
the associated storage asset in the external infrastructure is not removed.
-->
&lt;p>尽管 PV 被删除，但下层存储资源并未被删除，需要手动移除。&lt;/p>
&lt;p>总结一下，与 PersistentVolume 关联的回收策略在某些情况下会被忽略。
对于 &lt;code>Bound&lt;/code> 的 PV-PVC 对，PV-PVC 删除的顺序决定了回收策略是否被执行。
如果 PVC 先被删除，则回收策略被执行；但如果在删除 PVC 之前 PV 被删除，
则回收策略不会被执行。因此，外部基础设施中关联的存储资产未被移除。&lt;/p>
&lt;!--
## PV reclaim policy with Kubernetes v1.31
The new behavior ensures that the underlying storage object is deleted from the backend when users attempt to delete a PV manually.
#### How to enable new behavior?
To take advantage of the new behavior, you must have upgraded your cluster to the v1.31 release of Kubernetes
and run the CSI [`external-provisioner`](https://github.com/kubernetes-csi/external-provisioner) version `5.0.1` or later.
-->
&lt;h2 id="kubernetes-v1-31-的-pv-回收策略">Kubernetes v1.31 的 PV 回收策略&lt;/h2>
&lt;p>新的行为确保当用户尝试手动删除 PV 时，下层存储对象会从后端被删除。&lt;/p>
&lt;h4 id="如何启用新的行为">如何启用新的行为？&lt;/h4>
&lt;p>要利用新的行为，你必须将集群升级到 Kubernetes v1.31 版本，并运行
CSI &lt;a href="https://github.com/kubernetes-csi/external-provisioner">&lt;code>external-provisioner&lt;/code>&lt;/a>
v5.0.1 或更高版本。&lt;/p>
&lt;!--
#### How does it work?
For CSI volumes, the new behavior is achieved by adding a [finalizer](/docs/concepts/overview/working-with-objects/finalizers/) `external-provisioner.volume.kubernetes.io/finalizer`
on new and existing PVs. The finalizer is only removed after the storage from the backend is deleted.
`
An example of a PV with the finalizer, notice the new finalizer in the finalizers list
-->
&lt;h4 id="工作方式">工作方式&lt;/h4>
&lt;p>对于 CSI 卷，新的行为是通过在新创建和现有的 PV 上添加
&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/overview/working-with-objects/finalizers/">Finalizer&lt;/a>
&lt;code>external-provisioner.volume.kubernetes.io/finalizer&lt;/code> 来实现的。
只有在后端存储被删除后，Finalizer 才会被移除。&lt;/p>
&lt;p>下面是一个带 Finalizer 的 PV 示例，请注意 Finalizer 列表中的新 Finalizer：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>kubectl get pv pvc-a7b7e3ba-f837-45ba-b243-dec7d8aaed53 -o yaml
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>PersistentVolume&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">annotations&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">pv.kubernetes.io/provisioned-by&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>csi.vsphere.vmware.com&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">creationTimestamp&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;2021-11-17T19:28:56Z&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">finalizers&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- kubernetes.io/pv-protection&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- external-provisioner.volume.kubernetes.io/finalizer&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>pvc-a7b7e3ba-f837-45ba-b243-dec7d8aaed53&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">resourceVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;194711&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">uid&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>087f14f2-4157-4e95-8a70-8294b039d30e&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">accessModes&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- ReadWriteOnce&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">capacity&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">storage&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>1Gi&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">claimRef&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>PersistentVolumeClaim&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>example-vanilla-block-pvc&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">namespace&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>default&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">resourceVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;194677&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">uid&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>a7b7e3ba-f837-45ba-b243-dec7d8aaed53&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">csi&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">driver&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>csi.vsphere.vmware.com&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">fsType&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ext4&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">volumeAttributes&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">storage.kubernetes.io/csiProvisionerIdentity&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#666">1637110610497-8081&lt;/span>-csi.vsphere.vmware.com&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">type&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>vSphere CNS Block Volume&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">volumeHandle&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>2dacf297-803f-4ccc-afc7-3d3c3f02051e&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">persistentVolumeReclaimPolicy&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Delete&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">storageClassName&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>example-vanilla-block-sc&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">volumeMode&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Filesystem&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">status&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">phase&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Bound&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
The [finalizer](/docs/concepts/overview/working-with-objects/finalizers/) prevents this
PersistentVolume from being removed from the
cluster. As stated previously, the finalizer is only removed from the PV object
after it is successfully deleted from the storage backend. To learn more about
finalizers, please refer to [Using Finalizers to Control Deletion](/blog/2021/05/14/using-finalizers-to-control-deletion/).
Similarly, the finalizer `kubernetes.io/pv-controller` is added to dynamically provisioned in-tree plugin volumes.
-->
&lt;p>&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/overview/working-with-objects/finalizers/">Finalizer&lt;/a>
防止此 PersistentVolume 从集群中被移除。如前文所述，Finalizer 仅在从存储后端被成功删除后才会从
PV 对象中被移除。进一步了解 Finalizer，
请参阅&lt;a href="https://kubernetes.io/blog/2021/05/14/using-finalizers-to-control-deletion/">使用 Finalizer 控制删除&lt;/a>。&lt;/p>
&lt;p>同样，Finalizer &lt;code>kubernetes.io/pv-controller&lt;/code> 也被添加到动态制备的树内插件卷中。&lt;/p>
&lt;!--
#### What about CSI migrated volumes?
The fix applies to CSI migrated volumes as well.
### Some caveats
The fix does not apply to statically provisioned in-tree plugin volumes.
-->
&lt;h4 id="有关-csi-迁移的卷">有关 CSI 迁移的卷&lt;/h4>
&lt;p>本次修复同样适用于 CSI 迁移的卷。&lt;/p>
&lt;h3 id="一些注意事项">一些注意事项&lt;/h3>
&lt;p>本次修复不适用于静态制备的树内插件卷。&lt;/p>
&lt;!--
### References
-->
&lt;h3 id="参考">参考&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://github.com/kubernetes/enhancements/tree/master/keps/sig-storage/2644-honor-pv-reclaim-policy">KEP-2644&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes-csi/external-provisioner/issues/546">Volume leak issue&lt;/a>&lt;/li>
&lt;/ul>
&lt;!--
### How do I get involved?
The Kubernetes Slack channel [SIG Storage communication channels](https://github.com/kubernetes/community/blob/master/sig-storage/README.md#contact) are great mediums to reach out to the SIG Storage and migration working group teams.
Special thanks to the following people for the insightful reviews, thorough consideration and valuable contribution:
-->
&lt;h3 id="我该如何参与">我该如何参与？&lt;/h3>
&lt;p>Kubernetes Slack
&lt;a href="https://github.com/kubernetes/community/blob/master/sig-storage/README.md#contact">SIG Storage 交流频道&lt;/a>是与
SIG Storage 和迁移工作组团队联系的良好媒介。&lt;/p>
&lt;p>特别感谢以下人员的用心评审、周全考虑和宝贵贡献：&lt;/p>
&lt;ul>
&lt;li>Fan Baofa (carlory)&lt;/li>
&lt;li>Jan Šafránek (jsafrane)&lt;/li>
&lt;li>Xing Yang (xing-yang)&lt;/li>
&lt;li>Matthew Wong (wongma7)&lt;/li>
&lt;/ul>
&lt;!--
Join the [Kubernetes Storage Special Interest Group (SIG)](https://github.com/kubernetes/community/tree/master/sig-storage) if you're interested in getting involved with the design and development of CSI or any part of the Kubernetes Storage system. We’re rapidly growing and always welcome new contributors.
-->
&lt;p>如果你有兴趣参与 CSI 或 Kubernetes Storage 系统任何部分的设计和开发，请加入
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-storage">Kubernetes Storage SIG&lt;/a>。
我们正在快速成长，始终欢迎新的贡献者。&lt;/p></description></item><item><title>Kubernetes 1.31：基于 OCI 工件的只读卷 (Alpha)</title><link>https://kubernetes.io/zh-cn/blog/2024/08/16/kubernetes-1-31-image-volume-source/</link><pubDate>Fri, 16 Aug 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/08/16/kubernetes-1-31-image-volume-source/</guid><description>
&lt;!--
layout: blog
title: "Kubernetes 1.31: Read Only Volumes Based On OCI Artifacts (alpha)"
date: 2024-08-16
slug: kubernetes-1-31-image-volume-source
author: Sascha Grunert
-->
&lt;!--
The Kubernetes community is moving towards fulfilling more Artificial
Intelligence (AI) and Machine Learning (ML) use cases in the future. While the
project has been designed to fulfill microservice architectures in the past,
it’s now time to listen to the end users and introduce features which have a
stronger focus on AI/ML.
-->
&lt;p>Kubernetes 社区正朝着在未来满足更多人工智能（AI）和机器学习（ML）使用场景的方向发展。
虽然此项目在过去设计为满足微服务架构，但现在是时候听听最终用户的声音并引入更侧重于 AI/ML 的特性了。&lt;/p>
&lt;!--
One of these requirements is to support [Open Container Initiative (OCI)](https://opencontainers.org)
compatible images and artifacts (referred as OCI objects) directly as a native
volume source. This allows users to focus on OCI standards as well as enables
them to store and distribute any content using OCI registries. A feature like
this gives the Kubernetes project a chance to grow into use cases which go
beyond running particular images.
-->
&lt;p>其中一项需求是直接支持与&lt;a href="https://opencontainers.org">开放容器倡议（OCI）&lt;/a>
兼容的镜像和工件（称为 OCI 对象）作为原生卷源。
这使得用户能够专注于 OCI 标准，且能够使用 OCI 镜像仓库存储和分发任何内容。
与此类似的特性让 Kubernetes 项目有机会扩大其使用场景，不再局限于运行特定镜像。&lt;/p>
&lt;!--
Given that, the Kubernetes community is proud to present a new alpha feature
introduced in v1.31: The Image Volume Source
([KEP-4639](https://kep.k8s.io/4639)). This feature allows users to specify an
image reference as volume in a pod while reusing it as volume mount within
containers:
-->
&lt;p>在这一背景下，Kubernetes 社区自豪地展示在 v1.31 中引入的一项新的 Alpha 特性：
镜像卷源（&lt;a href="https://kep.k8s.io/4639">KEP-4639&lt;/a>）。
此特性允许用户在 Pod 中指定一个镜像引用作为卷，并在容器内将其作为卷挂载进行复用：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>…&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Pod&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">containers&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- …&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">volumeMounts&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>my-volume&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">mountPath&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>/path/to/directory&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">volumes&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>my-volume&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">image&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">reference&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>my-image:tag&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
The above example would result in mounting `my-image:tag` to
`/path/to/directory` in the pod’s container.
-->
&lt;p>上述示例的结果是将 &lt;code>my-image:tag&lt;/code> 挂载到 Pod 的容器中的 &lt;code>/path/to/directory&lt;/code>。&lt;/p>
&lt;!--
## Use cases
The goal of this enhancement is to stick as close as possible to the existing
[container image](/docs/concepts/containers/images/) implementation within the
kubelet, while introducing a new API surface to allow more extended use cases.
-->
&lt;h2 id="使用场景">使用场景&lt;/h2>
&lt;p>此增强特性的目标是在尽可能贴近 kubelet 中现有的&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/containers/images/">容器镜像&lt;/a>实现的同时，
引入新的 API 接口以支持更广泛的使用场景。&lt;/p>
&lt;!--
For example, users could share a configuration file among multiple containers in
a pod without including the file in the main image, so that they can minimize
security risks and the overall image size. They can also package and distribute
binary artifacts using OCI images and mount them directly into Kubernetes pods,
so that they can streamline their CI/CD pipeline as an example.
-->
&lt;p>例如，用户可以在 Pod 中的多个容器之间共享一个配置文件，而无需将此文件包含在主镜像中，
这样用户就可以将安全风险最小化和并缩减整体镜像大小。用户还可以使用 OCI 镜像打包和分发二进制工件，
并直接将它们挂载到 Kubernetes Pod 中，例如用户这样就可以简化其 CI/CD 流水线。&lt;/p>
&lt;!--
Data scientists, MLOps engineers, or AI developers, can mount large language
model weights or machine learning model weights in a pod alongside a
model-server, so that they can efficiently serve them without including them in
the model-server container image. They can package these in an OCI object to
take advantage of OCI distribution and ensure efficient model deployment. This
allows them to separate the model specifications/content from the executables
that process them.
-->
&lt;p>数据科学家、MLOps 工程师或 AI 开发者可以与模型服务器一起在 Pod 中挂载大语言模型权重或机器学习模型权重数据，
从而可以更高效地提供服务，且无需将这些模型包含在模型服务器容器镜像中。
他们可以将这些模型打包在 OCI 对象中，以利用 OCI 分发机制，还可以确保高效的模型部署。
这一新特性允许他们将模型规约/内容与处理它们的可执行文件分开。&lt;/p>
&lt;!--
Another use case is that security engineers can use a public image for a malware
scanner and mount in a volume of private (commercial) malware signatures, so
that they can load those signatures without baking their own combined image
(which might not be allowed by the copyright on the public image). Those files
work regardless of the OS or version of the scanner software.
-->
&lt;p>另一个使用场景是安全工程师可以使用公共镜像作为恶意软件扫描器，并将私有的（商业的）恶意软件签名挂载到卷中，
这样他们就可以加载这些签名且无需制作自己的组合镜像（公共镜像的版权要求可能不允许这样做）。
签名数据文件与操作系统或扫描器软件版本无关，总是可以被使用。&lt;/p>
&lt;!--
But in the long term it will be up to **you** as an end user of this project to
outline further important use cases for the new feature.
[SIG Node](https://github.com/kubernetes/community/blob/54a67f5/sig-node/README.md)
is happy to retrieve any feedback or suggestions for further enhancements to
allow more advanced usage scenarios. Feel free to provide feedback by either
using the [Kubernetes Slack (#sig-node)](https://kubernetes.slack.com/messages/sig-node)
channel or the [SIG Node mailinglist](https://groups.google.com/g/kubernetes-sig-node).
-->
&lt;p>但就长期而言，作为此项目的最终用户的你要负责为这一新特性的其他重要使用场景给出规划。
&lt;a href="https://github.com/kubernetes/community/blob/54a67f5/sig-node/README.md">SIG Node&lt;/a>
乐于接收与进一步增强此特性以适应更高级的使用场景有关的所有反馈或建议。你可以通过使用
&lt;a href="https://kubernetes.slack.com/messages/sig-node">Kubernetes Slack（#sig-node）&lt;/a>
频道或 &lt;a href="https://groups.google.com/g/kubernetes-sig-node">SIG Node 邮件列表&lt;/a>提供反馈。&lt;/p>
&lt;!--
## Detailed example {#example}
The Kubernetes alpha feature gate [`ImageVolume`](/docs/reference/command-line-tools-reference/feature-gates)
needs to be enabled on the [API Server](/docs/reference/command-line-tools-reference/kube-apiserver)
as well as the [kubelet](/docs/reference/command-line-tools-reference/kubelet)
to make it functional. If that’s the case and the [container runtime](/docs/setup/production-environment/container-runtimes)
has support for the feature (like CRI-O ≥ v1.31), then an example `pod.yaml`
like this can be created:
-->
&lt;h2 id="example">详细示例&lt;/h2>
&lt;p>你需要在 &lt;a href="https://kubernetes.io/zh-cn/docs/reference/command-line-tools-reference/kube-apiserver">API 服务器&lt;/a>以及
&lt;a href="https://kubernetes.io/zh-cn/docs/reference/command-line-tools-reference/kubelet">kubelet&lt;/a> 上启用
Kubernetes Alpha 特性门控 &lt;a href="https://kubernetes.io/zh-cn/docs/reference/command-line-tools-reference/feature-gates">&lt;code>ImageVolume&lt;/code>&lt;/a>，
才能使其正常工作。如果启用了此特性，
并且&lt;a href="https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes">容器运行时&lt;/a>支持此特性
（如 CRI-O ≥ v1.31），那就可以创建这样一个示例 &lt;code>pod.yaml&lt;/code>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Pod&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>pod&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">containers&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>test&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">image&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>registry.k8s.io/e2e-test-images/echoserver:2.3&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">volumeMounts&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>volume&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">mountPath&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>/volume&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">volumes&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>volume&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">image&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">reference&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>quay.io/crio/artifact:v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">pullPolicy&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>IfNotPresent&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
The pod declares a new volume using the `image.reference` of
`quay.io/crio/artifact:v1`, which refers to an OCI object containing two files.
The `pullPolicy` behaves in the same way as for container images and allows the
following values:
-->
&lt;p>此 Pod 使用值为 &lt;code>quay.io/crio/artifact:v1&lt;/code> 的 &lt;code>image.reference&lt;/code> 声明一个新卷，
该字段值引用了一个包含两个文件的 OCI 对象。&lt;code>pullPolicy&lt;/code> 的行为与容器镜像相同，允许以下值：&lt;/p>
&lt;!--
- `Always`: the kubelet always attempts to pull the reference and the container
creation will fail if the pull fails.
- `Never`: the kubelet never pulls the reference and only uses a local image or
artifact. The container creation will fail if the reference isn’t present.
- `IfNotPresent`: the kubelet pulls if the reference isn’t already present on
disk. The container creation will fail if the reference isn’t present and the
pull fails.
-->
&lt;ul>
&lt;li>&lt;code>Always&lt;/code>：kubelet 总是尝试拉取引用，如果拉取失败，容器创建将失败。&lt;/li>
&lt;li>&lt;code>Never&lt;/code>：kubelet 从不拉取引用，只使用本地镜像或工件。如果引用不存在，容器创建将失败。&lt;/li>
&lt;li>&lt;code>IfNotPresent&lt;/code>：kubelet 会在引用已不在磁盘上时进行拉取。如果引用不存在且拉取失败，容器创建将失败。&lt;/li>
&lt;/ul>
&lt;!--
The `volumeMounts` field is indicating that the container with the name `test`
should mount the volume under the path `/volume`.
If you now create the pod:
-->
&lt;p>&lt;code>volumeMounts&lt;/code> 字段表示名为 &lt;code>test&lt;/code> 的容器应将卷挂载到 &lt;code>/volume&lt;/code> 路径下。&lt;/p>
&lt;p>如果你现在创建 Pod：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>kubectl apply -f pod.yaml
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
And exec into it:
-->
&lt;p>然后通过 exec 进入此 Pod：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>kubectl &lt;span style="color:#a2f">exec&lt;/span> -it pod -- sh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
Then you’re able to investigate what has been mounted:
-->
&lt;p>那么你就能够查看已挂载的内容：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888">/ # ls /volume
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888">dir file
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888">/ # cat /volume/file
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888">2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888">/ # ls /volume/dir
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888">file
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888">/ # cat /volume/dir/file
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#888">1
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
**You managed to consume an OCI artifact using Kubernetes!**
The container runtime pulls the image (or artifact), mounts it to the
container and makes it finally available for direct usage. There are a bunch of
details in the implementation, which closely align to the existing image pull
behavior of the kubelet. For example:
-->
&lt;p>&lt;strong>你已经成功地使用 Kubernetes 访问了 OCI 工件！&lt;/strong>&lt;/p>
&lt;p>容器运行时拉取镜像（或工件），将其挂载到容器中，并最终使其可被直接使用。
在实现中有很多细节，这些细节与 kubelet 现有的镜像拉取行为密切相关。例如：&lt;/p>
&lt;!--
- If a `:latest` tag as `reference` is provided, then the `pullPolicy` will
default to `Always`, while in any other case it will default to `IfNotPresent`
if unset.
- The volume gets re-resolved if the pod gets deleted and recreated, which means
that new remote content will become available on pod recreation. A failure to
resolve or pull the image during pod startup will block containers from
starting and may add significant latency. Failures will be retried using
normal volume backoff and will be reported on the pod reason and message.
-->
&lt;ul>
&lt;li>如果提供给 &lt;code>reference&lt;/code> 的值包含 &lt;code>:latest&lt;/code> 标签，&lt;code>pullPolicy&lt;/code> 将默认为 &lt;code>Always&lt;/code>，
而在任何其他情况下，&lt;code>pullPolicy&lt;/code> 在未被设置的情况下都默认为 &lt;code>IfNotPresent&lt;/code>。&lt;/li>
&lt;li>如果 Pod 被删除并重新创建，卷将被重新解析，这意味着在 Pod 重新创建时将可以访问新的远端内容。
如果在 Pod 启动期间未能解析或未能拉取镜像，将会容器启动会被阻止，并可能显著增加延迟。
如果拉取镜像失败，将使用正常的卷回退机制进行重试，并将在 Pod 的原因和消息中报告出错原因。&lt;/li>
&lt;/ul>
&lt;!--
- Pull secrets will be assembled in the same way as for the container image by
looking up node credentials, service account image pull secrets, and pod spec
image pull secrets.
- The OCI object gets mounted in a single directory by merging the manifest
layers in the same way as for container images.
- The volume is mounted as read-only (`ro`) and non-executable files
(`noexec`).
-->
&lt;ul>
&lt;li>拉取 Secret 的组装方式与容器镜像所用的方式相同，也是通过查找节点凭据、服务账户镜像拉取 Secret
和 Pod 规约中的镜像拉取 Secret 来完成。&lt;/li>
&lt;li>OCI 对象被挂载到单个目录中，清单层的合并方式与容器镜像相同。&lt;/li>
&lt;li>卷以只读（&lt;code>ro&lt;/code>）和非可执行文件（&lt;code>noexec&lt;/code>）的方式被挂载。&lt;/li>
&lt;/ul>
&lt;!--
- Sub-path mounts for containers are not supported
(`spec.containers[*].volumeMounts.subpath`).
- The field `spec.securityContext.fsGroupChangePolicy` has no effect on this
volume type.
- The feature will also work with the [`AlwaysPullImages` admission plugin](/docs/reference/access-authn-authz/admission-controllers/#alwayspullimages)
if enabled.
-->
&lt;ul>
&lt;li>容器的子路径挂载不被支持（&lt;code>spec.containers[*].volumeMounts.subpath&lt;/code>）。&lt;/li>
&lt;li>字段 &lt;code>spec.securityContext.fsGroupChangePolicy&lt;/code> 对这种卷类型没有影响。&lt;/li>
&lt;li>如果已启用，此特性也将与
&lt;a href="https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/admission-controllers/#alwayspullimages">&lt;code>AlwaysPullImages&lt;/code> 准入插件&lt;/a>一起工作。&lt;/li>
&lt;/ul>
&lt;!--
Thank you for reading through the end of this blog post! SIG Node is proud and
happy to deliver this feature as part of Kubernetes v1.31.
As writer of this blog post, I would like to emphasize my special thanks to
**all** involved individuals out there! You all rock, let’s keep on hacking!
-->
&lt;p>感谢你阅读到这篇博客文章的结尾！对于将此特性作为 Kubernetes v1.31
的一部分交付，SIG Node 感到很高兴也很自豪。&lt;/p>
&lt;p>作为这篇博客的作者，我想特别感谢所有参与者！你们都很棒，让我们继续开发之旅！&lt;/p>
&lt;!--
## Further reading
- [Use an Image Volume With a Pod](/docs/tasks/configure-pod-container/image-volumes)
- [`image` volume overview](/docs/concepts/storage/volumes/#image)
-->
&lt;h2 id="进一步阅读">进一步阅读&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/image-volumes">在 Pod 中使用镜像卷&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/#image">&lt;code>image&lt;/code> 卷概览&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Kubernetes 1.31：通过 VolumeAttributesClass 修改卷进阶至 Beta</title><link>https://kubernetes.io/zh-cn/blog/2024/08/15/kubernetes-1-31-volume-attributes-class/</link><pubDate>Thu, 15 Aug 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/08/15/kubernetes-1-31-volume-attributes-class/</guid><description>
&lt;!--
layout: blog
title: "Kubernetes 1.31: VolumeAttributesClass for Volume Modification Beta"
date: 2024-08-15
slug: kubernetes-1-31-volume-attributes-class
author: >
Sunny Song (Google)
Matthew Cary (Google)
-->
&lt;!--
Volumes in Kubernetes have been described by two attributes: their storage class, and
their capacity. The storage class is an immutable property of the volume, while the
capacity can be changed dynamically with [volume
resize](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#expanding-persistent-volumes-claims).
This complicates vertical scaling of workloads with volumes. While cloud providers and
storage vendors often offer volumes which allow specifying IO quality of service
(Performance) parameters like IOPS or throughput and tuning them as workloads operate,
Kubernetes has no API which allows changing them.
-->
&lt;p>在 Kubernetes 中，卷由两个属性描述：存储类和容量。存储类是卷的不可变属性，
而容量可以通过&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/#expanding-persistent-volumes-claims">卷调整大小&lt;/a>进行动态变更。&lt;/p>
&lt;p>这使得使用卷的工作负载的垂直扩缩容变得复杂。
虽然云厂商和存储供应商通常提供了一些允许指定注入 IOPS 或吞吐量等 IO
服务质量（性能）参数的卷，并允许在工作负载运行期间调整这些参数，但 Kubernetes
没有提供用来更改这些参数的 API。&lt;/p>
&lt;!--
We are pleased to announce that the [VolumeAttributesClass
KEP](https://github.com/kubernetes/enhancements/blob/master/keps/sig-storage/3751-volume-attributes-class/README.md),
alpha since Kubernetes 1.29, will be beta in 1.31. This provides a generic,
Kubernetes-native API for modifying volume parameters like provisioned IO.
-->
&lt;p>我们很高兴地宣布，自 Kubernetes 1.29 起以 Alpha 引入的
&lt;a href="https://github.com/kubernetes/enhancements/blob/master/keps/sig-storage/3751-volume-attributes-class/README.md">VolumeAttributesClass KEP&lt;/a>
将在 1.31 中进入 Beta 阶段。这一机制提供了一个通用的、Kubernetes 原生的 API，
可用来修改诸如所提供的 IO 能力这类卷参数。&lt;/p>
&lt;!--
Like all new volume features in Kubernetes, this API is implemented via the [container
storage interface (CSI)](https://kubernetes-csi.github.io/docs/). In addition to the
VolumeAttributesClass feature gate, your provisioner-specific CSI driver must support the
new ModifyVolume API which is the CSI side of this feature.
See the [full
documentation](https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/)
for all details. Here we show the common workflow.
-->
&lt;p>类似于 Kubernetes 中所有新的卷特性，此 API 是通过&lt;a href="https://kubernetes-csi.github.io/docs/">容器存储接口（CSI）&lt;/a>实现的。
除了 VolumeAttributesClass 特性门控外，特定于制备器的 CSI 驱动还必须支持此特性在
CSI 一侧的全新的 ModifyVolume API。&lt;/p>
&lt;p>有关细节请参阅&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/storage/volume-attributes-classes/">完整文档&lt;/a>。
在这里，我们展示了常见的工作流程。&lt;/p>
&lt;!--
### Dynamically modifying volume attributes.
A `VolumeAttributesClass` is a cluster-scoped resource that specifies provisioner-specific
attributes. These are created by the cluster administrator in the same way as storage
classes. For example, a series of gold, silver and bronze volume attribute classes can be
created for volumes with greater or lessor amounts of provisioned IO.
-->
&lt;h3 id="dynamically-modifying-volume-attributes">动态修改卷属性 &lt;/h3>
&lt;p>&lt;code>VolumeAttributesClass&lt;/code> 是一个集群范围的资源，用来指定特定于制备器的属性。
这些属性由集群管理员创建，方式上与存储类相同。
例如，你可以为卷创建一系列金、银和铜级别的卷属性类，以区隔不同级别的 IO 能力。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>storage.k8s.io/v1alpha1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>VolumeAttributesClass&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>silver&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">driverName&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>your-csi-driver&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">parameters&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">provisioned-iops&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;500&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">provisioned-throughput&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;50MiB/s&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#00f;font-weight:bold">---&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>storage.k8s.io/v1alpha1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>VolumeAttributesClass&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>gold&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">driverName&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>your-csi-driver&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">parameters&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">provisioned-iops&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;10000&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">provisioned-throughput&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;500MiB/s&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
An attribute class is added to a PVC in much the same way as a storage class.
-->
&lt;p>属性类的添加方式与存储类类似。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>PersistentVolumeClaim&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>test-pv-claim&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">storageClassName&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>any-storage-class&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">volumeAttributesClassName&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>silver&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">accessModes&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- ReadWriteOnce&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">resources&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">requests&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">storage&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>64Gi&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
Unlike a storage class, the volume attributes class can be changed:
-->
&lt;p>与存储类不同，卷属性类可以被更改：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>kubectl patch pvc test-pv-claim -p &lt;span style="color:#b44">&amp;#39;{&amp;#34;spec&amp;#34;: &amp;#34;volumeAttributesClassName&amp;#34;: &amp;#34;gold&amp;#34;}&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
Kubernetes will work with the CSI driver to update the attributes of the
volume. The status of the PVC will track the current and desired attributes
class. The PV resource will also be updated with the new volume attributes class
which will be set to the currently active attributes of the PV.
-->
&lt;p>Kubernetes 将与 CSI 驱动协作来更新卷的属性。
PVC 的状态将跟踪当前和所需的属性类。
PV 资源也将依据新的卷属性类完成更新，卷属性类也会被依据 PV 当前活跃的属性完成设置。&lt;/p>
&lt;!--
### Limitations with the beta
As a beta feature, there are still some features which are planned for GA but not yet
present. The largest is quota support, see the
[KEP](https://github.com/kubernetes/enhancements/blob/master/keps/sig-storage/3751-volume-attributes-class/README.md)
and discussion in
[sig-storage](https://github.com/kubernetes/community/tree/master/sig-storage) for details.
See the [Kubernetes CSI driver
list](https://kubernetes-csi.github.io/docs/drivers.html) for up-to-date
information of support for this feature in CSI drivers.
-->
&lt;h3 id="limitations-with-the-beta">Beta 阶段的限制 &lt;/h3>
&lt;p>作为一个 Beta 特性，仍有一些特性计划在 GA 阶段推出，但尚未实现。最大的限制是配额支持，详见
&lt;a href="https://github.com/kubernetes/enhancements/blob/master/keps/sig-storage/3751-volume-attributes-class/README.md">KEP&lt;/a>
和 &lt;a href="https://github.com/kubernetes/community/tree/master/sig-storage">sig-storage&lt;/a> 中的讨论。&lt;/p>
&lt;p>有关此特性在 CSI 驱动中的最新支持信息，请参阅 &lt;a href="https://kubernetes-csi.github.io/docs/drivers.html">Kubernetes CSI 驱动列表&lt;/a>。&lt;/p></description></item><item><title>Kubernetes v1.31：通过基于缓存的一致性读加速集群性能</title><link>https://kubernetes.io/zh-cn/blog/2024/08/15/consistent-read-from-cache-beta/</link><pubDate>Thu, 15 Aug 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/08/15/consistent-read-from-cache-beta/</guid><description>
&lt;!--
layout: blog
title: 'Kubernetes v1.31: Accelerating Cluster Performance with Consistent Reads from Cache'
date: 2024-08-15
slug: consistent-read-from-cache-beta
author: >
Marek Siarkowicz (Google)
->
&lt;!--
Kubernetes is renowned for its robust orchestration of containerized applications,
but as clusters grow, the demands on the control plane can become a bottleneck.
A key challenge has been ensuring strongly consistent reads from the etcd datastore,
requiring resource-intensive quorum reads.
-->
&lt;p>Kubernetes 以其强大的容器化应用编排能力而闻名，但随着集群规模扩大，
对控制平面的需求可能成为性能瓶颈。其中一个主要挑战是确保从
etcd 数据存储进行强一致性读，这通常需要资源密集型仲裁读取操作。&lt;/p>
&lt;!--
Today, the Kubernetes community is excited to announce a major improvement:
_consistent reads from cache_, graduating to Beta in Kubernetes v1.31.
### Why consistent reads matter
-->
&lt;p>今天，Kubernetes 社区很高兴地宣布一个重大改进：&lt;strong>基于缓存的一致性读&lt;/strong>，
已在 Kubernetes v1.31 中晋升至 Beta 阶段。&lt;/p>
&lt;h3 id="why-consistent-reads-matter">为什么一致性读如此重要 &lt;/h3>
&lt;!--
Consistent reads are essential for ensuring that Kubernetes components have an accurate view of the latest cluster state.
Guaranteeing consistent reads is crucial for maintaining the accuracy and reliability of Kubernetes operations,
enabling components to make informed decisions based on up-to-date information.
In large-scale clusters, fetching and processing this data can be a performance bottleneck,
especially for requests that involve filtering results.
-->
&lt;p>一致性读是确保 Kubernetes 组件准确了解最新集群状态的关键。
保证一致性读对于保持 Kubernetes 操作准确性和可靠性至关重要，
使组件能够根据最新信息做出明智决策。
在大型集群中，数据的获取和处理往往会成为性能瓶颈，特别是那些需要过滤结果的请求。&lt;/p>
&lt;!--
While Kubernetes can filter data by namespace directly within etcd,
any other filtering by labels or field selectors requires the entire dataset to be fetched from etcd and then filtered in-memory by the Kubernetes API server.
This is particularly impactful for components like the kubelet,
which only needs to list pods scheduled to its node - but previously required the API Server and etcd to process all pods in the cluster.
-->
&lt;p>虽然 Kubernetes 可以直接在 etcd 中按命名空间过滤数据，但如果按标签或字段选择器过滤，
则需要从 etcd 获取整个数据集，然后由 Kubernetes API 服务器在内存中执行过滤操作。
这对 Kubelet 等组件的影响尤为显著，因为 Kubelet 现在仅需列出调度到其节点的 Pod，
而之前却需要 API 服务器和 etcd 处理集群中所有的 Pod。&lt;/p>
&lt;!--
### The breakthrough: Caching with confidence
Kubernetes has long used a watch cache to optimize read operations.
The watch cache stores a snapshot of the cluster state and receives updates through etcd watches.
However, until now, it couldn't serve consistent reads directly, as there was no guarantee the cache was sufficiently up-to-date.
-->
&lt;h3 id="the-breakthrough-Caching-with-confidence">突破：自信地缓存 &lt;/h3>
&lt;p>Kubernetes 长期以来一直使用监视缓存来优化读取操作。
监视缓存保存集群状态的快照，并通过对 etcd 的监视获取更新。
然而，直到现在,它无法直接支持一致性读，因为没有机制保证缓存是最新的。&lt;/p>
&lt;!--
The _consistent reads from cache_ feature addresses this by leveraging etcd's
[progress notifications](https://etcd.io/docs/v3.5/dev-guide/interacting_v3/#watch-progress)
mechanism.
These notifications inform the watch cache about how current its data is compared to etcd.
When a consistent read is requested, the system first checks if the watch cache is up-to-date.
-->
&lt;p>&lt;strong>基于缓存的一致性读&lt;/strong> 特性通过使用 etcd 的
&lt;a href="https://etcd.io/docs/v3.5/dev-guide/interacting_v3/#watch-progress">进度通知&lt;/a>
机制来解决这一问题。这些通知会向监视缓存说明其数据与 etcd 相比的新旧状态。
当发出一致性读请求时，系统会首先检查监视缓存是否为最新状态。&lt;/p>
&lt;!--
If the cache is not up-to-date, the system queries etcd for progress notifications until it's confirmed that the cache is sufficiently fresh.
Once ready, the read is efficiently served directly from the cache,
which can significantly improve performance,
particularly in cases where it would require fetching a lot of data from etcd.
This enables requests that filter data to be served from the cache,
with only minimal metadata needing to be read from etcd.
-->
&lt;p>如果缓存未更新到最新状态，系统会通过查询 etcd 的进度通知，直到确认缓存已经足够新。
一旦缓存就绪，读取操作就可以直接从缓存中高效地获取数据，这可以显著提升性能，
尤其是在需要从 etcd 获取大量数据的场景下。这种方式支持通过缓存处理数据过滤请求，
仅需从 etcd 读取少量的元数据。&lt;/p>
&lt;!--
**Important Note:** To benefit from this feature, your Kubernetes cluster must be running etcd version 3.4.31+ or 3.5.13+.
For older etcd versions, Kubernetes will automatically fall back to serving consistent reads directly from etcd.
### Performance gains you'll notice
This seemingly simple change has a profound impact on Kubernetes performance and scalability:
-->
&lt;p>&lt;strong>重要提示：&lt;/strong> 要享受此特性带来的好处，你的 Kubernetes 集群需运行
etcd 版本 3.4.31+ 或 3.5.13+。对于较早版本的 Etcd，Kubernetes
将自动回退为直接从 etcd 提供一致性读。&lt;/p>
&lt;h3 id="performance-gains-youll-notice">你将注意到的性能提升 &lt;/h3>
&lt;p>这个看似简单的改动，对 Kubernetes 的性能和可扩展性有着深远影响:&lt;/p>
&lt;!--
* **Reduced etcd Load:** Kubernetes v1.31 can offload work from etcd,
freeing up resources for other critical operations.
* **Lower Latency:** Serving reads from cache is significantly faster than fetching
and processing data from etcd. This translates to quicker responses for components,
improving overall cluster responsiveness.
* **Improved Scalability:** Large clusters with thousands of nodes and pods will
see the most significant gains, as the reduction in etcd load allows the
control plane to handle more requests without sacrificing performance.
-->
&lt;ul>
&lt;li>&lt;strong>降低 etcd 负载：&lt;/strong> Kubernetes v1.31 可以将部分工作从 etcd 分载出去，
为其他关键操作释放资源。&lt;/li>
&lt;li>&lt;strong>更低的延迟：&lt;/strong> 从缓存读取数据的速度显著快于从 etcd 获取并处理数据。
这使组件的响应速度更快，提升了集群整体的响应能力。&lt;/li>
&lt;li>&lt;strong>增强的可扩展性：&lt;/strong> 拥有数千个节点和 Pod 的大型集群将获得最显著的性能增益，
因为 etcd 负载的降低使得控制平面可以在不牺牲性能的情况下处理更多请求。&lt;/li>
&lt;/ul>
&lt;!--
**5k Node Scalability Test Results:** In recent scalability tests on 5,000 node
clusters, enabling consistent reads from cache delivered impressive improvements:
* **30% reduction** in kube-apiserver CPU usage
* **25% reduction** in etcd CPU usage
* **Up to 3x reduction** (from 5 seconds to 1.5 seconds) in 99th percentile pod LIST request latency
-->
&lt;p>&lt;strong>5 千节点扩缩容测试结果：&lt;/strong> 在最近针对 5,000 节点集群的扩缩容测试中，
启用基于缓存的一致性读带来了显著提升：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>kube-apiserver CPU 使用率降低 30%&lt;/strong>&lt;/li>
&lt;li>&lt;strong>etcd CPU 使用率降低 25%&lt;/strong>&lt;/li>
&lt;li>&lt;strong>第 99 百分位的 Pod 列表请求延迟出现了高至 3 倍的减少（从 5 秒降至 1.5 秒）&lt;/strong>&lt;/li>
&lt;/ul>
&lt;!--
### What's next?
With the graduation to beta, consistent reads from cache are enabled by default,
offering a seamless performance boost to all Kubernetes users running a supported
etcd version.
Our journey doesn't end here. Kubernetes community is actively exploring
pagination support in the watch cache, which will unlock even more performance
optimizations in the future.
-->
&lt;h2 id="whats-next">下一步是什么？ &lt;/h2>
&lt;p>随着基于缓存的一致性读特性晋升至 Beta 版，该特性已默认启用，为所有使用受支持 etcd
版本的 Kubernetes 用户提供了无缝的性能提升。&lt;/p>
&lt;p>我们的探索并未止步于此。Kubernetes 社区正积极研究在监视缓存中加入分页支持，
未来有望带来更多性能优化。&lt;/p>
&lt;!--
### Getting started
Upgrading to Kubernetes v1.31 and ensuring you are using etcd version 3.4.31+ or
3.5.13+ is the easiest way to experience the benefits of consistent reads from
cache.
If you have any questions or feedback, don't hesitate to reach out to the Kubernetes community.
-->
&lt;h3 id="getting-started">开始使用 &lt;/h3>
&lt;p>升级到 Kubernetes v1.31 并确保使用 etcd 版本 3.4.31+ 或 3.5.13+，
是体验基于缓存的一致性读优势的最简单方法。如果有任何问题或反馈，不要犹豫，
随时联系 Kubernetes 社区。&lt;/p>
&lt;!--
**Let us know how** _consistent reads from cache_ **transforms your Kubernetes experience!**
Special thanks to @ah8ad3 and @p0lyn0mial for their contributions to this feature!
-->
&lt;p>请让我们知道&lt;strong>基于缓存的一致性读&lt;/strong>如何改善了你的 Kubernetes 体验！&lt;/p>
&lt;p>特别感谢 @ah8ad3 和 @p0lyn0mial 对这一特性做出的贡献！&lt;/p></description></item><item><title>Kubernetes 1.31：对 cgroup v1 的支持转为维护模式</title><link>https://kubernetes.io/zh-cn/blog/2024/08/14/kubernetes-1-31-moving-cgroup-v1-support-maintenance-mode/</link><pubDate>Wed, 14 Aug 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/08/14/kubernetes-1-31-moving-cgroup-v1-support-maintenance-mode/</guid><description>
&lt;!--
layout: blog
title: "Kubernetes 1.31: Moving cgroup v1 Support into Maintenance Mode"
date: 2024-08-14
slug: kubernetes-1-31-moving-cgroup-v1-support-maintenance-mode
author: Harshal Patil
-->
&lt;!--
As Kubernetes continues to evolve and adapt to the changing landscape of
container orchestration, the community has decided to move cgroup v1 support
into [maintenance mode](#what-does-maintenance-mode-mean) in v1.31.
This shift aligns with the broader industry's move towards cgroup v2, offering
improved functionalities: including scalability and a more consistent interface.
Before we dive into the consequences for Kubernetes, let's take a step back to
understand what cgroups are and their significance in Linux.
-->
&lt;p>随着 Kubernetes 不断发展，为了适应容器编排全景图的变化，社区决定在 v1.31 中将对 cgroup v1
的支持转为&lt;a href="#what-does-maintenance-mode-mean">维护模式&lt;/a>。
这一转变与行业更广泛地向 cgroup v2 的迁移保持一致，后者的功能更强，
包括可扩展性和更加一致的接口。在我们深入探讨对 Kubernetes 的影响之前，
先回顾一下 cgroup 的概念及其在 Linux 中的重要意义。&lt;/p>
&lt;!--
## Understanding cgroups
[Control groups](https://man7.org/linux/man-pages/man7/cgroups.7.html), or
cgroups, are a Linux kernel feature that allows the allocation, prioritization,
denial, and management of system resources (such as CPU, memory, disk I/O,
and network bandwidth) among processes. This functionality is crucial for
maintaining system performance and ensuring that no single process can
monopolize system resources, which is especially important in multi-tenant
environments.
-->
&lt;h2 id="understanding-cgroups">理解 cgroup &lt;/h2>
&lt;p>&lt;a href="https://man7.org/linux/man-pages/man7/cgroups.7.html">控制组（Control Group）&lt;/a>也称为 cgroup，
是 Linux 内核的一项特性，允许在进程之间分配、划分优先级、拒绝和管理系统资源（如 CPU、内存、磁盘 I/O 和网络带宽）。
这一功能对于维护系统性能至关重要，确保没有单个进程能够垄断系统资源，这在多租户环境中尤其重要。&lt;/p>
&lt;!--
There are two versions of cgroups:
[v1](https://docs.kernel.org/admin-guide/cgroup-v1/index.html) and
[v2](https://docs.kernel.org/admin-guide/cgroup-v2.html). While cgroup v1
provided sufficient capabilities for resource management, it had limitations
that led to the development of cgroup v2. Cgroup v2 offers a more unified and
consistent interface, on top of better resource control features.
-->
&lt;p>cgroup 有两个版本：
&lt;a href="https://docs.kernel.org/admin-guide/cgroup-v1/index.html">v1&lt;/a> 和
&lt;a href="https://docs.kernel.org/admin-guide/cgroup-v2.html">v2&lt;/a>。
虽然 cgroup v1 提供了足够的资源管理能力，但其局限性促使了 cgroup v2 的开发。
cgroup v2 在更好的资源控制特性之外提供了更统一且更一致的接口。&lt;/p>
&lt;!--
## Cgroups in Kubernetes
For Linux nodes, Kubernetes relies heavily on cgroups to manage and isolate the
resources consumed by containers running in pods. Each container in Kubernetes
is placed in its own cgroup, which allows Kubernetes to enforce resource limits,
monitor usage, and ensure fair resource distribution among all containers.
-->
&lt;h2 id="kubernetes-中的-cgroup">Kubernetes 中的 cgroup&lt;/h2>
&lt;p>对于 Linux 节点，Kubernetes 在管理和隔离 Pod 中运行的容器所消耗的资源方面高度依赖 cgroup。
Kubernetes 中的每个容器都放在其自己的 cgroup 中，这使得 Kubernetes 能够强制执行资源限制、
监控使用情况并确保所有容器之间的资源公平分配。&lt;/p>
&lt;!--
### How Kubernetes uses cgroups
**Resource Allocation**
: Ensures that containers do not exceed their allocated CPU and memory limits.
**Isolation**
: Isolates containers from each other to prevent resource contention.
**Monitoring**
: Tracks resource usage for each container to provide insights and metrics.
-->
&lt;h3 id="how-kubernetes-uses-cgroups">Kubernetes 如何使用 cgroup &lt;/h3>
&lt;dl>
&lt;dt>&lt;strong>资源分配&lt;/strong>&lt;/dt>
&lt;dd>确保容器不超过其分配的 CPU 和内存限制。&lt;/dd>
&lt;dt>&lt;strong>隔离&lt;/strong>&lt;/dt>
&lt;dd>将容器相互隔离，防止资源争用。&lt;/dd>
&lt;dt>&lt;strong>监控&lt;/strong>&lt;/dt>
&lt;dd>跟踪每个容器的资源使用情况，以提供洞察数据和指标。&lt;/dd>
&lt;/dl>
&lt;!--
## Transitioning to Cgroup v2
The Linux community has been focusing on cgroup v2 for new features and
improvements. Major Linux distributions and projects like
[systemd](https://systemd.io/) are
[transitioning](https://github.com/systemd/systemd/issues/30852) towards cgroup v2.
Using cgroup v2 provides several benefits over cgroupv1, such as Unified Hierarchy,
Improved Interface, Better Resource Control,
[cgroup aware OOM killer](https://github.com/kubernetes/kubernetes/pull/117793),
[rootless support](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/2033-kubelet-in-userns-aka-rootless/README.md#cgroup) etc.
-->
&lt;h2 id="transitioning-to-cgroup-v2">向 cgroup v2 过渡 &lt;/h2>
&lt;p>Linux 社区一直在聚焦于为 cgroup v2 提供新特性和各项改进。
主要的 Linux 发行版和像 &lt;a href="https://systemd.io/">systemd&lt;/a>
这样的项目正在&lt;a href="https://github.com/systemd/systemd/issues/30852">过渡&lt;/a>到 cgroup v2。
使用 cgroup v2 相较于使用 cgroup v1 提供了多个好处，例如统一的层次结构、改进的接口、更好的资源控制，
以及 &lt;a href="https://github.com/kubernetes/kubernetes/pull/117793">cgroup 感知的 OOM 杀手&lt;/a>、
&lt;a href="https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/2033-kubelet-in-userns-aka-rootless/README.md#cgroup">非 root 支持&lt;/a>等。&lt;/p>
&lt;!--
Given these advantages, Kubernetes is also making the move to embrace cgroup
v2 more fully. However, this transition needs to be handled carefully to avoid
disrupting existing workloads and to provide a smooth migration path for users.
## Moving cgroup v1 support into maintenance mode
### What does maintenance mode mean?
When cgroup v1 is placed into maintenance mode in Kubernetes, it means that:
-->
&lt;p>鉴于这些优势，Kubernetes 也正在更全面地转向 cgroup v2。然而，
这一过渡需要谨慎处理，以避免干扰现有的工作负载，并为用户提供平滑的迁移路径。&lt;/p>
&lt;h2 id="moving-cgroup-v1-support-into-maintenance-mode">对 cgroup v1 的支持转入维护模式 &lt;/h2>
&lt;h3 id="what-does-maintenance-mode-mean">维护模式意味着什么？ &lt;/h3>
&lt;p>当 cgroup v1 在 Kubernetes 中被置于维护模式时，这意味着：&lt;/p>
&lt;!--
1. **Feature Freeze**: No new features will be added to cgroup v1 support.
2. **Security Fixes**: Critical security fixes will still be provided.
3. **Best-Effort Bug Fixes**: Major bugs may be fixed if feasible, but some
issues might remain unresolved.
-->
&lt;ol>
&lt;li>&lt;strong>特性冻结&lt;/strong>：不会再向 cgroup v1 添加新特性。&lt;/li>
&lt;li>&lt;strong>安全修复&lt;/strong>：仍将提供关键的安全修复。&lt;/li>
&lt;li>&lt;strong>尽力而为的 Bug 修复&lt;/strong>：在可行的情况下可能会修复重大 Bug，但某些问题可能保持未解决。&lt;/li>
&lt;/ol>
&lt;!--
### Why move to maintenance mode?
The move to maintenance mode is driven by the need to stay in line with the
broader ecosystem and to encourage the adoption of cgroup v2, which offers
better performance, security, and usability. By transitioning cgroup v1 to
maintenance mode, Kubernetes can focus on enhancing support for cgroup v2
and ensure it meets the needs of modern workloads. It's important to note
that maintenance mode does not mean deprecation; cgroup v1 will continue to
receive critical security fixes and major bug fixes as needed.
-->
&lt;h3 id="why-move-to-maintenance-mode">为什么要转入维护模式？ &lt;/h3>
&lt;p>转入维护模式的原因是为了与更广泛的生态体系保持一致，也为了鼓励采用 cgroup v2，后者提供了更好的性能、安全性和可用性。
通过将 cgroup v1 转入维护模式，Kubernetes 可以专注于增强对 cgroup v2 的支持，并确保其满足现代工作负载的需求。
需要注意的是，维护模式并不意味着弃用；cgroup v1 将继续按需进行关键的安全修复和重大 Bug 修复。&lt;/p>
&lt;!--
## What this means for cluster administrators
Users currently relying on cgroup v1 are highly encouraged to plan for the
transition to cgroup v2. This transition involves:
1. **Upgrading Systems**: Ensuring that the underlying operating systems and
container runtimes support cgroup v2.
2. **Testing Workloads**: Verifying that workloads and applications function
correctly with cgroup v2.
-->
&lt;h2 id="what-this-means-for-cluster-administrators">这对集群管理员意味着什么 &lt;/h2>
&lt;p>目前强烈鼓励那些依赖 cgroup v1 的用户做好向 cgroup v2 过渡的计划。这一过渡涉及：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>升级系统&lt;/strong>：确保底层操作系统和容器运行时支持 cgroup v2。&lt;/li>
&lt;li>&lt;strong>测试工作负载&lt;/strong>：验证工作负载和应用程序在 cgroup v2 下正常工作。&lt;/li>
&lt;/ol>
&lt;!--
## Further reading
- [Linux cgroups](https://man7.org/linux/man-pages/man7/cgroups.7.html)
- [Cgroup v2 in Kubernetes](/docs/concepts/architecture/cgroups/)
- [Kubernetes 1.25: cgroup v2 graduates to GA](/blog/2022/08/31/cgroupv2-ga-1-25/)
-->
&lt;h2 id="further-reading">进一步阅读 &lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://man7.org/linux/man-pages/man7/cgroups.7.html">Linux cgroup&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/architecture/cgroups/">Kubernetes 中的 cgroup v2&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://kubernetes.io/zh-cn/blog/2022/08/31/cgroupv2-ga-1-25/">Kubernetes 1.25：cgroup v2 进阶至 GA&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Kubernetes v1.31: PersistentVolume 的最后阶段转换时间进阶到 GA</title><link>https://kubernetes.io/zh-cn/blog/2024/08/14/last-phase-transition-time-ga/</link><pubDate>Wed, 14 Aug 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/08/14/last-phase-transition-time-ga/</guid><description>
&lt;!--
layout: blog
title: "Kubernetes v1.31: PersistentVolume Last Phase Transition Time Moves to GA"
date: 2024-08-14
slug: last-phase-transition-time-ga
author: >
Roman Bednář (Red Hat)
-->
&lt;!--
Announcing the graduation to General Availability (GA) of the PersistentVolume `lastTransitionTime` status
field, in Kubernetes v1.31!
The Kubernetes SIG Storage team is excited to announce that the "PersistentVolumeLastPhaseTransitionTime" feature, introduced
as an alpha in Kubernetes v1.28, has now reached GA status and is officially part of the Kubernetes v1.31 release. This enhancement
helps Kubernetes users understand when a [PersistentVolume](/docs/concepts/storage/persistent-volumes/) transitions between
different phases, allowing for more efficient and informed resource management.
-->
&lt;p>现在宣布 PersistentVolume 的 &lt;code>lastTransitionTime&lt;/code> 状态字段在 Kubernetes v1.31
版本进阶至正式发布（GA）！&lt;/p>
&lt;p>Kubernetes SIG Storage 团队很高兴地宣布，&amp;quot;PersistentVolumeLastPhaseTransitionTime&amp;quot;
特性自 Kubernetes v1.28 作为 Alpha 版本引入以来，现已进阶至正式发布（GA），并正式成为
Kubernetes v1.31 版本的一部分。该功能帮助 Kubernetes 用户增强对
&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/">PersistentVolume&lt;/a>
在不同阶段之间转换的理解，从而实现更高效和更明智的资源管理。&lt;/p>
&lt;!--
For a v1.31 cluster, you can now assume that every PersistentVolume object has a
`.status.lastTransitionTime` field, that holds a timestamp of
when the volume last transitioned its phase. This change is not immediate; the new field will be populated whenever a PersistentVolume
is updated and first transitions between phases (`Pending`, `Bound`, or `Released`) after upgrading to Kubernetes v1.31.
-->
&lt;p>在 v1.31 集群中，你可以默认每个 PersistentVolume 对象都包含
&lt;code>.status.lastTransitionTime&lt;/code> 字段，该字段记录存储卷最近一次发生阶段转换时的时间戳。
该更改不会立刻生效，而是在升级到 Kubernetes v1.31 后，当 PersistentVolume
发生更新并首次在（&lt;code>Pending&lt;/code>、&lt;code>Bound&lt;/code> 或 &lt;code>Released&lt;/code>）这几个阶段之间进行转换时，
才会填充该字段。&lt;/p>
&lt;!--
## What changed?
The API strategy for updating PersistentVolume objects has been modified to populate the `.status.lastTransitionTime` field with the
current timestamp whenever a PersistentVolume transitions phases. Users are allowed to set this field manually if needed, but it will
be overwritten when the PersistentVolume transitions phases again.
-->
&lt;h2 id="what-changed">有什么变化？ &lt;/h2>
&lt;p>更新 PersistentVolume 对象的 API 策略已经被修改，
当存储卷转换阶段时会自动填充当前时间戳到 &lt;code>.status.lastTransitionTime&lt;/code> 字段。
如果需要，用户可以手动设置该字段，但当 PersistentVolume
再次转换阶段时，该字段会被新时间戳覆盖。&lt;/p>
&lt;!--
For more details, read about
[Phase transition timestamp](/docs/concepts/storage/persistent-volumes/#phase-transition-timestamp) in the Kubernetes documentation.
You can also read the previous [blog post](/blog/2023/10/23/persistent-volume-last-phase-transition-time) announcing the feature as alpha in v1.28.
-->
&lt;p>想了解更多信息，可以查阅 Kubernetes 文档中的
&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/#phase-transition-timestamp">阶段转换时间戳&lt;/a>。
你还可以阅读此前的
&lt;a href="https://kubernetes.io/zh-cn/blog/2023/10/23/persistent-volume-last-phase-transition-time">博客文章&lt;/a>，
该文章介绍了此特性在 v1.28 版本中作为 Alpha 版本发布的情况。&lt;/p>
&lt;!--
To provide feedback, join our [Kubernetes Storage Special-Interest-Group](https://github.com/kubernetes/community/tree/master/sig-storage) (SIG)
or participate in discussions on our [public Slack channel](https://app.slack.com/client/T09NY5SBT/C09QZFCE5).
-->
&lt;p>要提供反馈，请加入我们的
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-storage">Kubernetes 存储特别兴趣小组&lt;/a> (SIG)
或参与&lt;a href="https://app.slack.com/client/T09NY5SBT/C09QZFCE5">公共 Slack 频道&lt;/a>上的讨论。&lt;/p></description></item><item><title>Kubernetes v1.31: Elli</title><link>https://kubernetes.io/zh-cn/blog/2024/08/13/kubernetes-v1-31-release/</link><pubDate>Tue, 13 Aug 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/08/13/kubernetes-v1-31-release/</guid><description>
&lt;!--
---
layout: blog
title: 'Kubernetes v1.31: Elli'
date: 2024-08-13
slug: kubernetes-v1-31-release
author: >
[Kubernetes v1.31 Release Team](https://github.com/kubernetes/sig-release/blob/master/releases/release-1.31/release-team.md)
---
-->
&lt;!--
**Editors:** Matteo Bianchi, Yigit Demirbas, Abigail McCarthy, Edith Puclla, Rashan Smith
Announcing the release of Kubernetes v1.31: Elli!
Similar to previous releases, the release of Kubernetes v1.31 introduces new
stable, beta, and alpha features.
The consistent delivery of high-quality releases underscores the strength of our development cycle and the vibrant support from our community.
This release consists of 45 enhancements.
Of those enhancements, 11 have graduated to Stable, 22 are entering Beta,
and 12 have graduated to Alpha.
-->
&lt;p>&lt;strong>编辑:&lt;/strong> Matteo Bianchi, Yigit Demirbas, Abigail McCarthy, Edith Puclla, Rashan Smith&lt;/p>
&lt;p>Kubernetes v1.31：Elli 宣布发布！&lt;/p>
&lt;p>与之前的版本类似，Kubernetes v1.31 的发布中引入了新的稳定版、Beta 版和 Alpha 特性功能。
持续提供高质量的版本彰显了我们开发周期的强劲实力以及社区的大力支持。
此版本包含 45 项增强功能。
在这些增强功能中，11 项已升级到稳定版，22 项正在进入 Beta 版，12 项已升级到 Alpha 版。&lt;/p>
&lt;!--
## Release theme and logo
-->
&lt;h2 id="发布主题和-logo">发布主题和 logo&lt;/h2>
&lt;figure class="release-logo ">
&lt;img src="https://kubernetes.io/images/blog/2024-08-13-kubernetes-1.31-release/k8s-1.31.png"
alt="Kubernetes v1.31 Elli logo"/>
&lt;/figure>
&lt;!--
The Kubernetes v1.31 Release Theme is "Elli".
Kubernetes v1.31's Elli is a cute and joyful dog, with a heart of gold and a nice sailor's cap, as a playful wink to the huge and diverse family of Kubernetes contributors.
-->
&lt;p>Kubernetes v1.31 的发布主题是 &amp;quot;Elli&amp;quot;。&lt;/p>
&lt;p>Kubernetes v1.31 的 Elli 是一只可爱欢快的小狗，戴着一顶漂亮的水手帽，这是对庞大而多样化的 Kubernetes 贡献者家族的一个俏皮致意。&lt;/p>
&lt;!--
Kubernetes v1.31 marks the first release after the project has successfully celebrated [its first 10 years](/blog/2024/06/06/10-years-of-kubernetes/).
Kubernetes has come a very long way since its inception, and it's still moving towards exciting new directions with each release.
After 10 years, it is awe-inspiring to reflect on the effort, dedication, skill, wit and tiring work of the countless Kubernetes contributors who have made this a reality.
-->
&lt;p>Kubernetes v1.31 标志着该项目成功庆祝其&lt;a href="https://kubernetes.io/blog/2024/06/06/10-years-of-kubernetes/">诞生十周年&lt;/a>后的首次发布。
自诞生以来，Kubernetes 已经走过了漫长的道路，并且每次发布都在朝着令人兴奋的新方向前进。
十年后，回顾无数 Kubernetes 贡献者为实现这一目标所付出的努力、奉献、技能、智慧和辛勤工作，令人敬畏。&lt;/p>
&lt;!--
And yet, despite the herculean effort needed to run the project, there is no shortage of people who show up, time and again, with enthusiasm, smiles and a sense of pride for contributing and being part of the community.
This "spirit" that we see from new and old contributors alike is the sign of a vibrant community, a "joyful" community, if we might call it that.
-->
&lt;p>还有，尽管运营项目需要付出巨大的努力，仍然有大量的人不断以热情、微笑和自豪感出现，为社区做出贡献并成为其中的一员。
我们从新老贡献者那里看到的这种&amp;quot;精神&amp;quot;是一个充满活力的社区的标志，我们可以称之为&amp;quot;欢乐&amp;quot;的社区。&lt;/p>
&lt;!--
Kubernetes v1.31's Elli is all about celebrating this wonderful spirit! Here's to the next decade of Kubernetes!
-->
&lt;p>Kubernetes v1.31 的 Elli 就是为了庆祝这种美好的精神!让我们为 Kubernetes 的下一个十年干杯!&lt;/p>
&lt;!--
## Highlights of features graduating to Stable
_This is a selection of some of the improvements that are now stable following the v1.31 release._
-->
&lt;h2 id="晋级为稳定版的功能亮点">晋级为稳定版的功能亮点&lt;/h2>
&lt;p>&lt;em>以下是 v1.31 发布后晋级为稳定版的部分改进。&lt;/em>&lt;/p>
&lt;!--
### AppArmor support is now stable
-->
&lt;h3 id="apparmor-支持现已稳定">AppArmor 支持现已稳定&lt;/h3>
&lt;!--
Kubernetes support for AppArmor is now GA. Protect your containers using AppArmor by setting the `appArmorProfile.type` field in the container's `securityContext`.
Note that before Kubernetes v1.30, AppArmor was controlled via annotations; starting in v1.30 it is controlled using fields.
It is recommended that you should migrate away from using annotations and start using the `appArmorProfile.type` field.
-->
&lt;p>Kubernetes 对 AppArmor 的支持现已正式发布。通过在容器的 &lt;code>securityContext&lt;/code> 中设置 &lt;code>appArmorProfile.type&lt;/code> 字段，可以使用 AppArmor 保护您的容器。
请注意，在 Kubernetes v1.30 之前，AppArmor 是通过注解控制的；从 v1.30 开始，它是通过字段控制的。
建议您停止使用注解，开始使用 &lt;code>appArmorProfile.type&lt;/code> 字段。&lt;/p>
&lt;!--
To learn more read the [AppArmor tutorial](/docs/tutorials/security/apparmor/).
This work was done as a part of [KEP #24](https://github.com/kubernetes/enhancements/issues/24), by [SIG Node](https://github.com/kubernetes/community/tree/master/sig-node).
-->
&lt;p>要了解更多信息，请阅读 &lt;a href="https://kubernetes.io/zh-cn/docs/tutorials/security/apparmor/">AppArmor 教程&lt;/a>。
这项工作是作为 &lt;a href="https://github.com/kubernetes/enhancements/issues/24">KEP #24&lt;/a> 的一部分由
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-node">SIG Node&lt;/a> 完成的。&lt;/p>
&lt;!--
### Improved ingress connectivity reliability for kube-proxy
-->
&lt;h3 id="改进-kube-proxy-的入站连接可靠性">改进 kube-proxy 的入站连接可靠性&lt;/h3>
&lt;!--
Kube-proxy improved ingress connectivity reliability is stable in v1.31.
One of the common problems with load balancers in Kubernetes is the synchronization between the different components involved to avoid traffic drop.
This feature implements a mechanism in kube-proxy for load balancers to do connection draining for terminating Nodes exposed by services of `type: LoadBalancer` and `externalTrafficPolicy: Cluster` and establish some best practices for cloud providers and Kubernetes load balancers implementations.
-->
&lt;p>kube-proxy 改进的入站连接可靠性在 v1.31 中已稳定。
Kubernetes 中负载均衡器的一个常见问题是为避免流量丢失而在不同组件之间进行同步的机制。
此特性在 kube-proxy 中实现了一种机制，用于负载均衡器对 &lt;code>type: LoadBalancer&lt;/code> 和 &lt;code>externalTrafficPolicy: Cluster&lt;/code>
服务所公开的、进入终止进程的 Node 进行连接排空，并为云提供商和 Kubernetes 负载均衡器实现建立了一些最佳实践。&lt;/p>
&lt;!--
To use this feature, kube-proxy needs to run as default service proxy on the cluster and the load balancer needs to support connection draining.
There are no specific changes required for using this feature, it has been enabled by default in kube-proxy since v1.30 and been promoted to stable in v1.31.
-->
&lt;p>要使用此特性，kube-proxy 需要在集群上作为默认服务代理运行，并且负载均衡器需要支持连接排空。
使用此特性不需要进行特定的更改，它自 v1.30 以来在 kube-proxy 中默认启用，并在 v1.31 中晋级为稳定版。&lt;/p>
&lt;!--
For more details about this feature please visit the [Virtual IPs and Service Proxies documentation page](/docs/reference/networking/virtual-ips/#external-traffic-policy).
-->
&lt;p>有关此特性的更多详细信息，请访问&lt;a href="https://kubernetes.io/zh-cn/docs/reference/networking/virtual-ips/#external-traffic-policy">虚拟 IP 和服务代理文档页面&lt;/a>。&lt;/p>
&lt;!--
This work was done as part of [KEP #3836](https://github.com/kubernetes/enhancements/issues/3836) by [SIG Network](https://github.com/kubernetes/community/tree/master/sig-network).
-->
&lt;p>这项工作是作为 &lt;a href="https://github.com/kubernetes/enhancements/issues/3836">KEP #3836&lt;/a> 的一部分由
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-network">SIG Network&lt;/a> 完成的。&lt;/p>
&lt;!--
### Persistent Volume last phase transition time
-->
&lt;h3 id="持久卷最近阶段转换时间">持久卷最近阶段转换时间&lt;/h3>
&lt;!--
Persistent Volume last phase transition time feature moved to GA in v1.31.
This feature adds a `PersistentVolumeStatus` field which holds a timestamp of when a PersistentVolume last transitioned to a different phase.
With this feature enabled, every PersistentVolume object will have a new field `.status.lastTransitionTime`, that holds a timestamp of
when the volume last transitioned its phase.
This change is not immediate; the new field will be populated whenever a PersistentVolume is updated and first transitions between phases (`Pending`, `Bound`, or `Released`) after upgrading to Kubernetes v1.31.
This allows you to measure time between when a PersistentVolume moves from `Pending` to `Bound`. This can be also useful for providing metrics and SLOs.
-->
&lt;p>持久卷最近阶段转换时间功能在 v1.31 中晋级为正式版（GA）。
此特性添加了一个 &lt;code>PersistentVolumeStatus&lt;/code> 字段，用于保存 PersistentVolume 最近转换到不同阶段的时间戳。
启用此特性后，每个 PersistentVolume 对象将有一个新字段 &lt;code>.status.lastTransitionTime&lt;/code> 保存卷最近转换阶段的时间戳。
这种变化并不是立即的；新字段将在 PersistentVolume 更新并在升级到 Kubernetes v1.31 后首次在各阶段（&lt;code>Pending&lt;/code>、&lt;code>Bound&lt;/code> 或 &lt;code>Released&lt;/code>）之间转换时填充。
这允许您测量 PersistentVolume 从 &lt;code>Pending&lt;/code> 移动到 &lt;code>Bound&lt;/code> 之间的时间。这对于提供指标和 SLO 也很有用。&lt;/p>
&lt;!--
For more details about this feature please visit the [PersistentVolume documentation page](/docs/concepts/storage/persistent-volumes/).
-->
&lt;p>有关此特性的更多详细信息，请访问 &lt;a href="https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/">PersistentVolume 文档页面&lt;/a>。&lt;/p>
&lt;!--
his work was done as a part of [KEP #3762](https://github.com/kubernetes/enhancements/issues/3762) by [SIG Storage](https://github.com/kubernetes/community/tree/master/sig-storage).
-->
&lt;p>这项工作是作为 &lt;a href="https://github.com/kubernetes/enhancements/issues/3762">KEP #3762&lt;/a> 的一部分由
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-storage">SIG Storage&lt;/a> 完成的。&lt;/p>
&lt;!--
## Highlights of features graduating to Beta
-->
&lt;h2 id="晋级为-beta-版的功能亮点">晋级为 Beta 版的功能亮点&lt;/h2>
&lt;!--
_This is a selection of some of the improvements that are now beta following the v1.31 release._
-->
&lt;p>&lt;em>以下是 v1.31 发布后晋级为 Beta 版的部分改进。&lt;/em>&lt;/p>
&lt;!--
### nftables backend for kube-proxy
-->
&lt;h3 id="kube-proxy-的-nftables-后端">kube-proxy 的 nftables 后端&lt;/h3>
&lt;!--
The nftables backend moves to beta in v1.31, behind the `NFTablesProxyMode` feature gate which is now enabled by default.
-->
&lt;p>nftables 后端在 v1.31 中晋级为 Beta 版，由 &lt;code>NFTablesProxyMode&lt;/code> 特性门控控制，现在默认启用。&lt;/p>
&lt;!--
The nftables API is the successor to the iptables API and is designed to provide better performance and scalability than iptables.
The `nftables` proxy mode is able to process changes to service endpoints faster and more efficiently than the `iptables` mode, and is also able to more efficiently process packets in the kernel (though this only
becomes noticeable in clusters with tens of thousands of services).
-->
&lt;p>nftables API 是 iptables API 的继任者，旨在提供比 iptables 更好的性能和可扩展性。
&lt;code>nftables&lt;/code> 代理模式能够比 &lt;code>iptables&lt;/code> 模式更快、更高效地处理服务端点的变化，并且在内核中也能更高效地处理数据包（尽管这只有在拥有数万个服务的集群中才会显著）。&lt;/p>
&lt;!--
As of Kubernetes v1.31, the `nftables` mode is still relatively new, and may not be compatible with all network plugins; consult the documentation for your network plugin.
This proxy mode is only available on Linux nodes, and requires kernel 5.13 or later.
Before migrating, note that some features, especially around NodePort services, are not implemented exactly the same in nftables mode as they are in iptables mode.
Check the [migration guide](/docs/reference/networking/virtual-ips/#migrating-from-iptables-mode-to-nftables) to see if you need to override the default configuration.
-->
&lt;p>截至 Kubernetes v1.31，nftables 模式仍相对较新，可能与某些网络插件不兼容；请查阅您的网络插件文档。
此代理模式仅在 Linux 节点上可用，并且需要内核 5.13 或更高版本。
在迁移之前，请注意某些功能，特别是与 NodePort 服务相关的功能，在 nftables 模式下的实现方式与 iptables 模式不完全相同。
查看&lt;a href="https://kubernetes.io/zh-cn/docs/reference/networking/virtual-ips/#migrating-from-iptables-mode-to-nftables">迁移指南&lt;/a>以了解是否需要覆盖默认配置。&lt;/p>
&lt;!--
This work was done as part of [KEP #3866](https://github.com/kubernetes/enhancements/issues/3866) by [SIG Network](https://github.com/kubernetes/community/tree/master/sig-network).
-->
&lt;p>这项工作是作为 &lt;a href="https://github.com/kubernetes/enhancements/issues/3866">KEP #3866&lt;/a> 的一部分由
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-network">SIG Network&lt;/a> 完成的。&lt;/p>
&lt;!--
### Changes to reclaim policy for PersistentVolumes
-->
&lt;h3 id="persistentvolumes-回收策略的变更">PersistentVolumes 回收策略的变更&lt;/h3>
&lt;!--
The Always Honor PersistentVolume Reclaim Policy feature has advanced to beta in Kubernetes v1.31.
This enhancement ensures that the PersistentVolume (PV) reclaim policy is respected even after the associated PersistentVolumeClaim (PVC) is deleted, thereby preventing the leakage of volumes.
-->
&lt;p>始终遵循 PersistentVolume 回收策略这一特性在 Kubernetes v1.31 中晋级为 Beta 版。
这项增强确保即使在所关联的 PersistentVolumeClaim (PVC) 被删除后，PersistentVolume (PV) 回收策略也会被遵循，从而防止卷的泄漏。&lt;/p>
&lt;!--
Prior to this feature, the reclaim policy linked to a PV could be disregarded under specific conditions, depending on whether the PV or PVC was deleted first.
Consequently, the corresponding storage resource in the external infrastructure might not be removed, even if the reclaim policy was set to "Delete".
This led to potential inconsistencies and resource leaks.
-->
&lt;p>在此特性之前，与 PV 相关联的回收策略可能在特定条件下被忽视，这取决于 PV 或 PVC 是否先被删除。
因此，即使回收策略设置为 &amp;quot;Delete&amp;quot;，外部基础设施中相应的存储资源也可能不会被删除。
这导致了潜在的不一致性和资源泄漏。&lt;/p>
&lt;!--
With the introduction of this feature, Kubernetes now guarantees that the "Delete" reclaim policy will be enforced, ensuring the deletion of the underlying storage object from the backend infrastructure, regardless of the deletion sequence of the PV and PVC.
-->
&lt;p>随着这项功能的引入，Kubernetes 现在保证 &amp;quot;Delete&amp;quot; 回收策略将被执行，确保底层存储对象从后端基础设施中删除，无论 PV 和 PVC 的删除顺序如何。&lt;/p>
&lt;!--
This work was done as a part of [KEP #2644](https://github.com/kubernetes/enhancements/issues/2644) and by [SIG Storage](https://github.com/kubernetes/community/tree/master/sig-storage).
-->
&lt;p>这项工作是作为 &lt;a href="https://github.com/kubernetes/enhancements/issues/2644">KEP #2644&lt;/a> 的一部分由
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-storage">SIG Storage&lt;/a> 完成的。&lt;/p>
&lt;!--
### Bound service account token improvements
-->
&lt;h3 id="绑定服务账户令牌的改进">绑定服务账户令牌的改进&lt;/h3>
&lt;!--
The `ServiceAccountTokenNodeBinding` feature is promoted to beta in v1.31.
This feature allows requesting a token bound only to a node, not to a pod, which includes node information in claims in the token and validates the existence of the node when the token is used.
For more information, read the [bound service account tokens documentation](/docs/reference/access-authn-authz/service-accounts-admin/#bound-service-account-tokens).
-->
&lt;p>&lt;code>ServiceAccountTokenNodeBinding&lt;/code> 功能在 v1.31 中晋级为 Beta 版。
此特性允许请求仅绑定到节点而不是 Pod 的令牌，在令牌中包含节点信息的声明，并在使用令牌时验证节点的存在。
有关更多信息，请阅读&lt;a href="https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/service-accounts-admin/#bound-service-account-tokens">绑定服务账户令牌文档&lt;/a>。&lt;/p>
&lt;!--
This work was done as part of [KEP #4193](https://github.com/kubernetes/enhancements/issues/4193) by [SIG Auth](https://github.com/kubernetes/community/tree/master/sig-auth).
-->
&lt;p>这项工作是作为 &lt;a href="https://github.com/kubernetes/enhancements/issues/4193">KEP #4193&lt;/a> 的一部分由
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-auth">SIG Auth&lt;/a> 完成的。&lt;/p>
&lt;!--
### Multiple Service CIDRs
-->
&lt;h3 id="多个-service-cidr">多个 Service CIDR&lt;/h3>
&lt;!--
Support for clusters with multiple Service CIDRs moves to beta in v1.31 (disabled by default).
-->
&lt;p>支持具有多个服务 CIDR 的集群在 v1.31 中晋级为 Beta 版(默认禁用)。&lt;/p>
&lt;!--
There are multiple components in a Kubernetes cluster that consume IP addresses: Nodes, Pods and Services.
Nodes and Pods IP ranges can be dynamically changed because depend on the infrastructure or the network plugin respectively.
However, Services IP ranges are defined during the cluster creation as a hardcoded flag in the kube-apiserver.
IP exhaustion has been a problem for long lived or large clusters, as admins needed to expand, shrink or even replace entirely the assigned Service CIDR range.
These operations were never supported natively and were performed via complex and delicate maintenance operations, often causing downtime on their clusters. This new feature allows users and cluster admins to dynamically modify Service CIDR ranges with zero downtime.
-->
&lt;p>Kubernetes 集群中有多个组件消耗 IP 地址: Node、Pod 和 Service。
Node 和 Pod 的 IP 范围可以动态更改，因为它们分别取决于基础设施或网络插件。
然而，Service IP 范围是在集群创建期间作为 kube-apiserver 中的硬编码标志定义的。
IP 耗尽一直是长期存在或大型集群的问题，因为管理员需要扩展、缩小甚至完全替换分配的服务 CIDR 范围。
这些操作从未得到原生支持，并且是通过复杂和精细的维护操作执行的，经常导致集群无法正常服务。
这个新特性允许用户和集群管理员以零中断时间动态修改服务 CIDR 范围。&lt;/p>
&lt;!--
For more details about this feature please visit the
[Virtual IPs and Service Proxies](/docs/reference/networking/virtual-ips/#ip-address-objects) documentation page.
-->
&lt;p>有关此特性的更多详细信息，请访问&lt;a href="https://kubernetes.io/zh-cn/docs/reference/networking/virtual-ips/#ip-address-objects">虚拟 IP 和服务代理&lt;/a>文档页面。&lt;/p>
&lt;!--
This work was done as part of [KEP #1880](https://github.com/kubernetes/enhancements/issues/1880) by [SIG Network](https://github.com/kubernetes/community/tree/master/sig-network).
-->
&lt;p>这项工作是作为 &lt;a href="https://github.com/kubernetes/enhancements/issues/1880">KEP #1880&lt;/a> 的一部分由
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-network">SIG Network&lt;/a> 完成的。&lt;/p>
&lt;!--
### Traffic distribution for Services
-->
&lt;h3 id="service-的流量分配">Service 的流量分配&lt;/h3>
&lt;!--
Traffic distribution for Services moves to beta in v1.31 and is enabled by default.
-->
&lt;p>Service 的流量分配在 v1.31 中晋级为 Beta 版，并默认启用。&lt;/p>
&lt;!--
After several iterations on finding the best user experience and traffic engineering capabilities for Services networking, SIG Networking implemented the `trafficDistribution` field in the Service specification, which serves as a guideline for the underlying implementation to consider while making routing decisions.
-->
&lt;p>为实现 Service 联网的最佳用户体验和流量工程能力，经过多次迭代后，SIG Networking 在服务规约中实现了
&lt;code>trafficDistribution&lt;/code> 字段，作为底层实现在做出路由决策时考虑的指导原则。&lt;/p>
&lt;!--
For more details about this feature please read the
[1.30 Release Blog](/blog/2024/04/17/kubernetes-v1-30-release/#traffic-distribution-for-services-sig-network-https-github-com-kubernetes-community-tree-master-sig-network)
or visit the [Service](/docs/concepts/services-networking/service/#traffic-distribution) documentation page.
-->
&lt;p>有关此特性的更多详细信息，请阅读 &lt;a href="https://kubernetes.io/blog/2024/04/17/kubernetes-v1-30-release/#traffic-distribution-for-services-sig-network-https-github-com-kubernetes-community-tree-master-sig-network">1.30 发布博客&lt;/a> 或访问 &lt;a href="https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/#traffic-distribution">Service&lt;/a> 文档页面。&lt;/p>
&lt;!--
This work was done as part of [KEP #4444](https://github.com/kubernetes/enhancements/issues/4444) by [SIG Network](https://github.com/kubernetes/community/tree/master/sig-network).
-->
&lt;p>这项工作是作为 &lt;a href="https://github.com/kubernetes/enhancements/issues/4444">KEP #4444&lt;/a> 的一部分由
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-network">SIG Network&lt;/a> 完成的。&lt;/p>
&lt;!--
### Kubernetes VolumeAttributesClass ModifyVolume
-->
&lt;h3 id="kubernetes-volumeattributesclass-modifyvolume">Kubernetes VolumeAttributesClass ModifyVolume&lt;/h3>
&lt;!--
[VolumeAttributesClass](/docs/concepts/storage/volume-attributes-classes/) API is moving to beta in v1.31.
The VolumeAttributesClass provides a generic,
Kubernetes-native API for modifying dynamically volume parameters like provisioned IO.
This allows workloads to vertically scale their volumes on-line to balance cost and performance, if supported by their provider.
This feature had been alpha since Kubernetes 1.29.
-->
&lt;p>&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/storage/volume-attributes-classes/">VolumeAttributesClass&lt;/a> API 在 v1.31 中晋级为 Beta 版。
VolumeAttributesClass 提供了一个通用的、Kubernetes 原生的 API，用于修改动态卷参数，如所提供的 IO 能力。
这允许工作负载在线垂直扩展其卷，以平衡成本和性能（如果提供商支持）。
该功能自 Kubernetes 1.29 以来一直处于 Alpha 状态。&lt;/p>
&lt;!--
This work was done as a part of [KEP #3751](https://github.com/kubernetes/enhancements/issues/3751) and lead by [SIG Storage](https://github.com/kubernetes/community/tree/master/sig-storage).
-->
&lt;p>这项工作是作为 &lt;a href="https://github.com/kubernetes/enhancements/issues/3751">KEP #3751&lt;/a> 的一部分完成的，由 &lt;a href="https://github.com/kubernetes/community/tree/master/sig-storage">SIG Storage&lt;/a> 领导。&lt;/p>
&lt;!--
## New features in Alpha
-->
&lt;h2 id="alpha-版的新功能">Alpha 版的新功能&lt;/h2>
&lt;!--
_This is a selection of some of the improvements that are now alpha following the v1.31 release._
-->
&lt;p>&lt;em>以下是 v1.31 发布后晋级为 Alpha 版的部分改进。&lt;/em>&lt;/p>
&lt;!--
### New DRA APIs for better accelerators and other hardware management
-->
&lt;h3 id="用于更好管理加速器和其他硬件的新-dra-api">用于更好管理加速器和其他硬件的新 DRA API&lt;/h3>
&lt;!--
Kubernetes v1.31 brings an updated dynamic resource allocation (DRA) API and design.
The main focus in the update is on structured parameters because they make resource information and requests transparent to Kubernetes and clients and enable implementing features like cluster autoscaling.
DRA support in the kubelet was updated such that version skew between kubelet and the control plane is possible. With structured parameters, the scheduler allocates ResourceClaims while scheduling a pod.
Allocation by a DRA driver controller is still supported through what is now called "classic DRA".
-->
&lt;p>Kubernetes v1.31 带来了更新的动态资源分配（DRA）API 和设计。
此次更新的主要焦点是结构化参数，因为它们使资源信息和请求对 Kubernetes 和客户端透明，并能够实现集群自动扩缩容等功能。
kubelet 中的 DRA 支持已更新，使得 kubelet 和控制平面之间的版本偏差成为可能。通过结构化参数，调度器在调度 Pod 时分配 ResourceClaims。
通过现在称为&amp;quot;经典 DRA&amp;quot;的方式，仍然支持由 DRA 驱动程序控制器进行分配。&lt;/p>
&lt;!--
With Kubernetes v1.31, classic DRA has a separate feature gate named `DRAControlPlaneController`, which you need to enable explicitly.
With such a control plane controller, a DRA driver can implement allocation policies that are not supported yet through structured parameters.
-->
&lt;p>从 Kubernetes v1.31 开始,经典 DRA 有一个单独的特性门控名为 &lt;code>DRAControlPlaneController&lt;/code>，您需要显式启用它。
通过这样的控制平面控制器，DRA 驱动程序可以实现尚未通过结构化参数支持的分配策略。&lt;/p>
&lt;!--
This work was done as part of [KEP #3063](https://github.com/kubernetes/enhancements/issues/3063) by [SIG Node](https://github.com/kubernetes/community/tree/master/sig-node).
-->
&lt;p>这项工作是作为 &lt;a href="https://github.com/kubernetes/enhancements/issues/3063">KEP #3063&lt;/a> 的一部分由
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-node">SIG Node&lt;/a> 完成的。&lt;/p>
&lt;!--
### Support for image volumes
-->
&lt;h3 id="对镜像卷的支持">对镜像卷的支持&lt;/h3>
&lt;!--
The Kubernetes community is moving towards fulfilling more Artificial Intelligence (AI) and Machine Learning (ML) use cases in the future.
-->
&lt;p>Kubernetes 社区正在朝着在未来满足更多人工智能(AI)和机器学习(ML)用例的方向发展。&lt;/p>
&lt;!--
One of the requirements to fulfill these use cases is to support Open Container Initiative (OCI) compatible images and artifacts (referred as OCI objects) directly as a native volume source.
This allows users to focus on OCI standards as well as enables them to store and distribute any content using OCI registries.
-->
&lt;p>满足这些用例的要求之一是直接将开放容器倡议(OCI)兼容的镜像和工件(称为 OCI 对象)作为原生卷源支持。
这允许用户专注于 OCI 标准，并使他们能够使用 OCI 注册表存储和分发任何内容。&lt;/p>
&lt;!--
Given that, v1.31 adds a new alpha feature to allow using an OCI image as a volume in a Pod.
This feature allows users to specify an image reference as volume in a pod while reusing it as volume
mount within containers. You need to enable the `ImageVolume` feature gate to try this out.
-->
&lt;p>鉴于此，v1.31 添加了一个新的 Alpha 特性，允许在 Pod 中使用 OCI 镜像作为卷。
此特性允许用户在 pod 中指定镜像引用作为卷，同时在容器内重用它作为卷挂载。您需要启用 &lt;code>ImageVolume&lt;/code> 特性门控才能尝试此特性。&lt;/p>
&lt;!--
This work was done as part of [KEP #4639](https://github.com/kubernetes/enhancements/issues/4639) by [SIG Node](https://github.com/kubernetes/community/tree/master/sig-node) and [SIG Storage](https://github.com/kubernetes/community/tree/master/sig-storage).
-->
&lt;p>这项工作是作为 &lt;a href="https://github.com/kubernetes/enhancements/issues/4639">KEP #4639&lt;/a> 的一部分由 &lt;a href="https://github.com/kubernetes/community/tree/master/sig-node">SIG Node&lt;/a> 和 &lt;a href="https://github.com/kubernetes/community/tree/master/sig-storage">SIG Storage&lt;/a> 完成的。&lt;/p>
&lt;!--
### Exposing device health information through Pod status
-->
&lt;h3 id="通过-pod-状态暴露设备健康信息">通过 Pod 状态暴露设备健康信息&lt;/h3>
&lt;!--
Expose device health information through the Pod Status is added as a new alpha feature in v1.31, disabled by default.
-->
&lt;p>通过 Pod 状态暴露设备健康信息作为新的 Alpha 特性添加到 v1.31 中，默认被禁用。&lt;/p>
&lt;!--
Before Kubernetes v1.31, the way to know whether or not a Pod is associated with the failed device is to use the [PodResources API](/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/#monitoring-device-plugin-resources).
-->
&lt;p>在 Kubernetes v1.31 之前，了解 Pod 是否与故障设备关联的方法是使用 &lt;a href="https://kubernetes.io/zh-cn/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/#monitoring-device-plugin-resources">PodResources API&lt;/a>。&lt;/p>
&lt;!--
By enabling this feature, the field `allocatedResourcesStatus` will be added to each container status, within the `.status` for each Pod. The `allocatedResourcesStatus` field reports health information for each device assigned to the container.
-->
&lt;p>通过启用此特性，字段 &lt;code>allocatedResourcesStatus&lt;/code> 将添加到每个容器状态中，在每个 Pod 的 &lt;code>.status&lt;/code> 内。
&lt;code>allocatedResourcesStatus&lt;/code> 字段报告分配给容器的各个设备的健康信息。&lt;/p>
&lt;!--
This work was done as part of [KEP #4680](https://github.com/kubernetes/enhancements/issues/4680) by [SIG Node](https://github.com/kubernetes/community/tree/master/sig-node).
-->
&lt;p>这项工作是作为 &lt;a href="https://github.com/kubernetes/enhancements/issues/4680">KEP #4680&lt;/a> 的一部分由
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-node">SIG Node&lt;/a> 完成的。&lt;/p>
&lt;!--
### Finer-grained authorization based on selectors
-->
&lt;h3 id="基于选择算符的细粒度鉴权">基于选择算符的细粒度鉴权&lt;/h3>
&lt;!--
This feature allows webhook authorizers and future (but not currently designed) in-tree authorizers to
allow **list** and **watch** requests, provided those requests use label and/or field selectors.
For example, it is now possible for an authorizer to express: this user cannot list all pods, but can list all pods where `.spec.nodeName` matches some specific value. Or to allow a user to watch all Secrets in a namespace
that are _not_ labelled as `confidential: true`.
Combined with CRD field selectors (also moving to beta in v1.31), it is possible to write more secure
per-node extensions.
-->
&lt;p>此特性允许 Webhook 鉴权组件和未来（但目前尚未设计）的树内鉴权组件允许 &lt;strong>list&lt;/strong> 和 &lt;strong>watch&lt;/strong> 请求，
前提是这些请求使用标签和/或字段选择算符。
例如，现在鉴权组件可以表达：此用户不能列出所有 Pod，但可以列举所有 &lt;code>.spec.nodeName&lt;/code> 匹配某个特定值的 Pod。
或者允许用户监视命名空间中所有&lt;strong>未&lt;/strong>标记为 &lt;code>confidential: true&lt;/code> 的 Secret。
结合 CRD 字段选择器（在 v1.31 中也晋级为 Beta 版），可以编写更安全的节点级别扩展。&lt;/p>
&lt;!--
This work was done as part of [KEP #4601](https://github.com/kubernetes/enhancements/issues/4601) by [SIG Auth](https://github.com/kubernetes/community/tree/master/sig-auth).
-->
&lt;p>这项工作是作为 &lt;a href="https://github.com/kubernetes/enhancements/issues/4601">KEP #4601&lt;/a> 的一部分由
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-auth">SIG Auth&lt;/a> 完成的。&lt;/p>
&lt;!--
### Restrictions on anonymous API access
-->
&lt;h3 id="对匿名-api-访问的限制">对匿名 API 访问的限制&lt;/h3>
&lt;!--
By enabling the feature gate `AnonymousAuthConfigurableEndpoints` users can now use the authentication configuration file to configure the endpoints that can be accessed by anonymous requests.
This allows users to protect themselves against RBAC misconfigurations that can give anonymous users broad access to the cluster.
-->
&lt;p>通过启用特性门控 &lt;code>AnonymousAuthConfigurableEndpoints&lt;/code>，用户现在可以使用身份认证配置文件来配置可以通过匿名请求访问的端点。
这允许用户保护自己免受 RBAC 错误配置的影响；错误的配置可能会给匿名用户提供对集群的更多访问权限。&lt;/p>
&lt;!--
This work was done as a part of [KEP #4633](https://github.com/kubernetes/enhancements/issues/4633) and by [SIG Auth](https://github.com/kubernetes/community/tree/master/sig-auth).
-->
&lt;p>这项工作是作为 &lt;a href="https://github.com/kubernetes/enhancements/issues/4633">KEP #4633&lt;/a> 的一部分由
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-auth">SIG Auth&lt;/a> 完成的。&lt;/p>
&lt;!--
## Graduations, deprecations, and removals in 1.31
-->
&lt;h2 id="1-31-中的晋级-弃用和移除">1.31 中的晋级、弃用和移除&lt;/h2>
&lt;!--
### Graduations to Stable
-->
&lt;h3 id="晋级为稳定版">晋级为稳定版&lt;/h3>
&lt;!--
This lists all the features that graduated to stable (also known as _general availability_). For a full list of updates including new features and graduations from alpha to beta, see the release notes.
-->
&lt;p>以下列出了所有晋级为稳定版（也称为 &lt;em>正式可用&lt;/em> ）的功能。有关包括新功能和从 Alpha 晋级到 Beta 的完整列表，请参阅发行说明。&lt;/p>
&lt;!--
This release includes a total of 11 enhancements promoted to Stable:
-->
&lt;p>此版本包括总共 11 项晋级为稳定版的增强:&lt;/p>
&lt;!--
* [PersistentVolume last phase transition time](https://github.com/kubernetes/enhancements/issues/3762)
* [Metric cardinality enforcement](https://github.com/kubernetes/enhancements/issues/2305)
* [Kube-proxy improved ingress connectivity reliability](https://github.com/kubernetes/enhancements/issues/3836)
* [Add CDI devices to device plugin API](https://github.com/kubernetes/enhancements/issues/4009)
* [Move cgroup v1 support into maintenance mode](https://github.com/kubernetes/enhancements/issues/4569)
* [AppArmor support](https://github.com/kubernetes/enhancements/issues/24)
* [PodHealthyPolicy for PodDisruptionBudget](https://github.com/kubernetes/enhancements/issues/3017)
* [Retriable and non-retriable Pod failures for Jobs](https://github.com/kubernetes/enhancements/issues/3329)
* [Elastic Indexed Jobs](https://github.com/kubernetes/enhancements/issues/3715)
* [Allow StatefulSet to control start replica ordinal numbering](https://github.com/kubernetes/enhancements/issues/3335)
* [Random Pod selection on ReplicaSet downscaling](https://github.com/kubernetes/enhancements/issues/2185)
-->
&lt;ul>
&lt;li>&lt;a href="https://github.com/kubernetes/enhancements/issues/3762">PersistentVolume 最后阶段转换时间&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes/enhancements/issues/2305">Metric 基数强制执行&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes/enhancements/issues/3836">Kube-proxy 改进的入站连接可靠性&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes/enhancements/issues/4009">将 CDI 设备添加到设备插件 API&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes/enhancements/issues/4569">将 cgroup v1 支持移入维护模式&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes/enhancements/issues/24">AppArmor 支持&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes/enhancements/issues/3017">PodDisruptionBudget 的 PodHealthyPolicy&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes/enhancements/issues/3329">Job 的可重试和不可重试 Pod 失败&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes/enhancements/issues/3715">弹性的带索引的 Job&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes/enhancements/issues/3335">允许 StatefulSet 控制起始副本序号编号&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes/enhancements/issues/2185">ReplicaSet 缩小时随机选择 Pod&lt;/a>&lt;/li>
&lt;/ul>
&lt;!--
### Deprecations and Removals
-->
&lt;h3 id="弃用和移除">弃用和移除&lt;/h3>
&lt;!--
As Kubernetes develops and matures, features may be deprecated, removed, or replaced with better ones for the project's overall health.
See the Kubernetes [deprecation and removal policy](/docs/reference/using-api/deprecation-policy/) for more details on this process.
-->
&lt;p>随着 Kubernetes 的发展和成熟，某些特性可能会被弃用、移除或替换为更好的特性，以确保项目的整体健康。
有关此过程的更多详细信息，请参阅 Kubernetes &lt;a href="https://kubernetes.io/zh-cn/docs/reference/using-api/deprecation-policy/">弃用和移除策略&lt;/a>。&lt;/p>
&lt;!--
#### Cgroup v1 enters the maintenance mode
-->
&lt;h4 id="cgroup-v1-进入维护模式">Cgroup v1 进入维护模式&lt;/h4>
&lt;!--
As Kubernetes continues to evolve and adapt to the changing landscape of container orchestration, the community has decided to move cgroup v1 support into maintenance mode in v1.31.
This shift aligns with the broader industry's move towards [cgroup v2](/docs/concepts/architecture/cgroups/), offering improved functionality, scalability, and a more consistent interface.
Kubernetes maintance mode means that no new features will be added to cgroup v1 support.
Critical security fixes will still be provided, however, bug-fixing is now best-effort, meaning major bugs may be fixed if feasible, but some issues might remain unresolved.
-->
&lt;p>随着 Kubernetes 继续发展并适应容器编排不断变化的格局，社区决定在 v1.31 中将 cgroup v1 支持移入维护模式。
这一转变与行业中普遍向 &lt;a href="https://kubernetes.io/zh-cn/docs/concepts/architecture/cgroups/">cgroup v2&lt;/a> 迁移的趋势一致，
提供了改进的功能、可扩展性和更一致的接口。
Kubernetes 维护模式意味着不会向 cgroup v1 支持添加新功能。
社区仍将提供关键的安全修复，但是，错误修复现在是尽力而为。
这意味着如果可行，可能会修复重大错误，但某些问题可能保持未解决状态。&lt;/p>
&lt;!--
It is recommended that you start switching to use cgroup v2 as soon as possible.
This transition depends on your architecture, including ensuring the underlying operating systems and container runtimes support cgroup v2 and testing workloads to verify that workloads and applications function correctly with cgroup v2.
-->
&lt;p>建议您尽快开始切换到使用 cgroup v2。
这种转变取决于您的架构，包括确保底层操作系统和容器运行时支持 cgroup v2，以及测试工作负载以验证工作负载和应用程序在 cgroup v2 下是否正常运行。&lt;/p>
&lt;!--
Please report any problems you encounter by filing an [issue](https://github.com/kubernetes/kubernetes/issues/new/choose).
-->
&lt;p>如果遇到任何问题,请通过提交 &lt;a href="https://github.com/kubernetes/kubernetes/issues/new/choose">issue&lt;/a> 进行报告。&lt;/p>
&lt;!--
This work was done as part of [KEP #4569](https://github.com/kubernetes/enhancements/issues/4569) by [SIG Node](https://github.com/kubernetes/community/tree/master/sig-node).
-->
&lt;p>这项工作是作为 &lt;a href="https://github.com/kubernetes/enhancements/issues/4569">KEP #4569&lt;/a> 的一部分由
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-node">SIG Node&lt;/a> 完成的。&lt;/p>
&lt;!--
#### A note about SHA-1 signature support
-->
&lt;h4 id="关于-sha-1-签名支持的说明">关于 SHA-1 签名支持的说明&lt;/h4>
&lt;!--
In [go1.18](https://go.dev/doc/go1.18#sha1) (released in March 2022), the crypto/x509 library started to reject certificates signed with a SHA-1 hash function.
While SHA-1 is established to be unsafe and publicly trusted Certificate Authorities have not issued SHA-1 certificates since 2015, there might still be cases in the context of Kubernetes where user-provided certificates are signed using a SHA-1 hash function through private authorities with them being used for Aggregated API Servers or webhooks.
If you have relied on SHA-1 based certificates, you must explicitly opt back into its support by setting `GODEBUG=x509sha1=1` in your environment.
-->
&lt;p>在 &lt;a href="https://go.dev/doc/go1.18#sha1">go1.18&lt;/a>（2022 年 3 月发布）中，crypto/x509 库开始拒绝使用 SHA-1 哈希函数签名的证书。
虽然 SHA-1 已被确定为不安全，并且公共信任的证书颁发机构自 2015 年以来就不再颁发 SHA-1 证书，
但在 Kubernetes 语境中可能仍然存在用户提供的证书通过私有机构使用 SHA-1 哈希函数签名的情况，
这些证书用于聚合 API 服务器或 Webhook。
如果您依赖基于 SHA-1 的证书，必须通过在环境变量中设置 &lt;code>GODEBUG=x509sha1=1&lt;/code> 来明确选择重新启用其支持。&lt;/p>
&lt;!--
Given Go's [compatibility policy for GODEBUGs](https://go.dev/blog/compat), the `x509sha1` GODEBUG and the support for SHA-1 certificates will [fully go away in go1.24](https://tip.golang.org/doc/go1.23) which will be released in the first half of 2025.
If you rely on SHA-1 certificates, please start moving off them.
-->
&lt;p>鉴于 Go 的 &lt;a href="https://go.dev/blog/compat">GODEBUG 兼容性策略&lt;/a>，&lt;code>x509sha1&lt;/code> GODEBUG 和对 SHA-1
证书的支持&lt;a href="https://tip.golang.org/doc/go1.23">将在 go1.24 中完全消失&lt;/a>，
而 go1.24 将在 2025 年上半年发布。
如果您依赖 SHA-1 证书,请开始迁移离开它们。&lt;/p>
&lt;!--
Please see [Kubernetes issue #125689](https://github.com/kubernetes/kubernetes/issues/125689) to get a better idea of timelines around the support for SHA-1 going away, when Kubernetes releases plans to adopt go1.24, and for more details on how to detect usage of SHA-1 certificates via metrics and audit logging.
-->
&lt;p>请查看 &lt;a href="https://github.com/kubernetes/kubernetes/issues/125689">Kubernetes issue #125689&lt;/a>
以了解有关 SHA-1 支持消失的时间线、Kubernetes 发布计划何时采用 go1.24，
以及如何通过指标和审计日志检测 SHA-1 证书使用情况的更多详细信息。&lt;/p>
&lt;!--
#### Deprecation of `status.nodeInfo.kubeProxyVersion` field for Nodes ([KEP 4004](https://github.com/kubernetes/enhancements/issues/4004))
-->
&lt;h4 id="弃用-node-节点的-status-nodeinfo-kubeproxyversion-字段-kep-4004-https-github-com-kubernetes-enhancements-issues-4004">弃用 Node 节点的 &lt;code>status.nodeInfo.kubeProxyVersion&lt;/code> 字段 (&lt;a href="https://github.com/kubernetes/enhancements/issues/4004">KEP 4004&lt;/a>)&lt;/h4>
&lt;!--
The `.status.nodeInfo.kubeProxyVersion` field of Nodes has been deprecated in Kubernetes v1.31,
and will be removed in a later release.
It's being deprecated because the value of this field wasn't (and isn't) accurate.
This field is set by the kubelet, which does not have reliable information about the kube-proxy version or whether kube-proxy is running.
-->
&lt;p>节点的 &lt;code>.status.nodeInfo.kubeProxyVersion&lt;/code> 字段在 Kubernetes v1.31 中已被弃用,
并将在以后的版本中删除。
它被弃用是因为这个字段的值不准确（现在也不准确）。
这个字段是由 kubelet 设置的，而 kubelet 没有关于 kube-proxy 版本或 kube-proxy 是否正在运行的可靠信息。&lt;/p>
&lt;!--
The `DisableNodeKubeProxyVersion` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) will be set to `true` in by default in v1.31 and the kubelet will no longer attempt to set the `.status.kubeProxyVersion` field for its associated Node.
-->
&lt;p>&lt;code>DisableNodeKubeProxyVersion&lt;/code> &lt;a href="https://kubernetes.io/zh-cn/docs/reference/command-line-tools-reference/feature-gates/">特性门控&lt;/a>将在 v1.31
中默认设置为 &lt;code>true&lt;/code>，kubelet 将不再尝试为其关联的节点设置 &lt;code>.status.kubeProxyVersion&lt;/code> 字段。&lt;/p>
&lt;!--
#### Removal of all in-tree integrations with cloud providers
-->
&lt;h4 id="移除所有树内云提供商集成">移除所有树内云提供商集成&lt;/h4>
&lt;!--
As highlighted in a [previous article](/blog/2024/05/20/completing-cloud-provider-migration/), the last remaining in-tree support for cloud provider integration has been removed as part of the v1.31 release.
This doesn't mean you can't integrate with a cloud provider, however you now **must** use the
recommended approach using an external integration. Some integrations are part of the Kubernetes
project and others are third party software.
-->
&lt;p>正如之前的文章中强调的那样，作为 v1.31 发布的一部分，最后剩余的树内云平台集成支持已被移除。
这并不意味着您不能与云平台集成，但是您现在&lt;strong>必须&lt;/strong>使用推荐的方法使用外部集成。一些集成是 Kubernetes 项目的一部分，而其他则是第三方软件。&lt;/p>
&lt;!--
This milestone marks the completion of the externalization process for all cloud providers' integrations from the Kubernetes core ([KEP-2395](https://github.com/kubernetes/enhancements/blob/master/keps/sig-cloud-provider/2395-removing-in-tree-cloud-providers/README.md)), a process started with Kubernetes v1.26.
This change helps Kubernetes to get closer to being a truly vendor-neutral platform.
-->
&lt;p>这一里程碑标志着所有云提供商集成从 Kubernetes 核心外部化过程的完成（&lt;a href="https://github.com/kubernetes/enhancements/blob/master/keps/sig-cloud-provider/2395-removing-in-tree-cloud-providers/README.md">KEP-2395&lt;/a>），这个过程始于 Kubernetes v1.26。
这一变化有助于 Kubernetes 更接近成为一个真正供应商中立的平台。&lt;/p>
&lt;!--
For further details on the cloud provider integrations, read our [v1.29 Cloud Provider Integrations feature blog](/blog/2023/12/14/cloud-provider-integration-changes/).
For additional context about the in-tree code removal, we invite you to check the ([v1.29 deprecation blog](/blog/2023/11/16/kubernetes-1-29-upcoming-changes/#removal-of-in-tree-integrations-with-cloud-providers-kep-2395-https-kep-k8s-io-2395)).
-->
&lt;p>有关云提供商集成的更多详细信息，请阅读我们的 &lt;a href="https://kubernetes.io/blog/2023/12/14/cloud-provider-integration-changes/">v1.29 云提供商集成功能博客&lt;/a>。
有关树内代码移除的额外背景，我们邀请您查看（&lt;a href="https://kubernetes.io/blog/2023/11/16/kubernetes-1-29-upcoming-changes/#removal-of-in-tree-integrations-with-cloud-providers-kep-2395-https-kep-k8s-io-2395">v1.29 弃用博客&lt;/a>）。&lt;/p>
&lt;!--
The latter blog also contains useful information for users who need to migrate to version v1.29 and later.
-->
&lt;p>后者的博客还包含了需要迁移到 v1.29 及更高版本的用户的有用信息。&lt;/p>
&lt;!--
#### Removal of in-tree provider feature gates
-->
&lt;h4 id="移除树内供应商特性门控">移除树内供应商特性门控&lt;/h4>
&lt;!--
In Kubernetes v1.31, the following alpha feature gates `InTreePluginAWSUnregister`, `InTreePluginAzureDiskUnregister`, `InTreePluginAzureFileUnregister`, `InTreePluginGCEUnregister`, `InTreePluginOpenStackUnregister`, and `InTreePluginvSphereUnregister` have been removed. These feature gates were introduced to facilitate the testing of scenarios where in-tree volume plugins were removed from the codebase, without actually removing them. Since Kubernetes 1.30 had deprecated these in-tree volume plugins, these feature gates were redundant and no longer served a purpose. The only CSI migration gate still standing is `InTreePluginPortworxUnregister`, which will remain in alpha until the CSI migration for Portworx is completed and its in-tree volume plugin will be ready for removal.
-->
&lt;p>在 Kubernetes v1.31 中，以下 Alpha 特性门控 &lt;code>InTreePluginAWSUnregister&lt;/code>、&lt;code>InTreePluginAzureDiskUnregister&lt;/code>、
&lt;code>InTreePluginAzureFileUnregister&lt;/code>、&lt;code>InTreePluginGCEUnregister&lt;/code>、&lt;code>InTreePluginOpenStackUnregister&lt;/code>
和 &lt;code>InTreePluginvSphereUnregister&lt;/code> 已被移除。
这些特性门控的引入是为了便于测试从代码库中移除树内卷插件的场景，而无需实际移除它们。
由于 Kubernetes 1.30 已弃用这些树内卷插件，这些特性门控变得多余，不再有用。
唯一仍然存在的 CSI 迁移门控是 &lt;code>InTreePluginPortworxUnregister&lt;/code>，它将保持 Alpha 状态，
直到 Portworx 的 CSI 迁移完成，其树内卷插件准备好被移除。&lt;/p>
&lt;!--
#### Removal of kubelet `--keep-terminated-pod-volumes` command line flag
-->
&lt;h4 id="移除-kubelet-的-keep-terminated-pod-volumes-命令行标志">移除 kubelet 的 &lt;code>--keep-terminated-pod-volumes&lt;/code> 命令行标志&lt;/h4>
&lt;!--
The kubelet flag `--keep-terminated-pod-volumes`, which was deprecated in 2017, has been removed as
part of the v1.31 release.
You can find more details in the pull request [#122082](https://github.com/kubernetes/kubernetes/pull/122082).
-->
&lt;p>作为 v1.31 版本的一部分，已移除 kubelet 标志 &lt;code>--keep-terminated-pod-volumes&lt;/code>。该标志于 2017 年被弃用。&lt;/p>
&lt;p>您可以在拉取请求 &lt;a href="https://github.com/kubernetes/kubernetes/pull/122082">#122082&lt;/a> 中找到更多详细信息。&lt;/p>
&lt;!--
#### Removal of CephFS volume plugin
[CephFS volume plugin](/docs/concepts/storage/volumes/#cephfs) was removed in this release and the `cephfs` volume type became non-functional.
It is recommended that you use the [CephFS CSI driver](https://github.com/ceph/ceph-csi/) as a third-party storage driver instead. If you were using the CephFS volume plugin before upgrading the cluster version to v1.31, you must re-deploy your application to use the new driver.
CephFS volume plugin was formally marked as deprecated in v1.28.
-->
&lt;h4 id="移除-cephfs-卷插件">移除 CephFS 卷插件&lt;/h4>
&lt;p>本次发布中移除了 &lt;a href="https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/#cephfs">CephFS 卷插件&lt;/a>，&lt;code>cephfs&lt;/code> 卷类型变为不可用。&lt;/p>
&lt;p>建议您改用 &lt;a href="https://github.com/ceph/ceph-csi/">CephFS CSI 驱动&lt;/a> 作为第三方存储驱动程序。
如果您在将集群版本升级到 v1.31 之前使用了 CephFS 卷插件，则必须重新部署应用程序以使用新的驱动程序。&lt;/p>
&lt;p>CephFS 卷插件在 v1.28 中正式标记为废弃。&lt;/p>
&lt;!--
#### Removal of Ceph RBD volume plugin
The v1.31 release removes the [Ceph RBD volume plugin](/docs/concepts/storage/volumes/#rbd) and its CSI migration support, making the `rbd` volume type non-functional.
It's recommended that you use the [RBD CSI driver](https://github.com/ceph/ceph-csi/) in your clusters instead.
If you were using Ceph RBD volume plugin before upgrading the cluster version to v1.31, you must re-deploy your application to use the new driver.
The Ceph RBD volume plugin was formally marked as deprecated in v1.28.
-->
&lt;h4 id="移除-ceph-rbd-卷插件">移除 Ceph RBD 卷插件&lt;/h4>
&lt;p>v1.31 版本移除了 &lt;a href="https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/#rbd">Ceph RBD volume plugin&lt;/a> 及其 CSI 迁移支持，使 &lt;code>rbd&lt;/code> 卷类型变为不可用。&lt;/p>
&lt;p>建议您在集群中改用 &lt;a href="https://github.com/ceph/ceph-csi/">RBD CSI driver&lt;/a>。
如果您在将集群版本升级到 v1.31 之前使用了 Ceph RBD 卷插件，则必须重新部署应用程序以使用新的驱动程序。&lt;/p>
&lt;p>Ceph RBD 卷插件在 v1.28 中正式标记为废弃。&lt;/p>
&lt;!--
#### Deprecation of non-CSI volume limit plugins in kube-scheduler
-->
&lt;h4 id="废弃-kube-scheduler-中的非-csi-卷限制插件">废弃 kube-scheduler 中的非 CSI 卷限制插件&lt;/h4>
&lt;!--
The v1.31 release will deprecate all non-CSI volume limit scheduler plugins, and will remove some
already deprected plugins from the [default plugins](/docs/reference/scheduling/config/), including:
- `AzureDiskLimits`
- `CinderLimits`
- `EBSLimits`
- `GCEPDLimits`
-->
&lt;p>v1.31 版本将废弃所有非 CSI 卷限制调度器插件，并将从&lt;a href="https://kubernetes.io/zh-cn/docs/reference/scheduling/config/">默认插件&lt;/a>中移除一些已废弃的插件，包括：&lt;/p>
&lt;ul>
&lt;li>&lt;code>AzureDiskLimits&lt;/code>&lt;/li>
&lt;li>&lt;code>CinderLimits&lt;/code>&lt;/li>
&lt;li>&lt;code>EBSLimits&lt;/code>&lt;/li>
&lt;li>&lt;code>GCEPDLimits&lt;/code>&lt;/li>
&lt;/ul>
&lt;!--
It's recommended that you use the `NodeVolumeLimits` plugin instead because it can handle the same functionality as the removed plugins since those volume types have been migrated to CSI.
Please replace the deprecated plugins with the `NodeVolumeLimits` plugin if you explicitly use them in the [scheduler config](/docs/reference/scheduling/config/).
The `AzureDiskLimits`, `CinderLimits`, `EBSLimits`, and `GCEPDLimits` plugins will be removed in a future release.
-->
&lt;p>建议您改用 &lt;code>NodeVolumeLimits&lt;/code> 插件，因为自从这些卷类型迁移到 CSI 后，该插件可以处理与已移除插件相同的功能。
如果您在调度器配置中明确使用了已废弃的插件，请将它们替换为 &lt;code>NodeVolumeLimits&lt;/code> 插件。
&lt;code>AzureDiskLimits&lt;/code>、&lt;code>CinderLimits&lt;/code>、&lt;code>EBSLimits&lt;/code> 和 &lt;code>GCEPDLimits&lt;/code> 插件将在未来的版本中被移除。&lt;/p>
&lt;!--
These plugins will be removed from the default scheduler plugins list as they have been deprecated since Kubernetes v1.14.
-->
&lt;p>这些插件自 Kubernetes v1.14 以来已被废弃，将从默认调度器插件列表中移除。&lt;/p>
&lt;!--
### Release notes and upgrade actions required
Check out the full details of the Kubernetes v1.31 release in our [release notes](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.31.md).
-->
&lt;h3 id="发布说明和所需的升级操作">发布说明和所需的升级操作&lt;/h3>
&lt;p>请在我们的&lt;a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.31.md">发布说明&lt;/a>中查看 Kubernetes v1.31 版本的完整详细信息。&lt;/p>
&lt;!--
#### Scheduler now uses QueueingHint when `SchedulerQueueingHints` is enabled
Added support to the scheduler to start using a QueueingHint registered for Pod/Updated events,
to determine whether updates to previously unschedulable Pods have made them schedulable.
The new support is active when the feature gate `SchedulerQueueingHints` is enabled.
Previously, when unschedulable Pods were updated, the scheduler always put Pods back to into a queue
(`activeQ` / `backoffQ`). However not all updates to Pods make Pods schedulable, especially considering
many scheduling constraints nowadays are immutable. Under the new behaviour, once unschedulable Pods
are updated, the scheduling queue checks with QueueingHint(s) whether the update may make the
pod(s) schedulable, and requeues them to `activeQ` or `backoffQ` only when at least one
QueueingHint returns `Queue`.
-->
&lt;h4 id="启用-schedulerqueueinghints-时-调度器现在使用-queueinghint">启用 &lt;code>SchedulerQueueingHints&lt;/code> 时，调度器现在使用 QueueingHint&lt;/h4>
&lt;p>社区为调度器添加了支持，以便在启用 &lt;code>SchedulerQueueingHints&lt;/code> 功能门控时，开始使用为 Pod/Updated
事件注册的 QueueingHint，以确定对先前不可调度的 Pod 的更新是否使其变得可调度。
以前，当不可调度的 Pod 被更新时，调度器总是将 Pod 放回队列（&lt;code>activeQ&lt;/code> / &lt;code>backoffQ&lt;/code>）。
然而，并非所有对 Pod 的更新都会使 Pod 变得可调度，特别是考虑到现在许多调度约束是不可变更的。
在新的行为下，一旦不可调度的 Pod 被更新，调度队列会通过 QueueingHint 检查该更新是否可能使 Pod 变得可调度，
并且只有当至少一个 QueueingHint 返回 Queue 时，才将它们重新排队到 &lt;code>activeQ&lt;/code> 或 &lt;code>backoffQ&lt;/code>。&lt;/p>
&lt;!--
**Action required for custom scheduler plugin developers**:
Plugins have to implement a QueueingHint for Pod/Update event if the rejection from them could be resolved by updating unscheduled Pods themselves. Example: suppose you develop a custom plugin that denies Pods that have a `schedulable=false` label. Given Pods with a `schedulable=false` label will be schedulable if the `schedulable=false` label is removed, this plugin would implement QueueingHint for Pod/Update event that returns Queue when such label changes are made in unscheduled Pods. You can find more details in the pull request [#122234](https://github.com/kubernetes/kubernetes/pull/122234).
-->
&lt;p>&lt;strong>自定义调度器插件开发者需要采取的操作&lt;/strong>：
如果插件的拒绝可以通过更新未调度的 Pod 本身来解决，那么插件必须为 Pod/Update 事件实现 QueueingHint。
例如：假设您开发了一个自定义插件，该插件拒绝具有 &lt;code>schedulable=false&lt;/code> 标签的 Pod。
鉴于带有 &lt;code>schedulable=false&lt;/code> 标签的 Pod 在移除该标签后将变得可调度，这个插件将为 Pod/Update
事件实现 QueueingHint，当在未调度的 Pod 中进行此类标签更改时返回 Queue。
您可以在 pull request &lt;a href="https://github.com/kubernetes/kubernetes/pull/122234">#122234&lt;/a> 中找到更多详细信息。&lt;/p>
&lt;!--
#### Removal of kubelet --keep-terminated-pod-volumes command line flag
The kubelet flag `--keep-terminated-pod-volumes`, which was deprecated in 2017, was removed as part of the v1.31 release.
You can find more details in the pull request [#122082](https://github.com/kubernetes/kubernetes/pull/122082).
-->
&lt;h4 id="移除-kubelet-keep-terminated-pod-volumes-命令行标志">移除 kubelet --keep-terminated-pod-volumes 命令行标志&lt;/h4>
&lt;p>作为 v1.31 版本的一部分，已移除 kubelet 标志 &lt;code>--keep-terminated-pod-volumes&lt;/code>。该标志于 2017 年被弃用。
您可以在拉取请求 &lt;a href="https://github.com/kubernetes/kubernetes/pull/122082">#122082&lt;/a> 中找到更多详细信息。&lt;/p>
&lt;!--
## Availability
Kubernetes v1.31 is available for download on [GitHub](https://github.com/kubernetes/kubernetes/releases/tag/v1.31.0) or on the [Kubernetes download page](/releases/download/).
To get started with Kubernetes, check out these [interactive tutorials](/docs/tutorials/) or run local Kubernetes clusters using [minikube](https://minikube.sigs.k8s.io/). You can also easily install v1.31 using [kubeadm](/docs/setup/independent/create-cluster-kubeadm/).
-->
&lt;h2 id="可用性">可用性&lt;/h2>
&lt;p>Kubernetes v1.31 可在 &lt;a href="https://github.com/kubernetes/kubernetes/releases/tag/v1.31.0">GitHub&lt;/a> 或 &lt;a href="https://kubernetes.io/zh-cn/releases/download/">Kubernetes 下载页面&lt;/a>上下载。&lt;/p>
&lt;p>要开始使用 Kubernetes，请查看这些&lt;a href="https://kubernetes.io/zh-cn/docs/tutorials/">交互式教程&lt;/a>或使用 &lt;a href="https://minikube.sigs.k8s.io/">minikube&lt;/a>
运行本地 Kubernetes 集群。您还可以使用 &lt;a href="https://kubernetes.io/zh-cn/docs/setup/independent/create-cluster-kubeadm/">kubeadm&lt;/a> 轻松安装 v1.31。&lt;/p>
&lt;!--
## Release team
Kubernetes is only possible with the support, commitment, and hard work of its community.
Each release team is made up of dedicated community volunteers who work together to build the many pieces that make up the Kubernetes releases you rely on.
This requires the specialized skills of people from all corners of our community, from the code itself to its documentation and project management.
We would like to thank the entire [release team](https://github.com/kubernetes/sig-release/blob/master/releases/release-1.31/release-team.md) for the hours spent hard at work to deliver the Kubernetes v1.31 release to our community.
The Release Team's membership ranges from first-time shadows to returning team leads with experience forged over several release cycles.
A very special thanks goes out our release lead, Angelos Kolaitis, for supporting us through a successful release cycle, advocating for us, making sure that we could all contribute in the best way possible, and challenging us to improve the release process.
-->
&lt;h2 id="发布团队">发布团队&lt;/h2>
&lt;p>Kubernetes 的实现离不开社区的支持、投入和辛勤工作。
每个发布团队由致力于构建 Kubernetes 发布版本各个部分的专门社区志愿者组成。
这需要来自我们社区各个角落的人员的专业技能，从代码本身到文档和项目管理。&lt;/p>
&lt;p>我们要感谢整个&lt;a href="https://github.com/kubernetes/sig-release/blob/master/releases/release-1.31/release-team.md">发布团队&lt;/a>为向我们的社区交付 Kubernetes v1.31 版本所付出的时间和努力。
发布团队的成员从首次参与的影子成员到经历多个发布周期的回归团队负责人不等。
特别感谢我们的发布负责人 Angelos Kolaitis，他支持我们完成了一个成功的发布周期，为我们发声，确保我们都能以最佳方式贡献，并挑战我们改进发布过程。&lt;/p>
&lt;!--
## Project velocity
-->
&lt;h2 id="项目速度">项目速度&lt;/h2>
&lt;!--
The CNCF K8s DevStats project aggregates a number of interesting data points related to the velocity of Kubernetes and various sub-projects. This includes everything from individual contributions to the number of companies that are contributing and is an illustration of the depth and breadth of effort that goes into evolving this ecosystem.
-->
&lt;p>CNCF K8s DevStats 项目汇总了许多与 Kubernetes 及各个子项目速度相关的有趣数据点。
这包括从个人贡献到贡献公司数量的所有内容，展示了进化这个生态系统所投入的深度和广度。&lt;/p>
&lt;!--
In the v1.31 release cycle, which ran for 14 weeks (May 7th to August 13th), we saw contributions to Kubernetes from 113 different companies and 528 individuals.
-->
&lt;p>在为期 14 周的 v1.31 发布周期（5 月 7 日至 8 月 13 日）中，我们看到来自 113 家不同公司和 528 个个人对 Kubernetes 的贡献。&lt;/p>
&lt;!--
In the whole Cloud Native ecosystem we have 379 companies counting 2268 total contributors - which means that respect to the previous release cycle we experienced an astounding 63% increase on individuals contributing!
-->
&lt;p>在整个云原生生态系统中，我们有 379 家公司，共计 2268 名贡献者 - 这意味着相比上一个发布周期，个人贡献者数量惊人地增加了 63%！&lt;/p>
&lt;!--
Source for this data:
- [Companies contributing to Kubernetes](https://k8s.devstats.cncf.io/d/11/companies-contributing-in-repository-groups?orgId=1&amp;from=1715032800000&amp;to=1723586399000&amp;var-period=d28&amp;var-repogroup_name=Kubernetes&amp;var-repo_name=kubernetes%2Fkubernetes)
- [Overall ecosystem contributions](https://k8s.devstats.cncf.io/d/11/companies-contributing-in-repository-groups?orgId=1&amp;from=1715032800000&amp;to=1723586399000&amp;var-period=d28&amp;var-repogroup_name=All&amp;var-repo_name=kubernetes%2Fkubernetes)
-->
&lt;p>数据来源：&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://k8s.devstats.cncf.io/d/11/companies-contributing-in-repository-groups?orgId=1&amp;from=1715032800000&amp;to=1723586399000&amp;var-period=d28&amp;var-repogroup_name=Kubernetes&amp;var-repo_name=kubernetes%2Fkubernetes">为 Kubernetes 贡献的公司&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://k8s.devstats.cncf.io/d/11/companies-contributing-in-repository-groups?orgId=1&amp;from=1715032800000&amp;to=1723586399000&amp;var-period=d28&amp;var-repogroup_name=All&amp;var-repo_name=kubernetes%2Fkubernetes">整体生态系统贡献&lt;/a>&lt;/li>
&lt;/ul>
&lt;!--
By contribution we mean when someone makes a commit, code review, comment, creates an issue or PR, reviews a PR (including blogs and documentation) or comments on issues and PRs.
-->
&lt;p>贡献指的是当某人进行提交、代码审查、评论、创建问题或 PR、审查 PR（包括博客和文档）或对问题和 PR 进行评论。&lt;/p>
&lt;!--
If you are interested in contributing visit [this page](https://www.kubernetes.dev/docs/guide/#getting-started) to get started.
-->
&lt;p>如果您有兴趣贡献，请访问&lt;a href="https://www.kubernetes.dev/docs/guide/#getting-started">此页面&lt;/a>开始。&lt;/p>
&lt;!--
[Check out DevStats](https://k8s.devstats.cncf.io/d/11/companies-contributing-in-repository-groups?orgId=1&amp;var-period=m&amp;var-repogroup_name=All) to learn more about the overall velocity of the Kubernetes project and community.
-->
&lt;p>&lt;a href="https://k8s.devstats.cncf.io/d/11/companies-contributing-in-repository-groups?orgId=1&amp;var-period=m&amp;var-repogroup_name=All">查看 DevStats&lt;/a> 以了解更多关于 Kubernetes 项目和社区整体速度的信息。&lt;/p>
&lt;!--
## Event update
Explore the upcoming Kubernetes and cloud-native events from August to November 2024, featuring KubeCon, KCD, and other notable conferences worldwide. Stay informed and engage with the Kubernetes community.
-->
&lt;h2 id="活动更新">活动更新&lt;/h2>
&lt;p>探索 2024 年 8 月至 11 月即将举行的 Kubernetes 和云原生活动，包括 KubeCon、KCD 和其他全球知名会议。保持了解并参与 Kubernetes 社区。&lt;/p>
&lt;!--
**August 2024**
- [**KubeCon + CloudNativeCon + Open Source Summit China 2024**](https://events.linuxfoundation.org/kubecon-cloudnativecon-open-source-summit-ai-dev-china/): August 21-23, 2024 | Hong Kong
- [**KubeDay Japan**](https://events.linuxfoundation.org/kubeday-japan/): August 27, 2024 | Tokyo, Japan
-->
&lt;p>&lt;strong>2024 年 8 月&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://events.linuxfoundation.org/kubecon-cloudnativecon-open-source-summit-ai-dev-china/">&lt;strong>KubeCon + CloudNativeCon + 开源峰会中国 2024&lt;/strong>&lt;/a>：2024 年 8 月 21-23 日 | 中国香港&lt;/li>
&lt;li>&lt;a href="https://events.linuxfoundation.org/kubeday-japan/">&lt;strong>KubeDay Japan&lt;/strong>&lt;/a>：2024 年 8 月 27 日 | 东京，日本&lt;/li>
&lt;/ul>
&lt;!--
**September 2024**
- [**KCD Lahore - Pakistan 2024**](https://community.cncf.io/events/details/cncf-kcd-lahore-presents-kcd-lahore-pakistan-2024/): September 1, 2024 | Lahore, Pakistan
- [**KuberTENes Birthday Bash Stockholm**](https://community.cncf.io/events/details/cncf-stockholm-presents-kubertenes-birthday-bash-stockholm-a-couple-of-months-late/): September 5, 2024 | Stockholm, Sweden
- [**KCD Sydney ’24**](https://community.cncf.io/events/details/cncf-kcd-australia-presents-kcd-sydney-24/): September 5-6, 2024 | Sydney, Australia
- [**KCD Washington DC 2024**](https://community.cncf.io/events/details/cncf-kcd-washington-dc-presents-kcd-washington-dc-2024/): September 24, 2024 | Washington, DC, United States
- [**KCD Porto 2024**](https://community.cncf.io/events/details/cncf-kcd-porto-presents-kcd-porto-2024/): September 27-28, 2024 | Porto, Portugal
-->
&lt;p>&lt;strong>2024 年 9 月&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://community.cncf.io/events/details/cncf-kcd-lahore-presents-kcd-lahore-pakistan-2024/">&lt;strong>KCD 拉合尔 - 巴基斯坦 2024&lt;/strong>&lt;/a>: 2024 年 9 月 1 日 | 拉合尔，巴基斯坦&lt;/li>
&lt;li>&lt;a href="https://community.cncf.io/events/details/cncf-stockholm-presents-kubertenes-birthday-bash-stockholm-a-couple-of-months-late/">&lt;strong>KuberTENes 生日庆典 斯德哥尔摩&lt;/strong>&lt;/a>: 2024 年 9 月 5 日 | 斯德哥尔摩，瑞典&lt;/li>
&lt;li>&lt;a href="https://community.cncf.io/events/details/cncf-kcd-australia-presents-kcd-sydney-24/">&lt;strong>KCD Sydney ’24&lt;/strong>&lt;/a>: 2024 年 9 月 5-6 日 | 悉尼，澳大利亚&lt;/li>
&lt;li>&lt;a href="https://community.cncf.io/events/details/cncf-kcd-washington-dc-presents-kcd-washington-dc-2024/">&lt;strong>KCD Washington DC 2024&lt;/strong>&lt;/a>: 2024 年 9 月 24 日 | 华盛顿特区，美国&lt;/li>
&lt;li>&lt;a href="https://community.cncf.io/events/details/cncf-kcd-porto-presents-kcd-porto-2024/">&lt;strong>KCD Porto 2024&lt;/strong>&lt;/a>: 2024 年 9 月 27-28 日 | 波尔图，葡萄牙&lt;/li>
&lt;/ul>
&lt;!--
**October 2024**
- [**KCD Austria 2024**](https://community.cncf.io/events/details/cncf-kcd-austria-presents-kcd-austria-2024/): October 8-10, 2024 | Wien, Austria
- [**KubeDay Australia**](https://events.linuxfoundation.org/kubeday-australia/): October 15, 2024 | Melbourne, Australia
- [**KCD UK - London 2024**](https://community.cncf.io/events/details/cncf-kcd-uk-presents-kubernetes-community-days-uk-london-2024/): October 22-23, 2024 | Greater London, United Kingdom
-->
&lt;p>&lt;strong>2024 年 10 月&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://community.cncf.io/events/details/cncf-kcd-austria-presents-kcd-austria-2024/">&lt;strong>KCD Austria 2024&lt;/strong>&lt;/a>: 2024 年 10 月 8-10 日 | 维也纳，奥地利&lt;/li>
&lt;li>&lt;a href="https://events.linuxfoundation.org/kubeday-australia/">&lt;strong>KubeDay Australia&lt;/strong>&lt;/a>: 2024 年 10 月 15 日 | 墨尔本，澳大利亚&lt;/li>
&lt;li>&lt;a href="https://community.cncf.io/events/details/cncf-kcd-uk-presents-kubernetes-community-days-uk-london-2024/">&lt;strong>KCD UK - London 2024&lt;/strong>&lt;/a>: 2024 年 10 月 22-23 日 | 伦敦，英国&lt;/li>
&lt;/ul>
&lt;!--
**November 2024**
- [**KubeCon + CloudNativeCon North America 2024**](https://events.linuxfoundation.org/kubecon-cloudnativecon-north-america/): November 12-15, 2024 | Salt Lake City, United States
- [**Kubernetes on EDGE Day North America**](https://events.linuxfoundation.org/kubecon-cloudnativecon-north-america/co-located-events/kubernetes-on-edge-day/): November 12, 2024 | Salt Lake City, United States
-->
&lt;p>&lt;strong>2024 年 11 月&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://events.linuxfoundation.org/kubecon-cloudnativecon-north-america/">&lt;strong>KubeCon + CloudNativeCon North America 2024&lt;/strong>&lt;/a>: 2024 年 11 月 12-15 日 | 盐湖城，美国&lt;/li>
&lt;li>&lt;a href="https://events.linuxfoundation.org/kubecon-cloudnativecon-north-america/co-located-events/kubernetes-on-edge-day/">&lt;strong>Kubernetes on EDGE Day North America&lt;/strong>&lt;/a>: 2024 年 11 月 12 日 | 盐湖城，美国&lt;/li>
&lt;/ul>
&lt;!--
## Upcoming release webinar
Join members of the Kubernetes v1.31 release team on Thursday, Thu Sep 12, 2024 10am PT to learn about the major features of this release, as well as deprecations and removals to help plan for upgrades.
For more information and registration, visit the [event page](https://community.cncf.io/events/details/cncf-cncf-online-programs-presents-cncf-live-webinar-kubernetes-131-release/) on the CNCF Online Programs site.
-->
&lt;h2 id="即将举行的发布网络研讨会">即将举行的发布网络研讨会&lt;/h2>
&lt;p>加入 Kubernetes v1.31 发布团队成员，于 2024 年 9 月 12 日星期四太平洋时间上午 10 点了解此版本的主要特性，以及废弃和移除的内容，以帮助规划升级。
有关更多信息和注册，请访问 CNCF 在线项目网站上的&lt;a href="https://community.cncf.io/events/details/cncf-cncf-online-programs-presents-cncf-live-webinar-kubernetes-131-release/">活动页面&lt;/a>。&lt;/p>
&lt;!--
## Get involved
The simplest way to get involved with Kubernetes is by joining one of the many [Special Interest Groups](https://github.com/kubernetes/community/blob/master/sig-list.md) (SIGs) that align with your interests.
Have something you’d like to broadcast to the Kubernetes community?
Share your voice at our weekly [community meeting](https://github.com/kubernetes/community/tree/master/communication), and through the channels below.
Thank you for your continued feedback and support.
- Follow us on X [@Kubernetesio](https://x.com/kubernetesio) for latest updates
- Join the community discussion on [Discuss](https://discuss.kubernetes.io/)
- Join the community on [Slack](http://slack.k8s.io/)
- Post questions (or answer questions) on [Stack Overflow](http://stackoverflow.com/questions/tagged/kubernetes)
- Share your Kubernetes [story](https://docs.google.com/a/linuxfoundation.org/forms/d/e/1FAIpQLScuI7Ye3VQHQTwBASrgkjQDSS5TP0g3AXfFhwSM9YpHgxRKFA/viewform)
- Read more about what’s happening with Kubernetes on the [blog](https://kubernetes.io/blog/)
- Learn more about the [Kubernetes Release Team](https://github.com/kubernetes/sig-release/tree/master/release-team)
-->
&lt;h2 id="参与其中">参与其中&lt;/h2>
&lt;p>参与 Kubernetes 的最简单方式是加入与您兴趣相符的众多特殊兴趣小组（&lt;a href="https://github.com/kubernetes/community/blob/master/sig-list.md">SIG&lt;/a>）之一。
您有什么想向 Kubernetes 社区广播的内容吗？
在我们的每周&lt;a href="https://github.com/kubernetes/community/tree/master/communication">社区会议&lt;/a>上分享您的声音，并通过以下渠道。
感谢您持续的反馈和支持。&lt;/p>
&lt;ul>
&lt;li>在 X 上关注我们 &lt;a href="https://x.com/kubernetesio">@Kubernetesio&lt;/a> 获取最新更新&lt;/li>
&lt;li>在 &lt;a href="https://discuss.kubernetes.io/">Discuss&lt;/a> 上加入社区讨论&lt;/li>
&lt;li>在 &lt;a href="http://slack.k8s.io/">Slack&lt;/a> 上加入社区&lt;/li>
&lt;li>在 &lt;a href="http://stackoverflow.com/questions/tagged/kubernetes">Stack Overflow&lt;/a> 上发布问题（或回答问题）&lt;/li>
&lt;li>分享您的 Kubernetes &lt;a href="https://docs.google.com/a/linuxfoundation.org/forms/d/e/1FAIpQLScuI7Ye3VQHQTwBASrgkjQDSS5TP0g3AXfFhwSM9YpHgxRKFA/viewform">故事&lt;/a>&lt;/li>
&lt;li>在&lt;a href="https://kubernetes.io/blog/">博客&lt;/a>上阅读更多关于 Kubernetes 的最新动态&lt;/li>
&lt;li>了解更多关于 &lt;a href="https://github.com/kubernetes/sig-release/tree/master/release-team">Kubernetes 发布团队&lt;/a>的信息&lt;/li>
&lt;/ul></description></item><item><title>向 Client-Go 引入特性门控：增强灵活性和控制力</title><link>https://kubernetes.io/zh-cn/blog/2024/08/12/feature-gates-in-client-go/</link><pubDate>Mon, 12 Aug 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/08/12/feature-gates-in-client-go/</guid><description>
&lt;!--
layout: blog
title: 'Introducing Feature Gates to Client-Go: Enhancing Flexibility and Control'
date: 2024-08-12
slug: feature-gates-in-client-go
author: >
Ben Luddy (Red Hat),
Lukasz Szaszkiewicz (Red Hat)
-->
&lt;!--
Kubernetes components use on-off switches called _feature gates_ to manage the risk of adding a new feature.
The feature gate mechanism is what enables incremental graduation of a feature through the stages Alpha, Beta, and GA.
-->
&lt;p>Kubernetes 组件使用称为“特性门控（Feature Gates）”的开关来管理添加新特性的风险，
特性门控机制使特性能够通过 Alpha、Beta 和 GA 阶段逐步升级。&lt;/p>
&lt;!--
Kubernetes components, such as kube-controller-manager and kube-scheduler, use the client-go library to interact with the API.
The same library is used across the Kubernetes ecosystem to build controllers, tools, webhooks, and more. client-go now includes
its own feature gating mechanism, giving developers and cluster administrators more control over how they adopt client features.
-->
&lt;p>Kubernetes 组件（例如 kube-controller-manager 和 kube-scheduler）使用 client-go 库与 API 交互，
整个 Kubernetes 生态系统使用相同的库来构建控制器、工具、webhook 等。
client-go 现在包含自己的特性门控机制，使开发人员和集群管理员能够更好地控制如何使用客户端特性。&lt;/p>
&lt;!--
To learn more about feature gates in Kubernetes, visit [Feature Gates](/docs/reference/command-line-tools-reference/feature-gates/).
-->
&lt;p>要了解有关 Kubernetes 中特性门控的更多信息，请参阅&lt;a href="https://kubernetes.io/zh-cn/docs/reference/command-line-tools-reference/feature-gates/">特性门控&lt;/a>。&lt;/p>
&lt;!--
## Motivation
In the absence of client-go feature gates, each new feature separated feature availability from enablement in its own way, if at all.
Some features were enabled by updating to a newer version of client-go. Others needed to be actively configured in each program that used them.
A few were configurable at runtime using environment variables. Consuming a feature-gated functionality exposed by the kube-apiserver sometimes
required a client-side fallback mechanism to remain compatible with servers that don’t support the functionality due to their age or configuration.
In cases where issues were discovered in these fallback mechanisms, mitigation required updating to a fixed version of client-go or rolling back.
-->
&lt;h2 id="动机">动机&lt;/h2>
&lt;p>在没有 client-go 特性门控的情况下，每个新特性都以自己的方式（如果有的话）将特性可用性与特性的启用分开。
某些特性可通过更新到较新版本的 client-go 来启用，其他特性则需要在每个使用它们的程序中进行主动配置，
其中一些可在运行时使用环境变量进行配置。使用 kube-apiserver 公开的特性门控功能时，有时需要客户端回退机制，
以保持与由于版本新旧或配置不同而不支持该特性服务器的兼容性。
如果在这些回退机制中发现问题，则缓解措施需要更新到 client-go 的固定版本或回滚。&lt;/p>
&lt;!--
None of these approaches offer good support for enabling a feature by default in some, but not all, programs that consume client-go.
Instead of enabling a new feature at first only for a single component, a change in the default setting immediately affects the default
for all Kubernetes components, which broadens the blast radius significantly.
-->
&lt;p>这些方法都无法很好地支持为某些（但不是全部）使用 client-go 的程序默认启用特性。
默认设置的更改不会首先仅为单个组件启用新特性，而是会立即影响所有 Kubernetes 组件的默认设置，从而大大扩大影响半径。&lt;/p>
&lt;!--
## Feature gates in client-go
To address these challenges, substantial client-go features will be phased in using the new feature gate mechanism.
It will allow developers and users to enable or disable features in a way that will be familiar to anyone who has experience
with feature gates in the Kubernetes components.
-->
&lt;h2 id="client-go-中的特性门控">client-go 中的特性门控&lt;/h2>
&lt;p>为了应对这些挑战，大量的 client-go 特性将使用新的特性门控机制来逐步引入。
这一机制将允许开发人员和用户以类似 Kubernetes 组件特性门控的管理方式启用或禁用特性。&lt;/p>
&lt;!--
Out of the box, simply by using a recent version of client-go, this offers several benefits.
For people who use software built with client-go:
-->
&lt;p>作为一种开箱即用的能力，用户只需使用最新版本的 client-go。这种设计带来多种好处。&lt;/p>
&lt;p>对于使用通过 client-go 构建的软件的用户：&lt;/p>
&lt;!--
* Early adopters can enable a default-off client-go feature on a per-process basis.
* Misbehaving features can be disabled without building a new binary.
* The state of all known client-go feature gates is logged, allowing users to inspect it.
-->
&lt;ul>
&lt;li>早期采用者可以针对各个进程分别启用默认关闭的 client-go 特性。&lt;/li>
&lt;li>无需构建新的二进制文件即可禁用行为不当的特性。&lt;/li>
&lt;li>所有已知的 client-go 特性门控的状态都会被记录到日志中，允许用户检查。&lt;/li>
&lt;/ul>
&lt;!--
For people who develop software built with client-go:
* By default, client-go feature gate overrides are read from environment variables.
If a bug is found in a client-go feature, users will be able to disable it without waiting for a new release.
* Developers can replace the default environment-variable-based overrides in a program to change defaults,
read overrides from another source, or disable runtime overrides completely.
The Kubernetes components use this customizability to integrate client-go feature gates with
the existing `--feature-gates` command-line flag, feature enablement metrics, and logging.
-->
&lt;p>对于开发使用 client-go 构建的软件的人员：&lt;/p>
&lt;ul>
&lt;li>默认情况下，client-go 特性门控覆盖是从环境变量中读取的。
如果在 client-go 特性中发现错误，用户将能够禁用它，而无需等待新版本发布。&lt;/li>
&lt;li>开发人员可以替换程序中基于默认环境变量的覆盖值以更改默认值、从其他源读取覆盖值或完全禁用运行时覆盖值。
Kubernetes 组件使用这种可定制性将 client-go 特性门控与现有的 &lt;code>--feature-gates&lt;/code> 命令行标志、特性启用指标和日志记录集成在一起。&lt;/li>
&lt;/ul>
&lt;!--
## Overriding client-go feature gates
**Note**: This describes the default method for overriding client-go feature gates at runtime.
It can be disabled or customized by the developer of a particular program.
In Kubernetes components, client-go feature gate overrides are controlled by the `--feature-gates` flag.
Features of client-go can be enabled or disabled by setting environment variables prefixed with `KUBE_FEATURE`.
For example, to enable a feature named `MyFeature`, set the environment variable as follows:
-->
&lt;h2 id="覆盖-client-go-特性门控">覆盖 client-go 特性门控&lt;/h2>
&lt;p>&lt;strong>注意&lt;/strong>：这描述了在运行时覆盖 client-go 特性门控的默认方法，它可以由特定程序的开发人员禁用或自定义。
在 Kubernetes 组件中，client-go 特性门控覆盖由 &lt;code>--feature-gates&lt;/code> 标志控制。&lt;/p>
&lt;p>可以通过设置以 &lt;code>KUBE_FEATURE&lt;/code> 为前缀的环境变量来启用或禁用 client-go 的特性。
例如，要启用名为 &lt;code>MyFeature&lt;/code> 的特性，请按如下方式设置环境变量：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b8860b">KUBE_FEATURE_MyFeature&lt;/span>&lt;span style="color:#666">=&lt;/span>&lt;span style="color:#a2f">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
To disable the feature, set the environment variable to `false`:
-->
&lt;p>要禁用特性，可将环境变量设置为 &lt;code>false&lt;/code>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b8860b">KUBE_FEATURE_MyFeature&lt;/span>&lt;span style="color:#666">=&lt;/span>&lt;span style="color:#a2f">false&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
**Note**: Environment variables are case-sensitive on some operating systems.
Therefore, `KUBE_FEATURE_MyFeature` and `KUBE_FEATURE_MYFEATURE` would be considered two different variables.
-->
&lt;p>&lt;strong>注意&lt;/strong>：在某些操作系统上，环境变量区分大小写。
因此，&lt;code>KUBE_FEATURE_MyFeature&lt;/code> 和 &lt;code>KUBE_FEATURE_MYFEATURE&lt;/code> 将被视为两个不同的变量。&lt;/p>
&lt;!--
## Customizing client-go feature gates
The default environment-variable based mechanism for feature gate overrides can be sufficient for many programs in the Kubernetes ecosystem,
and requires no special integration. Programs that require different behavior can replace it with their own custom feature gate provider.
This allows a program to do things like force-disable a feature that is known to work poorly,
read feature gates directly from a remote configuration service, or accept feature gate overrides through command-line options.
-->
&lt;h2 id="自定义-client-go-特性门控">自定义 client-go 特性门控&lt;/h2>
&lt;p>基于环境变量的默认特性门控覆盖机制足以满足 Kubernetes 生态系统中许多程序的需求，无需特殊集成。
需要不同行为的程序可以用自己的自定义特性门控提供程序替换它。
这允许程序执行诸如强制禁用已知运行不良的特性、直接从远程配置服务读取特性门控或通过命令行选项接受特性门控覆盖等操作。&lt;/p>
&lt;!--
The Kubernetes components replace client-go’s default feature gate provider with a shim to the existing Kubernetes feature gate provider.
For all practical purposes, client-go feature gates are treated the same as other Kubernetes
feature gates: they are wired to the `--feature-gates` command-line flag, included in feature enablement metrics, and logged on startup.
-->
&lt;p>Kubernetes 组件将 client-go 的默认特性门控提供程序替换为现有 Kubernetes 特性门控提供程序的转换层。
在所有实际应用场合中，client-go 特性门控与其他 Kubernetes 特性门控的处理方式相同：
它们连接到 &lt;code>--feature-gates&lt;/code> 命令行标志，包含在特性启用指标中，并在启动时记录。&lt;/p>
&lt;!--
To replace the default feature gate provider, implement the Gates interface and call ReplaceFeatureGates
at package initialization time, as in this simple example:
-->
&lt;p>要替换默认的特性门控提供程序，请实现 Gates 接口并在包初始化时调用 ReplaceFeatureGates，如以下简单示例所示：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a2f;font-weight:bold">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#b44">&amp;#34;k8s.io/client-go/features&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a2f;font-weight:bold">type&lt;/span> AlwaysEnabledGates &lt;span style="color:#a2f;font-weight:bold">struct&lt;/span>{}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a2f;font-weight:bold">func&lt;/span> (AlwaysEnabledGates) &lt;span style="color:#00a000">Enabled&lt;/span>(features.Feature) &lt;span style="color:#0b0;font-weight:bold">bool&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a2f;font-weight:bold">return&lt;/span> &lt;span style="color:#a2f;font-weight:bold">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a2f;font-weight:bold">func&lt;/span> &lt;span style="color:#00a000">init&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> features.&lt;span style="color:#00a000">ReplaceFeatureGates&lt;/span>(AlwaysEnabledGates{})
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
Implementations that need the complete list of defined client-go features can get it by implementing the Registry interface
and calling `AddFeaturesToExistingFeatureGates`.
For a complete example, refer to [the usage within Kubernetes](https://github.com/kubernetes/kubernetes/blob/64ba17c605a41700f7f4c4e27dca3684b593b2b9/pkg/features/kube_features.go#L990-L997).
-->
&lt;p>需要定义的 client-go 特性完整列表的实现可以通过实现 Registry 接口并调用 &lt;code>AddFeaturesToExistingFeatureGates&lt;/code> 来获取它。
完整示例请参考
&lt;a href="https://github.com/kubernetes/kubernetes/blob/64ba17c605a41700f7f4c4e27dca3684b593b2b9/pkg/features/kube_features.go#L990-L997">Kubernetes 内部使用&lt;/a>。&lt;/p>
&lt;!--
## Summary
With the introduction of feature gates in client-go v1.30, rolling out a new client-go feature has become safer and easier.
Users and developers can control the pace of their own adoption of client-go features.
The work of Kubernetes contributors is streamlined by having a common mechanism for graduating features that span both sides of the Kubernetes API boundary.
-->
&lt;h2 id="总结">总结&lt;/h2>
&lt;p>随着 client-go v1.30 中特性门控的引入，推出新的 client-go 特性变得更加安全、简单。
用户和开发人员可以控制自己采用 client-go 特性的步伐。
通过为跨 Kubernetes API 边界两侧的特性提供一种通用的培育机制，Kubernetes 贡献者的工作得到了简化。&lt;/p>
&lt;!--
Special shoutout to [@sttts](https://github.com/sttts) and [@deads2k](https://github.com/deads2k) for their help in shaping this feature.
-->
&lt;p>特别感谢 &lt;a href="https://github.com/sttts">@sttts&lt;/a> 和 &lt;a href="https://github.com/deads2k">@deads2k&lt;/a> 对此特性提供的帮助。&lt;/p></description></item><item><title>聚焦 SIG API Machinery</title><link>https://kubernetes.io/zh-cn/blog/2024/08/07/sig-api-machinery-spotlight-2024/</link><pubDate>Wed, 07 Aug 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/08/07/sig-api-machinery-spotlight-2024/</guid><description>
&lt;!--
layout: blog
title: "Spotlight on SIG API Machinery"
slug: sig-api-machinery-spotlight-2024
canonicalUrl: https://www.kubernetes.dev/blog/2024/08/07/sig-api-machinery-spotlight-2024
date: 2024-08-07
author: "Frederico Muñoz (SAS Institute)"
-->
&lt;!--
We recently talked with [Federico Bongiovanni](https://github.com/fedebongio) (Google) and [David
Eads](https://github.com/deads2k) (Red Hat), Chairs of SIG API Machinery, to know a bit more about
this Kubernetes Special Interest Group.
-->
&lt;p>我们最近与 SIG API Machinery 的主席
&lt;a href="https://github.com/fedebongio">Federico Bongiovanni&lt;/a>（Google）和
&lt;a href="https://github.com/deads2k">David Eads&lt;/a>（Red Hat）进行了访谈，
了解一些有关这个 Kubernetes 特别兴趣小组的信息。&lt;/p>
&lt;!--
## Introductions
**Frederico (FSM): Hello, and thank your for your time. To start with, could you tell us about
yourselves and how you got involved in Kubernetes?**
-->
&lt;h2 id="introductions">介绍 &lt;/h2>
&lt;p>&lt;strong>Frederico (FSM)：你好，感谢你抽时间参与访谈。首先，你能做个自我介绍以及你是如何参与到 Kubernetes 的？&lt;/strong>&lt;/p>
&lt;!--
**David**: I started working on
[OpenShift](https://www.redhat.com/en/technologies/cloud-computing/openshift) (the Red Hat
distribution of Kubernetes) in the fall of 2014 and got involved pretty quickly in API Machinery. My
first PRs were fixing kube-apiserver error messages and from there I branched out to `kubectl`
(_kubeconfigs_ are my fault!), `auth` ([RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) and `*Review` APIs are ports
from OpenShift), `apps` (_workqueues_ and _sharedinformers_ for example). Don’t tell the others,
but API Machinery is still my favorite :)
-->
&lt;p>&lt;strong>David&lt;/strong>：我在 2014 年秋天开始在
&lt;a href="https://www.redhat.com/zh/technologies/cloud-computing/openshift">OpenShift&lt;/a>
（Red Hat 的 Kubernetes 发行版）工作，很快就参与到 API Machinery 的工作中。
我的第一个 PR 是修复 kube-apiserver 的错误消息，然后逐渐扩展到 &lt;code>kubectl&lt;/code>（&lt;em>kubeconfigs&lt;/em> 是我的杰作！），
&lt;code>auth&lt;/code>（&lt;a href="https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/rbac/">RBAC&lt;/a>
和 &lt;code>*Review&lt;/code> API 是从 OpenShift 移植过来的），&lt;code>apps&lt;/code>（例如 &lt;em>workqueues&lt;/em> 和 &lt;em>sharedinformers&lt;/em>）。
别告诉别人，但 API Machinery 仍然是我的最爱 :)&lt;/p>
&lt;!--
**Federico**: I was not as early in Kubernetes as David, but now it's been more than six years. At
my previous company we were starting to use Kubernetes for our own products, and when I came across
the opportunity to work directly with Kubernetes I left everything and boarded the ship (no pun
intended). I joined Google and Kubernetes in early 2018, and have been involved since.
-->
&lt;p>&lt;strong>Federico&lt;/strong>：我加入 Kubernetes 没有 David 那么早，但现在也已经超过六年了。
在我之前的公司，我们开始为自己的产品使用 Kubernetes，当我有机会直接参与 Kubernetes 的工作时，
我放下了一切，登上了这艘船（无意双关）。我在 2018 年初加入 Google 从事 Kubernetes 的相关工作，
从那时起一直参与其中。&lt;/p>
&lt;!--
## SIG Machinery's scope
**FSM: It only takes a quick look at the SIG API Machinery charter to see that it has quite a
significant scope, nothing less than the Kubernetes control plane. Could you describe this scope in
your own words?**
-->
&lt;h2 id="sig-machinerys-scope">SIG Machinery 的范围 &lt;/h2>
&lt;p>&lt;strong>FSM：只需快速浏览一下 SIG API Machinery 的章程，就可以看到它的范围相当广泛，
不亚于 Kubernetes 的控制平面。你能用自己的话描述一下这个范围吗？&lt;/strong>&lt;/p>
&lt;!--
**David**: We own the `kube-apiserver` and how to efficiently use it. On the backend, that includes
its contract with backend storage and how it allows API schema evolution over time. On the
frontend, that includes schema best practices, serialization, client patterns, and controller
patterns on top of all of it.
**Federico**: Kubernetes has a lot of different components, but the control plane has a really
critical mission: it's your communication layer with the cluster and also owns all the extensibility
mechanisms that make Kubernetes so powerful. We can't make mistakes like a regression, or an
incompatible change, because the blast radius is huge.
-->
&lt;p>&lt;strong>David&lt;/strong>：我们全权负责 &lt;code>kube-apiserver&lt;/code> 以及如何高效地使用它。
在后端，这包括它与后端存储的契约以及如何让 API 模式随时间演变。
在前端，这包括模式的最佳实践、序列化、客户端模式以及在其之上的控制器模式。&lt;/p>
&lt;p>&lt;strong>Federico&lt;/strong>：Kubernetes 有很多不同的组件，但控制平面有一个非常关键的任务：
它是你与集群的通信层，同时也拥有所有使 Kubernetes 如此强大的可扩展机制。
我们不能犯像回归或不兼容变更这样的错误，因为影响范围太大了。&lt;/p>
&lt;!--
**FSM: Given this breadth, how do you manage the different aspects of it?**
**Federico**: We try to organize the large amount of work into smaller areas. The working groups and
subprojects are part of it. Different people on the SIG have their own areas of expertise, and if
everything fails, we are really lucky to have people like David, Joe, and Stefan who really are "all
terrain", in a way that keeps impressing me even after all these years. But on the other hand this
is the reason why we need more people to help us carry the quality and excellence of Kubernetes from
release to release.
-->
&lt;p>&lt;strong>FSM：鉴于这个广度，你们如何管理它的不同方面？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>Federico&lt;/strong>：我们尝试将大量工作组织成较小的领域。工作组和子项目是其中的一部分。
SIG 中的各位贡献者有各自的专长领域，如果一切都失败了，我们很幸运有像 David、Joe 和 Stefan 这样的人，
他们真的是“全能型”，这种方式让我在这些年里一直感到惊叹。但另一方面，
这也是为什么我们需要更多人来帮助我们在版本变迁之时保持 Kubernetes 的质量和卓越。&lt;/p>
&lt;!--
## An evolving collaboration model
**FSM: Was the existing model always like this, or did it evolve with time - and if so, what would
you consider the main changes and the reason behind them?**
**David**: API Machinery has evolved over time both growing and contracting in scope. When trying
to satisfy client access patterns it’s very easy to add scope both in terms of features and applying
them.
-->
&lt;h2 id="an-evolving-collaboration-model">不断演变的协作模式 &lt;/h2>
&lt;p>&lt;strong>FSM：现有的模式一直是这样，还是随着时间的推移而演变的 - 如果是在演变的，你认为主要的变化以及背后的原因是什么？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>David&lt;/strong>：API Machinery 在随着时间的推移不断发展，既有扩展也有收缩。
在尝试满足客户端访问模式时，它很容易在特性和应用方面扩大范围。&lt;/p>
&lt;!--
A good example of growing scope is the way that we identified a need to reduce memory utilization by
clients writing controllers and developed shared informers. In developing shared informers and the
controller patterns use them (workqueues, error handling, and listers), we greatly reduced memory
utilization and eliminated many expensive lists. The downside: we grew a new set of capability to
support and effectively took ownership of that area from sig-apps.
-->
&lt;p>一个范围扩大的好例子是我们认识到需要减少客户端写入控制器时的内存使用率而开发了共享通知器。
在开发共享通知器和使用它们的控制器模式（工作队列、错误处理和列举器）时，
我们大大减少了内存使用率，并消除了许多占用资源较多的列表。
缺点是：我们增加了一套新的权能来提供支持，并有效地从 sig-apps 接管了该领域的所有权。&lt;/p>
&lt;!--
For an example of more shared ownership: building out cooperative resource management (the goal of
server-side apply), `kubectl` expanded to take ownership of leveraging the server-side apply
capability. The transition isn’t yet complete, but [SIG
CLI](https://github.com/kubernetes/community/tree/master/sig-cli) manages that usage and owns it.
-->
&lt;p>一个更多共享所有权的例子是：构建出合作的资源管理（服务器端应用的目标），
&lt;code>kubectl&lt;/code> 扩展为负责利用服务器端应用的权能。这个过渡尚未完成，
但 &lt;a href="https://github.com/kubernetes/community/tree/master/sig-cli">SIG CLI&lt;/a> 管理其使用情况并拥有它。&lt;/p>
&lt;!--
**FSM: And for the boundary between approaches, do you have any guidelines?**
**David**: I think much depends on the impact. If the impact is local in immediate effect, we advise
other SIGs and let them move at their own pace. If the impact is global in immediate effect without
a natural incentive, we’ve found a need to press for adoption directly.
**FSM: Still on that note, SIG Architecture has an API Governance subproject, is it mostly
independent from SIG API Machinery or are there important connection points?**
-->
&lt;p>&lt;strong>FSM：对于方法之间的权衡，你们有什么指导方针吗？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>David&lt;/strong>：我认为这很大程度上取决于影响。如果影响在立即见效中是局部的，
我们会给其他 SIG 提出建议并让他们以自己的节奏推进。
如果影响在立即见效中是全局的且没有自然的激励，我们发现需要直接推动采用。&lt;/p>
&lt;p>&lt;strong>FSM：仍然在这个话题上，SIG Architecture 有一个 API Governance 子项目，
它与 SIG API Machinery 是否完全独立，还是有重要的连接点？&lt;/strong>&lt;/p>
&lt;!--
**David**: The projects have similar sounding names and carry some impacts on each other, but have
different missions and scopes. API Machinery owns the how and API Governance owns the what. API
conventions, the API approval process, and the final say on individual k8s.io APIs belong to API
Governance. API Machinery owns the REST semantics and non-API specific behaviors.
**Federico**: I really like how David put it: *"API Machinery owns the how and API Governance owns
the what"*: we don't own the actual APIs, but the actual APIs live through us.
-->
&lt;p>&lt;strong>David&lt;/strong>：这些项目有相似的名称并对彼此产生一些影响，但有不同的使命和范围。
API Machinery 负责“如何做”，而 API Governance 负责“做什么”。
API 约定、API 审批过程以及对单个 k8s.io API 的最终决定权属于 API Governance。
API Machinery 负责 REST 语义和非 API 特定行为。&lt;/p>
&lt;p>&lt;strong>Federico&lt;/strong>：我真得很喜欢 David 的说法：
&lt;strong>“API Machinery 负责‘如何做’，而 API Governance 负责‘做什么’”&lt;/strong>：
我们并未拥有实际的 API，但实际的 API 依靠我们存在。&lt;/p>
&lt;!--
## The challenges of Kubernetes popularity
**FSM: With the growth in Kubernetes adoption we have certainly seen increased demands from the
Control Plane: how is this felt and how does it influence the work of the SIG?**
**David**: It’s had a massive influence on API Machinery. Over the years we have often responded to
and many times enabled the evolutionary stages of Kubernetes. As the central orchestration hub of
nearly all capability on Kubernetes clusters, we both lead and follow the community. In broad
strokes I see a few evolution stages for API Machinery over the years, with constantly high
activity.
-->
&lt;h2 id="the-challenge-of-kubernetes-popularity">Kubernetes 受欢迎的挑战 &lt;/h2>
&lt;p>&lt;strong>FSM：随着 Kubernetes 的采用率上升，我们肯定看到了对控制平面的需求增加：你们对这点的感受如何，它如何影响 SIG 的工作？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>David&lt;/strong>：这对 API Machinery 产生了巨大的影响。多年来，我们经常响应并多次促进了 Kubernetes 的发展阶段。
作为几乎所有 Kubernetes 集群上权能的集中编排中心，我们既领导又跟随社区。
从广义上讲，我看到多年来 API Machinery 经历了一些发展阶段，活跃度一直很高。&lt;/p>
&lt;!--
1. **Finding purpose**: `pre-1.0` up until `v1.3` (up to our first 1000+ nodes/namespaces) or
so. This time was characterized by rapid change. We went through five different versions of our
schemas and rose to meet the need. We optimized for quick, in-tree API evolution (sometimes to
the detriment of longer term goals), and defined patterns for the first time.
2. **Scaling to meet the need**: `v1.3-1.9` (up to shared informers in controllers) or so. When we
started trying to meet customer needs as we gained adoption, we found severe scale limitations in
terms of CPU and memory. This was where we broadened API machinery to include access patterns, but
were still heavily focused on in-tree types. We built the watch cache, protobuf serialization,
and shared caches.
-->
&lt;ol>
&lt;li>
&lt;p>&lt;strong>寻找目标&lt;/strong>：从 &lt;code>pre-1.0&lt;/code> 到 &lt;code>v1.3&lt;/code>（我们达到了第一个 1000+ 节点/命名空间）。
这段时间以快速变化为特征。我们经历了五个不同版本的模式，并满足了需求。
我们优化了快速、树内 API 的演变（有时以牺牲长期目标为代价），并首次定义了模式。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>满足需求的扩展&lt;/strong>：&lt;code>v1.3-1.9&lt;/code>（直到控制器中的共享通知器）。
当我们开始尝试满足客户需求时，我们发现了严重的 CPU 和内存规模限制。
这也是为什么我们将 API Machinery 扩展到包含访问模式，但我们仍然非常关注树内类型。
我们构建了 watch 缓存、protobuf 序列化和共享缓存。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;!--
3. **Fostering the ecosystem**: `v1.8-1.21` (up to CRD v1) or so. This was when we designed and wrote
CRDs (the considered replacement for third-party-resources), the immediate needs we knew were
coming (admission webhooks), and evolution to best practices we knew we needed (API schemas).
This enabled an explosion of early adopters willing to work very carefully within the constraints
to enable their use-cases for servicing pods. The adoption was very fast, sometimes outpacing
our capability, and creating new problems.
-->
&lt;ol start="3">
&lt;li>&lt;strong>培育生态系统&lt;/strong>：&lt;code>v1.8-1.21&lt;/code>（直到 CRD v1）。这是我们设计和编写 CRD（视为第三方资源的替代品）的时间，
满足我们知道即将到来的即时需求（准入 Webhook），以及我们知道需要的最佳实践演变（API 模式）。
这促成了早期采用者的爆发式增长，他们愿意在约束内非常谨慎地工作，以实现服务 Pod 的用例。
采用速度非常快，有时超出了我们的权能，并形成了新的问题。&lt;/li>
&lt;/ol>
&lt;!--
4. **Simplifying deployments**: `v1.22+`. In the relatively recent past, we’ve been responding to
pressures or running kube clusters at scale with large numbers of sometimes-conflicting ecosystem
projects using our extensions mechanisms. Lots of effort is now going into making platform
extensions easier to write and safer to manage by people who don't hold PhDs in kubernetes. This
started with things like server-side-apply and continues today with features like webhook match
conditions and validating admission policies.
-->
&lt;ol start="4">
&lt;li>&lt;strong>简化部署&lt;/strong>：&lt;code>v1.22+&lt;/code>。在不久之前，
我们采用扩展机制来响应运行大规模的 Kubernetes 集群的压力，其中包含大量有时会发生冲突的生态系统项目。
我们投入了许多努力，使平台更易于扩展，管理更安全，就算不是很精通 Kubernetes 的人也能做到。
这些努力始于服务器端应用，并在如今延续到 Webhook 匹配状况和验证准入策略等特性。&lt;/li>
&lt;/ol>
&lt;!--
Work in API Machinery has a broad impact across the project and the ecosystem. It’s an exciting
area to work for those able to make a significant time investment on a long time horizon.
## The road ahead
**FSM: With those different evolutionary stages in mind, what would you pinpoint as the top
priorities for the SIG at this time?**
-->
&lt;p>API Machinery 的工作对整个项目和生态系统有广泛的影响。
对于那些能够长期投入大量时间的人来说，这是一个令人兴奋的工作领域。&lt;/p>
&lt;h2 id="the-road-ahead">未来发展 &lt;/h2>
&lt;p>&lt;strong>FSM：考虑到这些不同的发展阶段，你能说说这个 SIG 的当前首要任务是什么吗？&lt;/strong>&lt;/p>
&lt;!--
**David:** **Reliability, efficiency, and capability** in roughly that order.
With the increased usage of our `kube-apiserver` and extensions mechanisms, we find that our first
set of extensions mechanisms, while fairly complete in terms of capability, carry significant risks
in terms of potential mis-use with large blast radius. To mitigate these risks, we’re investing in
features that reduce the blast radius for accidents (webhook match conditions) and which provide
alternative mechanisms with lower risk profiles for most actions (validating admission policy).
-->
&lt;p>&lt;strong>David&lt;/strong>：大致的顺序为&lt;strong>可靠性、效率和权能&lt;/strong>。&lt;/p>
&lt;p>随着 &lt;code>kube-apiserver&lt;/code> 和扩展机制的使用增加，我们发现第一套扩展机制虽然在权能方面相当完整，
但在潜在误用方面存在重大风险，影响范围很大。为了减轻这些风险，我们正在致力于减少事故影响范围的特性
（Webhook 匹配状况）以及为大多数操作提供风险配置较低的替代机制（验证准入策略）。&lt;/p>
&lt;!--
At the same time, the increased usage has made us more aware of scaling limitations that we can
improve both server and client-side. Efforts here include more efficient serialization (CBOR),
reduced etcd load (consistent reads from cache), and reduced peak memory usage (streaming lists).
And finally, the increased usage has highlighted some long existing
gaps that we’re closing. Things like field selectors for CRDs which
the [Batch Working Group](https://github.com/kubernetes/community/blob/master/wg-batch/README.md)
is eager to leverage and will eventually form the basis for a new way
to prevent trampoline pod attacks from exploited nodes.
-->
&lt;p>同时，使用量的增加使我们更加意识到我们可以同时改进服务器端和客户端的扩缩限制。
这里的努力包括更高效的序列化（CBOR），减少 etcd 负载（从缓存中一致读取）和减少峰值内存使用量（流式列表）。&lt;/p>
&lt;p>最后，使用量的增加突显了一些长期存在的、我们正在设法填补的差距。这些包括针对 CRD 的字段选择算符，
&lt;a href="https://github.com/kubernetes/community/blob/master/wg-batch/README.md">Batch Working Group&lt;/a>
渴望利用这些选择算符，并最终构建一种新的方法以防止从有漏洞的节点实施“蹦床式”的 Pod 攻击。&lt;/p>
&lt;!--
## Joining the fun
**FSM: For anyone wanting to start contributing, what's your suggestions?**
**Federico**: SIG API Machinery is not an exception to the Kubernetes motto: **Chop Wood and Carry
Water**. There are multiple weekly meetings that are open to everybody, and there is always more
work to be done than people to do it.
-->
&lt;h2 id="joining-the-fun">加入有趣的我们 &lt;/h2>
&lt;p>&lt;strong>FSM：如果有人想要开始贡献，你有什么建议？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>Federico&lt;/strong>：SIG API Machinery 毫不例外也遵循 Kubernetes 的风格：&lt;strong>砍柴和挑水（踏实工作，注重细节）&lt;/strong>。
有多个每周例会对所有人开放，总是有更多的工作要做，人手总是不够。&lt;/p>
&lt;!--
I acknowledge that API Machinery is not easy, and the ramp up will be steep. The bar is high,
because of the reasons we've been discussing: we carry a huge responsibility. But of course with
passion and perseverance many people has ramped up through the years, and we hope more will come.
In terms of concrete opportunities, there is the SIG meeting every two weeks. Everyone is welcome to
attend and listen, see what the group talks about, see what's going on in this release, etc.
-->
&lt;p>我承认 API Machinery 并不容易，入门的坡度会比较陡峭。门槛较高，就像我们所讨论的原因：我们肩负着巨大的责任。
当然凭借激情和毅力，多年来有许多人已经跟了上来，我们希望更多的人加入。&lt;/p>
&lt;p>具体的机会方面，每两周有一次 SIG 会议。欢迎所有人参会和听会，了解小组在讨论什么，了解这个版本中发生了什么等等。&lt;/p>
&lt;!--
Also two times a week, Tuesday and Thursday, we have the public Bug Triage, where we go through
everything new from the last meeting. We've been keeping this practice for more than 7 years
now. It's a great opportunity to volunteer to review code, fix bugs, improve documentation,
etc. Tuesday's it's at 1 PM (PST) and Thursday is on an EMEA friendly time (9:30 AM PST). We are
always looking to improve, and we hope to be able to provide more concrete opportunities to join and
participate in the future.
-->
&lt;p>此外，每周两次，周二和周四，我们有公开的 Bug 分类管理会，在会上我们会讨论上次会议以来的所有新内容。
我们已经保持这种做法 7 年多了。这是一个很好的机会，你可以志愿审查代码、修复 Bug、改进文档等。
周二的会议在下午 1 点（PST），周四是在 EMEA 友好时间（上午 9:30 PST）。
我们总是在寻找改进的机会，希望能够在未来提供更多具体的参与机会。&lt;/p>
&lt;!--
**FSM: Excellent, thank you! Any final comments you would like to share with our readers?**
**Federico**: As I mentioned, the first steps might be hard, but the reward is also larger. Working
on API Machinery is working on an area of huge impact (millions of users?), and your contributions
will have a direct outcome in the way that Kubernetes works and the way that it's used. For me
that's enough reward and motivation!
-->
&lt;p>&lt;strong>FSM：太好了，谢谢！你们还有什么想与我们的读者分享吗？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>Federico&lt;/strong>：正如我提到的，第一步可能较难，但回报也更大。
参与 API Machinery 的工作就是在加入一个影响巨大（百万用户？）的领域，
你的贡献将直接影响 Kubernetes 的工作方式和使用方式。对我来说，这已经足够作为回报和动力了！&lt;/p></description></item><item><title>Kubernetes v1.31 中的移除和主要变更</title><link>https://kubernetes.io/zh-cn/blog/2024/07/19/kubernetes-1-31-upcoming-changes/</link><pubDate>Fri, 19 Jul 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/07/19/kubernetes-1-31-upcoming-changes/</guid><description>
&lt;!--
layout: blog
title: 'Kubernetes Removals and Major Changes In v1.31'
date: 2024-07-19
slug: kubernetes-1-31-upcoming-changes
author: >
Abigail McCarthy,
Edith Puclla,
Matteo Bianchi,
Rashan Smith,
Yigit Demirbas
-->
&lt;!--
As Kubernetes develops and matures, features may be deprecated, removed, or replaced with better ones for the project's overall health.
This article outlines some planned changes for the Kubernetes v1.31 release that the release team feels you should be aware of for the continued maintenance of your Kubernetes environment.
The information listed below is based on the current status of the v1.31 release.
It may change before the actual release date.
-->
&lt;p>随着 Kubernetes 的发展和成熟，为了项目的整体健康，某些特性可能会被弃用、删除或替换为更好的特性。
本文阐述了 Kubernetes v1.31 版本的一些更改计划，发行团队认为你应当了解这些更改，
以便持续维护 Kubernetes 环境。
下面列出的信息基于 v1.31 版本的当前状态；这些状态可能会在实际发布日期之前发生变化。&lt;/p>
&lt;!--
## The Kubernetes API removal and deprecation process
The Kubernetes project has a well-documented [deprecation policy](/docs/reference/using-api/deprecation-policy/) for features.
This policy states that stable APIs may only be deprecated when a newer, stable version of that API is available and that APIs have a minimum lifetime for each stability level.
A deprecated API has been marked for removal in a future Kubernetes release.
It will continue to function until removal (at least one year from the deprecation), but usage will display a warning.
Removed APIs are no longer available in the current version, so you must migrate to using the replacement.
-->
&lt;h2 id="kubernetes-api-删除和弃用流程">Kubernetes API 删除和弃用流程&lt;/h2>
&lt;p>Kubernetes 项目针对其功能特性有一个详细说明的&lt;a href="https://kubernetes.io/zh-cn/docs/reference/using-api/deprecation-policy/">弃用策略&lt;/a>。
此策略规定，只有当某稳定 API 的更新、稳定版本可用时，才可以弃用该 API，并且 API
的各个稳定性级别都有对应的生命周期下限。
已弃用的 API 标记为在未来的 Kubernetes 版本中删除，
这类 API 将继续发挥作用，直至被删除（从弃用起至少一年），但使用时会显示警告。
已删除的 API 在当前版本中不再可用，因此你必须将其迁移到替换版本。&lt;/p>
&lt;!--
* Generally available (GA) or stable API versions may be marked as deprecated but must not be removed within a major version of Kubernetes.
* Beta or pre-release API versions must be supported for 3 releases after the deprecation.
* Alpha or experimental API versions may be removed in any release without prior deprecation notice.
-->
&lt;ul>
&lt;li>
&lt;p>正式发布的（GA）或稳定的 API 版本可被标记为已弃用，但不得在 Kubernetes 主要版本未变时删除。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Beta 或预发布 API 版本在被弃用后，必须保持 3 个发布版本中仍然可用。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Alpha 或实验性 API 版本可以在任何版本中删除，不必提前通知。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!--
Whether an API is removed because a feature graduated from beta to stable or because that API did not succeed, all removals comply with this deprecation policy.
Whenever an API is removed, migration options are communicated in the [documentation](/docs/reference/using-api/deprecation-guide/).
-->
&lt;p>无论 API 是因为某个特性从 Beta 版升级到稳定版，还是因为此 API 未成功而被删除，所有删除都将符合此弃用策略。
每当删除 API 时，迁移选项都会在&lt;a href="https://kubernetes.io/zh-cn/docs/reference/using-api/deprecation-guide/">文档&lt;/a>中传达。&lt;/p>
&lt;!--
## A note about SHA-1 signature support
In [go1.18](https://go.dev/doc/go1.18#sha1) (released in March 2022), the crypto/x509 library started to reject certificates signed with a SHA-1 hash function.
While SHA-1 is established to be unsafe and publicly trusted Certificate Authorities have not issued SHA-1 certificates since 2015, there might still be cases in the context of Kubernetes where user-provided certificates are signed using a SHA-1 hash function through private authorities with them being used for Aggregated API Servers or webhooks.
If you have relied on SHA-1 based certificates, you must explicitly opt back into its support by setting `GODEBUG=x509sha1=1` in your environment.
-->
&lt;h2 id="关于-sha-1-签名支持的说明">关于 SHA-1 签名支持的说明&lt;/h2>
&lt;p>在 &lt;a href="https://go.dev/doc/go1.18#sha1">go1.18&lt;/a>（2022 年 3 月发布）中，crypto/x509
库开始拒绝使用 SHA-1 哈希函数签名的证书。
虽然 SHA-1 被确定为不安全，并且公众信任的证书颁发机构自 2015 年以来就没有颁发过 SHA-1 证书，
但在 Kubernetes 环境中，仍可能存在用户提供的证书通过私人颁发机构使用 SHA-1 哈希函数签名的情况，
这些证书用于聚合 API 服务器或 Webhook。
如果你依赖基于 SHA-1 的证书，则必须通过在环境中设置 &lt;code>GODEBUG=x509sha1=1&lt;/code> 以明确选择重新支持这种证书。&lt;/p>
&lt;!--
Given Go's [compatibility policy for GODEBUGs](https://go.dev/blog/compat), the `x509sha1` GODEBUG and the support for SHA-1 certificates will [fully go away in go1.24](https://tip.golang.org/doc/go1.23) which will be released in the first half of 2025.
If you rely on SHA-1 certificates, please start moving off them.
Please see [Kubernetes issue #125689](https://github.com/kubernetes/kubernetes/issues/125689) to get a better idea of timelines around the support for SHA-1 going away, when Kubernetes releases plans to adopt go1.24, and for more details on how to detect usage of SHA-1 certificates via metrics and audit logging.
-->
&lt;p>鉴于 Go 的 &lt;a href="https://go.dev/blog/compat">GODEBUG 兼容性策略&lt;/a>，&lt;code>x509sha1&lt;/code> GODEBUG
和对 SHA-1 证书的支持将 &lt;a href="https://tip.golang.org/doc/go1.23">在 2025 年上半年发布的 go1.24&lt;/a>
中完全消失。
如果你依赖 SHA-1 证书，请开始放弃使用它们。&lt;/p>
&lt;p>请参阅 &lt;a href="https://github.com/kubernetes/kubernetes/issues/125689">Kubernetes 问题 #125689&lt;/a>，
以更好地了解对 SHA-1 支持的时间表，以及 Kubernetes 发布采用 go1.24
的计划时间、如何通过指标和审计日志检测 SHA-1 证书使用情况的更多详细信息。&lt;/p>
&lt;!--
## Deprecations and removals in Kubernetes 1.31
### Deprecation of `status.nodeInfo.kubeProxyVersion` field for Nodes ([KEP 4004](https://github.com/kubernetes/enhancements/issues/4004))
-->
&lt;h2 id="kubernetes-1-31-中的弃用和删除">Kubernetes 1.31 中的弃用和删除&lt;/h2>
&lt;h3 id="弃用节点的-status-nodeinfo-kubeproxyversion-字段-kep-4004-https-github-com-kubernetes-enhancements-issues-4004">弃用节点的 &lt;code>status.nodeInfo.kubeProxyVersion&lt;/code> 字段（&lt;a href="https://github.com/kubernetes/enhancements/issues/4004">KEP 4004&lt;/a>）&lt;/h3>
&lt;!--
The `.status.nodeInfo.kubeProxyVersion` field of Nodes is being deprecated in Kubernetes v1.31,and will be removed in a later release.
It's being deprecated because the value of this field wasn't (and isn't) accurate.
This field is set by the kubelet, which does not have reliable information about the kube-proxy version or whether kube-proxy is running.
The `DisableNodeKubeProxyVersion` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) will be set to `true` in by default in v1.31 and the kubelet will no longer attempt to set the `.status.kubeProxyVersion` field for its associated Node.
-->
&lt;p>Node 的 &lt;code>.status.nodeInfo.kubeProxyVersion&lt;/code> 字段在 Kubernetes v1.31 中将被弃用，
并将在后续版本中删除。该字段被弃用是因为其取值原来不准确，并且现在也不准确。
该字段由 kubelet 设置，而 kubelet 没有关于 kube-proxy 版本或 kube-proxy 是否正在运行的可靠信息。&lt;/p>
&lt;p>在 v1.31 中，&lt;code>DisableNodeKubeProxyVersion&lt;/code>
&lt;a href="https://kubernetes.io/zh-cn/docs/reference/command-line-tools-reference/feature-gates/">特性门控&lt;/a>将默认设置为 &lt;code>true&lt;/code>，
并且 kubelet 将不再尝试为其关联的 Node 设置 &lt;code>.status.kubeProxyVersion&lt;/code> 字段。&lt;/p>
&lt;!--
### Removal of all in-tree integrations with cloud providers
As highlighted in a [previous article](/blog/2024/05/20/completing-cloud-provider-migration/), the last remaining in-tree support for cloud provider integration will be removed as part of the v1.31 release.
This doesn't mean you can't integrate with a cloud provider, however you now **must** use the
recommended approach using an external integration. Some integrations are part of the Kubernetes
project and others are third party software.
-->
&lt;h3 id="删除所有云驱动的树内集成组件">删除所有云驱动的树内集成组件&lt;/h3>
&lt;p>正如&lt;a href="https://kubernetes.io/blog/2024/05/20/completing-cloud-provider-migration/">之前一篇文章&lt;/a>中所强调的，
v1.31 版本将删除云驱动集成的树内支持的最后剩余部分。
这并不意味着你无法与某云驱动集成，只是你现在&lt;strong>必须&lt;/strong>使用推荐的外部集成方法。
一些集成组件是 Kubernetes 项目的一部分，其余集成组件则是第三方软件。&lt;/p>
&lt;!--
This milestone marks the completion of the externalization process for all cloud providers' integrations from the Kubernetes core ([KEP-2395](https://github.com/kubernetes/enhancements/blob/master/keps/sig-cloud-provider/2395-removing-in-tree-cloud-providers/README.md)), a process started with Kubernetes v1.26.
This change helps Kubernetes to get closer to being a truly vendor-neutral platform.
For further details on the cloud provider integrations, read our [v1.29 Cloud Provider Integrations feature blog](/blog/2023/12/14/cloud-provider-integration-changes/).
For additional context about the in-tree code removal, we invite you to check the ([v1.29 deprecation blog](/blog/2023/11/16/kubernetes-1-29-upcoming-changes/#removal-of-in-tree-integrations-with-cloud-providers-kep-2395-https-kep-k8s-io-2395)).
The latter blog also contains useful information for users who need to migrate to version v1.29 and later.
-->
&lt;p>这一里程碑标志着将所有云驱动集成组件从 Kubernetes 核心外部化的过程已经完成
（&lt;a href="https://github.com/kubernetes/enhancements/blob/master/keps/sig-cloud-provider/2395-removing-in-tree-cloud-providers/README.md">KEP-2395&lt;/a>），
该过程从 Kubernetes v1.26 开始。
这一变化有助于 Kubernetes 进一步成为真正的供应商中立平台。&lt;/p>
&lt;p>有关云驱动集成的更多详细信息，请阅读我们的 &lt;a href="https://kubernetes.io/zh-cn/blog/2023/12/14/cloud-provider-integration-changes/">v1.29 云驱动集成特性的博客&lt;/a>。
有关树内代码删除的更多背景信息，请阅读
（&lt;a href="https://kubernetes.io/blog/2023/11/16/kubernetes-1-29-upcoming-changes/#removal-of-in-tree-integrations-with-cloud-providers-kep-2395-https-kep-k8s-io-2395">v1.29 弃用博客&lt;/a>）。&lt;/p>
&lt;p>后一个博客还包含对需要迁移到 v1.29 及更高版本的用户有用的信息。&lt;/p>
&lt;!--
### Removal of kubelet `--keep-terminated-pod-volumes` command line flag
The kubelet flag `--keep-terminated-pod-volumes`, which was deprecated in 2017, will be removed as
part of the v1.31 release.
You can find more details in the pull request [#122082](https://github.com/kubernetes/kubernetes/pull/122082).
-->
&lt;h3 id="删除-kubelet-keep-terminated-pod-volumes-命令行标志">删除 kubelet &lt;code>--keep-terminated-pod-volumes&lt;/code> 命令行标志&lt;/h3>
&lt;p>kubelet 标志 &lt;code>--keep-terminated-pod-volumes&lt;/code> 已于 2017 年弃用，将在 v1.31 版本中被删除。&lt;/p>
&lt;p>你可以在拉取请求 &lt;a href="https://github.com/kubernetes/kubernetes/pull/122082">#122082&lt;/a>
中找到更多详细信息。&lt;/p>
&lt;!--
### Removal of CephFS volume plugin
[CephFS volume plugin](/docs/concepts/storage/volumes/#cephfs) was removed in this release and the `cephfs` volume type became non-functional.
It is recommended that you use the [CephFS CSI driver](https://github.com/ceph/ceph-csi/) as a third-party storage driver instead. If you were using the CephFS volume plugin before upgrading the cluster version to v1.31, you must re-deploy your application to use the new driver.
CephFS volume plugin was formally marked as deprecated in v1.28.
-->
&lt;h3 id="删除-cephfs-卷插件">删除 CephFS 卷插件&lt;/h3>
&lt;p>&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/#cephfs">CephFS 卷插件&lt;/a>已在此版本中删除，
并且 &lt;code>cephfs&lt;/code> 卷类型已无法使用。&lt;/p>
&lt;p>建议你改用 &lt;a href="https://github.com/ceph/ceph-csi/">CephFS CSI 驱动程序&lt;/a> 作为第三方存储驱动程序。
如果你在将集群版本升级到 v1.31 之前在使用 CephFS 卷插件，则必须重新部署应用才能使用新驱动。&lt;/p>
&lt;p>CephFS 卷插件在 v1.28 中正式标记为已弃用。&lt;/p>
&lt;!--
### Removal of Ceph RBD volume plugin
The v1.31 release will remove the [Ceph RBD volume plugin](/docs/concepts/storage/volumes/#rbd) and its CSI migration support, making the `rbd` volume type non-functional.
It's recommended that you use the [RBD CSI driver](https://github.com/ceph/ceph-csi/) in your clusters instead.
If you were using Ceph RBD volume plugin before upgrading the cluster version to v1.31, you must re-deploy your application to use the new driver.
The Ceph RBD volume plugin was formally marked as deprecated in v1.28.
-->
&lt;h3 id="删除-ceph-rbd-卷插件">删除 Ceph RBD 卷插件&lt;/h3>
&lt;p>v1.31 版本将删除 &lt;a href="https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/#rbd">Ceph RBD 卷插件&lt;/a>及其 CSI 迁移支持，
&lt;code>rbd&lt;/code> 卷类型将无法继续使用。&lt;/p>
&lt;p>建议你在集群中使用 &lt;a href="https://github.com/ceph/ceph-csi/">RBD CSI 驱动&lt;/a>。
如果你在将集群版本升级到 v1.31 之前在使用 Ceph RBD 卷插件，则必须重新部署应用以使用新驱动。&lt;/p>
&lt;p>Ceph RBD 卷插件在 v1.28 中正式标记为已弃用。&lt;/p>
&lt;!--
### Deprecation of non-CSI volume limit plugins in kube-scheduler
The v1.31 release will deprecate all non-CSI volume limit scheduler plugins, and will remove some
already deprected plugins from the [default plugins](/docs/reference/scheduling/config/), including:
-->
&lt;h3 id="kube-scheduler-中非-csi-卷限制插件的弃用">kube-scheduler 中非 CSI 卷限制插件的弃用&lt;/h3>
&lt;p>v1.31 版本将弃用所有非 CSI 卷限制调度程序插件，
并将从&lt;a href="https://kubernetes.io/zh-cn/docs/reference/scheduling/config/">默认插件&lt;/a>中删除一些已弃用的插件，包括：&lt;/p>
&lt;ul>
&lt;li>&lt;code>AzureDiskLimits&lt;/code>&lt;/li>
&lt;li>&lt;code>CinderLimits&lt;/code>&lt;/li>
&lt;li>&lt;code>EBSLimits&lt;/code>&lt;/li>
&lt;li>&lt;code>GCEPDLimits&lt;/code>&lt;/li>
&lt;/ul>
&lt;!--
It's recommended that you use the `NodeVolumeLimits` plugin instead because it can handle the same functionality as the removed plugins since those volume types have been migrated to CSI.
Please replace the deprecated plugins with the `NodeVolumeLimits` plugin if you explicitly use them in the [scheduler config](/docs/reference/scheduling/config/).
The `AzureDiskLimits`, `CinderLimits`, `EBSLimits`, and `GCEPDLimits` plugins will be removed in a future release.
These plugins will be removed from the default scheduler plugins list as they have been deprecated since Kubernetes v1.14.
-->
&lt;p>建议你改用 &lt;code>NodeVolumeLimits&lt;/code> 插件，因为它可以处理与已删除插件相同的功能，因为这些卷类型已迁移到 CSI。
如果你在&lt;a href="https://kubernetes.io/zh-cn/docs/reference/scheduling/config/">调度器配置&lt;/a>中显式使用已弃用的插件，
请用 &lt;code>NodeVolumeLimits&lt;/code> 插件替换它们。
&lt;code>AzureDiskLimits&lt;/code>、&lt;code>CinderLimits&lt;/code>、&lt;code>EBSLimits&lt;/code> 和 &lt;code>GCEPDLimits&lt;/code> 插件将在未来的版本中被删除。&lt;/p>
&lt;p>这些插件将从默认调度程序插件列表中删除，因为它们自 Kubernetes v1.14 以来已被弃用。&lt;/p>
&lt;!--
## Looking ahead
The official list of API removals planned for [Kubernetes v1.32](/docs/reference/using-api/deprecation-guide/#v1-32) include:
* The `flowcontrol.apiserver.k8s.io/v1beta3` API version of FlowSchema and PriorityLevelConfiguration will be removed.
To prepare for this, you can edit your existing manifests and rewrite client software to use the `flowcontrol.apiserver.k8s.io/v1 API` version, available since v1.29.
All existing persisted objects are accessible via the new API. Notable changes in flowcontrol.apiserver.k8s.io/v1beta3 include that the PriorityLevelConfiguration `spec.limited.nominalConcurrencyShares` field only defaults to 30 when unspecified, and an explicit value of 0 is not changed to 30.
For more information, please refer to the [API deprecation guide](/docs/reference/using-api/deprecation-guide/#v1-32).
-->
&lt;h2 id="展望未来">展望未来&lt;/h2>
&lt;p>&lt;a href="https://kubernetes.io/zh-cn/docs/reference/using-api/deprecation-guide/#v1-32">Kubernetes v1.32&lt;/a> 计划删除的官方 API 包括：&lt;/p>
&lt;ul>
&lt;li>将删除 &lt;code>flowcontrol.apiserver.k8s.io/v1beta3&lt;/code> API 版本的 FlowSchema 和 PriorityLevelConfiguration。
为了做好准备，你可以编辑现有清单并重写客户端软件以使用自 v1.29 起可用的 &lt;code>flowcontrol.apiserver.k8s.io/v1 API&lt;/code> 版本。
所有现有的持久化对象都可以通过新 API 访问。&lt;code>flowcontrol.apiserver.k8s.io/v1beta3&lt;/code> 中需要注意的变化包括优先级配置
&lt;code>spec.limited.nominalConcurrencyShares&lt;/code> 字段仅在未指定时默认为 30，并且显式设置为 0 的话不会被更改为 30。&lt;/li>
&lt;/ul>
&lt;p>有关更多信息，请参阅 &lt;a href="https://kubernetes.io/zh-cn/docs/reference/using-api/deprecation-guide/#v1-32">API 弃用指南&lt;/a>。&lt;/p>
&lt;!--
## Want to know more?
The Kubernetes release notes announce deprecations.
We will formally announce the deprecations in [Kubernetes v1.31](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.31.md#deprecation) as part of the CHANGELOG for that release.
You can see the announcements of pending deprecations in the release notes for:
-->
&lt;h2 id="想要了解更多">想要了解更多？&lt;/h2>
&lt;p>Kubernetes 发行说明中会宣布弃用信息。
我们将在 &lt;a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.31.md#deprecation">Kubernetes v1.31&lt;/a>
中正式宣布弃用信息，作为该版本的 CHANGELOG 的一部分。&lt;/p>
&lt;p>你可以在发行说明中看到待弃用的公告：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.30.md#deprecation">Kubernetes v1.30&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.29.md#deprecation">Kubernetes v1.29&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.28.md#deprecation">Kubernetes v1.28&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.27.md#deprecation">Kubernetes v1.27&lt;/a>&lt;/p>
&lt;/li>
&lt;/ul></description></item><item><title>Kubernetes 的十年</title><link>https://kubernetes.io/zh-cn/blog/2024/06/06/10-years-of-kubernetes/</link><pubDate>Thu, 06 Jun 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/06/06/10-years-of-kubernetes/</guid><description>
&lt;!--
layout: blog
title: "10 Years of Kubernetes"
date: 2024-06-06
slug: 10-years-of-kubernetes
author: >
[Bob Killen](https://github.com/mrbobbytables) (CNCF),
[Chris Short](https://github.com/chris-short) (AWS),
[Frederico Muñoz](https://github.com/fsmunoz) (SAS),
[Kaslin Fields](https://github.com/kaslin) (Google),
[Tim Bannister](https://github.com/sftim) (The Scale Factory),
and every contributor across the globe
-->
&lt;!--
![KCSEU 2024 group photo](kcseu2024.jpg)
Ten (10) years ago, on June 6th, 2014, the
[first commit](https://github.com/kubernetes/kubernetes/commit/2c4b3a562ce34cddc3f8218a2c4d11c7310e6d56)
of Kubernetes was pushed to GitHub. That first commit with 250 files and 47,501 lines of go, bash
and markdown kicked off the project we have today. Who could have predicted that 10 years later,
Kubernetes would grow to become one of the largest Open Source projects to date with over
[88,000 contributors](https://k8s.devstats.cncf.io/d/24/overall-project-statistics?orgId=1) from
more than [8,000 companies](https://www.cncf.io/reports/kubernetes-project-journey-report/), across
44 countries.
-->
&lt;p>&lt;img alt="KCSEU 2024 团体照片" src="https://kubernetes.io/zh-cn/blog/2024/06/06/10-years-of-kubernetes/kcseu2024.jpg">&lt;/p>
&lt;p>十年前的 2014 年 6 月 6 日，Kubernetes
的&lt;a href="https://github.com/kubernetes/kubernetes/commit/2c4b3a562ce34cddc3f8218a2c4d11c7310e6d56">第一次提交&lt;/a>被推送到 GitHub。
第一次提交包含了 250 个文件和 47,501 行的 Go、Bash 和 Markdown 代码，
开启了我们今天所拥有的项目。谁能预测到 10 年后，Kubernetes 会成长为迄今为止最大的开源项目之一，
拥有来自超过 8,000 家公司、来自 44 个国家的
&lt;a href="https://k8s.devstats.cncf.io/d/24/overall-project-statistics?orgId=1">88,000 名贡献者&lt;/a>。&lt;/p>
&lt;img src="kcscn2019.jpg" alt="KCSCN 2019" class="left" style="max-width: 20em; margin: 1em" >
&lt;!--
This milestone isn't just for Kubernetes but for the Cloud Native ecosystem that blossomed from
it. There are close to [200 projects](https://all.devstats.cncf.io/d/18/overall-project-statistics-table?orgId=1)
within the CNCF itself, with contributions from
[240,000+ individual contributors](https://all.devstats.cncf.io/d/18/overall-project-statistics-table?orgId=1) and
thousands more in the greater ecosystem. Kubernetes would not be where it is today without them, the
[7M+ Developers](https://www.cncf.io/blog/2022/05/18/slashdata-cloud-native-continues-to-grow-with-more-than-7-million-developers-worldwide/),
and the even larger user community that have all helped shape the ecosystem that it is today.
-->
&lt;p>这一里程碑不仅属于 Kubernetes，也属于由此蓬勃发展的云原生生态系统。
在 CNCF 本身就有近 &lt;a href="https://all.devstats.cncf.io/d/18/overall-project-statistics-table?orgId=1">200 个项目&lt;/a>，有来自
&lt;a href="https://all.devstats.cncf.io/d/18/overall-project-statistics-table?orgId=1">240,000 多名个人贡献者&lt;/a>，
还有数千名来自更大的生态系统的贡献者的贡献。
如果没有 &lt;a href="https://www.cncf.io/blog/2022/05/18/slashdata-cloud-native-continues-to-grow-with-more-than-7-million-developers-worldwide/">700 多万开发者&lt;/a>和更庞大的用户社区，
Kubernetes 就不会达到今天的成就，他们一起帮助塑造了今天的生态系统。&lt;/p>
&lt;!--
## Kubernetes' beginnings - a converging of technologies
The ideas underlying Kubernetes started well before the first commit, or even the first prototype
([which came about in 2013](/blog/2018/07/20/the-history-of-kubernetes-the-community-behind-it/)).
In the early 2000s, Moore's Law was well in effect. Computing hardware was becoming more and more
powerful at an incredibly fast rate. Correspondingly, applications were growing more and more
complex. This combination of hardware commoditization and application complexity pointed to a need
to further abstract software from hardware, and solutions started to emerge.
-->
&lt;h2 id="kubernetes-的起源-技术的融合">Kubernetes 的起源 - 技术的融合&lt;/h2>
&lt;p>Kubernetes 背后的理念早在第一次提交之前，
甚至第一个原型（&lt;a href="https://kubernetes.io/blog/2018/07/20/the-history-of-kubernetes-the-community-behind-it/">在 2013 年问世&lt;/a>之前就已经存在。
在 21 世纪初，摩尔定律仍然成立。计算硬件正以惊人的速度变得越来越强大。
相应地，应用程序变得越来越复杂。硬件商品化和应用程序复杂性的结合表明需要进一步将软件从硬件中抽象出来，
因此解决方案开始出现。&lt;/p>
&lt;!--
Like many companies at the time, Google was scaling rapidly, and its engineers were interested in
the idea of creating a form of isolation in the Linux kernel. Google engineer Rohit Seth described
the concept in an [email in 2006](https://lwn.net/Articles/199643/):
-->
&lt;p>像当时的许多公司一样，Google 正在快速扩张，其工程师对在 Linux 内核中创建一种隔离形式的想法很感兴趣。
Google 工程师 Rohit Seth 在 &lt;a href="https://lwn.net/Articles/199643/">2006 年的一封电子邮件&lt;/a>中描述了这个概念：&lt;/p>
&lt;!--
> We use the term container to indicate a structure against which we track and charge utilization of
system resources like memory, tasks, etc. for a Workload.
-->
&lt;blockquote>
&lt;p>我们使用术语 “容器” 来表示一种结构，通过该结构我们可以对负载的系统资源（如内存、任务等）利用情况进行跟踪和计费。&lt;/p>
&lt;/blockquote>
&lt;img src="future.png" alt="The future of Linux containers" class="right" style="max-width: 20em; margin: 1em">
&lt;!--
In March of 2013, a 5-minute lightning talk called
["The future of Linux Containers," presented by Solomon Hykes at PyCon](https://youtu.be/wW9CAH9nSLs?si=VtK_VFQHymOT7BIB),
introduced an upcoming open source tool called "Docker" for creating and using Linux
Containers. Docker introduced a level of usability to Linux Containers that made them accessible to
more users than ever before, and the popularity of Docker, and thus of Linux Containers,
skyrocketed. With Docker making the abstraction of Linux Containers accessible to all, running
applications in much more portable and repeatable ways was suddenly possible, but the question of
scale remained.
-->
&lt;p>2013 年 3 月，&lt;a href="https://youtu.be/wW9CAH9nSLs?si=VtK_VFQHymOT7BIB">Solomon Hykes 在 PyCon 上进行了一场名为 “Linux容器的未来”&lt;/a>的
5 分钟闪电演讲，介绍了名为 “Docker” 的一款即将被推出的开源工具，用于创建和使用 Linux 容器。Docker
提升了 Linux 容器的可用性，使其比以往更容易被更多用户使用，从而使
Docker 和Linux 容器的流行度飙升。随着 Docker 使 Linux 容器的抽象概念可供所有人使用，
以更便于移植且可重复的方式运行应用突然成为可能，但大规模使用的问题仍然存在。&lt;/p>
&lt;!--
Google's Borg system for managing application orchestration at scale had adopted Linux containers as
they were developed in the mid-2000s. Since then, the company had also started working on a new
version of the system called "Omega." Engineers at Google who were familiar with the Borg and Omega
systems saw the popularity of containerization driven by Docker. They recognized not only the need
for an open source container orchestration system but its "inevitability," as described by Brendan
Burns in this [blog post](/blog/2018/07/20/the-history-of-kubernetes-the-community-behind-it/). That
realization in the fall of 2013 inspired a small team to start working on a project that would later
become **Kubernetes**. That team included Joe Beda, Brendan Burns, Craig McLuckie, Ville Aikas, Tim
Hockin, Dawn Chen, Brian Grant, and Daniel Smith.
-->
&lt;p>Google 用来管理大规模应用编排的 Borg 系统在 2000 年代中期采用当时所开发的 Linux 容器技术。
此后，该公司还开始研发该系统的一个新版本，名为 “Omega”。
熟悉 Borg 和 Omega 系统的 Google 工程师们看到了 Docker 所推动的容器化技术的流行。
他们意识到对一个开源的容器编排系统的需求，而且意识到这一系统的“必然性”，正如
Brendan Burns 在这篇&lt;a href="https://kubernetes.io/blog/2018/07/20/the-history-of-kubernetes-the-community-behind-it/">博文&lt;/a>中所描述的。
这一认识在 2013 年秋天激发了一个小团队开始着手一个后来成为 &lt;strong>Kubernetes&lt;/strong>
的项目。该团队包括 Joe Beda、Brendan Burns、Craig McLuckie、Ville Aikas、Tim Hockin、Dawn Chen、Brian Grant
和 Daniel Smith。&lt;/p>
&lt;!--
## A decade of Kubernetes
&lt;img src="kubeconeu2017.jpg" alt="KubeCon EU 2017" class="left" style="max-width: 20em; margin: 1em">
Kubernetes' history begins with that historic commit on June 6th, 2014, and the subsequent
announcement of the project in a June 10th
[keynote by Google engineer Eric Brewer at DockerCon 2014](https://youtu.be/YrxnVKZeqK8?si=Q_wYBFn7dsS9H3k3)
(and its corresponding [Google blog](https://cloudplatform.googleblog.com/2014/06/an-update-on-container-support-on-google-cloud-platform.html)).
-->
&lt;h2 id="kubernetes-十年回顾">Kubernetes 十年回顾&lt;/h2>
&lt;img src="kubeconeu2017.jpg" alt="KubeCon EU 2017" class="left" style="max-width: 20em; margin: 1em">
&lt;p>Kubernetes 的历史始于 2014 年 6 月 6 日的那次历史性提交，随后，
&lt;a href="https://youtu.be/YrxnVKZeqK8?si=Q_wYBFn7dsS9H3k3">Google 工程师 Eric Brewer 在 2014 年 6 月 10 日的 DockerCon 2014
上的主题演讲&lt;/a>(&lt;a href="https://cloudplatform.googleblog.com/2014/06/an-update-on-container-support-on-google-cloud-platform.html">及其相应的 Google 博客&lt;/a>)中由宣布了该项目。&lt;/p>
&lt;!--
Over the next year, a small community of
[contributors, largely from Google and Red Hat](https://k8s.devstats.cncf.io/d/9/companies-table?orgId=1&amp;var-period_name=Before%20joining%20CNCF&amp;var-metric=contributors),
worked hard on the project, culminating in a [version 1.0 release on July 21st, 2015](https://cloudplatform.googleblog.com/2015/07/Kubernetes-V1-Released.html).
Alongside 1.0, Google announced that Kubernetes would be donated to a newly formed branch of the
Linux Foundation called the
[Cloud Native Computing Foundation (CNCF)](https://www.cncf.io/announcements/2015/06/21/new-cloud-native-computing-foundation-to-drive-alignment-among-container-technologies/).
-->
&lt;p>在接下来的一年里，一个由&lt;a href="https://k8s.devstats.cncf.io/d/9/companies-table?orgId=1&amp;var-period_name=Before%20joining%20CNCF&amp;var-metric=contributors">主要来自 Google 和 Red Hat 等公司的贡献者&lt;/a>组成的小型社区为该项目付出了辛勤的努力，最终在
2015 年 7 月 21 日发布了 &lt;a href="https://cloudplatform.googleblog.com/2015/07/Kubernetes-V1-Released.html">1.0 版本&lt;/a>。
在发布 1.0 版本的同时，Google 宣布将 Kubernetes 捐赠给 Linux 基金会下的一个新成立的分支，
即&lt;a href="https://www.cncf.io/announcements/2015/06/21/new-cloud-native-computing-foundation-to-drive-alignment-among-container-technologies/">云原生计算基金会 (Cloud Native Computing Foundation，CNCF)&lt;/a>。&lt;/p>
&lt;!--
Despite reaching 1.0, the Kubernetes project was still very challenging to use and
understand. Kubernetes contributor Kelsey Hightower took special note of the project's shortcomings
in ease of use and on July 7, 2016, he pushed the
[first commit of his famed "Kubernetes the Hard Way" guide](https://github.com/kelseyhightower/kubernetes-the-hard-way/commit/9d7ace8b186f6ebd2e93e08265f3530ec2fba81c).
-->
&lt;p>尽管到了 1.0 版本，但 Kubernetes 项目的使用和理解仍然很困难。Kubernetes
贡献者 Kelsey Hightower 特别注意到了该项目在易用性方面的不足，并于 2016 年 7 月 7 日推出了他著名的
“Kubernetes the Hard Way” 指南的&lt;a href="https://github.com/kelseyhightower/kubernetes-the-hard-way/commit/9d7ace8b186f6ebd2e93e08265f3530ec2fba81c">第一次提交&lt;/a>。&lt;/p>
&lt;!--
The project has changed enormously since its original 1.0 release; experiencing a number of big wins
such as
[Custom Resource Definitions (CRD) going GA in 1.16](/blog/2019/09/18/kubernetes-1-16-release-announcement/)
or [full dual stack support launching in 1.23](/blog/2021/12/08/dual-stack-networking-ga/) and
community "lessons learned" from the [removal of widely used beta APIs in 1.22](/blog/2021/07/14/upcoming-changes-in-kubernetes-1-22/)
or the deprecation of [Dockershim](/blog/2020/12/02/dockershim-faq/
-->
&lt;p>自从最初的 1.0 版本发布以来，项目经历了巨大的变化，取得了许多重大的成就，例如
&lt;a href="https://kubernetes.io/blog/2019/09/18/kubernetes-1-16-release-announcement/">在 1.16 版本中正式发布的 Custom Resource Definitions (CRD) &lt;/a>，
或者&lt;a href="https://kubernetes.io/blog/2021/12/08/dual-stack-networking-ga/">在 1.23 版本中推出的全面双栈支持&lt;/a>，以及社区从
&lt;a href="https://kubernetes.io/blog/2021/07/14/upcoming-changes-in-kubernetes-1-22/">1.22 版本中移除广泛使用的 Beta API&lt;/a>
和&lt;a href="https://kubernetes.io/blog/2020/12/02/dockershim-faq/">弃用 Dockershim&lt;/a> 中吸取的“教训”。&lt;/p>
&lt;!--
Some notable updates, milestones and events since 1.0 include:
* December 2016 - [Kubernetes 1.5](/blog/2016/12/kubernetes-1-5-supporting-production-workloads/) introduces runtime pluggability with initial CRI support and alpha Windows node support. OpenAPI also appears for the first time, paving the way for clients to be able to discover extension APIs.
* This release also introduced StatefulSets and PodDisruptionBudgets in Beta.
-->
&lt;p>自 1.0 版本以来的一些值得注意的更新、里程碑和事件包括：&lt;/p>
&lt;ul>
&lt;li>2016 年 12 月 - &lt;a href="https://kubernetes.io/blog/2016/12/kubernetes-1-5-supporting-production-workloads/">Kubernetes 1.5&lt;/a>
引入了运行时可插拔性，初步支持 CRI 和 Alpha 版 Windows 节点支持。
OpenAPI 也首次出现，为客户端能够发现扩展 API 铺平了道路。
&lt;ul>
&lt;li>此版本还引入了 Beta 版的 StatefulSet 和 PodDisruptionBudget。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;!--
* April 2017 — [Introduction of Role-Based Access Controls or RBAC](/blog/2017/04/rbac-support-in-kubernetes/).
* June 2017 — In [Kubernetes 1.7](/blog/2017/06/kubernetes-1-7-security-hardening-stateful-application-extensibility-updates/), ThirdPartyResources or "TPRs" are replaced with CustomResourceDefinitions (CRDs).
* December 2017 — [Kubernetes 1.9](/blog/2017/12/kubernetes-19-workloads-expanded-ecosystem/) sees the Workloads API becoming GA (Generally Available). The release blog states: _"Deployment and ReplicaSet, two of the most commonly used objects in Kubernetes, are now stabilized after more than a year of real-world use and feedback."_
-->
&lt;ul>
&lt;li>2017 年 4 月 — &lt;a href="https://kubernetes.io/blog/2017/04/rbac-support-in-kubernetes/">引入基于角色的访问控制（RBAC）&lt;/a>。&lt;/li>
&lt;li>2017 年 6 月 — 在 &lt;a href="https://kubernetes.io/blog/2017/06/kubernetes-1-7-security-hardening-stateful-application-extensibility-updates/">Kubernetes 1.7&lt;/a>
中，ThirdPartyResources 或 &amp;quot;TPRs&amp;quot; 被 CustomResourceDefinitions（CRD）取代。&lt;/li>
&lt;li>2017 年 12 月 — &lt;a href="https://kubernetes.io/blog/2017/12/kubernetes-19-workloads-expanded-ecosystem/">Kubernetes 1.9&lt;/a> 中，
工作负载 API 成为 GA（正式可用）。发布博客中指出：“Deployment 和 ReplicaSet 是 Kubernetes 中最常用的两个对象，
在经过一年多的实际使用和反馈后，现在已经稳定下来。”&lt;/li>
&lt;/ul>
&lt;!--
* December 2018 — In 1.13, the Container Storage Interface (CSI) reaches GA, kubeadm tool for bootstrapping minimum viable clusters reaches GA, and CoreDNS becomes the default DNS server.
* September 2019 — [Custom Resource Definitions go GA](/blog/2019/09/18/kubernetes-1-16-release-announcement/) in Kubernetes 1.16.
* August 2020 — [Kubernetes 1.19](/blog/2020/08/31/kubernetes-1-19-feature-one-year-support/) increases the support window for releases to 1 year.
* December 2020 — [Dockershim is deprecated](/blog/2020/12/18/kubernetes-1.20-pod-impersonation-short-lived-volumes-in-csi/) in 1.20
-->
&lt;ul>
&lt;li>2018 年 12 月 — 在 1.13 版本中，容器存储接口（CSI）达到 GA，用于引导最小可用集群的 kubeadm 工具达到 GA，并且 CoreDNS 成为默认的 DNS 服务器。&lt;/li>
&lt;li>2019 年 9 月 — &lt;a href="https://kubernetes.io/blog/2019/09/18/kubernetes-1-16-release-announcement/">自定义资源定义（Custom Resource Definition）在 Kubernetes 1.16 中正式发布&lt;/a>。&lt;/li>
&lt;li>2020 年 8 月 — &lt;a href="https://kubernetes.io/blog/2020/08/31/kubernetes-1-19-feature-one-year-support/">Kubernetes 1.19&lt;/a> 将发布支持窗口增加到 1 年。&lt;/li>
&lt;li>2020 年 12 月 — &lt;a href="https://kubernetes.io/zh-cn/blog/2020/12/18/kubernetes-1.20-pod-impersonation-short-lived-volumes-in-csi/">Dockershim 在 1.20 版本中被弃用&lt;/a>。&lt;/li>
&lt;/ul>
&lt;!--
* April 2021 — the [Kubernetes release cadence changes](/blog/2021/07/20/new-kubernetes-release-cadence/#:~:text=On%20April%2023%2C%202021%2C%20the,Kubernetes%20community's%20contributors%20and%20maintainers.) from 4 releases per year to 3 releases per year.
* July 2021 — Widely used beta APIs are [removed](/blog/2021/07/14/upcoming-changes-in-kubernetes-1-22/) in Kubernetes 1.22.
* May 2022 — Kubernetes 1.24 sees [beta APIs become disabled by default](/blog/2022/05/03/kubernetes-1-24-release-announcement/) to reduce upgrade conflicts and removal of [Dockershim](/dockershim), leading to [widespread user confusion](https://www.youtube.com/watch?v=a03Hh1kd6KE) (we've since [improved our communication!](https://github.com/kubernetes/community/tree/master/communication/contributor-comms))
* December 2022 — In 1.26, there was a significant batch and [Job API overhaul](/blog/2022/12/29/scalable-job-tracking-ga/) that paved the way for better support for AI /ML / batch workloads.
-->
&lt;ul>
&lt;li>2021 年 4 月 - &lt;a href="https://kubernetes.io/blog/2021/07/20/new-kubernetes-release-cadence/#:~:text=On%20April%2023%2C%202021%2C%20the,Kubernetes%20community's%20contributors%20and%20maintainers.">Kubernetes 发布节奏变更&lt;/a>，从每年发布 4 个版本变为每年发布 3 个版本。&lt;/li>
&lt;li>2021 年 7 月 - 在 Kubernetes 1.22 中&lt;a href="https://kubernetes.io/blog/2021/07/14/upcoming-changes-in-kubernetes-1-22/">移除了广泛使用的 Beta API&lt;/a>。&lt;/li>
&lt;li>2022 年 5 月 - 在 Kubernetes 1.24 中，&lt;a href="https://kubernetes.io/zh-cn/blog/2022/05/03/kubernetes-1-24-release-announcement/">Beta API 默认被禁用&lt;/a>，
以减少升级冲突，并移除了 &lt;a href="https://kubernetes.io/zh-cn/dockershim">Dockershim&lt;/a>，导致&lt;a href="https://www.youtube.com/watch?v=a03Hh1kd6KE">用户普遍感到困惑&lt;/a>
（我们已经&lt;a href="https://github.com/kubernetes/community/tree/master/communication/contributor-comms">改进了我们的沟通方式！&lt;/a>）&lt;/li>
&lt;li>2022 年 12 月 - 在 1.26 版本中，进行了重大的&lt;a href="https://kubernetes.io/blog/2022/12/29/scalable-job-tracking-ga/">批处理和作业 API 改进&lt;/a>，
为更好地支持 AI/ML/批处理工作负载铺平了道路。&lt;/li>
&lt;/ul>
&lt;!--
**PS:** Curious to see how far the project has come for yourself? Check out this [tutorial for spinning up a Kubernetes 1.0 cluster](https://github.com/spurin/kubernetes-v1.0-lab) created by community members Carlos Santana, Amim Moises Salum Knabben, and James Spurin.
-->
&lt;p>&lt;strong>附言:&lt;/strong> 想亲自体会一下这个项目的进展么？可以查看由社区成员 Carlos Santana、Amim Moises Salum Knabben 和 James Spurin
创建的 &lt;a href="https://github.com/spurin/kubernetes-v1.0-lab">Kubernetes 1.0 集群搭建教程&lt;/a>。&lt;/p>
&lt;hr>
&lt;!--
Kubernetes offers more extension points than we can count. Originally designed to work with Docker
and only Docker, now you can plug in any container runtime that adheres to the CRI standard. There
are other similar interfaces: CSI for storage and CNI for networking. And that's far from all you
can do. In the last decade, whole new patterns have emerged, such as using
[Custom Resource Definitions](/docs/concepts/extend-kubernetes/api-extension/custom-resources/)
(CRDs) to support third-party controllers - now a huge part of the Kubernetes ecosystem.
-->
&lt;p>Kubernetes 提供的扩展点多得数不胜数。最初设计用于与 Docker 一起工作，现在你可以插入任何符合
CRI 标准的容器运行时。还有其他类似的接口：用于存储的 CSI 和用于网络的 CNI。
而且这还远远不是全部。在过去的十年中，出现了全新的模式，例如使用&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/extend-kubernetes/api-extension/custom-resources/">自定义资源定义&lt;/a>（CRD）
来支持第三方控制器 - 这现在是 Kubernetes 生态系统的重要组成部分。&lt;/p>
&lt;!--
The community building the project has also expanded immensely over the last decade. Using
[DevStats](https://k8s.devstats.cncf.io/d/24/overall-project-statistics?orgId=1), we can see the
incredible volume of contribution over the last decade that has made Kubernetes the
[second-largest open source project in the world](https://www.cncf.io/reports/kubernetes-project-journey-report/):
* **88,474** contributors
* **15,121** code committers
* **4,228,347** contributions
* **158,530** issues
* **311,787** pull requests
-->
&lt;p>在过去十年间，参与构建该项目的社区也得到了巨大的扩展。通过使用
&lt;a href="https://k8s.devstats.cncf.io/d/24/overall-project-statistics?orgId=1">DevStats&lt;/a>，我们可以看到过去十年中令人难以置信的贡献量，这使得
Kubernetes 成为了&lt;a href="https://www.cncf.io/reports/kubernetes-project-journey-report/">全球第二大开源项目&lt;/a>：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>88,474&lt;/strong> 位贡献者&lt;/li>
&lt;li>&lt;strong>15,121&lt;/strong> 位代码提交者&lt;/li>
&lt;li>&lt;strong>4,228,347&lt;/strong> 次贡献&lt;/li>
&lt;li>&lt;strong>158,530&lt;/strong> 个问题&lt;/li>
&lt;li>&lt;strong>311,787&lt;/strong> 个拉取请求&lt;/li>
&lt;/ul>
&lt;!--
## Kubernetes today
&lt;img src="welcome.jpg" alt="KubeCon NA 2023" class="left" style="max-width: 20em; margin: 1em">
Since its early days, the project has seen enormous growth in technical capability, usage, and
contribution. The project is still actively working to improve and better serve its users.
-->
&lt;h2 id="kubernetes-现状">Kubernetes 现状&lt;/h2>
&lt;img src="welcome.jpg" alt="KubeCon NA 2023" class="left" style="max-width: 20em; margin: 1em">
&lt;p>自项目初期以来，项目在技术能力、使用率和贡献方面取得了巨大的增长。
项目仍在积极努力改进并更好地为用户服务。&lt;/p>
&lt;!--
In the upcoming 1.31 release, the project will celebrate the culmination of an important long-term
project: the removal of in-tree cloud provider code. In this
[largest migration in Kubernetes history](/blog/2024/05/20/completing-cloud-provider-migration/),
roughly 1.5 million lines of code have been removed, reducing the binary sizes of core components
by approximately 40%. In the project's early days, it was clear that extensibility would be key to
success. However, it wasn't always clear how that extensibility should be achieved. This migration
removes a variety of vendor-specific capabilities from the core Kubernetes code
base. Vendor-specific capabilities can now be better served by other pluggable extensibility
features or patterns, such as
[Custom Resource Definitions (CRDs)](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/)
or API standards like the [Gateway API](https://gateway-api.sigs.k8s.io/).
Kubernetes also faces new challenges in serving its vast user base, and the community is adapting
accordingly. One example of this is the migration of image hosting to the new, community-owned
registry.k8s.io. The egress bandwidth and costs of providing pre-compiled binary images for user
consumption have become immense. This new registry change enables the community to continue
providing these convenient images in more cost- and performance-efficient ways. Make sure you check
out the [blog post](/blog/2022/11/28/registry-k8s-io-faster-cheaper-ga/) and
update any automation you have to use registry.k8s.io!
-->
&lt;p>在即将发布的 1.31 版本中，该项目将庆祝一个重要的长期项目的完成：移除内部云提供商代码。在这个
&lt;a href="https://kubernetes.io/zh-cn/blog/2024/05/20/completing-cloud-provider-migration/">Kubernetes 历史上最大的迁移&lt;/a>中，大约删除了
150 万行代码，将核心组件的二进制文件大小减小了约 40%。在项目早期，很明显可扩展性是成功的关键。
然而，如何实现这种可扩展性并不总是很清楚。此次迁移从核心 Kubernetes 代码库中删除了各种特定于供应商的功能。
现在，特定于供应商的功能可以通过其他可插拔的扩展功能或模式更好地提供，例如&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/extend-kubernetes/api-extension/custom-resources/">自定义资源定义（CRD）&lt;/a>
或 &lt;a href="https://gateway-api.sigs.k8s.io/">Gateway API&lt;/a> 等 API 标准。
Kubernetes 在为其庞大的用户群体提供服务时也面临着新的挑战，社区正在相应地进行调整。其中一个例子是将镜像托管迁移到新的、由社区拥有的
registry.k8s.io。为用户提供预编译二进制镜像的出口带宽和成本已经变得非常巨大。这一新的仓库变更使社区能够以更具成本效益和性能高效的方式继续提供这些便利的镜像。
请务必查看&lt;a href="https://kubernetes.io/blog/2022/11/28/registry-k8s-io-faster-cheaper-ga/">此博客文章&lt;/a>并更新你必须使用 registry.k8s.io 仓库的任何自动化设施！&lt;/p>
&lt;!--
## The future of Kubernetes
&lt;img src="lts.jpg" alt="" class="right" width="300px" style="max-width: 20em; margin: 1em">
A decade in, the future of Kubernetes still looks bright. The community is prioritizing changes that
both improve the user experiences, and enhance the sustainability of the project. The world of
application development continues to evolve, and Kubernetes is poised to change along with it.
-->
&lt;h2 id="kubernetes-的未来">Kubernetes 的未来&lt;/h2>
&lt;img src="lts.jpg" alt="" class="right" width="300px" style="max-width: 20em; margin: 1em">
&lt;p>十年过去了，Kubernetes 的未来依然光明。社区正在优先考虑改进用户体验和增强项目可持续性的变革。
应用程序开发的世界不断演变，Kubernetes 正准备随之变化。&lt;/p>
&lt;!--
In 2024, the advent of AI changed a once-niche workload type into one of prominent
importance. Distributed computing and workload scheduling has always gone hand-in-hand with the
resource-intensive needs of Artificial Intelligence, Machine Learning, and High Performance
Computing workloads. Contributors are paying close attention to the needs of newly developed
workloads and how Kubernetes can best serve them. The new
[Serving Working Group](https://github.com/kubernetes/community/tree/master/wg-serving) is one
example of how the community is organizing to address these workloads' needs. It's likely that the
next few years will see improvements to Kubernetes' ability to manage various types of hardware, and
its ability to manage the scheduling of large batch-style workloads which are run across hardware in
chunks.
-->
&lt;p>2024 年，人工智能的进展将一种曾经小众的工作负载类型变成了一种非常重要的工作负载类型。
分布式计算和工作负载调度一直与人工智能、机器学习和高性能计算工作负载的资源密集需求密切相关。
贡献者们密切关注新开发的工作负载的需求以及 Kubernetes 如何为它们提供最佳服务。新成立的
&lt;a href="https://github.com/kubernetes/community/tree/master/wg-serving">Serving 工作组&lt;/a>
就是社区组织来解决这些工作负载需求的一个例子。未来几年可能会看到
Kubernetes 在管理各种类型的硬件以及管理跨硬件运行的大型批处理工作负载的调度能力方面的改进。&lt;/p>
&lt;!--
The ecosystem around Kubernetes will continue to grow and evolve. In the future, initiatives to
maintain the sustainability of the project, like the migration of in-tree vendor code and the
registry change, will be ever more important.
-->
&lt;p>Kubernetes 周围的生态系统将继续发展壮大。未来，为了保持项目的可持续性，
像内部供应商代码的迁移和仓库变更这样的举措将变得更加重要。&lt;/p>
&lt;!--
The next 10 years of Kubernetes will be guided by its users and the ecosystem, but most of all, by
the people who contribute to it. The community remains open to new contributors. You can find more
information about contributing in our New Contributor Course at
[https://k8s.dev/docs/onboarding](https://k8s.dev/docs/onboarding).
We look forward to building the future of Kubernetes with you!
&lt;figure>
&lt;img src="https://kubernetes.io/zh-cn/blog/2024/06/06/10-years-of-kubernetes/kcsna2023.jpg"
alt="KCSNA 2023"/>
&lt;/figure>
-->
&lt;p>Kubernetes 的未来 10 年将由其用户和生态系统引领，但最重要的是，由为其做出贡献的人引领。
社区对新贡献者持开放态度。你可以在我们的新贡献者课程
&lt;a href="https://k8s.dev/docs/onboarding">https://k8s.dev/docs/onboarding&lt;/a> 中找到更多有关贡献的信息。&lt;/p>
&lt;p>我们期待与你一起构建 Kubernetes 的未来！&lt;/p>
&lt;figure>
&lt;img src="https://kubernetes.io/zh-cn/blog/2024/06/06/10-years-of-kubernetes/kcsna2023.jpg"
alt="KCSNA 2023"/>
&lt;/figure></description></item><item><title>完成 Kubernetes 史上最大规模迁移</title><link>https://kubernetes.io/zh-cn/blog/2024/05/20/completing-cloud-provider-migration/</link><pubDate>Mon, 20 May 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/05/20/completing-cloud-provider-migration/</guid><description>
&lt;!--
layout: blog
title: 'Completing the largest migration in Kubernetes history'
date: 2024-05-20
slug: completing-cloud-provider-migration
author: >
Andrew Sy Kim (Google),
Michelle Au (Google),
Walter Fender (Google),
Michael McCune (Red Hat)
-->
&lt;!--
Since as early as Kubernetes v1.7, the Kubernetes project has pursued the ambitious goal of removing built-in cloud provider integrations ([KEP-2395](https://github.com/kubernetes/enhancements/blob/master/keps/sig-cloud-provider/2395-removing-in-tree-cloud-providers/README.md)).
While these integrations were instrumental in Kubernetes' early development and growth, their removal was driven by two key factors:
the growing complexity of maintaining native support for every cloud provider across millions of lines of Go code, and the desire to establish
Kubernetes as a truly vendor-neutral platform.
-->
&lt;p>早自 Kubernetes v1.7 起，Kubernetes 项目就开始追求取消集成内置云驱动
（&lt;a href="https://github.com/kubernetes/enhancements/blob/master/keps/sig-cloud-provider/2395-removing-in-tree-cloud-providers/README.md">KEP-2395&lt;/a>）。
虽然这些集成对于 Kubernetes 的早期发展和增长发挥了重要作用，但它们的移除是由两个关键因素驱动的：
为各云启动维护数百万行 Go 代码的原生支持所带来的日趋增长的复杂度，以及将 Kubernetes 打造为真正的供应商中立平台的愿景。&lt;/p>
&lt;!--
After many releases, we're thrilled to announce that all cloud provider integrations have been successfully migrated from the core Kubernetes repository to external plugins.
In addition to achieving our initial objectives, we've also significantly streamlined Kubernetes by removing roughly 1.5 million lines of code and reducing the binary sizes of core components by approximately 40%.
-->
&lt;p>历经很多发布版本之后，我们很高兴地宣布所有云驱动集成组件已被成功地从核心 Kubernetes 仓库迁移到外部插件中。
除了实现我们最初的目标之外，我们还通过删除大约 150 万行代码，将核心组件的可执行文件大小减少了大约 40%，
极大简化了 Kubernetes。&lt;/p>
&lt;!--
This migration was a complex and long-running effort due to the numerous impacted components and the critical code paths that relied on the built-in integrations for the
five initial cloud providers: Google Cloud, AWS, Azure, OpenStack, and vSphere. To successfully complete this migration, we had to build four new subsystems from the ground up:
-->
&lt;p>由于受影响的组件众多，而且关键代码路径依赖于五个初始云驱动（Google Cloud、AWS、Azure、OpenStack 和 vSphere）
的内置集成，因此此次迁移是一项复杂且耗时的工作。
为了成功完成此迁移，我们必须从头开始构建四个新的子系统：&lt;/p>
&lt;!--
1. **Cloud controller manager** ([KEP-2392](https://github.com/kubernetes/enhancements/blob/master/keps/sig-cloud-provider/2392-cloud-controller-manager/README.md))
1. **API server network proxy** ([KEP-1281](https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/1281-network-proxy))
1. **kubelet credential provider plugins** ([KEP-2133](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2133-kubelet-credential-providers))
1. **Storage migration to use [CSI](https://github.com/container-storage-interface/spec?tab=readme-ov-file#container-storage-interface-csi-specification-)** ([KEP-625](https://github.com/kubernetes/enhancements/blob/master/keps/sig-storage/625-csi-migration/README.md))
-->
&lt;ol>
&lt;li>&lt;strong>云控制器管理器（Cloud controller manager）&lt;/strong>（&lt;a href="https://github.com/kubernetes/enhancements/blob/master/keps/sig-cloud-provider/2392-cloud-controller-manager/README.md">KEP-2392&lt;/a>）&lt;/li>
&lt;li>&lt;strong>API 服务器网络代理&lt;/strong>（&lt;a href="https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/1281-network-proxy">KEP-1281&lt;/a>）&lt;/li>
&lt;li>&lt;strong>kubelet 凭证提供程序插件&lt;/strong>（&lt;a href="https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2133-kubelet-credential-providers">KEP-2133&lt;/a>）&lt;/li>
&lt;li>&lt;strong>存储迁移以使用 &lt;a href="https://github.com/container-storage-interface/spec?tab=readme-ov-file#container-storage-interface-csi-specification-">CSI&lt;/a>&lt;/strong>（&lt;a href="https://github.com/kubernetes/enhancements/blob/master/keps/sig-storage/625-csi-migration/README.md">KEP-625&lt;/a>）&lt;/li>
&lt;/ol>
&lt;!--
Each subsystem was critical to achieve full feature parity with built-in capabilities and required several releases to bring each subsystem to GA-level maturity with a safe and
reliable migration path. More on each subsystem below.
-->
&lt;p>就与内置功能实现完全的特性等价而言，每个子系统都至关重要，
并且需要迭代多个版本才能使每个子系统达到 GA 级别并具有安全可靠的迁移路径。
下面详细介绍每个子系统。&lt;/p>
&lt;!--
### Cloud controller manager
The cloud controller manager was the first external component introduced in this effort, replacing functionality within the kube-controller-manager and kubelet that directly interacted with cloud APIs.
This essential component is responsible for initializing nodes by applying metadata labels that indicate the cloud region and zone a Node is running on, as well as IP addresses that are only known to the cloud provider.
Additionally, it runs the service controller, which is responsible for provisioning cloud load balancers for Services of type LoadBalancer.
-->
&lt;h3 id="云控制器管理器">云控制器管理器&lt;/h3>
&lt;p>云控制器管理器是这项工作中引入的第一个外部组件，取代了 kube-controller-manager 和 kubelet 中直接与云 API 交互的功能。
这个基本组件负责通过施加元数据标签来初始化节点。所施加的元数据标签标示节点运行所在的云区域和可用区，
以及只有云驱动知道的 IP 地址。
此外，它还运行服务控制器，该控制器负责为 LoadBalancer 类型的 Service 配置云负载均衡器。&lt;/p>
&lt;p>&lt;img alt="Kubernetes 组件" src="https://kubernetes.io/images/docs/components-of-kubernetes.svg">&lt;/p>
&lt;!--
To learn more, read [Cloud Controller Manager](/docs/concepts/architecture/cloud-controller/) in the Kubernetes documentation.
-->
&lt;p>要进一步了解相关信息，请阅读 Kubernetes 文档中的&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/architecture/cloud-controller/">云控制器管理器&lt;/a>。&lt;/p>
&lt;!--
### API server network proxy
The API Server Network Proxy project, initiated in 2018 in collaboration with SIG API Machinery, aimed to replace the SSH tunneler functionality within the kube-apiserver.
This tunneler had been used to securely proxy traffic between the Kubernetes control plane and nodes, but it heavily relied on provider-specific implementation details embedded in the kube-apiserver to establish these SSH tunnels.
-->
&lt;h3 id="api-服务器网络代理">API 服务器网络代理&lt;/h3>
&lt;p>API 服务器网络代理项目于 2018 年与 SIG API Machinery 合作启动，旨在取代 kube-apiserver 中的 SSH 隧道功能。
该隧道器原用于安全地代理 Kubernetes 控制平面和节点之间的流量，但它重度依赖于
kube-apiserver 中所嵌入的、特定于提供商的实现细节来建立这些 SSH 隧道。&lt;/p>
&lt;!--
Now, the API Server Network Proxy is a GA-level extension point within the kube-apiserver. It offers a generic proxying mechanism that can route traffic from the API server to nodes through a secure proxy,
eliminating the need for the API server to have any knowledge of the specific cloud provider it is running on. This project also introduced the Konnectivity project, which has seen growing adoption in production environments.
-->
&lt;p>现在，API 服务器网络代理成为 kube-apiserver 中 GA 级别的扩展点。
提供了一种通用代理机制，可以通过一个安全的代理将流量从 API 服务器路由到节点，
从而使 API 服务器无需了解其运行所在的特定云驱动。
此项目还引入了 Konnectivity 项目，该项目在生产环境中的采用越来越多。&lt;/p>
&lt;!--
You can learn more about the API Server Network Proxy from its [README](https://github.com/kubernetes-sigs/apiserver-network-proxy#readme).
-->
&lt;p>你可以在其 &lt;a href="https://github.com/kubernetes-sigs/apiserver-network-proxy#readme">README&lt;/a>
中了解有关 API 服务器网络代理的更多信息。&lt;/p>
&lt;!--
### Credential provider plugins for the kubelet
The Kubelet credential provider plugin was developed to replace the kubelet's built-in functionality for dynamically fetching credentials for image registries hosted on Google Cloud, AWS, or Azure.
The legacy capability was convenient as it allowed the kubelet to seamlessly retrieve short-lived tokens for pulling images from GCR, ECR, or ACR. However, like other areas of Kubernetes, supporting
this required the kubelet to have specific knowledge of different cloud environments and APIs.
-->
&lt;h3 id="kubelet-的凭据提供程序插件">kubelet 的凭据提供程序插件&lt;/h3>
&lt;p>kubelet 凭据提供程序插件的开发是为了取代 kubelet 的内置功能，用于动态获取用于托管在
Google Cloud、AWS 或 Azure 上的镜像仓库的凭据。
原来所实现的功能很方便，因为它允许 kubelet 无缝地获取短期令牌以从 GCR、ECR 或 ACR 拉取镜像
然而，与 Kubernetes 的其他领域一样，支持这一点需要 kubelet 具有不同云环境和 API 的特定知识。&lt;/p>
&lt;!--
Introduced in 2019, the credential provider plugin mechanism offers a generic extension point for the kubelet to execute plugin binaries that dynamically provide credentials for images hosted on various clouds.
This extensibility expands the kubelet's capabilities to fetch short-lived tokens beyond the initial three cloud providers.
-->
&lt;p>凭据驱动插件机制于 2019 年推出，为 kubelet 提供了一个通用扩展点用于执行插件的可执行文件，
进而为访问各种云上托管的镜像动态提供凭据。
可扩展性扩展了 kubelet 获取短期令牌的能力，且不受限于最初的三个云驱动。&lt;/p>
&lt;!--
To learn more, read [kubelet credential provider for authenticated image pulls](/docs/concepts/containers/images/#kubelet-credential-provider).
-->
&lt;p>要了解更多信息，请阅读&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/containers/images/#kubelet-credential-provider">用于认证镜像拉取的 kubelet 凭据提供程序&lt;/a>。&lt;/p>
&lt;!--
### Storage plugin migration from in-tree to CSI
The Container Storage Interface (CSI) is a control plane standard for managing block and file storage systems in Kubernetes and other container orchestrators that went GA in 1.13.
It was designed to replace the in-tree volume plugins built directly into Kubernetes with drivers that can run as Pods within the Kubernetes cluster.
These drivers communicate with kube-controller-manager storage controllers via the Kubernetes API, and with kubelet through a local gRPC endpoint.
Now there are over 100 CSI drivers available across all major cloud and storage vendors, making stateful workloads in Kubernetes a reality.
-->
&lt;h3 id="存储插件从树内迁移到-csi">存储插件从树内迁移到 CSI&lt;/h3>
&lt;p>容器存储接口（Container Storage Interface，CSI）是一种控制平面标准，用于管理 Kubernetes
和其他容器编排系统中的块和文件存储系统，已在 1.13 中进入正式发布状态。
它的设计目标是用可在 Kubernetes 集群中 Pod 内运行的驱动程序替换直接内置于 Kubernetes 中的树内卷插件。
这些驱动程序通过 Kubernetes API 与 kube-controller-manager 存储控制器通信，并通过本地 gRPC 端点与 kubelet 进行通信。
现在，所有主要云和存储供应商一起提供了 100 多个 CSI 驱动，使 Kubernetes 中运行有状态工作负载成为现实。&lt;/p>
&lt;!--
However, a major challenge remained on how to handle all the existing users of in-tree volume APIs. To retain API backwards compatibility,
we built an API translation layer into our controllers that will convert the in-tree volume API into the equivalent CSI API. This allowed us to redirect all storage operations to the CSI driver,
paving the way for us to remove the code for the built-in volume plugins without removing the API.
-->
&lt;p>然而，如何处理树内卷 API 的所有现有用户仍然是一个重大挑战。
为了保持 API 向后兼容性，我们在控制器中构建了一个 API 转换层，把树内卷 API 转换为等效的 CSI API。
这使我们能够将所有存储操作重定向到 CSI 驱动程序，为我们在不删除 API 的情况下删除内置卷插件的代码铺平了道路。&lt;/p>
&lt;!--
You can learn more about In-tree Storage migration in [Kubernetes In-Tree to CSI Volume Migration Moves to Beta](https://kubernetes.io/blog/2019/12/09/kubernetes-1-17-feature-csi-migration-beta/).
-->
&lt;p>你可以在 &lt;a href="https://kubernetes.io/blog/2019/12/09/kubernetes-1-17-feature-csi-migration-beta/">Kubernetes 树内卷到 CSI 卷的迁移进入 Beta 阶段&lt;/a>。&lt;/p>
&lt;!--
## What's next?
This migration has been the primary focus for SIG Cloud Provider over the past few years. With this significant milestone achieved, we will be shifting our efforts towards exploring new
and innovative ways for Kubernetes to better integrate with cloud providers, leveraging the external subsystems we've built over the years. This includes making Kubernetes smarter in
hybrid environments where nodes in the cluster can run on both public and private clouds, as well as providing better tools and frameworks for developers of external providers to simplify and streamline their integration efforts.
-->
&lt;h2 id="下一步是什么">下一步是什么？&lt;/h2>
&lt;p>过去几年，这一迁移工程一直是 SIG Cloud Provider 的主要关注点。
随着这一重要里程碑的实现，我们将把努力转向探索新的创新方法，让 Kubernetes 更好地与云驱动集成，利用我们多年来构建的外部子系统。
这包括使 Kubernetes 在混合环境中变得更加智能，其集群中的节点可以运行在公共云和私有云上，
以及为外部驱动的开发人员提供更好的工具和框架，以简化他们的集成工作，提高效率。&lt;/p>
&lt;!--
With all the new features, tools, and frameworks being planned, SIG Cloud Provider is not forgetting about the other side of the equation: testing. Another area of focus for the SIG's future activities is the improvement of
cloud controller testing to include more providers. The ultimate goal of this effort being to create a testing framework that will include as many providers as possible so that we give the Kubernetes community the highest
levels of confidence about their Kubernetes environments.
-->
&lt;p>在规划所有这些新特性、工具和框架的同时，SIG Cloud Provider 并没有忘记另一项同样重要的工作：测试。
SIG 未来活动的另一个重点领域是改进云控制器测试以涵盖更多的驱动。
这项工作的最终目标是创建一个包含尽可能多驱动的测试框架，以便我们让 Kubernetes 社区对其 Kubernetes 环境充满信心。&lt;/p>
&lt;!--
If you're using a version of Kubernetes older than v1.29 and haven't migrated to an external cloud provider yet, we recommend checking out our previous blog post [Kubernetes 1.29: Cloud Provider Integrations Are Now Separate Components](/blog/2023/12/14/cloud-provider-integration-changes/).
It provides detailed information on the changes we've made and offers guidance on how to migrate to an external provider.
Starting in v1.31, in-tree cloud providers will be permanently disabled and removed from core Kubernetes components.
-->
&lt;p>如果你使用的 Kubernetes 版本早于 v1.29 并且尚未迁移到外部云驱动，我们建议你查阅我们之前的博客文章
&lt;a href="https://kubernetes.io/zh-cn/blog/2023/12/14/cloud-provider-integration-changes/">Kubernetes 1.29：云驱动集成现在是单独的组件&lt;/a>。
该博客包含与我们所作的变更相关的详细信息，并提供了有关如何迁移到外部驱动的指导。
从 v1.31 开始，树内云驱动将被永久禁用并从核心 Kubernetes 组件中删除。&lt;/p>
&lt;!--
If you’re interested in contributing, come join our [bi-weekly SIG meetings](https://github.com/kubernetes/community/tree/master/sig-cloud-provider#meetings)!
-->
&lt;p>如果你有兴趣做出贡献，请参加我们的&lt;a href="https://github.com/kubernetes/community/tree/master/sig-cloud-provider#meetings">每两周一次的 SIG 会议&lt;/a>!&lt;/p></description></item><item><title>Gateway API v1.1：服务网格、GRPCRoute 和更多变化</title><link>https://kubernetes.io/zh-cn/blog/2024/05/09/gateway-api-v1-1/</link><pubDate>Thu, 09 May 2024 09:00:00 -0800</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/05/09/gateway-api-v1-1/</guid><description>
&lt;!--
layout: blog
title: "Gateway API v1.1: Service mesh, GRPCRoute, and a whole lot more"
date: 2024-05-09T09:00:00-08:00
slug: gateway-api-v1-1
author: >
[Richard Belleville](https://github.com/gnossen) (Google),
[Frank Budinsky](https://github.com/frankbu) (IBM),
[Arko Dasgupta](https://github.com/arkodg) (Tetrate),
[Flynn](https://github.com/kflynn) (Buoyant),
[Candace Holman](https://github.com/candita) (Red Hat),
[John Howard](https://github.com/howardjohn) (Solo.io),
[Christine Kim](https://github.com/xtineskim) (Isovalent),
[Mattia Lavacca](https://github.com/mlavacca) (Kong),
[Keith Mattix](https://github.com/keithmattix) (Microsoft),
[Mike Morris](https://github.com/mikemorris) (Microsoft),
[Rob Scott](https://github.com/robscott) (Google),
[Grant Spence](https://github.com/gcs278) (Red Hat),
[Shane Utt](https://github.com/shaneutt) (Kong),
[Gina Yeh](https://github.com/ginayeh) (Google),
and other review and release note contributors
-->
&lt;p>&lt;img alt="Gateway API logo" src="https://kubernetes.io/zh-cn/blog/2024/05/09/gateway-api-v1-1/gateway-api-logo.svg">&lt;/p>
&lt;!--
Following the GA release of Gateway API last October, Kubernetes
SIG Network is pleased to announce the v1.1 release of
[Gateway API](https://gateway-api.sigs.k8s.io/). In this release, several features are graduating to
_Standard Channel_ (GA), notably including support for service mesh and
GRPCRoute. We're also introducing some new experimental features, including
session persistence and client certificate verification.
-->
&lt;p>继去年十月正式发布 Gateway API 之后，Kubernetes SIG Network 现在又很高兴地宣布
&lt;a href="https://gateway-api.sigs.k8s.io/">Gateway API&lt;/a> v1.1 版本发布。
在本次发布中，有几个特性已进阶至&lt;strong>标准渠道&lt;/strong>（GA），特别是对服务网格和 GRPCRoute 的支持也已进阶。
我们还引入了一些新的实验性特性，包括会话持久性和客户端证书验证。&lt;/p>
&lt;!--
## What's new
### Graduation to Standard
-->
&lt;h2 id="whats-new">新内容 &lt;/h2>
&lt;h3 id="graduation-to-standard">进阶至标准渠道 &lt;/h3>
&lt;!--
This release includes the graduation to Standard of four eagerly awaited features.
This means they are no longer experimental concepts; inclusion in the Standard
release channel denotes a high level of confidence in the API surface and
provides guarantees of backward compatibility. Of course, as with any other
Kubernetes API, Standard Channel features can continue to evolve with
backward-compatible additions over time, and we certainly expect further
refinements and improvements to these new features in the future.
For more information on how all of this works, refer to the
[Gateway API Versioning Policy](https://gateway-api.sigs.k8s.io/concepts/versioning/).
-->
&lt;p>本次发布有四个备受期待的特性进阶至标准渠道。这意味着它们不再是实验性的概念；
包含在标准发布渠道中的举措展现了大家对 API 接口的高度信心，并提供向后兼容的保证。
当然，与所有其他 Kubernetes API 一样，标准渠道的特性可以随着时间的推移通过向后兼容的方式演进，
我们当然期待未来对这些新特性有进一步的优化和改进。
有关细节请参阅 &lt;a href="https://gateway-api.sigs.k8s.io/concepts/versioning/">Gateway API 版本控制政策&lt;/a>。&lt;/p>
&lt;!--
#### [Service Mesh Support](https://gateway-api.sigs.k8s.io/mesh/)
Service mesh support in Gateway API allows service mesh users to use the same
API to manage ingress traffic and mesh traffic, reusing the same policy and
routing interfaces. In Gateway API v1.1, routes (such as HTTPRoute) can now have
a Service as a `parentRef`, to control how traffic to specific services behave.
For more information, read the
[Gateway API service mesh documentation](https://gateway-api.sigs.k8s.io/mesh/)
or see the
[list of Gateway API implementations](https://gateway-api.sigs.k8s.io/implementations/#service-mesh-implementation-status).
-->
&lt;h4 id="服务网格支持-https-gateway-api-sigs-k8s-io-mesh">&lt;a href="https://gateway-api.sigs.k8s.io/mesh/">服务网格支持&lt;/a>&lt;/h4>
&lt;p>在 Gateway API 中支持服务网格意味着允许服务网格用户使用相同的 API 来管理 Ingress 流量和网格流量，
能够重用相同的策略和路由接口。在 Gateway API v1.1 中，路由（如 HTTPRoute）现在可以将一个 Service 作为 &lt;code>parentRef&lt;/code>，
以控制到特定服务的流量行为。有关细节请查阅
&lt;a href="https://gateway-api.sigs.k8s.io/mesh/">Gateway API 服务网格文档&lt;/a>或
&lt;a href="https://gateway-api.sigs.k8s.io/implementations/#service-mesh-implementation-status">Gateway API 实现列表&lt;/a>。&lt;/p>
&lt;!--
As an example, one could do a canary deployment of a workload deep in an
application's call graph with an HTTPRoute as follows:
-->
&lt;p>例如，你可以使用如下 HTTPRoute 以金丝雀部署深入到应用调用图中的工作负载：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>gateway.networking.k8s.io/v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>HTTPRoute&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>color-canary&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">namespace&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>faces&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">parentRefs&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>color&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Service&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">group&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">port&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#666">80&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">rules&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">backendRefs&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>color&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">port&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#666">80&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">weight&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#666">50&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>color2&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">port&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#666">80&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">weight&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#666">50&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
This would split traffic sent to the `color` Service in the `faces` namespace
50/50 between the original `color` Service and the `color2` Service, using a
portable configuration that's easy to move from one mesh to another.
-->
&lt;p>通过使用一种便于从一个网格迁移到另一个网格的可移植配置，
此 HTTPRoute 对象将把发送到 &lt;code>faces&lt;/code> 命名空间中的 &lt;code>color&lt;/code> Service 的流量按 50/50
拆分到原始的 &lt;code>color&lt;/code> Service 和 &lt;code>color2&lt;/code> Service 上。&lt;/p>
&lt;!--
#### [GRPCRoute](https://gateway-api.sigs.k8s.io/guides/grpc-routing/)
If you are already using the experimental version of GRPCRoute, we recommend holding
off on upgrading to the standard channel version of GRPCRoute until the
controllers you're using have been updated to support GRPCRoute v1. Until then,
it is safe to upgrade to the experimental channel version of GRPCRoute in v1.1
that includes both v1alpha2 and v1 API versions.
-->
&lt;h4 id="grpcroute-https-gateway-api-sigs-k8s-io-guides-grpc-routing">&lt;a href="https://gateway-api.sigs.k8s.io/guides/grpc-routing/">GRPCRoute&lt;/a>&lt;/h4>
&lt;p>如果你已经在使用实验性版本的 GRPCRoute，我们建议你暂时不要升级到标准渠道版本的 GRPCRoute，
除非你正使用的控制器已被更新为支持 GRPCRoute v1。
在此之后，你才可以安全地升级到实验性渠道版本的 GRPCRoute v1.1，这个版本同时包含了 v1alpha2 和 v1 的 API。&lt;/p>
&lt;!--
#### [ParentReference Port](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.ParentReference)
The `port` field was added to ParentReference, allowing you to attach resources
to Gateway Listeners, Services, or other parent resources
(depending on the implementation). Binding to a port also allows you to attach
to multiple Listeners at once.
-->
&lt;h4 id="parentreference-端口-https-gateway-api-sigs-k8s-io-reference-spec-gateway-networking-k8s-io-2fv1-parentreference">&lt;a href="https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.ParentReference">ParentReference 端口&lt;/a>&lt;/h4>
&lt;p>&lt;code>port&lt;/code> 字段已被添加到 ParentReference 中，
允许你将资源挂接到 Gateway 监听器、Service 或其他父资源（取决于实现）。
绑定到某个端口还允许你一次挂接到多个监听器。&lt;/p>
&lt;!--
For example, you can attach an HTTPRoute to one or more specific Listeners of a
Gateway as specified by the Listener `port`, instead of the Listener `name` field.
For more information, see
[Attaching to Gateways](https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways).
-->
&lt;p>例如，你可以将 HTTPRoute 挂接到由监听器 &lt;code>port&lt;/code> 而不是监听器 &lt;code>name&lt;/code> 字段所指定的一个或多个特定监听器。&lt;/p>
&lt;p>有关细节请参阅&lt;a href="https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways">挂接到 Gateways&lt;/a>。&lt;/p>
&lt;!--
#### [Conformance Profiles and Reports](https://gateway-api.sigs.k8s.io/concepts/conformance/#conformance-profiles)
The conformance report API has been expanded with the `mode` field (intended to
specify the working mode of the implementation), and the `gatewayAPIChannel`
(standard or experimental). The `gatewayAPIVersion` and `gatewayAPIChannel` are
now filled in automatically by the suite machinery, along with a brief
description of the testing outcome. The Reports have been reorganized in a more
structured way, and the implementations can now add information on how the tests
have been run and provide reproduction steps.
-->
&lt;h4 id="合规性配置文件和报告-https-gateway-api-sigs-k8s-io-concepts-conformance-conformance-profiles">&lt;a href="https://gateway-api.sigs.k8s.io/concepts/conformance/#conformance-profiles">合规性配置文件和报告&lt;/a>&lt;/h4>
&lt;p>合规性报告 API 被扩展了，添加了 &lt;code>mode&lt;/code> 字段（用于指定实现的工作模式）以及 &lt;code>gatewayAPIChannel&lt;/code>（标准或实验性）。
&lt;code>gatewayAPIVersion&lt;/code> 和 &lt;code>gatewayAPIChannel&lt;/code> 现在由套件机制自动填充，并附有测试结果的简要描述。
这些报告已通过更加结构化的方式进行重新组织，现在实现可以添加测试是如何运行的有关信息，还能提供复现步骤。&lt;/p>
&lt;!--
### New additions to Experimental channel
#### [Gateway Client Certificate Verification](https://gateway-api.sigs.k8s.io/geps/gep-91/)
Gateways can now configure client cert verification for each Gateway Listener by
introducing a new `frontendValidation` field within `tls`. This field
supports configuring a list of CA Certificates that can be used as a trust
anchor to validate the certificates presented by the client.
-->
&lt;h3 id="实验性渠道的新增内容">实验性渠道的新增内容&lt;/h3>
&lt;h4 id="gateway-客户端证书验证-https-gateway-api-sigs-k8s-io-geps-gep-91">&lt;a href="https://gateway-api.sigs.k8s.io/geps/gep-91/">Gateway 客户端证书验证&lt;/a>&lt;/h4>
&lt;p>Gateway 现在可以通过在 &lt;code>tls&lt;/code> 内引入的新字段 &lt;code>frontendValidation&lt;/code> 来为每个
Gateway 监听器配置客户端证书验证。此字段支持配置可用作信任锚的 CA 证书列表，以验证客户端呈现的证书。&lt;/p>
&lt;!--
The following example shows how the CACertificate stored in
the `foo-example-com-ca-cert` ConfigMap can be used to validate the certificates
presented by clients connecting to the `foo-https` Gateway Listener.
-->
&lt;p>以下示例显示了如何使用存储在 &lt;code>foo-example-com-ca-cert&lt;/code> ConfigMap 中的 CACertificate
来验证连接到 &lt;code>foo-https&lt;/code> Gateway 监听器的客户端所呈现的证书。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>gateway.networking.k8s.io/v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Gateway&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>client-validation-basic&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">gatewayClassName&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>acme-lb&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">listeners&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>foo-https&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">protocol&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>HTTPS&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">port&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#666">443&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">hostname&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>foo.example.com&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">tls&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">certificateRefs&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Secret&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">group&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>foo-example-com-cert&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">frontendValidation&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">caCertificateRefs&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ConfigMap&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">group&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>foo-example-com-ca-cert&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
#### [Session Persistence and BackendLBPolicy](https://gateway-api.sigs.k8s.io/geps/gep-1619/)
[Session Persistence](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.SessionPersistence)
is being introduced to Gateway API via a new policy
([BackendLBPolicy](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.BackendLBPolicy))
for Service-level configuration and as fields within HTTPRoute
and GRPCRoute for route-level configuration. The BackendLBPolicy and route-level
APIs provide the same session persistence configuration, including session
timeouts, session name, session type, and cookie lifetime type.
-->
&lt;h4 id="会话持久性和-backendlbpolicy-https-gateway-api-sigs-k8s-io-geps-gep-1619">&lt;a href="https://gateway-api.sigs.k8s.io/geps/gep-1619/">会话持久性和 BackendLBPolicy&lt;/a>&lt;/h4>
&lt;p>&lt;a href="https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.SessionPersistence">会话持久性&lt;/a>
通过新的策略（&lt;a href="https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.BackendLBPolicy">BackendLBPolicy&lt;/a>）
引入到 Gateway API 中用于服务级配置，在 HTTPRoute 和 GRPCRoute 内以字段的形式用于路由级配置。
BackendLBPolicy 和路由级 API 提供相同的会话持久性配置，包括会话超时、会话名称、会话类型和 cookie 生命周期类型。&lt;/p>
&lt;!--
Below is an example configuration of `BackendLBPolicy` that enables cookie-based
session persistence for the `foo` service. It sets the session name to
`foo-session`, defines absolute and idle timeouts, and configures the cookie to
be a session cookie:
-->
&lt;p>以下是 &lt;code>BackendLBPolicy&lt;/code> 的示例配置，为 &lt;code>foo&lt;/code> 服务启用基于 Cookie 的会话持久性。
它将会话名称设置为 &lt;code>foo-session&lt;/code>，定义绝对超时时间和空闲超时时间，并将 Cookie 配置为会话 Cookie：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>gateway.networking.k8s.io/v1alpha2&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>BackendLBPolicy&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>lb-policy&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">namespace&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>foo-ns&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">targetRefs&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">group&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>core&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>service&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>foo&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">sessionPersistence&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">sessionName&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>foo-session&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">absoluteTimeout&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>1h&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">idleTimeout&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>30m&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">type&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Cookie&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">cookieConfig&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">lifetimeType&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Session&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
### Everything else
#### [TLS Terminology Clarifications](https://gateway-api.sigs.k8s.io/geps/gep-2907/)
-->
&lt;h3 id="其他更新">其他更新&lt;/h3>
&lt;h4 id="tls-术语阐述-https-gateway-api-sigs-k8s-io-geps-gep-2907">&lt;a href="https://gateway-api.sigs.k8s.io/geps/gep-2907/">TLS 术语阐述&lt;/a>&lt;/h4>
&lt;!--
As part of a broader goal of making our TLS terminology more consistent
throughout the API, we've introduced some breaking changes to BackendTLSPolicy.
This has resulted in a new API version (v1alpha3) and will require any existing
implementations of this policy to properly handle the version upgrade, e.g.
by backing up data and uninstalling the v1alpha2 version before installing this
newer version.
Any references to v1alpha2 BackendTLSPolicy fields will need to be updated to
v1alpha3. Specific changes to fields include:
-->
&lt;p>为了在整个 API 中让我们的 TLS 术语更加一致以实现更广泛的目标，
我们对 BackendTLSPolicy 做了一些破坏性变更。
这就产生了新的 API 版本（v1alpha3），且将需要这个策略所有现有的实现来正确处理版本升级，
例如通过备份数据并在安装这个新版本之前卸载 v1alpha2 版本。&lt;/p>
&lt;p>所有引用了 v1alpha2 BackendTLSPolicy 的字段都将需要更新为 v1alpha3。这些字段的具体变更包括：&lt;/p>
&lt;!--
- `targetRef` becomes `targetRefs` to allow a BackendTLSPolicy to attach to
multiple targets
- `tls` becomes `validation`
- `tls.caCertRefs` becomes `validation.caCertificateRefs`
- `tls.wellKnownCACerts` becomes `validation.wellKnownCACertificates`
-->
&lt;ul>
&lt;li>&lt;code>targetRef&lt;/code> 变为 &lt;code>targetRefs&lt;/code> 以允许 BackendTLSPolicy 挂接到多个目标&lt;/li>
&lt;li>&lt;code>tls&lt;/code> 变为 &lt;code>validation&lt;/code>&lt;/li>
&lt;li>&lt;code>tls.caCertRefs&lt;/code> 变为 &lt;code>validation.caCertificateRefs&lt;/code>&lt;/li>
&lt;li>&lt;code>tls.wellKnownCACerts&lt;/code> 变为 &lt;code>validation.wellKnownCACertificates&lt;/code>&lt;/li>
&lt;/ul>
&lt;!--
For a full list of the changes included in this release, please refer to the
[v1.1.0 release notes](https://github.com/kubernetes-sigs/gateway-api/releases/tag/v1.1.0).
-->
&lt;p>有关本次发布包含的完整变更列表，请参阅
&lt;a href="https://github.com/kubernetes-sigs/gateway-api/releases/tag/v1.1.0">v1.1.0 发布说明&lt;/a>。&lt;/p>
&lt;!--
## Gateway API background
The idea of Gateway API was initially [proposed](https://youtu.be/Ne9UJL6irXY?si=wgtC9w8PMB5ZHil2)
at the 2019 KubeCon San Diego as the next generation
of Ingress API. Since then, an incredible community has formed to develop what
has likely become the
[most collaborative API in Kubernetes history](https://www.youtube.com/watch?v=V3Vu_FWb4l4).
Over 200 people have contributed to this API so far, and that number continues to grow.
-->
&lt;h2 id="gateway-api-background">Gateway API 背景 &lt;/h2>
&lt;p>Gateway API 的想法最初是在 2019 年 KubeCon San Diego 上作为下一代 Ingress API
&lt;a href="https://youtu.be/Ne9UJL6irXY?si=wgtC9w8PMB5ZHil2">提出的&lt;/a>。
从那时起，一个令人瞩目的社区逐渐形成，共同开发出了可能成为
&lt;a href="https://www.youtube.com/watch?v=V3Vu_FWb4l4">Kubernetes 历史上最具合作精神的 API&lt;/a>。
到目前为止，已有超过 200 人为该 API 做过贡献，而且这一数字还在不断攀升。&lt;/p>
&lt;!--
The maintainers would like to thank _everyone_ who's contributed to Gateway API, whether in the
form of commits to the repo, discussion, ideas, or general support. We literally
couldn't have gotten this far without the support of this dedicated and active
community.
-->
&lt;p>维护者们要感谢为 Gateway API 做出贡献的&lt;strong>每一个人&lt;/strong>，
无论是提交代码、参与讨论、提供创意，还是给予常规支持，我们都在此表示诚挚的感谢。
没有这个专注且活跃的社区的支持，我们不可能走到这一步。&lt;/p>
&lt;!--
## Try it out
Unlike other Kubernetes APIs, you don't need to upgrade to the latest version of
Kubernetes to get the latest version of Gateway API. As long as you're running
Kubernetes 1.26 or later, you'll be able to get up and running with this
version of Gateway API.
-->
&lt;h2 id="try-it-out">试用一下 &lt;/h2>
&lt;p>与其他 Kubernetes API 不同，你不需要升级到最新版本的 Kubernetes 即可获得最新版本的 Gateway API。
只要你运行的是 Kubernetes 1.26 或更高版本，你就可以使用这个版本的 Gateway API。&lt;/p>
&lt;!--
To try out the API, follow our [Getting Started Guide](https://gateway-api.sigs.k8s.io/guides/).
## Get involved
There are lots of opportunities to get involved and help define the future of
Kubernetes routing APIs for both ingress and service mesh.
-->
&lt;p>要试用此 API，请参阅&lt;a href="https://gateway-api.sigs.k8s.io/guides/">入门指南&lt;/a>。&lt;/p>
&lt;h2 id="get-involved">参与进来 &lt;/h2>
&lt;p>你有很多机会可以参与进来并帮助为 Ingress 和服务网格定义 Kubernetes 路由 API 的未来。&lt;/p>
&lt;!--
* Check out the [user guides](https://gateway-api.sigs.k8s.io/guides) to see what use-cases can be addressed.
* Try out one of the [existing Gateway controllers](https://gateway-api.sigs.k8s.io/implementations/).
* Or [join us in the community](https://gateway-api.sigs.k8s.io/contributing/)
and help us build the future of Gateway API together!
-->
&lt;ul>
&lt;li>查阅&lt;a href="https://gateway-api.sigs.k8s.io/guides">用户指南&lt;/a>以了解可以解决哪些用例。&lt;/li>
&lt;li>试用其中一个&lt;a href="https://gateway-api.sigs.k8s.io/implementations/">现有的 Gateway 控制器&lt;/a>。&lt;/li>
&lt;li>或者&lt;a href="https://gateway-api.sigs.k8s.io/contributing/">加入我们的社区&lt;/a>，帮助我们一起构建 Gateway API 的未来！&lt;/li>
&lt;/ul>
&lt;!--
## Related Kubernetes blog articles
* [New Experimental Features in Gateway API v1.0](/blog/2023/11/28/gateway-api-ga/)
11/2023
* [Gateway API v1.0: GA Release](/blog/2023/10/31/gateway-api-ga/)
10/2023
* [Introducing ingress2gateway; Simplifying Upgrades to Gateway API](/blog/2023/10/25/introducing-ingress2gateway/)
10/2023
* [Gateway API v0.8.0: Introducing Service Mesh Support](/blog/2023/08/29/gateway-api-v0-8/)
08/2023
-->
&lt;h2 id="related-kubernetes-blog-articles">相关的 Kubernetes 博文 &lt;/h2>
&lt;ul>
&lt;li>2023 年 11 月 &lt;a href="https://kubernetes.io/blog/2023/11/28/gateway-api-ga/">Gateway API v1.0 中的新实验性特性&lt;/a>&lt;/li>
&lt;li>2023 年 10 月 &lt;a href="https://kubernetes.io/zh-cn/blog/2023/10/31/gateway-api-ga/">Gateway API v1.0：正式发布（GA）&lt;/a>&lt;/li>
&lt;li>2023 年 10 月&lt;a href="https://kubernetes.io/blog/2023/10/25/introducing-ingress2gateway/">介绍 ingress2gateway；简化 Gateway API 升级&lt;/a>&lt;/li>
&lt;li>2023 年 8 月 &lt;a href="https://kubernetes.io/zh-cn/blog/2023/08/29/gateway-api-v0-8/">Gateway API v0.8.0：引入服务网格支持&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Kubernetes 1.30：防止未经授权的卷模式转换进阶到 GA</title><link>https://kubernetes.io/zh-cn/blog/2024/04/30/prevent-unauthorized-volume-mode-conversion-ga/</link><pubDate>Tue, 30 Apr 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/04/30/prevent-unauthorized-volume-mode-conversion-ga/</guid><description>
&lt;!--
layout: blog
title: "Kubernetes 1.30: Preventing unauthorized volume mode conversion moves to GA"
date: 2024-04-30
slug: prevent-unauthorized-volume-mode-conversion-ga
author: >
Raunak Pradip Shah (Mirantis)
-->
&lt;p>&lt;strong>作者:&lt;/strong> Raunak Pradip Shah (Mirantis)&lt;/p>
&lt;p>&lt;strong>译者:&lt;/strong> Xin Li (DaoCloud)&lt;/p>
&lt;!--
With the release of Kubernetes 1.30, the feature to prevent the modification of the volume mode
of a [PersistentVolumeClaim](/docs/concepts/storage/persistent-volumes/) that was created from
an existing VolumeSnapshot in a Kubernetes cluster, has moved to GA!
-->
&lt;p>随着 Kubernetes 1.30 的发布，防止修改从 Kubernetes 集群中现有
VolumeSnapshot 创建的 &lt;a href="https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/">PersistentVolumeClaim&lt;/a>
的卷模式的特性已被升级至 GA！&lt;/p>
&lt;!--
## The problem
The [Volume Mode](/docs/concepts/storage/persistent-volumes/#volume-mode) of a PersistentVolumeClaim
refers to whether the underlying volume on the storage device is formatted into a filesystem or
presented as a raw block device to the Pod that uses it.
Users can leverage the VolumeSnapshot feature, which has been stable since Kubernetes v1.20,
to create a PersistentVolumeClaim (shortened as PVC) from an existing VolumeSnapshot in
the Kubernetes cluster. The PVC spec includes a dataSource field, which can point to an
existing VolumeSnapshot instance.
Visit [Create a PersistentVolumeClaim from a Volume Snapshot](/docs/concepts/storage/persistent-volumes/#create-persistent-volume-claim-from-volume-snapshot)
for more details on how to create a PVC from an existing VolumeSnapshot in a Kubernetes cluster.
-->
&lt;h2 id="问题">问题&lt;/h2>
&lt;p>PersistentVolumeClaim 的&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/#volume-mode">卷模式&lt;/a>
是指存储设备上的底层卷是被格式化为某文件系统还是作为原始块设备呈现给使用它的 Pod。&lt;/p>
&lt;p>用户可以利用自 Kubernetes v1.20 以来一直稳定的 VolumeSnapshot 特性，基于
Kubernetes 集群中现有的 VolumeSnapshot 创建 PersistentVolumeClaim（简称 PVC）。
PVC 规约中包括一个 &lt;code>dataSource&lt;/code> 字段，它可以指向现有的 VolumeSnapshot 实例。
有关如何基于 Kubernetes 集群中现有 VolumeSnapshot 创建 PVC 的更多详细信息，
请访问&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/#create-persistent-volume-claim-from-volume-snapshot">使用卷快照创建 PersistentVolumeClaim&lt;/a>。&lt;/p>
&lt;!--
When leveraging the above capability, there is no logic that validates whether the mode of the
original volume, whose snapshot was taken, matches the mode of the newly created volume.
This presents a security gap that allows malicious users to potentially exploit an
as-yet-unknown vulnerability in the host operating system.
There is a valid use case to allow some users to perform such conversions. Typically, storage backup
vendors convert the volume mode during the course of a backup operation, to retrieve changed blocks
for greater efficiency of operations. This prevents Kubernetes from blocking the operation completely
and presents a challenge in distinguishing trusted users from malicious ones.
-->
&lt;p>当利用上述特性时，没有逻辑来验证制作快照的原始卷的模式是否与新创建的卷的模式匹配。&lt;/p>
&lt;p>这带来了一个安全漏洞，允许恶意用户潜在地利用主机操作系统中未知的漏洞。&lt;/p>
&lt;p>有一个合法的场景允许某些用户执行此类转换。
通常，存储备份供应商会在备份操作过程中转换卷模式，通过检索已被更改的块来提高操作效率。
这使得 Kubernetes 无法完全阻止此类操作，但给区分可信用户和恶意用户带来了挑战。&lt;/p>
&lt;!--
## Preventing unauthorized users from converting the volume mode
In this context, an authorized user is one who has access rights to perform **update**
or **patch** operations on VolumeSnapshotContents, which is a cluster-level resource.
It is up to the cluster administrator to provide these rights only to trusted users
or applications, like backup vendors.
Users apart from such authorized ones will never be allowed to modify the volume mode
of a PVC when it is being created from a VolumeSnapshot.
-->
&lt;h2 id="防止未经授权的用户转换卷模式">防止未经授权的用户转换卷模式&lt;/h2>
&lt;p>在此上下文中，授权用户是有权对 VolumeSnapshotContents（集群级资源）执行
&lt;strong>update&lt;/strong> 或 &lt;strong>patch&lt;/strong> 操作的用户。
集群管理员应仅向受信任的用户或应用程序（例如备份供应商）赋予这些权限。
当从 VolumeSnapshot 创建 PVC 时，除了此类授权用户之外的用户将永远不会被允许修改 PVC 的卷模式。&lt;/p>
&lt;!--
To convert the volume mode, an authorized user must do the following:
1. Identify the VolumeSnapshot that is to be used as the data source for a newly
created PVC in the given namespace.
2. Identify the VolumeSnapshotContent bound to the above VolumeSnapshot.
-->
&lt;p>要转换卷模式，授权用户必须执行以下操作：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>标识要用作给定命名空间中新创建的 PVC 的数据源的 VolumeSnapshot。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>识别与上述 VolumeSnapshot 绑定的 VolumeSnapshotContent。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>kubectl describe volumesnapshot -n &amp;lt;namespace&amp;gt; &amp;lt;name&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ol>
&lt;!--
3. Add the annotation [`snapshot.storage.kubernetes.io/allow-volume-mode-change: "true"`](/docs/reference/labels-annotations-taints/#snapshot-storage-kubernetes-io-allowvolumemodechange)
to the above VolumeSnapshotContent. The VolumeSnapshotContent annotations must include one similar to the following manifest fragment:
-->
&lt;ol start="3">
&lt;li>
&lt;p>在 VolumeSnapshotContent 上添加 &lt;a href="https://kubernetes.io/zh-cn/docs/reference/labels-annotations-taints/#snapshot-storage-kubernetes-io-allowvolumemodechange">&lt;code>snapshot.storage.kubernetes.io/allow-volume-mode-change: &amp;quot;true&amp;quot;&lt;/code>&lt;/a>
注解，VolumeSnapshotContent 注解必须包含类似于以下清单片段：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>VolumeSnapshotContent&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">annotations&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">snapshot.storage.kubernetes.io/allow-volume-mode-change&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;true&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#00f;font-weight:bold">...&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ol>
&lt;!--
**Note**: For pre-provisioned VolumeSnapshotContents, you must take an extra
step of setting `spec.sourceVolumeMode` field to either `Filesystem` or `Block`,
depending on the mode of the volume from which this snapshot was taken.
An example is shown below:
-->
&lt;p>&lt;strong>注意&lt;/strong>：对于预配置的 VolumeSnapshotContents，你必须执行额外的步骤，将
&lt;code>spec.sourceVolumeMode&lt;/code> 字段设置为 &lt;code>Filesystem&lt;/code> 或 &lt;code>Block&lt;/code>，
具体取决于用来制作此快照的卷的模式。&lt;/p>
&lt;p>一个例子如下所示：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>snapshot.storage.k8s.io/v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>VolumeSnapshotContent&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">annotations&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">snapshot.storage.kubernetes.io/allow-volume-mode-change&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;true&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&amp;lt;volume-snapshot-content-name&amp;gt;&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">deletionPolicy&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Delete&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">driver&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>hostpath.csi.k8s.io&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">source&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">snapshotHandle&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&amp;lt;snapshot-handle&amp;gt;&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">sourceVolumeMode&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Filesystem&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">volumeSnapshotRef&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&amp;lt;volume-snapshot-name&amp;gt;&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">namespace&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&amp;lt;namespace&amp;gt;&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
Repeat steps 1 to 3 for all VolumeSnapshotContents whose volume mode needs to be
converted during a backup or restore operation. This can be done either via software
with credentials of an authorized user or manually by the authorized user(s).
If the annotation shown above is present on a VolumeSnapshotContent object,
Kubernetes will not prevent the volume mode from being converted.
Users should keep this in mind before they attempt to add the annotation
to any VolumeSnapshotContent.
-->
&lt;p>对备份或恢复操作期间需要转换卷模式的所有 VolumeSnapshotContent 重复步骤 1 至 3。
这可以通过具有授权用户凭据的软件来完成，也可以由授权用户手动完成。&lt;/p>
&lt;p>如果 VolumeSnapshotContent 对象上存在上面显示的注解，Kubernetes 将不会阻止卷模式转换。
用户在尝试将注解添加到任何 VolumeSnapshotContent 之前应记住这一点。&lt;/p>
&lt;!--
## Action required
The `prevent-volume-mode-conversion` feature flag is enabled by default in the
external-provisioner `v4.0.0` and external-snapshotter `v7.0.0`. Volume mode change
will be rejected when creating a PVC from a VolumeSnapshot unless the steps
described above have been performed.
-->
&lt;h2 id="需要采取的行动">需要采取的行动&lt;/h2>
&lt;p>默认情况下，在 external-provisioner &lt;code>v4.0.0&lt;/code> 和 external-snapshotter &lt;code>v7.0.0&lt;/code>
中启用 &lt;code>prevent-volume-mode-conversion&lt;/code> 特性标志。
基于 VolumeSnapshot 来创建 PVC 时，卷模式更改将被拒绝，除非已执行上述步骤。&lt;/p>
&lt;!--
## What's next
To determine which CSI external sidecar versions support this feature, please head
over to the [CSI docs page](https://kubernetes-csi.github.io/docs/).
For any queries or issues, join [Kubernetes on Slack](https://slack.k8s.io/) and
create a thread in the #csi or #sig-storage channel. Alternately, create an issue in the
CSI external-snapshotter [repository](https://github.com/kubernetes-csi/external-snapshotter).
-->
&lt;h2 id="接下来">接下来&lt;/h2>
&lt;p>要确定哪些 CSI 外部 sidecar 版本支持此功能，请前往 &lt;a href="https://kubernetes-csi.github.io/docs/">CSI 文档页面&lt;/a>。
对于任何疑问或问题，请加入 &lt;a href="https://slack.k8s.io/">Slack 上的 Kubernetes&lt;/a> 并在 #csi 或 #sig-storage 频道中发起讨论。
或者，在 CSI 外部快照&lt;a href="https://github.com/kubernetes-csi/external-snapshotter">仓库&lt;/a>中登记问题。&lt;/p></description></item><item><title>Kubernetes 1.30：结构化身份认证配置进阶至 Beta</title><link>https://kubernetes.io/zh-cn/blog/2024/04/25/structured-authentication-moves-to-beta/</link><pubDate>Thu, 25 Apr 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/04/25/structured-authentication-moves-to-beta/</guid><description>
&lt;!--
layout: blog
title: "Kubernetes 1.30: Structured Authentication Configuration Moves to Beta"
date: 2024-04-25
slug: structured-authentication-moves-to-beta
author: >
[Anish Ramasekar](https://github.com/aramase) (Microsoft)
-->
&lt;!--
With Kubernetes 1.30, we (SIG Auth) are moving Structured Authentication Configuration to beta.
Today's article is about _authentication_: finding out who's performing a task, and checking
that they are who they say they are. Check back in tomorrow to find about what's new in
Kubernetes v1.30 around _authorization_ (deciding what someone can and can't access).
-->
&lt;p>在 Kubernetes 1.30 中，我们（SIG Auth）将结构化身份认证配置（Structured Authentication Configuration）进阶至 Beta。&lt;/p>
&lt;p>今天的文章是关于&lt;strong>身份认证&lt;/strong>：找出谁在执行任务，核查他们是否是自己所说的那个人。
本文还述及 Kubernetes v1.30 中关于 &lt;strong>鉴权&lt;/strong>（决定某些人能访问什么，不能访问什么）的新内容。&lt;/p>
&lt;!--
## Motivation
Kubernetes has had a long-standing need for a more flexible and extensible
authentication system. The current system, while powerful, has some limitations
that make it difficult to use in certain scenarios. For example, it is not
possible to use multiple authenticators of the same type (e.g., multiple JWT
authenticators) or to change the configuration without restarting the API server. The
Structured Authentication Configuration feature is the first step towards
addressing these limitations and providing a more flexible and extensible way
to configure authentication in Kubernetes.
-->
&lt;h2 id="motivation">动机 &lt;/h2>
&lt;p>Kubernetes 长期以来都需要一个更灵活、更好扩展的身份认证系统。
当前的系统虽然强大，但有一些限制，使其难以用在某些场景下。
例如，不可能同时使用多个相同类型的认证组件（例如，多个 JWT 认证组件），
也不可能在不重启 API 服务器的情况下更改身份认证配置。
结构化身份认证配置特性是解决这些限制并提供一种更灵活、更好扩展的方式来配置 Kubernetes 中身份认证的第一步。&lt;/p>
&lt;!--
## What is structured authentication configuration?
Kubernetes v1.30 builds on the experimental support for configurating authentication based on
a file, that was added as alpha in Kubernetes v1.30. At this beta stage, Kubernetes only supports configuring JWT
authenticators, which serve as the next iteration of the existing OIDC
authenticator. JWT authenticator is an authenticator to
authenticate Kubernetes users using JWT compliant tokens. The authenticator
will attempt to parse a raw ID token, verify it's been signed by the configured
issuer.
-->
&lt;h2 id="what-is-structured-authentication-configuration">什么是结构化身份认证配置？ &lt;/h2>
&lt;p>Kubernetes v1.30 针对基于文件来配置身份认证提供实验性支持，这是在 Kubernetes v1.30 中新增的 Alpha 特性。
在此 Beta 阶段，Kubernetes 仅支持配置 JWT 认证组件，这是现有 OIDC 认证组件的下一次迭代。
JWT 认证组件使用符合 JWT 标准的令牌对 Kubernetes 用户进行身份认证。
此认证组件将尝试解析原始 ID 令牌，验证其是否由配置的签发方签名。&lt;/p>
&lt;!--
The Kubernetes project added configuration from a file so that it can provide more
flexibility than using command line options (which continue to work, and are still supported).
Supporting a configuration file also makes it easy to deliver further improvements in upcoming
releases.
-->
&lt;p>Kubernetes 项目新增了基于文件的配置，以便提供比使用命令行选项（命令行依然有效，仍受支持）更灵活的方式。
对配置文件的支持还使得在即将发布的版本中更容易提供更多改进措施。&lt;/p>
&lt;!--
### Benefits of structured authentication configuration
Here's why using a configuration file to configure cluster authentication is a benefit:
-->
&lt;h3 id="benefits-of-structured-authentication-configuration">结构化身份认证配置的好处 &lt;/h3>
&lt;p>以下是使用配置文件来配置集群身份认证的好处：&lt;/p>
&lt;!--
1. **Multiple JWT authenticators**: You can configure multiple JWT authenticators
simultaneously. This allows you to use multiple identity providers (e.g.,
Okta, Keycloak, GitLab) without needing to use an intermediary like Dex
that handles multiplexing between multiple identity providers.
2. **Dynamic configuration**: You can change the configuration without
restarting the API server. This allows you to add, remove, or modify
authenticators without disrupting the API server.
-->
&lt;ol>
&lt;li>&lt;strong>多个 JWT 认证组件&lt;/strong>：你可以同时配置多个 JWT 认证组件。
这允许你使用多个身份提供程序（例如 Okta、Keycloak、GitLab）而无需使用像
Dex 这样的中间程序来处理多个身份提供程序之间的多路复用。&lt;/li>
&lt;li>&lt;strong>动态配置&lt;/strong>：你可以在不重启 API 服务器的情况下更改配置。
这允许你添加、移除或修改认证组件而不会中断 API 服务器。&lt;/li>
&lt;/ol>
&lt;!--
3. **Any JWT-compliant token**: You can use any JWT-compliant token for
authentication. This allows you to use tokens from any identity provider that
supports JWT. The minimum valid JWT payload must contain the claims documented
in [structured authentication configuration](/docs/reference/access-authn-authz/authentication/#using-authentication-configuration)
page in the Kubernetes documentation.
4. **CEL (Common Expression Language) support**: You can use [CEL](/docs/reference/using-api/cel/)
to determine whether the token's claims match the user's attributes in Kubernetes (e.g.,
username, group). This allows you to use complex logic to determine whether a
token is valid.
-->
&lt;ol start="3">
&lt;li>&lt;strong>任何符合 JWT 标准的令牌&lt;/strong>：你可以使用任何符合 JWT 标准的令牌进行身份认证。
这允许你使用任何支持 JWT 的身份提供程序的令牌。最小有效的 JWT 载荷必须包含 Kubernetes
文档中&lt;a href="https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/authentication/#using-authentication-configuration">结构化身份认证配置&lt;/a>页面中记录的申领。&lt;/li>
&lt;li>&lt;strong>CEL（通用表达式语言）支持&lt;/strong>：你可以使用 &lt;a href="https://kubernetes.io/zh-cn/docs/reference/using-api/cel/">CEL&lt;/a>
来确定令牌的申领是否与 Kubernetes 中用户的属性（例如用户名、组）匹配。
这允许你使用复杂逻辑来确定令牌是否有效。&lt;/li>
&lt;/ol>
&lt;!--
5. **Multiple audiences**: You can configure multiple audiences for a single
authenticator. This allows you to use the same authenticator for multiple
audiences, such as using a different OAuth client for `kubectl` and dashboard.
6. **Using identity providers that don't support OpenID connect discovery**: You
can use identity providers that don't support [OpenID Connect
discovery](https://openid.net/specs/openid-connect-discovery-1_0.html). The only
requirement is to host the discovery document at a different location than the
issuer (such as locally in the cluster) and specify the `issuer.discoveryURL` in
the configuration file.
-->
&lt;ol start="5">
&lt;li>&lt;strong>多个受众群体&lt;/strong>：你可以为单个认证组件配置多个受众群体。
这允许你为多个受众群体使用相同的认证组件，例如为 &lt;code>kubectl&lt;/code> 和仪表板使用不同的 OAuth 客户端。&lt;/li>
&lt;li>&lt;strong>使用不支持 OpenID 连接发现的身份提供程序&lt;/strong>：你可以使用不支持
&lt;a href="https://openid.net/specs/openid-connect-discovery-1_0.html">OpenID 连接发现&lt;/a> 的身份提供程序。
唯一的要求是将发现文档托管到与签发方不同的位置（例如在集群中本地），并在配置文件中指定 &lt;code>issuer.discoveryURL&lt;/code>。&lt;/li>
&lt;/ol>
&lt;!--
## How to use Structured Authentication Configuration
To use structured authentication configuration, you specify
the path to the authentication configuration using the `--authentication-config`
command line argument in the API server. The configuration file is a YAML file
that specifies the authenticators and their configuration. Here is an example
configuration file that configures two JWT authenticators:
-->
&lt;h2 id="how-to-use-structured-authentication-configuration">如何使用结构化身份认证配置 &lt;/h2>
&lt;p>要使用结构化身份认证配置，你可以使用 &lt;code>--authentication-config&lt;/code> 命令行参数在
API 服务器中指定身份认证配置的路径。此配置文件是一个 YAML 文件，指定认证组件及其配置。
以下是一个配置两个 JWT 认证组件的示例配置文件：&lt;/p>
&lt;!--
# Someone with a valid token from either of these issuers could authenticate
# against this cluster.
# second authenticator that exposes the discovery document at a different location
# than the issuer
-->
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>apiserver.config.k8s.io/v1beta1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>AuthenticationConfiguration&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#080;font-style:italic"># 如果某人具有这些 issuer 之一签发的有效令牌，则此人可以在集群上进行身份认证&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">jwt&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>- &lt;span style="color:#008000;font-weight:bold">issuer&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">url&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>https://issuer1.example.com&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">audiences&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- audience1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- audience2&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">audienceMatchPolicy&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>MatchAny&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">claimValidationRules&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;claims.hd == &amp;#34;example.com&amp;#34;&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">message&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;the hosted domain name must be example.com&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">claimMappings&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">username&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;claims.username&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">groups&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;claims.groups&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">uid&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;claims.uid&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">extra&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">key&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;example.com/tenant&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;claims.tenant&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">userValidationRules&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;!user.username.startsWith(&amp;#39;system:&amp;#39;)&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">message&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;username cannot use reserved system: prefix&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#080;font-style:italic"># 第二个认证组件将发现文档公布于与签发方不同的位置&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>- &lt;span style="color:#008000;font-weight:bold">issuer&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">url&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>https://issuer2.example.com&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">discoveryURL&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>https://discovery.example.com/.well-known/openid-configuration&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">audiences&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- audience3&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- audience4&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">audienceMatchPolicy&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>MatchAny&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">claimValidationRules&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;claims.hd == &amp;#34;example.com&amp;#34;&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">message&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;the hosted domain name must be example.com&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">claimMappings&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">username&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;claims.username&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">groups&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;claims.groups&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">uid&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;claims.uid&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">extra&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">key&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;example.com/tenant&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;claims.tenant&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">userValidationRules&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;!user.username.startsWith(&amp;#39;system:&amp;#39;)&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">message&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;username cannot use reserved system: prefix&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
## Migration from command line arguments to configuration file
The Structured Authentication Configuration feature is designed to be
backwards-compatible with the existing approach, based on command line options, for
configuring the JWT authenticator. This means that you can continue to use the existing
command-line options to configure the JWT authenticator. However, we (Kubernetes SIG Auth)
recommend migrating to the new configuration file-based approach, as it provides more
flexibility and extensibility.
-->
&lt;h2 id="migration-from-command-line-arguments-to-configuration-file">从命令行参数迁移到配置文件 &lt;/h2>
&lt;p>结构化身份认证配置特性旨在与基于命令行选项配置 JWT 认证组件的现有方法向后兼容。
这意味着你可以继续使用现有的命令行选项来配置 JWT 认证组件。
但是，我们（Kubernetes SIG Auth）建议迁移到新的基于配置文件的方法，因为这种方法更灵活，更好扩展。&lt;/p>
&lt;div class="alert alert-primary" role="alert">
&lt;h4 class="alert-heading">Note&lt;/h4>
&lt;!--
If you specify `--authentication-config` along with any of the `--oidc-*` command line arguments, this is
a misconfiguration. In this situation, the API server reports an error and then immediately exits.
If you want to switch to using structured authentication configuration, you have to remove the `--oidc-*`
command line arguments, and use the configuration file instead.
-->
&lt;p>如果你同时指定 &lt;code>--authentication-config&lt;/code> 和任何 &lt;code>--oidc-*&lt;/code> 命令行参数，这是一种错误的配置。
在这种情况下，API 服务器会报告错误，然后立即退出。&lt;/p>
&lt;p>如果你想切换到使用结构化身份认证配置，你必须移除 &lt;code>--oidc-*&lt;/code> 命令行参数，并改为使用配置文件。&lt;/p>
&lt;/div>
&lt;!--
Here is an example of how to migrate from the command-line flags to the
configuration file:
### Command-line arguments
-->
&lt;p>以下是如何从命令行标志迁移到配置文件的示例：&lt;/p>
&lt;h3 id="command-line-arguments">命令行参数 &lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>--oidc-issuer-url&lt;span style="color:#666">=&lt;/span>https://issuer.example.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>--oidc-client-id&lt;span style="color:#666">=&lt;/span>example-client-id
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>--oidc-username-claim&lt;span style="color:#666">=&lt;/span>username
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>--oidc-groups-claim&lt;span style="color:#666">=&lt;/span>groups
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>--oidc-username-prefix&lt;span style="color:#666">=&lt;/span>oidc:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>--oidc-groups-prefix&lt;span style="color:#666">=&lt;/span>oidc:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>--oidc-required-claim&lt;span style="color:#666">=&lt;/span>&lt;span style="color:#b44">&amp;#34;hd=example.com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>--oidc-required-claim&lt;span style="color:#666">=&lt;/span>&lt;span style="color:#b44">&amp;#34;admin=true&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>--oidc-ca-file&lt;span style="color:#666">=&lt;/span>/path/to/ca.pem
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
There is no equivalent in the configuration file for the `--oidc-signing-algs`.
For Kubernetes v1.30, the authenticator supports all the asymmetric algorithms listed in
[`oidc.go`](https://github.com/kubernetes/kubernetes/blob/b4935d910dcf256288694391ef675acfbdb8e7a3/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc.go#L222-L233).
### Configuration file
-->
&lt;p>在配置文件中没有与 &lt;code>--oidc-signing-algs&lt;/code> 相对应的配置项。
对于 Kubernetes v1.30，认证组件支持在
&lt;a href="https://github.com/kubernetes/kubernetes/blob/b4935d910dcf256288694391ef675acfbdb8e7a3/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc.go#L222-L233">&lt;code>oidc.go&lt;/code>&lt;/a>
中列出的所有非对称算法。&lt;/p>
&lt;h3 id="configuration-file">配置文件 &lt;/h3>
&lt;!--
certificateAuthority: &lt;value is the content of file /path/to/ca.pem>
-->
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>apiserver.config.k8s.io/v1beta1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>AuthenticationConfiguration&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">jwt&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>- &lt;span style="color:#008000;font-weight:bold">issuer&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">url&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>https://issuer.example.com&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">audiences&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- example-client-id&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">certificateAuthority&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&amp;lt;取值是 /path/to/ca.pem 文件的内容&amp;gt;&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">claimMappings&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">username&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">claim&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>username&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">prefix&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;oidc:&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">groups&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">claim&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>groups&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">prefix&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;oidc:&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">claimValidationRules&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">claim&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>hd&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">requiredValue&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;example.com&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">claim&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>admin&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">requiredValue&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;true&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
## What's next?
For Kubernetes v1.31, we expect the feature to stay in beta while we get more
feedback. In the coming releases, we want to investigate:
- Making distributed claims work via CEL expressions.
- Egress selector configuration support for calls to `issuer.url` and
`issuer.discoveryURL`.
-->
&lt;h2 id="whats-next">下一步是什么？ &lt;/h2>
&lt;p>对于 Kubernetes v1.31，我们预计该特性将保持在 Beta，我们要收集更多反馈意见。
在即将发布的版本中，我们希望调查以下内容：&lt;/p>
&lt;ul>
&lt;li>通过 CEL 表达式使分布式申领生效。&lt;/li>
&lt;li>对 &lt;code>issuer.url&lt;/code> 和 &lt;code>issuer.discoveryURL&lt;/code> 的调用提供 Egress 选择算符配置支持。&lt;/li>
&lt;/ul>
&lt;!--
You can learn more about this feature on the [structured authentication
configuration](/docs/reference/access-authn-authz/authentication/#using-authentication-configuration)
page in the Kubernetes documentation. You can also follow along on the
[KEP-3331](https://kep.k8s.io/3331) to track progress across the coming
Kubernetes releases.
-->
&lt;p>你可以在 Kubernetes
文档的&lt;a href="https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/authentication/#using-authentication-configuration">结构化身份认证配置&lt;/a>页面上了解关于此特性的更多信息。
你还可以通过 &lt;a href="https://kep.k8s.io/3331">KEP-3331&lt;/a> 跟踪未来 Kubernetes 版本中的进展。&lt;/p>
&lt;!--
## Try it out
In this post, I have covered the benefits the Structured Authentication
Configuration feature brings in Kubernetes v1.30. To use this feature, you must specify the path to the
authentication configuration using the `--authentication-config` command line
argument. From Kubernetes v1.30, the feature is in beta and enabled by default.
If you want to keep using command line arguments instead of a configuration file,
those will continue to work as-is.
-->
&lt;h2 id="try-it-out">试用一下 &lt;/h2>
&lt;p>在本文中，我介绍了结构化身份认证配置特性在 Kubernetes v1.30 中带来的好处。
要使用此特性，你必须使用 &lt;code>--authentication-config&lt;/code> 命令行参数指定身份认证配置的路径。
从 Kubernetes v1.30 开始，此特性处于 Beta 并默认启用。
如果你希望继续使用命令行参数而不想用配置文件，原来的命令行参数也将继续按原样起作用。&lt;/p>
&lt;!--
We would love to hear your feedback on this feature. Please reach out to us on the
[#sig-auth-authenticators-dev](https://kubernetes.slack.com/archives/C04UMAUC4UA)
channel on Kubernetes Slack (for an invitation, visit [https://slack.k8s.io/](https://slack.k8s.io/)).
-->
&lt;p>我们很高兴听取你对此特性的反馈意见。请在 Kubernetes Slack 上的
&lt;a href="https://kubernetes.slack.com/archives/C04UMAUC4UA">#sig-auth-authenticators-dev&lt;/a>
频道与我们联系（若要获取邀请，请访问 &lt;a href="https://slack.k8s.io/">https://slack.k8s.io/&lt;/a>）。&lt;/p>
&lt;!--
## How to get involved
If you are interested in getting involved in the development of this feature,
share feedback, or participate in any other ongoing SIG Auth projects, please
reach out on the [#sig-auth](https://kubernetes.slack.com/archives/C0EN96KUY)
channel on Kubernetes Slack.
-->
&lt;h2 id="how-to-get-involved">如何参与 &lt;/h2>
&lt;p>如果你有兴趣参与此特性的开发、分享反馈意见或参与任何其他 SIG Auth 项目，
请在 Kubernetes Slack 上的 &lt;a href="https://kubernetes.slack.com/archives/C0EN96KUY">#sig-auth&lt;/a> 频道联系我们。&lt;/p>
&lt;!--
You are also welcome to join the bi-weekly [SIG Auth
meetings](https://github.com/kubernetes/community/blob/master/sig-auth/README.md#meetings)
held every-other Wednesday.
-->
&lt;p>我们也欢迎你参加 &lt;a href="https://github.com/kubernetes/community/blob/master/sig-auth/README.md#meetings">SIG Auth 双周会议&lt;/a>。&lt;/p></description></item><item><title>Kubernetes 1.30：验证准入策略 ValidatingAdmissionPolicy 正式发布</title><link>https://kubernetes.io/zh-cn/blog/2024/04/24/validating-admission-policy-ga/</link><pubDate>Wed, 24 Apr 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/04/24/validating-admission-policy-ga/</guid><description>
&lt;!--
layout: blog
title: "Kubernetes 1.30: Validating Admission Policy Is Generally Available"
slug: validating-admission-policy-ga
date: 2024-04-24
author: >
Jiahui Feng (Google)
-->
&lt;!--
On behalf of the Kubernetes project, I am excited to announce that ValidatingAdmissionPolicy has reached
**general availability**
as part of Kubernetes 1.30 release. If you have not yet read about this new declarative alternative to
validating admission webhooks, it may be interesting to read our
[previous post](/blog/2022/12/20/validating-admission-policies-alpha/) about the new feature.
If you have already heard about ValidatingAdmissionPolicies and you are eager to try them out,
there is no better time to do it than now.
Let's have a taste of a ValidatingAdmissionPolicy, by replacing a simple webhook.
-->
&lt;p>我代表 Kubernetes 项目组成员，很高兴地宣布 ValidatingAdmissionPolicy 已经作为 Kubernetes 1.30 发布的一部分&lt;strong>正式发布&lt;/strong>。
如果你还不了解这个全新的声明式验证准入 Webhook 的替代方案，
请参阅有关这个新特性的&lt;a href="https://kubernetes.io/blog/2022/12/20/validating-admission-policies-alpha/">上一篇博文&lt;/a>。
如果你已经对 ValidatingAdmissionPolicy 有所了解并且想要尝试一下，那么现在是最好的时机。&lt;/p>
&lt;p>让我们替换一个简单的 Webhook，体验一下 ValidatingAdmissionPolicy。&lt;/p>
&lt;!--
## Example admission webhook
First, let's take a look at an example of a simple webhook. Here is an excerpt from a webhook that
enforces `runAsNonRoot`, `readOnlyRootFilesystem`, `allowPrivilegeEscalation`, and `privileged` to be set to the least permissive values.
-->
&lt;h2 id="准入-webhook-示例">准入 Webhook 示例&lt;/h2>
&lt;p>首先，让我们看一个简单 Webhook 的示例。以下是一个强制将
&lt;code>runAsNonRoot&lt;/code>、&lt;code>readOnlyRootFilesystem&lt;/code>、&lt;code>allowPrivilegeEscalation&lt;/code> 和 &lt;code>privileged&lt;/code> 设置为最低权限值的 Webhook 代码片段。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a2f;font-weight:bold">func&lt;/span> &lt;span style="color:#00a000">verifyDeployment&lt;/span>(deploy &lt;span style="color:#666">*&lt;/span>appsv1.Deployment) &lt;span style="color:#0b0;font-weight:bold">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a2f;font-weight:bold">var&lt;/span> errs []&lt;span style="color:#0b0;font-weight:bold">error&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a2f;font-weight:bold">for&lt;/span> i, c &lt;span style="color:#666">:=&lt;/span> &lt;span style="color:#a2f;font-weight:bold">range&lt;/span> deploy.Spec.Template.Spec.Containers {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a2f;font-weight:bold">if&lt;/span> c.Name &lt;span style="color:#666">==&lt;/span> &lt;span style="color:#b44">&amp;#34;&amp;#34;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a2f;font-weight:bold">return&lt;/span> fmt.&lt;span style="color:#00a000">Errorf&lt;/span>(&lt;span style="color:#b44">&amp;#34;container %d has no name&amp;#34;&lt;/span>, i)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a2f;font-weight:bold">if&lt;/span> c.SecurityContext &lt;span style="color:#666">==&lt;/span> &lt;span style="color:#a2f;font-weight:bold">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> errs = &lt;span style="color:#a2f">append&lt;/span>(errs, fmt.&lt;span style="color:#00a000">Errorf&lt;/span>(&lt;span style="color:#b44">&amp;#34;container %q does not have SecurityContext&amp;#34;&lt;/span>, c.Name))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a2f;font-weight:bold">if&lt;/span> c.SecurityContext.RunAsNonRoot &lt;span style="color:#666">==&lt;/span> &lt;span style="color:#a2f;font-weight:bold">nil&lt;/span> &lt;span style="color:#666">||&lt;/span> !&lt;span style="color:#666">*&lt;/span>c.SecurityContext.RunAsNonRoot {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> errs = &lt;span style="color:#a2f">append&lt;/span>(errs, fmt.&lt;span style="color:#00a000">Errorf&lt;/span>(&lt;span style="color:#b44">&amp;#34;container %q must set RunAsNonRoot to true in its SecurityContext&amp;#34;&lt;/span>, c.Name))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a2f;font-weight:bold">if&lt;/span> c.SecurityContext.ReadOnlyRootFilesystem &lt;span style="color:#666">==&lt;/span> &lt;span style="color:#a2f;font-weight:bold">nil&lt;/span> &lt;span style="color:#666">||&lt;/span> !&lt;span style="color:#666">*&lt;/span>c.SecurityContext.ReadOnlyRootFilesystem {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> errs = &lt;span style="color:#a2f">append&lt;/span>(errs, fmt.&lt;span style="color:#00a000">Errorf&lt;/span>(&lt;span style="color:#b44">&amp;#34;container %q must set ReadOnlyRootFilesystem to true in its SecurityContext&amp;#34;&lt;/span>, c.Name))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a2f;font-weight:bold">if&lt;/span> c.SecurityContext.AllowPrivilegeEscalation &lt;span style="color:#666">!=&lt;/span> &lt;span style="color:#a2f;font-weight:bold">nil&lt;/span> &lt;span style="color:#666">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#666">*&lt;/span>c.SecurityContext.AllowPrivilegeEscalation {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> errs = &lt;span style="color:#a2f">append&lt;/span>(errs, fmt.&lt;span style="color:#00a000">Errorf&lt;/span>(&lt;span style="color:#b44">&amp;#34;container %q must NOT set AllowPrivilegeEscalation to true in its SecurityContext&amp;#34;&lt;/span>, c.Name))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a2f;font-weight:bold">if&lt;/span> c.SecurityContext.Privileged &lt;span style="color:#666">!=&lt;/span> &lt;span style="color:#a2f;font-weight:bold">nil&lt;/span> &lt;span style="color:#666">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#666">*&lt;/span>c.SecurityContext.Privileged {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> errs = &lt;span style="color:#a2f">append&lt;/span>(errs, fmt.&lt;span style="color:#00a000">Errorf&lt;/span>(&lt;span style="color:#b44">&amp;#34;container %q must NOT set Privileged to true in its SecurityContext&amp;#34;&lt;/span>, c.Name))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a2f;font-weight:bold">return&lt;/span> errors.&lt;span style="color:#00a000">NewAggregate&lt;/span>(errs)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
Check out [What are admission webhooks?](/docs/reference/access-authn-authz/extensible-admission-controllers/#what-are-admission-webhooks)
Or, see the [full code](webhook.go) of this webhook to follow along with this walkthrough.
## The policy
Now let's try to recreate the validation faithfully with a ValidatingAdmissionPolicy.
-->
&lt;p>查阅&lt;a href="https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/extensible-admission-controllers/#what-are-admission-webhooks">什么是准入 Webhook？&lt;/a>，
或者查看这个 Webhook 的&lt;a href="webhook.go">完整代码&lt;/a>以便更好地理解下述演示。&lt;/p>
&lt;h2 id="策略">策略&lt;/h2>
&lt;p>现在，让我们尝试使用 ValidatingAdmissionPolicy 来忠实地重新创建验证。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>admissionregistration.k8s.io/v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ValidatingAdmissionPolicy&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;pod-security.policy.example.com&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">failurePolicy&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Fail&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">matchConstraints&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">resourceRules&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">apiGroups&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>[&lt;span style="color:#b44">&amp;#34;apps&amp;#34;&lt;/span>]&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">apiVersions&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>[&lt;span style="color:#b44">&amp;#34;v1&amp;#34;&lt;/span>]&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">operations&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>[&lt;span style="color:#b44">&amp;#34;CREATE&amp;#34;&lt;/span>,&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;UPDATE&amp;#34;&lt;/span>]&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">resources&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>[&lt;span style="color:#b44">&amp;#34;deployments&amp;#34;&lt;/span>]&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">validations&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>object.spec.template.spec.containers.all(c, has(c.securityContext) &amp;amp;&amp;amp; has(c.securityContext.runAsNonRoot) &amp;amp;&amp;amp; c.securityContext.runAsNonRoot)&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">message&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;all containers must set runAsNonRoot to true&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>object.spec.template.spec.containers.all(c, has(c.securityContext) &amp;amp;&amp;amp; has(c.securityContext.readOnlyRootFilesystem) &amp;amp;&amp;amp; c.securityContext.readOnlyRootFilesystem)&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">message&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;all containers must set readOnlyRootFilesystem to true&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>object.spec.template.spec.containers.all(c, !has(c.securityContext) || !has(c.securityContext.allowPrivilegeEscalation) || !c.securityContext.allowPrivilegeEscalation)&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">message&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;all containers must NOT set allowPrivilegeEscalation to true&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>object.spec.template.spec.containers.all(c, !has(c.securityContext) || !has(c.securityContext.Privileged) || !c.securityContext.Privileged)&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">message&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;all containers must NOT set privileged to true&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
Create the policy with `kubectl`. Great, no complain so far. But let's get the policy object back and take a look at its status.
-->
&lt;p>使用 &lt;code>kubectl&lt;/code> 创建策略。很好，到目前为止没有任何问题。那我们获取此策略对象并查看其状态。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>kubectl get -oyaml validatingadmissionpolicies/pod-security.policy.example.com
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">status&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">typeChecking&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">expressionWarnings&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">fieldRef&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>spec.validations[3].expression&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">warning&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>|&lt;span style="color:#b44;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44;font-style:italic"> apps/v1, Kind=Deployment: ERROR: &amp;lt;input&amp;gt;:1:76: undefined field &amp;#39;Privileged&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44;font-style:italic"> | object.spec.template.spec.containers.all(c, !has(c.securityContext) || !has(c.securityContext.Privileged) || !c.securityContext.Privileged)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44;font-style:italic"> | ...........................................................................^
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44;font-style:italic"> ERROR: &amp;lt;input&amp;gt;:1:128: undefined field &amp;#39;Privileged&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44;font-style:italic"> | object.spec.template.spec.containers.all(c, !has(c.securityContext) || !has(c.securityContext.Privileged) || !c.securityContext.Privileged)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44;font-style:italic"> | ...............................................................................................................................^&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
The policy was checked against its matched type, which is `apps/v1.Deployment`.
Looking at the `fieldRef`, the problem was with the 3rd expression (index starts with 0)
The expression in question accessed an undefined `Privileged` field.
Ahh, looks like it was a copy-and-paste error. The field name should be in lowercase.
-->
&lt;p>系统根据所匹配的类别 &lt;code>apps/v1.Deployment&lt;/code> 对策略执行了检查。
查看 &lt;code>fieldRef&lt;/code> 后，发现问题出现在第 3 个表达式上（索引从 0 开始）。
有问题的表达式访问了一个未定义的 &lt;code>Privileged&lt;/code> 字段。
噢，看起来是一个复制粘贴错误。字段名应该是小写的。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>admissionregistration.k8s.io/v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ValidatingAdmissionPolicy&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;pod-security.policy.example.com&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">failurePolicy&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Fail&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">matchConstraints&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">resourceRules&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">apiGroups&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>[&lt;span style="color:#b44">&amp;#34;apps&amp;#34;&lt;/span>]&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">apiVersions&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>[&lt;span style="color:#b44">&amp;#34;v1&amp;#34;&lt;/span>]&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">operations&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>[&lt;span style="color:#b44">&amp;#34;CREATE&amp;#34;&lt;/span>,&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;UPDATE&amp;#34;&lt;/span>]&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">resources&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>[&lt;span style="color:#b44">&amp;#34;deployments&amp;#34;&lt;/span>]&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">validations&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>object.spec.template.spec.containers.all(c, has(c.securityContext) &amp;amp;&amp;amp; has(c.securityContext.runAsNonRoot) &amp;amp;&amp;amp; c.securityContext.runAsNonRoot)&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">message&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;all containers must set runAsNonRoot to true&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>object.spec.template.spec.containers.all(c, has(c.securityContext) &amp;amp;&amp;amp; has(c.securityContext.readOnlyRootFilesystem) &amp;amp;&amp;amp; c.securityContext.readOnlyRootFilesystem)&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">message&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;all containers must set readOnlyRootFilesystem to true&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>object.spec.template.spec.containers.all(c, !has(c.securityContext) || !has(c.securityContext.allowPrivilegeEscalation) || !c.securityContext.allowPrivilegeEscalation)&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">message&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;all containers must NOT set allowPrivilegeEscalation to true&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>object.spec.template.spec.containers.all(c, !has(c.securityContext) || !has(c.securityContext.privileged) || !c.securityContext.privileged)&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">message&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;all containers must NOT set privileged to true&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
Check its status again, and you should see all warnings cleared.
Next, let's create a namespace for our tests.
-->
&lt;p>再次检查状态，你应该看到所有警告都已被清除。&lt;/p>
&lt;p>接下来，我们创建一个命名空间进行测试。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>kubectl create namespace policy-test
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
Then, I bind the policy to the namespace. But at this point, I set the action to `Warn`
so that the policy prints out [warnings](/blog/2020/09/03/warnings/) instead of rejecting the requests.
This is especially useful to collect results from all expressions during development and automated testing.
-->
&lt;p>接下来，我将策略绑定到命名空间。但此时我将动作设置为 &lt;code>Warn&lt;/code>，
这样此策略将打印出&lt;a href="https://kubernetes.io/zh-cn/blog/2020/09/03/warnings/">警告&lt;/a>而不是拒绝请求。
这对于在开发和自动化测试期间收集所有表达式的结果非常有用。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>admissionregistration.k8s.io/v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ValidatingAdmissionPolicyBinding&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;pod-security.policy-binding.example.com&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">policyName&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;pod-security.policy.example.com&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">validationActions&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>[&lt;span style="color:#b44">&amp;#34;Warn&amp;#34;&lt;/span>]&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">matchResources&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">namespaceSelector&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">matchLabels&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">&amp;#34;kubernetes.io/metadata.name&amp;#34;: &lt;/span>&lt;span style="color:#b44">&amp;#34;policy-test&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
Tests out policy enforcement.
-->
&lt;p>测试策略的执行过程。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>kubectl create -n policy-test -f- &lt;span style="color:#b44">&amp;lt;&amp;lt;EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44">apiVersion: apps/v1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44">kind: Deployment
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44">metadata:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> labels:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> app: nginx
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> name: nginx
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44">spec:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> selector:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> matchLabels:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> app: nginx
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> template:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> metadata:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> labels:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> app: nginx
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> spec:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> containers:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> - image: nginx
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> name: nginx
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> securityContext:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> privileged: true
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> allowPrivilegeEscalation: true
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>Warning: Validation failed for ValidatingAdmissionPolicy &amp;#39;pod-security.policy.example.com&amp;#39; with binding &amp;#39;pod-security.policy-binding.example.com&amp;#39;: all containers must set runAsNonRoot to true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Warning: Validation failed for ValidatingAdmissionPolicy &amp;#39;pod-security.policy.example.com&amp;#39; with binding &amp;#39;pod-security.policy-binding.example.com&amp;#39;: all containers must set readOnlyRootFilesystem to true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Warning: Validation failed for ValidatingAdmissionPolicy &amp;#39;pod-security.policy.example.com&amp;#39; with binding &amp;#39;pod-security.policy-binding.example.com&amp;#39;: all containers must NOT set allowPrivilegeEscalation to true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Warning: Validation failed for ValidatingAdmissionPolicy &amp;#39;pod-security.policy.example.com&amp;#39; with binding &amp;#39;pod-security.policy-binding.example.com&amp;#39;: all containers must NOT set privileged to true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Error from server: error when creating &amp;#34;STDIN&amp;#34;: admission webhook &amp;#34;webhook.example.com&amp;#34; denied the request: [container &amp;#34;nginx&amp;#34; must set RunAsNonRoot to true in its SecurityContext, container &amp;#34;nginx&amp;#34; must set ReadOnlyRootFilesystem to true in its SecurityContext, container &amp;#34;nginx&amp;#34; must NOT set AllowPrivilegeEscalation to true in its SecurityContext, container &amp;#34;nginx&amp;#34; must NOT set Privileged to true in its SecurityContext]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
Looks great! The policy and the webhook give equivalent results.
After a few other cases, when we are confident with our policy, maybe it is time to do some cleanup.
- For every expression, we repeat access to `object.spec.template.spec.containers` and to each `securityContext`;
- There is a pattern of checking presence of a field and then accessing it, which looks a bit verbose.
-->
&lt;p>看起来很不错！策略和 Webhook 给出了等效的结果。
又测试了其他几种情形后，当我们对策略有信心时，也许是时候进行一些清理工作了。&lt;/p>
&lt;ul>
&lt;li>对于每个表达式，我们重复访问 &lt;code>object.spec.template.spec.containers&lt;/code> 和每个 &lt;code>securityContext&lt;/code>；&lt;/li>
&lt;li>有一个检查某字段是否存在然后访问该字段的模式，这种模式看起来有点繁琐。&lt;/li>
&lt;/ul>
&lt;!--
Fortunately, since Kubernetes 1.28, we have new solutions for both issues.
Variable Composition allows us to extract repeated sub-expressions into their own variables.
Kubernetes enables [the optional library](https://github.com/google/cel-spec/wiki/proposal-246) for CEL, which are excellent to work with fields that are, you guessed it, optional.
With both features in mind, let's refactor the policy a bit.
-->
&lt;p>幸运的是，自 Kubernetes 1.28 以来，我们对这两个问题都有了新的解决方案。
变量组合（Variable Composition）允许我们将重复的子表达式提取到单独的变量中。
Kubernetes 允许为 CEL 使用&lt;a href="https://github.com/google/cel-spec/wiki/proposal-246">可选库&lt;/a>，
这些库非常适合处理可选的字段，你猜对了。&lt;/p>
&lt;p>在了解了这两个特性后，让我们稍微重构一下此策略。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>admissionregistration.k8s.io/v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ValidatingAdmissionPolicy&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;pod-security.policy.example.com&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">failurePolicy&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Fail&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">matchConstraints&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">resourceRules&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">apiGroups&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>[&lt;span style="color:#b44">&amp;#34;apps&amp;#34;&lt;/span>]&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">apiVersions&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>[&lt;span style="color:#b44">&amp;#34;v1&amp;#34;&lt;/span>]&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">operations&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>[&lt;span style="color:#b44">&amp;#34;CREATE&amp;#34;&lt;/span>,&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;UPDATE&amp;#34;&lt;/span>]&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">resources&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>[&lt;span style="color:#b44">&amp;#34;deployments&amp;#34;&lt;/span>]&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">variables&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>containers&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>object.spec.template.spec.containers&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>securityContexts&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;variables.containers.map(c, c.?securityContext)&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">validations&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>variables.securityContexts.all(c, c.?runAsNonRoot == optional.of(true))&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">message&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;all containers must set runAsNonRoot to true&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>variables.securityContexts.all(c, c.?readOnlyRootFilesystem == optional.of(true))&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">message&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;all containers must set readOnlyRootFilesystem to true&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>variables.securityContexts.all(c, c.?allowPrivilegeEscalation != optional.of(true))&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">message&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;all containers must NOT set allowPrivilegeEscalation to true&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">expression&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>variables.securityContexts.all(c, c.?privileged != optional.of(true))&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">message&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#39;all containers must NOT set privileged to true&amp;#39;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
The policy is now much cleaner and more readable. Update the policy, and you should see
it function the same as before.
Now let's change the policy binding from warning to actually denying requests that fail validation.
-->
&lt;p>策略现在更简洁、更易读。更新策略后，你应该看到它的功用与之前无异。&lt;/p>
&lt;p>现在让我们将策略绑定从警告更改为实际拒绝验证失败的请求。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>admissionregistration.k8s.io/v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>ValidatingAdmissionPolicyBinding&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;pod-security.policy-binding.example.com&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">policyName&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;pod-security.policy.example.com&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">validationActions&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>[&lt;span style="color:#b44">&amp;#34;Deny&amp;#34;&lt;/span>]&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">matchResources&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">namespaceSelector&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">matchLabels&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">&amp;#34;kubernetes.io/metadata.name&amp;#34;: &lt;/span>&lt;span style="color:#b44">&amp;#34;policy-test&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
And finally, remove the webhook. Now the result should include only messages from
the policy.
-->
&lt;p>最后，移除 Webhook。现在结果应该只包含来自策略的消息。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>kubectl create -n policy-test -f- &lt;span style="color:#b44">&amp;lt;&amp;lt;EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44">apiVersion: apps/v1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44">kind: Deployment
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44">metadata:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> labels:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> app: nginx
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> name: nginx
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44">spec:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> selector:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> matchLabels:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> app: nginx
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> template:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> metadata:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> labels:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> app: nginx
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> spec:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> containers:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> - image: nginx
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> name: nginx
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> securityContext:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> privileged: true
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44"> allowPrivilegeEscalation: true
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#b44">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>The deployments &amp;#34;nginx&amp;#34; is invalid: : ValidatingAdmissionPolicy &amp;#39;pod-security.policy.example.com&amp;#39; with binding &amp;#39;pod-security.policy-binding.example.com&amp;#39; denied request: all containers must set runAsNonRoot to true
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
Please notice that, by design, the policy will stop evaluation after the first expression that causes the request to be denied.
This is different from what happens when the expressions generate only warnings.
-->
&lt;p>请注意，根据设计，此策略在第一个导致请求被拒绝的表达式之后停止处理。
这与表达式只生成警告时的情况不同。&lt;/p>
&lt;!--
## Set up monitoring
Unlike a webhook, a policy is not a dedicated process that can expose its own metrics.
Instead, you can use metrics from the API server in their place.
Here are some examples in Prometheus Query Language of common monitoring tasks.
To find the 95th percentile execution duration of the policy shown above.
-->
&lt;h2 id="设置监控">设置监控&lt;/h2>
&lt;p>与 Webhook 不同，策略不是一个可以公开其自身指标的专用进程。
相反，你可以使用源自 API 服务器的指标来代替。&lt;/p>
&lt;p>以下是使用 Prometheus 查询语言执行一些常见监控任务的示例。&lt;/p>
&lt;p>找到上述策略执行期间的 95 分位值：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>histogram_quantile(0.95, sum(rate(apiserver_validating_admission_policy_check_duration_seconds_bucket{policy=&amp;#34;pod-security.policy.example.com&amp;#34;}[5m])) by (le))
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
To find the rate of the policy evaluation.
-->
&lt;p>找到策略评估的速率：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>rate(apiserver_validating_admission_policy_check_total{policy=&amp;#34;pod-security.policy.example.com&amp;#34;}[5m])
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
You can read [the metrics reference](/docs/reference/instrumentation/metrics/) to learn more about the metrics above.
The metrics of ValidatingAdmissionPolicy are currently in alpha,
and more and better metrics will come while the stability graduates in the future release.
-->
&lt;p>你可以阅读&lt;a href="https://kubernetes.io/docs/reference/instrumentation/metrics/">指标参考&lt;/a>了解有关上述指标的更多信息。
ValidatingAdmissionPolicy 的指标目前处于 Alpha 阶段，随着稳定性在未来版本中的提升，将会有更多和更好的指标。&lt;/p></description></item><item><title>Kubernetes 1.30：只读卷挂载终于可以真正实现只读了</title><link>https://kubernetes.io/zh-cn/blog/2024/04/23/recursive-read-only-mounts/</link><pubDate>Tue, 23 Apr 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/04/23/recursive-read-only-mounts/</guid><description>
&lt;p>&lt;strong>作者:&lt;/strong> Akihiro Suda (NTT)&lt;/p>
&lt;p>&lt;strong>译者:&lt;/strong> Xin Li (DaoCloud)&lt;/p>
&lt;!--
layout: blog
title: 'Kubernetes 1.30: Read-only volume mounts can be finally literally read-only'
date: 2024-04-23
slug: recursive-read-only-mounts
author: >
Akihiro Suda (NTT)
-->
&lt;!--
Read-only volume mounts have been a feature of Kubernetes since the beginning.
Surprisingly, read-only mounts are not completely read-only under certain conditions on Linux.
As of the v1.30 release, they can be made completely read-only,
with alpha support for _recursive read-only mounts_.
-->
&lt;p>只读卷挂载从一开始就是 Kubernetes 的一个特性。
令人惊讶的是，在 Linux 上的某些条件下，只读挂载并不是完全只读的。
从 v1.30 版本开始，这类卷挂载可以被处理为完全只读；v1.30 为&lt;strong>递归只读挂载&lt;/strong>提供 Alpha 支持。&lt;/p>
&lt;!--
## Read-only volume mounts are not really read-only by default
Volume mounts can be deceptively complicated.
You might expect that the following manifest makes everything under `/mnt` in the containers read-only:
-->
&lt;h2 id="默认情况下-只读卷装载并不是真正的只读">默认情况下，只读卷装载并不是真正的只读&lt;/h2>
&lt;p>卷挂载可能看似复杂。&lt;/p>
&lt;p>你可能期望以下清单使容器中 &lt;code>/mnt&lt;/code> 下的所有内容变为只读：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#00f;font-weight:bold">---&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Pod&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">volumes&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>mnt&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">hostPath&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">path&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>/mnt&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">containers&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">volumeMounts&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>mnt&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">mountPath&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>/mnt&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">readOnly&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#a2f;font-weight:bold">true&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
However, any sub-mounts beneath `/mnt` may still be writable!
For example, consider that `/mnt/my-nfs-server` is writeable on the host.
Inside the container, writes to `/mnt/*` will be rejected but `/mnt/my-nfs-server/*` will still be writeable.
-->
&lt;p>但是，&lt;code>/mnt&lt;/code> 下的任何子挂载可能仍然是可写的！
例如，假设 &lt;code>/mnt/my-nfs-server&lt;/code> 在主机上是可写的。
在容器内部，写入 &lt;code>/mnt/*&lt;/code> 将被拒绝，但 &lt;code>/mnt/my-nfs-server/*&lt;/code> 仍然可写。&lt;/p>
&lt;!--
## New mount option: recursiveReadOnly
Kubernetes 1.30 added a new mount option `recursiveReadOnly` so as to make submounts recursively read-only.
The option can be enabled as follows:
-->
&lt;h2 id="新的挂载选项-递归只读">新的挂载选项：递归只读&lt;/h2>
&lt;p>Kubernetes 1.30 添加了一个新的挂载选项 &lt;code>recursiveReadOnly&lt;/code>，以使子挂载递归只读。&lt;/p>
&lt;p>可以按如下方式启用该选项：&lt;/p>
&lt;!--
# Possible values are `Enabled`, `IfPossible`, and `Disabled`.
# Needs to be specified in conjunction with `readOnly: true`.
-->
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#00f;font-weight:bold">---&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Pod&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">volumes&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>mnt&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">hostPath&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">path&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>/mnt&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">containers&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">volumeMounts&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- &lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>mnt&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">mountPath&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>/mnt&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">readOnly&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#a2f;font-weight:bold">true&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex; background-color:#dfdfdf">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#080;font-style:italic"># NEW&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex; background-color:#dfdfdf">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#080;font-style:italic"># 可能的值为 `Enabled`、`IfPossible` 和 `Disabled`。&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex; background-color:#dfdfdf">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#080;font-style:italic"># 需要与 `readOnly: true` 一起指定。&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex; background-color:#dfdfdf">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">recursiveReadOnly&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>Enabled&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;!--
This is implemented by applying the `MOUNT_ATTR_RDONLY` attribute with the `AT_RECURSIVE` flag
using [`mount_setattr(2)`](https://man7.org/linux/man-pages/man2/mount_setattr.2.html) added in
Linux kernel v5.12.
For backwards compatibility, the `recursiveReadOnly` field is not a replacement for `readOnly`,
but is used _in conjunction_ with it.
To get a properly recursive read-only mount, you must set both fields.
-->
&lt;p>这是通过使用 Linux 内核 v5.12 中添加的
&lt;a href="https://man7.org/linux/man-pages/man2/mount_setattr.2.html">&lt;code>mount_setattr(2)&lt;/code>&lt;/a>
应用带有 &lt;code>AT_RECURSIVE&lt;/code> 标志的 &lt;code>MOUNT_ATTR_RDONLY&lt;/code> 属性来实现的。&lt;/p>
&lt;p>为了向后兼容，&lt;code>recursiveReadOnly&lt;/code> 字段不是 &lt;code>readOnly&lt;/code> 的替代品，而是与其结合使用。
要获得正确的递归只读挂载，你必须设置这两个字段。&lt;/p>
&lt;!--
## Feature availability {#availability}
To enable `recursiveReadOnly` mounts, the following components have to be used:
-->
&lt;h2 id="availability">特性可用性 &lt;/h2>
&lt;p>要启用 &lt;code>recursiveReadOnly&lt;/code> 挂载，必须使用以下组件：&lt;/p>
&lt;!--
* Kubernetes: v1.30 or later, with the `RecursiveReadOnlyMounts`
[feature gate](/docs/reference/command-line-tools-reference/feature-gates/) enabled.
As of v1.30, the gate is marked as alpha.
* CRI runtime:
* containerd: v2.0 or later
* OCI runtime:
* runc: v1.1 or later
* crun: v1.8.6 or later
* Linux kernel: v5.12 or later
-->
&lt;ul>
&lt;li>
&lt;p>Kubernetes：v1.30 或更新版本，并启用 &lt;code>RecursiveReadOnlyMounts&lt;/code> &lt;a href="https://kubernetes.io/zh-cn/docs/reference/command-line-tools-reference/feature-gates/">特性门控&lt;/a>。
从 v1.30 开始，此特性被标记为 Alpha。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>CRI 运行时：&lt;/p>
&lt;ul>
&lt;li>containerd：v2.0 或更新版本&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>OCI 运行时：&lt;/p>
&lt;ul>
&lt;li>runc：v1.1 或更新版本&lt;/li>
&lt;li>crun: v1.8.6 或更新版本&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>Linux 内核: v5.12 或更新版本&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!--
## What's next?
Kubernetes SIG Node hope - and expect - that the feature will be promoted to beta and eventually
general availability (GA) in future releases of Kubernetes, so that users no longer need to enable
the feature gate manually.
The default value of `recursiveReadOnly` will still remain `Disabled`, for backwards compatibility.
-->
&lt;h2 id="接下来">接下来&lt;/h2>
&lt;p>Kubernetes SIG Node 希望并期望该特性将在 Kubernetes
的未来版本中升级为 Beta 版本并最终稳定可用（GA），以便用户不再需要手动启用此特性门控。&lt;/p>
&lt;p>为了向后兼容，&lt;code>recursive ReadOnly&lt;/code> 的默认值仍将保持 &lt;code>Disabled&lt;/code>。&lt;/p>
&lt;!--
## How can I learn more?
-->
&lt;h2 id="怎样才能了解更多">怎样才能了解更多？&lt;/h2>
&lt;!-- https://github.com/kubernetes/website/pull/45159 -->
&lt;!--
Please check out the [documentation](/docs/concepts/storage/volumes/#read-only-mounts)
for the further details of `recursiveReadOnly` mounts.
-->
&lt;p>请查看&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/#read-only-mounts">文档&lt;/a>以获取
&lt;code>recursiveReadOnly&lt;/code> 挂载的更多详细信息。&lt;/p>
&lt;!--
## How to get involved?
This feature is driven by the SIG Node community. Please join us to connect with
the community and share your ideas and feedback around the above feature and
beyond. We look forward to hearing from you!
-->
&lt;h2 id="如何参与">如何参与？&lt;/h2>
&lt;p>此特性由 SIG Node 社区推动。
请加入我们，与社区建立联系，并分享你对上述特性及其他特性的想法和反馈。
我们期待你的回音！&lt;/p></description></item><item><title>Kubernetes 1.30：对 Pod 使用用户命名空间的支持进阶至 Beta</title><link>https://kubernetes.io/zh-cn/blog/2024/04/22/userns-beta/</link><pubDate>Mon, 22 Apr 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/04/22/userns-beta/</guid><description>
&lt;!--
layout: blog
title: "Kubernetes 1.30: Beta Support For Pods With User Namespaces"
date: 2024-04-22
slug: userns-beta
author: >
Rodrigo Campos Catelin (Microsoft),
Giuseppe Scrivano (Red Hat),
Sascha Grunert (Red Hat)
-->
&lt;!--
Linux provides different namespaces to isolate processes from each other. For
example, a typical Kubernetes pod runs within a network namespace to isolate the
network identity and a PID namespace to isolate the processes.
One Linux namespace that was left behind is the [user
namespace](https://man7.org/linux/man-pages/man7/user_namespaces.7.html). This
namespace allows us to isolate the user and group identifiers (UIDs and GIDs) we
use inside the container from the ones on the host.
-->
&lt;p>Linux 提供了不同的命名空间来将进程彼此隔离。
例如，一个典型的 Kubernetes Pod 运行在一个网络命名空间中可以隔离网络身份，运行在一个 PID 命名空间中可以隔离进程。&lt;/p>
&lt;p>Linux 有一个以前一直未被容器化应用所支持的命名空间是&lt;a href="https://man7.org/linux/man-pages/man7/user_namespaces.7.html">用户命名空间&lt;/a>。
这个命名空间允许我们将容器内使用的用户标识符和组标识符（UID 和 GID）与主机上的标识符隔离开来。&lt;/p>
&lt;!--
This is a powerful abstraction that allows us to run containers as "root": we
are root inside the container and can do everything root can inside the pod,
but our interactions with the host are limited to what a non-privileged user can
do. This is great for limiting the impact of a container breakout.
-->
&lt;p>这是一个强大的抽象，允许我们以 “root” 身份运行容器：
我们在容器内部有 root 权限，可以在 Pod 内执行所有 root 能做的操作，
但我们与主机的交互仅限于非特权用户可以执行的操作。这对于限制容器逃逸的影响非常有用。&lt;/p>
&lt;!--
A container breakout is when a process inside a container can break out
onto the host using some unpatched vulnerability in the container runtime or the
kernel and can access/modify files on the host or other containers. If we
run our pods with user namespaces, the privileges the container has over the
rest of the host are reduced, and the files outside the container it can access
are limited too.
-->
&lt;p>容器逃逸是指容器内的进程利用容器运行时或内核中的某些未打补丁的漏洞逃逸到主机上，
并可以访问/修改主机或其他容器上的文件。如果我们以用户命名空间运行我们的 Pod，
容器对主机其余部分的特权将减少，并且此容器可以访问的容器外的文件也将受到限制。&lt;/p>
&lt;!--
In Kubernetes v1.25, we introduced support for user namespaces only for stateless
pods. Kubernetes 1.28 lifted that restriction, and now, with Kubernetes 1.30, we
are moving to beta!
-->
&lt;p>在 Kubernetes v1.25 中，我们仅为无状态 Pod 引入了对用户命名空间的支持。
Kubernetes 1.28 取消了这一限制，目前在 Kubernetes 1.30 中，这个特性进阶到了 Beta！&lt;/p>
&lt;!--
## What is a user namespace?
Note: Linux user namespaces are a different concept from [Kubernetes
namespaces](/docs/concepts/overview/working-with-objects/namespaces/).
The former is a Linux kernel feature; the latter is a Kubernetes feature.
-->
&lt;h2 id="what-is-a-user-namespace">什么是用户命名空间？ &lt;/h2>
&lt;p>注意：Linux 用户命名空间与
&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/overview/working-with-objects/namespaces/">Kubernetes 命名空间&lt;/a>是不同的概念。
前者是一个 Linux 内核特性；后者是一个 Kubernetes 特性。&lt;/p>
&lt;!--
User namespaces are a Linux feature that isolates the UIDs and GIDs of the
containers from the ones on the host. The identifiers in the container can be
mapped to identifiers on the host in a way where the host UID/GIDs used for
different containers never overlap. Furthermore, the identifiers can be mapped
to unprivileged, non-overlapping UIDs and GIDs on the host. This brings two key
benefits:
-->
&lt;p>用户命名空间是一个 Linux 特性，它将容器的 UID 和 GID 与主机上的隔离开来。
容器中的标识符可以被映射为主机上的标识符，并且保证不同容器所使用的主机 UID/GID 不会重叠。
此外，这些标识符可以被映射到主机上没有特权的、非重叠的 UID 和 GID。这带来了两个关键好处：&lt;/p>
&lt;!--
* _Prevention of lateral movement_: As the UIDs and GIDs for different
containers are mapped to different UIDs and GIDs on the host, containers have a
harder time attacking each other, even if they escape the container boundaries.
For example, suppose container A runs with different UIDs and GIDs on the host
than container B. In that case, the operations it can do on container B's files and processes
are limited: only read/write what a file allows to others, as it will never
have permission owner or group permission (the UIDs/GIDs on the host are
guaranteed to be different for different containers).
-->
&lt;ul>
&lt;li>&lt;strong>防止横向移动&lt;/strong>：由于不同容器的 UID 和 GID 被映射到主机上的不同 UID 和 GID，
即使这些标识符逃出了容器的边界，容器之间也很难互相攻击。
例如，假设容器 A 在主机上使用的 UID 和 GID 与容器 B 不同。
在这种情况下，它对容器 B 的文件和进程的操作是有限的：只能读取/写入某文件所允许的操作，
因为它永远不会拥有文件所有者或组权限（主机上的 UID/GID 保证对不同容器是不同的）。&lt;/li>
&lt;/ul>
&lt;!--
* _Increased host isolation_: As the UIDs and GIDs are mapped to unprivileged
users on the host, if a container escapes the container boundaries, even if it
runs as root inside the container, it has no privileges on the host. This
greatly protects what host files it can read/write, which process it can send
signals to, etc. Furthermore, capabilities granted are only valid inside the
user namespace and not on the host, limiting the impact a container
escape can have.
-->
&lt;ul>
&lt;li>&lt;strong>增加主机隔离&lt;/strong>：由于 UID 和 GID 被映射到主机上的非特权用户，如果某容器逃出了它的边界，
即使它在容器内部以 root 身份运行，它在主机上也没有特权。
这大大保护了它可以读取/写入的主机文件，它可以向哪个进程发送信号等。
此外，所授予的权能仅在用户命名空间内有效，而在主机上无效，这就限制了容器逃逸的影响。&lt;/li>
&lt;/ul>
&lt;!--
&lt;figure>
&lt;img src="https://kubernetes.io/images/blog/2024-04-22-userns-beta/userns-ids.png"
alt="Image showing IDs 0-65535 are reserved to the host, pods use higher IDs"/> &lt;figcaption>
&lt;h4>User namespace IDs allocation&lt;/h4>
&lt;/figcaption>
&lt;/figure>
-->
&lt;figure>
&lt;img src="https://kubernetes.io/images/blog/2024-04-22-userns-beta/userns-ids.png"
alt="此图显示了 ID 0-65535 为主机预留，Pod 使用更大的 ID"/> &lt;figcaption>
&lt;h4>用户命名空间 ID 分配&lt;/h4>
&lt;/figcaption>
&lt;/figure>
&lt;!--
Without using a user namespace, a container running as root in the case of a
container breakout has root privileges on the node. If some capabilities
were granted to the container, the capabilities are valid on the host too. None
of this is true when using user namespaces (modulo bugs, of course 🙂).
-->
&lt;p>如果不使用用户命名空间，容器逃逸时以 root 运行的容器在节点上将具有 root 特权。
如果某些权能授权给了此容器，这些权能在主机上也会有效。
如果使用用户命名空间，就不会是这种情况（当然，除非有漏洞 🙂）。&lt;/p>
&lt;!--
## Changes in 1.30
In Kubernetes 1.30, besides moving user namespaces to beta, the contributors
working on this feature:
-->
&lt;h2 id="changes-in-1.30">1.30 的变化 &lt;/h2>
&lt;p>在 Kubernetes 1.30 中，除了将用户命名空间进阶至 Beta，参与此特性的贡献者们还：&lt;/p>
&lt;!--
* Introduced a way for the kubelet to use custom ranges for the UIDs/GIDs mapping
* Have added a way for Kubernetes to enforce that the runtime supports all the features
needed for user namespaces. If they are not supported, Kubernetes will show a
clear error when trying to create a pod with user namespaces. Before 1.30, if
the container runtime didn't support user namespaces, the pod could be created
without a user namespace.
* Added more tests, including [tests in the
cri-tools](https://github.com/kubernetes-sigs/cri-tools/pull/1354)
repository.
-->
&lt;ul>
&lt;li>为 kubelet 引入了一种使用自定义范围进行 UID/GID 映射的方式&lt;/li>
&lt;li>为 Kubernetes 添加了一种强制执行的方式让运行时支持用户命名空间所需的所有特性。
如果不支持这些特性，Kubernetes 在尝试创建具有用户命名空间的 Pod 时，会显示一个明确的错误。
在 1.30 之前，如果容器运行时不支持用户命名空间，Pod 可能会在没有用户命名空间的情况下被创建。&lt;/li>
&lt;li>新增了更多的测试，包括在 &lt;a href="https://github.com/kubernetes-sigs/cri-tools/pull/1354">cri-tools&lt;/a> 仓库中的测试。&lt;/li>
&lt;/ul>
&lt;!--
You can check the
[documentation](/docs/concepts/workloads/pods/user-namespaces/#set-up-a-node-to-support-user-namespaces)
on user namespaces for how to configure custom ranges for the mapping.
-->
&lt;p>你可以查阅有关用户命名空间的&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/user-namespaces/#set-up-a-node-to-support-user-namespaces">文档&lt;/a>，
了解如何配置映射的自定义范围。&lt;/p>
&lt;!--
## Demo
A few months ago, [CVE-2024-21626][runc-cve] was disclosed. This **vulnerability
score is 8.6 (HIGH)**. It allows an attacker to escape a container and
**read/write to any path on the node and other pods hosted on the same node**.
Rodrigo created a demo that exploits [CVE 2024-21626][runc-cve] and shows how
the exploit, which works without user namespaces, **is mitigated when user
namespaces are in use.**
-->
&lt;h2 id="demo">演示 &lt;/h2>
&lt;p>几个月前，&lt;a href="https://github.com/opencontainers/runc/security/advisories/GHSA-xr7r-f8xq-vfvv">CVE-2024-21626&lt;/a> 被披露。
这个 &lt;strong>漏洞评分为 8.6（高）&lt;/strong>。它允许攻击者让容器逃逸，并&lt;strong>读取/写入节点上的任何路径以及同一节点上托管的其他 Pod&lt;/strong>。&lt;/p>
&lt;p>Rodrigo 创建了一个滥用 &lt;a href="https://github.com/opencontainers/runc/security/advisories/GHSA-xr7r-f8xq-vfvv">CVE 2024-21626&lt;/a> 的演示，
演示了此漏洞在没有用户命名空间时的工作方式，而在使用用户命名空间后 &lt;strong>得到了缓解&lt;/strong>。&lt;/p>
&lt;!--
&lt;div class="youtube-quote-sm">
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="allowfullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/07y5bl5UDdA?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" title="Mitigation of CVE-2024-21626 on Kubernetes by enabling User Namespace support"
>&lt;/iframe>
&lt;/div>
-->
&lt;div class="youtube-quote-sm">
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="allowfullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/07y5bl5UDdA?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" title="通过启用用户命名空间支持来在 Kubernetes 上缓解 CVE-2024-21626"
>&lt;/iframe>
&lt;/div>
&lt;!--
Please note that with user namespaces, an attacker can do on the host file system
what the permission bits for "others" allow. Therefore, the CVE is not
completely prevented, but the impact is greatly reduced.
-->
&lt;p>请注意，使用用户命名空间时，攻击者可以在主机文件系统上执行“其他”权限位所允许的操作。
因此，此 CVE 并没有完全被修复，但影响大大降低。&lt;/p>
&lt;!--
## Node system requirements
There are requirements on the Linux kernel version and the container
runtime to use this feature.
On Linux you need Linux 6.3 or greater. This is because the feature relies on a
kernel feature named idmap mounts, and support for using idmap mounts with tmpfs
was merged in Linux 6.3.
-->
&lt;h2 id="node-system-requirements">节点系统要求 &lt;/h2>
&lt;p>使用此特性对 Linux 内核版本和容器运行时有一些要求。&lt;/p>
&lt;p>在 Linux 上，你需要 Linux 6.3 或更高版本。
这是因为此特性依赖于一个名为 idmap 挂载的内核特性，而支持 idmap 挂载与 tmpfs 一起使用的特性是在 Linux 6.3 中合并的。&lt;/p>
&lt;!--
Suppose you are using [CRI-O][crio] with crun; as always, you can expect support for
Kubernetes 1.30 with CRI-O 1.30. Please note you also need [crun][crun] 1.9 or
greater. If you are using CRI-O with [runc][runc], this is still not supported.
Containerd support is currently targeted for [containerd][containerd] 2.0, and
the same crun version requirements apply. If you are using containerd with runc,
this is still not supported.
-->
&lt;p>假设你使用 &lt;a href="https://cri-o.io/">CRI-O&lt;/a> 和 crun；就像往常一样，你可以期待 CRI-O 1.30 支持 Kubernetes 1.30。
请注意，你还需要 &lt;a href="https://github.com/containers/crun">crun&lt;/a> 1.9 或更高版本。如果你使用的是 CRI-O 和 &lt;a href="https://github.com/opencontainers/runc/">runc&lt;/a>，则仍然不支持用户命名空间。&lt;/p>
&lt;p>containerd 对此特性的支持目前锁定为 &lt;a href="https://containerd.io/">containerd&lt;/a> 2.0，同样 crun 也有适用的版本要求。
如果你使用的是 containerd 和 runc，则仍然不支持用户命名空间。&lt;/p>
&lt;!--
Please note that containerd 1.7 added _experimental_ support for user
namespaces, as implemented in Kubernetes 1.25 and 1.26. We did a redesign in
Kubernetes 1.27, which requires changes in the container runtime. Those changes
are not present in containerd 1.7, so it only works with user namespaces
support in Kubernetes 1.25 and 1.26.
-->
&lt;p>请注意，正如在 Kubernetes 1.25 和 1.26 中实现的那样，containerd 1.7 增加了对用户命名空间的&lt;strong>实验性&lt;/strong>支持。
我们曾在 Kubernetes 1.27 中进行了重新设计，所以容器运行时需要做一些变更。
而 containerd 1.7 并未包含这些变更，所以它仅在 Kubernetes 1.25 和 1.26 中支持使用用户命名空间。&lt;/p>
&lt;!--
Another limitation of containerd 1.7 is that it needs to change the
ownership of every file and directory inside the container image during Pod
startup. This has a storage overhead and can significantly impact the
container startup latency. Containerd 2.0 will probably include an implementation
that will eliminate the added startup latency and storage overhead. Consider
this if you plan to use containerd 1.7 with user namespaces in
production.
None of these containerd 1.7 limitations apply to CRI-O.
-->
&lt;p>containerd 1.7 的另一个限制是，它需要在 Pod 启动期间变更容器镜像内的每个文件和目录的所有权。
这会增加存储开销，并可能显著影响容器启动延迟。containerd 2.0 可能会包含一个实现，以消除增加的启动延迟和存储开销。
如果你计划在生产环境中使用 containerd 1.7 和用户命名空间，请考虑这一点。&lt;/p>
&lt;p>containerd 1.7 的这些限制均不适用于 CRI-O。&lt;/p>
&lt;!--
## How do I get involved?
You can reach SIG Node by several means:
- Slack: [#sig-node](https://kubernetes.slack.com/messages/sig-node)
- [Mailing list](https://groups.google.com/forum/#!forum/kubernetes-sig-node)
- [Open Community Issues/PRs](https://github.com/kubernetes/community/labels/sig%2Fnode)
-->
&lt;h2 id="how-do-i-get-involved">如何参与？ &lt;/h2>
&lt;p>你可以通过以下方式联系 SIG Node：&lt;/p>
&lt;ul>
&lt;li>Slack：&lt;a href="https://kubernetes.slack.com/messages/sig-node">#sig-node&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://groups.google.com/forum/#!forum/kubernetes-sig-node">邮件列表&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/kubernetes/community/labels/sig%2Fnode">提交社区 Issue/PR&lt;/a>&lt;/li>
&lt;/ul>
&lt;!--
You can also contact us directly:
- GitHub: @rata @giuseppe @saschagrunert
- Slack: @rata @giuseppe @sascha
-->
&lt;p>你也可以通过以下方式直接联系我们：&lt;/p>
&lt;ul>
&lt;li>GitHub：@rata @giuseppe @saschagrunert&lt;/li>
&lt;li>Slack：@rata @giuseppe @sascha&lt;/li>
&lt;/ul></description></item><item><title>SIG Architecture 特别报道：代码组织</title><link>https://kubernetes.io/zh-cn/blog/2024/04/11/sig-architecture-code-spotlight-2024/</link><pubDate>Thu, 11 Apr 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/04/11/sig-architecture-code-spotlight-2024/</guid><description>
&lt;!--
layout: blog
title: "Spotlight on SIG Architecture: Code Organization"
slug: sig-architecture-code-spotlight-2024
canonicalUrl: https://www.kubernetes.dev/blog/2024/04/11/sig-architecture-code-spotlight-2024
date: 2024-04-11
author: >
Frederico Muñoz (SAS Institute)
-->
&lt;p>&lt;strong>作者:&lt;/strong> Frederico Muñoz (SAS Institute)&lt;/p>
&lt;p>&lt;strong>译者:&lt;/strong> Xin Li (DaoCloud)&lt;/p>
&lt;!--
_This is the third interview of a SIG Architecture Spotlight series that will cover the different
subprojects. We will cover [SIG Architecture: Code Organization](https://github.com/kubernetes/community/blob/e44c2c9d0d3023e7111d8b01ac93d54c8624ee91/sig-architecture/README.md#code-organization)._
In this SIG Architecture spotlight I talked with [Madhav Jivrajani](https://github.com/MadhavJivrajani)
(VMware), a member of the Code Organization subproject.
-->
&lt;p>&lt;strong>这是 SIG Architecture Spotlight 系列的第三次采访，该系列将涵盖不同的子项目。
我们将介绍 &lt;a href="https://github.com/kubernetes/community/blob/e44c2c9d0d3023e7111d8b01ac93d54c8624ee91/sig-architecture/README.md#code-organization">SIG Architecture：代码组织&lt;/a>。&lt;/strong>&lt;/p>
&lt;p>在本次 SIG Architecture 聚焦中，我与代码组织子项目的成员
&lt;a href="https://github.com/MadhavJivrajani">Madhav Jivrajani&lt;/a>（VMware）进行了交谈。&lt;/p>
&lt;!--
## Introducing the Code Organization subproject
**Frederico (FSM)**: Hello Madhav, thank you for your availability. Could you start by telling us a
bit about yourself, your role and how you got involved in Kubernetes?
-->
&lt;h2 id="介绍代码组织子项目">介绍代码组织子项目&lt;/h2>
&lt;p>&lt;strong>Frederico (FSM)&lt;/strong>：你好，Madhav，感谢你百忙之中接受我们的采访。你能否首先向我们介绍一下你自己、你的角色以及你是如何参与 Kubernetes 的？&lt;/p>
&lt;!--
**Madhav Jivrajani (MJ)**: Hello! My name is Madhav Jivrajani, I serve as a technical lead for SIG
Contributor Experience and a GitHub Admin for the Kubernetes project. Apart from that I also
contribute to SIG API Machinery and SIG Etcd, but more recently, I’ve been helping out with the work
that is needed to help Kubernetes [stay on supported versions of
Go](https://github.com/kubernetes/enhancements/tree/cf6ee34e37f00d838872d368ec66d7a0b40ee4e6/keps/sig-release/3744-stay-on-supported-go-versions),
and it is through this that I am involved with the Code Organization subproject of SIG Architecture.
-->
&lt;p>&lt;strong>Madhav Jivrajani (MJ)&lt;/strong>：你好！我叫 Madhav Jivrajani，担任 SIG 贡献者体验的技术主管和 Kubernetes 项目的 GitHub 管理员。
除此之外，我还为 SIG API Machinery 和 SIG Etcd 做出贡献，但最近，我一直在帮助完成 Kubernetes
&lt;a href="https://github.com/kubernetes/enhancements/tree/cf6ee34e37f00d838872d368ec66d7a0b40ee4e6/keps/sig-release/3744-stay-on-supported-go-versions">保留受支持的 Go 版本&lt;/a> 所需的工作，
正是通过这一点，参与到了 SIG Architecture 的代码组织子项目中。&lt;/p>
&lt;!--
**FSM**: A project the size of Kubernetes must have unique challenges in terms of code organization
-- is this a fair assumption? If so, what would you pick as some of the main challenges that are
specific to Kubernetes?
-->
&lt;p>&lt;strong>FSM&lt;/strong>：像 Kubernetes 这样规模的项目在代码组织方面肯定会遇到独特的挑战 -- 这是一个合理的假设吗？
如果是这样，你认为 Kubernetes 特有的一些主要挑战是什么？&lt;/p>
&lt;!--
**MJ**: That’s a fair assumption! The first interesting challenge comes from the sheer size of the
Kubernetes codebase. We have ≅2.2 million lines of Go code (which is steadily decreasing thanks to
[dims](https://github.com/dims) and other folks in this sub-project!), and a little over 240
dependencies that we rely on either directly or indirectly, which is why having a sub-project
dedicated to helping out with dependency management is crucial: we need to know what dependencies
we’re pulling in, what versions these dependencies are at, and tooling to help make sure we are
managing these dependencies across different parts of the codebase in a consistent manner.
-->
&lt;p>&lt;strong>MJ&lt;/strong>：这是一个合理的假设！第一个有趣的挑战来自 Kubernetes 代码库的庞大规模。
我们有大约 220 万行 Go 代码（由于 &lt;a href="https://github.com/dims">dims&lt;/a> 和这个子项目中的其他人的努力，该代码正在稳步减少！），
而且我们的依赖项（无论是直接还是间接）超过 240 个，这就是为什么拥有一个致力于帮助进行依赖项管理的子项目至关重要：
我们需要知道我们正在引入哪些依赖项，这些依赖项处于什么版本，
以及帮助确保我们能够以一致的方式管理代码库不同部分的依赖关系的工具。
以一致的方式管理代码库不同部分的这些依赖关系。&lt;/p>
&lt;!--
Another interesting challenge with Kubernetes is that we publish a lot of Go modules as part of the
Kubernetes release cycles, one example of this is
[`client-go`](https://github.com/kubernetes/client-go).However, we as a project would also like the
benefits of having everything in one repository to get the advantages of using a monorepo, like
atomic commits... so, because of this, code organization works with other SIGs (like SIG Release) to
automate the process of publishing code from the monorepo to downstream individual repositories
which are much easier to consume, and this way you won’t have to import the entire Kubernetes
codebase!
-->
&lt;p>Kubernetes 的另一个有趣的挑战是，我们在 Kubernetes 发布周期中发布了许多 Go 模块，其中一个例子是
&lt;a href="https://github.com/kubernetes/client-go">&lt;code>client-go&lt;/code>&lt;/a>。
然而，作为一个项目，我们也希望将所有内容都放在一个仓库中，便获得使用单一仓库的优势，例如原子性的提交……
因此，代码组织与其他 SIG（例如 SIG Release）合作，以实现将代码从单一仓库发布到下游仓库的自动化过程，
下游仓库更容易使用，因为你就不必导入整个 Kubernetes 代码库！&lt;/p>
&lt;!--
## Code organization and Kubernetes
**FSM**: For someone just starting contributing to Kubernetes code-wise, what are the main things
they should consider in terms of code organization? How would you sum up the key concepts?
**MJ**: I think one of the key things to keep in mind at least as you’re starting off is the concept
of staging directories. In the [`kubernetes/kubernetes`](https://github.com/kubernetes/kubernetes)
repository, you will come across a directory called
[`staging/`](https://github.com/kubernetes/kubernetes/tree/master/staging). The sub-folders in this
directory serve as a bunch of pseudo-repositories. For example, the
[`kubernetes/client-go`](https://github.com/kubernetes/client-go) repository that publishes releases
for `client-go` is actually a [staging
repo](https://github.com/kubernetes/kubernetes/tree/master/staging/src/k8s.io/client-go).
-->
&lt;h2 id="代码组织和-kubernetes">代码组织和 Kubernetes&lt;/h2>
&lt;p>&lt;strong>FSM&lt;/strong>：对于刚刚开始为 Kubernetes 代码做出贡献的人来说，在代码组织方面他们应该考虑的主要事项是什么？
你认为有哪些关键概念？&lt;/p>
&lt;p>&lt;strong>MJ&lt;/strong>：我认为至少在开始时要记住的关键事情之一是 staging 目录的概念。
在 &lt;a href="https://github.com/kubernetes/kubernetes">&lt;code>kubernetes/kubernetes&lt;/code>&lt;/a> 中，你会遇到一个名为
&lt;a href="https://github.com/kubernetes/kubernetes/tree/master/staging">&lt;code>staging/&lt;/code>&lt;/a> 的目录。
该目录中的子文件夹充当一堆伪仓库。
例如，发布 &lt;code>client-go&lt;/code> 版本的 &lt;a href="https://github.com/kubernetes/client-go">&lt;code>kubernetes/client-go&lt;/code>&lt;/a>
仓库实际上是一个 &lt;a href="https://github.com/kubernetes/kubernetes/tree/master/staging/src/k8s.io/client-go">staging 仓库&lt;/a>。&lt;/p>
&lt;!--
**FSM**: So the concept of staging directories fundamentally impact contributions?
**MJ**: Precisely, because if you’d like to contribute to any of the staging repos, you will need to
send in a PR to its corresponding staging directory in `kubernetes/kubernetes`. Once the code merges
there, we have a bot called the [`publishing-bot`](https://github.com/kubernetes/publishing-bot)
that will sync the merged commits to the required staging repositories (like
`kubernetes/client-go`). This way we get the benefits of a monorepo but we also can modularly
publish code for downstream consumption. PS: The `publishing-bot` needs more folks to help out!
For more information on staging repositories, please see the [contributor
documentation](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/staging.md).
-->
&lt;p>&lt;strong>FSM&lt;/strong>：那么 staging 目录的概念会从根本上影响贡献？&lt;/p>
&lt;p>&lt;strong>MJ&lt;/strong>：准确地说，因为如果你想为任何 staging 仓库做出贡献，你需要将 PR 发送到 &lt;code>kubernetes/kubernetes&lt;/code> 中相应的 staging 目录。
一旦代码合并到那里，我们就会让一个名为 &lt;a href="https://github.com/kubernetes/publishing-bot">&lt;code>publishing-bot&lt;/code>&lt;/a>
的机器人将合并的提交同步到必要的 staging 仓库（例如 &lt;code>kubernetes/client-go&lt;/code>）中。
通过这种方式，我们可以获得单一仓库的好处，但我们也可以以模块化的形式发布代码以供下游使用。
PS：&lt;code>publishing-bot&lt;/code> 需要更多人的帮助！&lt;/p>
&lt;!--
**FSM**: Speaking of contributions, the very high number of contributors, both individuals and
companies, must also be a challenge: how does the subproject operate in terms of making sure that
standards are being followed?
-->
&lt;p>&lt;strong>FSM&lt;/strong>：说到贡献，贡献者数量非常多，包括个人和公司，也一定是一个挑战：这个子项目是如何运作的以确保大家都遵循标准呢？&lt;/p>
&lt;!--
**MJ**: When it comes to dependency management in the project, there is a [dedicated
team](https://github.com/kubernetes/org/blob/a106af09b8c345c301d072bfb7106b309c0ad8e9/config/kubernetes/org.yaml#L1329)
that helps review and approve dependency changes. These are folks who have helped lay the foundation
of much of the
[tooling](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/vendor.md)
that Kubernetes uses today for dependency management. This tooling helps ensure there is a
consistent way that contributors can make changes to dependencies. The project has also worked on
additional tooling to signal statistics of dependencies that is being added or removed:
[`depstat`](https://github.com/kubernetes-sigs/depstat)
-->
&lt;p>&lt;strong>MJ&lt;/strong>：当涉及到项目中的依赖关系管理时，
有一个&lt;a href="https://github.com/kubernetes/org/blob/a106af09b8c345c301d072bfb7106b309c0ad8e9/config/kubernetes/org.yaml#L1329">专门团队&lt;/a>帮助审查和批准依赖关系更改。
这些人为目前 Kubernetes 用于管理依赖的许多&lt;a href="https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/vendor.md">工具&lt;/a>做了开拓性的工作。
这些工具帮助我们确保贡献者可以以一致的方式更改依赖项。
这个子项目还开发了其他工具来基于被添加或删除的依赖项的统计信息发出通知：
&lt;a href="https://github.com/kubernetes-sigs/depstat">&lt;code>depstat&lt;/code>&lt;/a>&lt;/p>
&lt;!--
Apart from dependency management, another crucial task that the project does is management of the
staging repositories. The tooling for achieving this (`publishing-bot`) is completely transparent to
contributors and helps ensure that the staging repos get a consistent view of contributions that are
submitted to `kubernetes/kubernetes`.
Code Organization also works towards making sure that Kubernetes [stays on supported versions of
Go](https://github.com/kubernetes/enhancements/tree/cf6ee34e37f00d838872d368ec66d7a0b40ee4e6/keps/sig-release/3744-stay-on-supported-go-versions). The
linked KEP provides more context on why we need to do this. We collaborate with SIG Release to
ensure that we are testing Kubernetes as rigorously and as early as we can on Go releases and
working on changes that break our CI as a part of this. An example of how we track this process can
be found [here](https://github.com/kubernetes/release/issues/3076).
-->
&lt;p>除了依赖管理之外，这个项目执行的另一项重要任务是管理 staging 仓库。
用于实现此目的的工具（&lt;code>publishing-bot&lt;/code>）对贡献者完全透明，
有助于确保就提交给 &lt;code>kubernetes/kubernetes&lt;/code> 的贡献而言，各个 staging 仓库获得的视图是一致的。&lt;/p>
&lt;p>代码组织还致力于确保 Kubernetes
&lt;a href="https://github.com/kubernetes/enhancements/tree/cf6ee34e37f00d838872d368ec66d7a0b40ee4e6/keps/sig-release/3744-stay-on-supported-go-versions">一直在使用受支持的 Go 版本&lt;/a>。
链接所指向的 KEP 中包含更详细的背景信息，用来说明为什么我们需要这样做。
我们与 SIG Release 合作，确保我们在 Go 版本上尽可能严格、尽早地测试 Kubernetes；
作为这些工作的一部分，我们要处理会破坏我们的 CI 的那些变更。
我们如何跟踪此过程的示例可以在&lt;a href="https://github.com/kubernetes/release/issues/3076">此处&lt;/a>找到。&lt;/p>
&lt;!--
## Release cycle and current priorities
**FSM**: Is there anything that changes during the release cycle?
**MJ** During the release cycle, specifically before code freeze, there are often changes that go in
that add/update/delete dependencies, fix code that needs fixing as part of our effort to stay on
supported versions of Go.
Furthermore, some of these changes are also candidates for
[backporting](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-release/cherry-picks.md)
to our supported release branches.
-->
&lt;h2 id="发布周期和当前优先级">发布周期和当前优先级&lt;/h2>
&lt;p>&lt;strong>FSM&lt;/strong>：在发布周期中有什么变化吗？&lt;/p>
&lt;p>&lt;strong>MJ&lt;/strong>：在发布周期内，特别是在代码冻结之前，通常会发生添加、更新、删除依赖项的变更，以及修复需要修复的代码等更改，
这些都是我们继续使用受支持的 Go 版本的努力的一部分。&lt;/p>
&lt;p>此外，其中一些更改也可以&lt;a href="https://github.com/kubernetes/community/blob/master/contributors/devel/sig-release/cherry-picks.md">向后移植&lt;/a>
到我们支持的发布分支。&lt;/p>
&lt;!--
**FSM**: Is there any major project or theme the subproject is working on right now that you would
like to highlight?
**MJ**: I think one very interesting and immensely useful change that
has been recently added (and I take the opportunity to specifically
highlight the work of [Tim Hockin](https://github.com/thockin) on
this) is the introduction of [Go workspaces to the Kubernetes
repo](https://www.kubernetes.dev/blog/2024/03/19/go-workspaces-in-kubernetes/). A lot of our
current tooling for dependency management and code publishing, as well
as the experience of editing code in the Kubernetes repo, can be
significantly improved by this change.
-->
&lt;p>&lt;strong>FSM&lt;/strong>：就子项目中目前正在进行的主要项目或主题而言你有什么要特别强调的吗？&lt;/p>
&lt;p>&lt;strong>MJ&lt;/strong>：我认为最近添加的一个非常有趣且非常有用的变更（我借这个机会特别强调
&lt;a href="https://github.com/thockin">Tim Hockin&lt;/a> 在这方面的工作）是引入
&lt;a href="https://www.kubernetes.dev/blog/2024/03/19/go-workspaces-in-kubernetes/">Go 工作空间的概念到Kubernetes 仓库中&lt;/a>。
我们当前的许多依赖管理和代码发布工具，以及在 Kubernetes 仓库中编辑代码的体验，
都可以通过此更改得到显着改善。&lt;/p>
&lt;!--
## Wrapping up
**FSM**: How would someone interested in the topic start helping the subproject?
**MJ**: The first step, as is the first step with any project in Kubernetes, is to join our slack:
[slack.k8s.io](https://slack.k8s.io), and after that join the `#k8s-code-organization` channel. There is also a
[code-organization office
hours](https://github.com/kubernetes/community/tree/master/sig-architecture#meetings) that takes
place that you can choose to attend. Timezones are hard, so feel free to also look at the recordings
or meeting notes and follow up on slack!
-->
&lt;h2 id="收尾">收尾&lt;/h2>
&lt;p>&lt;strong>FSM&lt;/strong>：对这个主题感兴趣的人要怎样开始帮助这个子项目？&lt;/p>
&lt;p>&lt;strong>MJ&lt;/strong>：与 Kubernetes 中任何项目的第一步一样，第一步是加入我们的
Slack：&lt;a href="https://slack.k8s.io">slack.k8s.io&lt;/a>，然后加入 &lt;code>#k8s-code-organization&lt;/code> 频道，
你还可以选择参加&lt;a href="https://github.com/kubernetes/community/tree/master/sig-architecture#meetings">代码组织办公时间&lt;/a>。
时区是个困难点，所以请随时查看录音或会议记录并跟进 Slack！&lt;/p>
&lt;!--
**FSM**: Excellent, thank you! Any final comments you would like to share?
**MJ**: The Code Organization subproject always needs help! Especially areas like the publishing
bot, so don’t hesitate to get involved in the `#k8s-code-organization` Slack channel.
-->
&lt;p>&lt;strong>FSM&lt;/strong>：非常好，谢谢！最后你还有什么想分享的吗？&lt;/p>
&lt;p>&lt;strong>MJ&lt;/strong>：代码组织子项目总是需要帮助！特别是像发布机器人这样的领域，所以请不要犹豫，参与到 &lt;code>#k8s-code-organization&lt;/code> Slack 频道中。&lt;/p></description></item><item><title>Kubernetes v1.30 初探</title><link>https://kubernetes.io/zh-cn/blog/2024/03/12/kubernetes-1-30-upcoming-changes/</link><pubDate>Tue, 12 Mar 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/03/12/kubernetes-1-30-upcoming-changes/</guid><description>
&lt;!--
layout: blog
title: 'A Peek at Kubernetes v1.30'
date: 2024-03-12
slug: kubernetes-1-30-upcoming-changes
-->
&lt;!--
**Authors:** Amit Dsouza, Frederick Kautz, Kristin Martin, Abigail McCarthy, Natali Vlatko
-->
&lt;p>&lt;strong>作者:&lt;/strong> Amit Dsouza, Frederick Kautz, Kristin Martin, Abigail McCarthy, Natali Vlatko&lt;/p>
&lt;p>&lt;strong>译者:&lt;/strong> Paco Xu (DaoCloud)&lt;/p>
&lt;!--
## A quick look: exciting changes in Kubernetes v1.30
It's a new year and a new Kubernetes release. We're halfway through the release cycle and
have quite a few interesting and exciting enhancements coming in v1.30. From brand new features
in alpha, to established features graduating to stable, to long-awaited improvements, this release
has something for everyone to pay attention to!
To tide you over until the official release, here's a sneak peek of the enhancements we're most
excited about in this cycle!
-->
&lt;h2 id="快速预览-kubernetes-v1-30-中令人兴奋的变化">快速预览：Kubernetes v1.30 中令人兴奋的变化&lt;/h2>
&lt;p>新年新版本，v1.30 发布周期已过半，我们将迎来一系列有趣且令人兴奋的增强功能。
从全新的 alpha 特性，到已有的特性升级为稳定版，再到期待已久的改进，这个版本对每个人都有值得关注的内容！&lt;/p>
&lt;p>为了让你在正式发布之前对其有所了解，下面给出我们在这个周期中最为期待的增强功能的预览！&lt;/p>
&lt;!--
## Major changes for Kubernetes v1.30
-->
&lt;h2 id="kubernetes-v1-30-的主要变化">Kubernetes v1.30 的主要变化&lt;/h2>
&lt;!--
### Structured parameters for dynamic resource allocation ([KEP-4381](https://kep.k8s.io/4381))
-->
&lt;h3 id="动态资源分配-dra-的结构化参数-kep-4381-https-kep-k8s-io-4381">动态资源分配（DRA）的结构化参数 (&lt;a href="https://kep.k8s.io/4381">KEP-4381&lt;/a>)&lt;/h3>
&lt;!--
[Dynamic resource allocation](/docs/concepts/scheduling-eviction/dynamic-resource-allocation/) was
added to Kubernetes as an alpha feature in v1.26. It defines an alternative to the traditional
device-plugin API for requesting access to third-party resources. By design, dynamic resource
allocation uses parameters for resources that are completely opaque to core Kubernetes. This
approach poses a problem for the Cluster Autoscaler (CA) or any higher-level controller that
needs to make decisions for a group of pods (e.g. a job scheduler). It cannot simulate the effect of
allocating or deallocating claims over time. Only the third-party DRA drivers have the information
available to do this.
-->
&lt;p>&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/dynamic-resource-allocation/">动态资源分配（DRA）&lt;/a> 在 Kubernetes v1.26 中作为 alpha 特性添加。
它定义了一种替代传统设备插件 device plugin API 的方式，用于请求访问第三方资源。
在设计上，动态资源分配（DRA）使用的资源参数对于核心 Kubernetes 完全不透明。
这种方法对于集群自动缩放器（CA）或任何需要为一组 Pod 做决策的高级控制器（例如作业调度器）都会带来问题。
这一设计无法模拟在不同时间分配或释放请求的效果。
只有第三方 DRA 驱动程序才拥有信息来做到这一点。&lt;/p>
&lt;!--
​​Structured Parameters for dynamic resource allocation is an extension to the original
implementation that addresses this problem by building a framework to support making these claim
parameters less opaque. Instead of handling the semantics of all claim parameters themselves,
drivers could manage resources and describe them using a specific "structured model" pre-defined by
Kubernetes. This would allow components aware of this "structured model" to make decisions about
these resources without outsourcing them to some third-party controller. For example, the scheduler
could allocate claims rapidly without back-and-forth communication with dynamic resource
allocation drivers. Work done for this release centers on defining the framework necessary to enable
different "structured models" and to implement the "named resources" model. This model allows
listing individual resource instances and, compared to the traditional device plugin API, adds the
ability to select those instances individually via attributes.
-->
&lt;p>动态资源分配（DRA）的结构化参数是对原始实现的扩展，它通过构建一个框架来支持增加请求参数的透明度来解决这个问题。
驱动程序不再需要自己处理所有请求参数的语义，而是可以使用 Kubernetes 预定义的特定“结构化模型”来管理和描述资源。
这一设计允许了解这个“结构化规范”的组件做出关于这些资源的决策，而不再将它们外包给某些第三方控制器。
例如，调度器可以在不与动态资源分配（DRA）驱动程序反复通信的前提下快速完成分配请求。
这个版本的工作重点是定义一个框架来支持不同的“结构化模型”，并实现“命名资源”模型。
此模型允许列出各个资源实例，同时，与传统的设备插件 API 相比，模型增加了通过属性逐一选择实例的能力。&lt;/p>
&lt;!--
### Node memory swap support ([KEP-2400](https://kep.k8s.io/2400))
-->
&lt;h3 id="节点交换内存-swap-支持-kep-2400-https-kep-k8s-io-2400">节点交换内存 SWAP 支持 (&lt;a href="https://kep.k8s.io/2400">KEP-2400&lt;/a>)&lt;/h3>
&lt;!--
In Kubernetes v1.30, memory swap support on Linux nodes gets a big change to how it works - with a
strong emphasis on improving system stability. In previous Kubernetes versions, the `NodeSwap`
feature gate was disabled by default, and when enabled, it used `UnlimitedSwap` behavior as the
default behavior. To achieve better stability, `UnlimitedSwap` behavior (which might compromise node
stability) will be removed in v1.30.
-->
&lt;p>在 Kubernetes v1.30 中，Linux 节点上的交换内存支持机制有了重大改进，其重点是提高系统的稳定性。
以前的 Kubernetes 版本默认情况下禁用了 &lt;code>NodeSwap&lt;/code> 特性门控。当门控被启用时，&lt;code>UnlimitedSwap&lt;/code> 行为被作为默认行为。
为了提高稳定性，&lt;code>UnlimitedSwap&lt;/code> 行为（可能会影响节点的稳定性）将在 v1.30 中被移除。&lt;/p>
&lt;!--
The updated, still-beta support for swap on Linux nodes will be available by default. However, the
default behavior will be to run the node set to `NoSwap` (not `UnlimitedSwap`) mode. In `NoSwap`
mode, the kubelet supports running on a node where swap space is active, but Pods don't use any of
the page file. You'll still need to set `--fail-swap-on=false` for the kubelet to run on that node.
However, the big change is the other mode: `LimitedSwap`. In this mode, the kubelet actually uses
the page file on that node and allows Pods to have some of their virtual memory paged out.
Containers (and their parent pods) do not have access to swap beyond their memory limit, but the
system can still use the swap space if available.
-->
&lt;p>更新后的 Linux 节点上的交换内存支持仍然是 beta 级别，并且默认情况下开启。
然而，节点默认行为是使用 &lt;code>NoSwap&lt;/code>（而不是 &lt;code>UnlimitedSwap&lt;/code>）模式。
在 &lt;code>NoSwap&lt;/code> 模式下，kubelet 支持在启用了磁盘交换空间的节点上运行，但 Pod 不会使用页面文件（pagefile）。
你仍然需要为 kubelet 设置 &lt;code>--fail-swap-on=false&lt;/code> 才能让 kubelet 在该节点上运行。
特性的另一个重大变化是针对另一种模式：&lt;code>LimitedSwap&lt;/code>。
在 &lt;code>LimitedSwap&lt;/code> 模式下，kubelet 会实际使用节点上的页面文件，并允许 Pod 的一些虚拟内存被换页出去。
容器（及其父 Pod）访问交换内存空间不可超出其内存限制，但系统的确可以使用可用的交换空间。&lt;/p>
&lt;!--
Kubernetes' Node special interest group (SIG Node) will also update the documentation to help you
understand how to use the revised implementation, based on feedback from end users, contributors,
and the wider Kubernetes community.
-->
&lt;p>Kubernetes 的 SIG Node 小组还将根据最终用户、贡献者和更广泛的 Kubernetes 社区的反馈更新文档，
以帮助你了解如何使用经过修订的实现。&lt;/p>
&lt;!--
Read the previous [blog post](/blog/2023/08/24/swap-linux-beta/) or the [node swap
documentation](/docs/concepts/architecture/nodes/#swap-memory) for more details on
Linux node swap support in Kubernetes.
-->
&lt;p>阅读之前的&lt;a href="https://kubernetes.io/zh-cn/blog/2023/08/24/swap-linux-beta/">博客文章&lt;/a>或&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/architecture/nodes/#swap-memory">交换内存管理文档&lt;/a>以获取有关
Kubernetes 中 Linux 节点交换支持的更多详细信息。&lt;/p>
&lt;!--
### Support user namespaces in pods ([KEP-127](https://kep.k8s.io/127))
-->
&lt;h3 id="支持-pod-运行在用户命名空间-kep-127-https-kep-k8s-io-127">支持 Pod 运行在用户命名空间 (&lt;a href="https://kep.k8s.io/127">KEP-127&lt;/a>)&lt;/h3>
&lt;!--
[User namespaces](/docs/concepts/workloads/pods/user-namespaces) is a Linux-only feature that better
isolates pods to prevent or mitigate several CVEs rated high/critical, including
[CVE-2024-21626](https://github.com/opencontainers/runc/security/advisories/GHSA-xr7r-f8xq-vfvv),
published in January 2024. In Kubernetes 1.30, support for user namespaces is migrating to beta and
now supports pods with and without volumes, custom UID/GID ranges, and more!
-->
&lt;p>&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/user-namespaces">用户命名空间&lt;/a> 是一个仅在 Linux 上可用的特性，它更好地隔离 Pod，
以防止或减轻几个高/严重级别的 CVE，包括 2024 年 1 月发布的 &lt;a href="https://github.com/opencontainers/runc/security/advisories/GHSA-xr7r-f8xq-vfvv">CVE-2024-21626&lt;/a>。
在 Kubernetes 1.30 中，对用户命名空间的支持正在迁移到 beta，并且现在支持带有和不带有卷的 Pod，自定义 UID/GID 范围等等！&lt;/p>
&lt;!--
### Structured authorization configuration ([KEP-3221](https://kep.k8s.io/3221))
-->
&lt;h3 id="结构化鉴权配置-kep-3221-https-kep-k8s-io-3221">结构化鉴权配置(&lt;a href="https://kep.k8s.io/3221">KEP-3221&lt;/a>)&lt;/h3>
&lt;!--
Support for [structured authorization
configuration](/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file)
is moving to beta and will be enabled by default. This feature enables the creation of
authorization chains with multiple webhooks with well-defined parameters that validate requests in a
particular order and allows fine-grained control – such as explicit Deny on failures. The
configuration file approach even allows you to specify [CEL](/docs/reference/using-api/cel/) rules
to pre-filter requests before they are dispatched to webhooks, helping you to prevent unnecessary
invocations. The API server also automatically reloads the authorizer chain when the configuration
file is modified.
-->
&lt;p>对&lt;a href="https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file">结构化鉴权配置&lt;/a>的支持正在晋级到 Beta 版本，并将默认启用。
这个特性支持创建具有明确参数定义的多个 Webhook 所构成的鉴权链；这些 Webhook 按特定顺序验证请求，
并允许进行细粒度的控制，例如在失败时明确拒绝。
配置文件方法甚至允许你指定 &lt;a href="https://kubernetes.io/zh-cn/docs/reference/using-api/cel/">CEL&lt;/a> 规则，以在将请求分派到 Webhook 之前对其进行预过滤，帮助你防止不必要的调用。
当配置文件被修改时，API 服务器还会自动重新加载鉴权链。&lt;/p>
&lt;!--
You must specify the path to that authorization configuration using the `--authorization-config`
command line argument. If you want to keep using command line flags instead of a
configuration file, those will continue to work as-is. To gain access to new authorization webhook
capabilities like multiple webhooks, failure policy, and pre-filter rules, switch to putting options
in an `--authorization-config` file. From Kubernetes 1.30, the configuration file format is
beta-level, and only requires specifying `--authorization-config` since the feature gate is enabled by
default. An example configuration with all possible values is provided in the [Authorization
docs](/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file).
For more details, read the [Authorization
docs](/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file).
-->
&lt;p>你必须使用 &lt;code>--authorization-config&lt;/code> 命令行参数指定鉴权配置的路径。
如果你想继续使用命令行标志而不是配置文件，命令行方式没有变化。
要访问新的 Webhook 功能，例如多 Webhook 支持、失败策略和预过滤规则，需要切换到将选项放在 &lt;code>--authorization-config&lt;/code> 文件中。
从 Kubernetes 1.30 开始，配置文件格式约定是 beta 级别的，只需要指定 &lt;code>--authorization-config&lt;/code>，因为特性门控默认启用。
&lt;a href="https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file">鉴权文档&lt;/a>
中提供了一个包含所有可能值的示例配置。
有关更多详细信息，请阅读&lt;a href="https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file">鉴权文档&lt;/a>。&lt;/p>
&lt;!--
### Container resource based pod autoscaling ([KEP-1610](https://kep.k8s.io/1610))
-->
&lt;h3 id="基于容器资源指标的-pod-自动扩缩容-kep-1610-https-kep-k8s-io-1610">基于容器资源指标的 Pod 自动扩缩容 (&lt;a href="https://kep.k8s.io/1610">KEP-1610&lt;/a>)&lt;/h3>
&lt;!--
Horizontal pod autoscaling based on `ContainerResource` metrics will graduate to stable in v1.30.
This new behavior for HorizontalPodAutoscaler allows you to configure automatic scaling based on the
resource usage for individual containers, rather than the aggregate resource use over a Pod. See our
[previous article](/blog/2023/05/02/hpa-container-resource-metric/) for further details, or read
[container resource metrics](/docs/tasks/run-application/horizontal-pod-autoscale/#container-resource-metrics).
-->
&lt;p>基于 &lt;code>ContainerResource&lt;/code> 指标的 Pod 水平自动扩缩容将在 v1.30 中升级为稳定版。
HorizontalPodAutoscaler 的这一新行为允许你根据各个容器的资源使用情况而不是 Pod 的聚合资源使用情况来配置自动伸缩。
有关更多详细信息，请参阅我们的&lt;a href="https://kubernetes.io/zh-cn/blog/2023/05/02/hpa-container-resource-metric/">先前文章&lt;/a>，
或阅读&lt;a href="https://kubernetes.io/zh-cn/docs/tasks/run-application/horizontal-pod-autoscale/#container-resource-metrics">容器资源指标&lt;/a>。&lt;/p>
&lt;!--
### CEL for admission control ([KEP-3488](https://kep.k8s.io/3488))
-->
&lt;h3 id="在准入控制中使用-cel-kep-3488-https-kep-k8s-io-3488">在准入控制中使用 CEL (&lt;a href="https://kep.k8s.io/3488">KEP-3488&lt;/a>)&lt;/h3>
&lt;!--
Integrating Common Expression Language (CEL) for admission control in Kubernetes introduces a more
dynamic and expressive way of evaluating admission requests. This feature allows complex,
fine-grained policies to be defined and enforced directly through the Kubernetes API, enhancing
security and governance capabilities without compromising performance or flexibility.
-->
&lt;p>Kubernetes 为准入控制集成了 Common Expression Language (CEL) 。
这一集成引入了一种更动态、表达能力更强的方式来判定准入请求。
这个特性允许通过 Kubernetes API 直接定义和执行复杂的、细粒度的策略，同时增强了安全性和治理能力，而不会影响性能或灵活性。&lt;/p>
&lt;!--
CEL's addition to Kubernetes admission control empowers cluster administrators to craft intricate
rules that can evaluate the content of API requests against the desired state and policies of the
cluster without resorting to Webhook-based access controllers. This level of control is crucial for
maintaining the integrity, security, and efficiency of cluster operations, making Kubernetes
environments more robust and adaptable to various use cases and requirements. For more information
on using CEL for admission control, see the [API
documentation](/docs/reference/access-authn-authz/validating-admission-policy/) for
ValidatingAdmissionPolicy.
-->
&lt;p>将 CEL 引入到 Kubernetes 的准入控制后，集群管理员就具有了制定复杂规则的能力，
这些规则可以根据集群的期望状态和策略来评估 API 请求的内容，而无需使用基于 Webhook 的访问控制器。
这种控制水平对于维护集群操作的完整性、安全性和效率至关重要，使 Kubernetes 环境更加健壮，更适应各种用例和需求。
有关使用 CEL 进行准入控制的更多信息，请参阅 &lt;a href="https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/validating-admission-policy/">API 文档&lt;/a>中的 ValidatingAdmissionPolicy。&lt;/p>
&lt;!--
We hope you're as excited for this release as we are. Keep an eye out for the official release
blog in a few weeks for more highlights!
-->
&lt;p>我们希望你和我们一样对这个版本的发布感到兴奋。请在未来几周内密切关注官方发布博客，以了解其他亮点！&lt;/p></description></item><item><title>走进 Kubernetes 读书会（Book Club）</title><link>https://kubernetes.io/zh-cn/blog/2024/02/22/k8s-book-club/</link><pubDate>Thu, 22 Feb 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/02/22/k8s-book-club/</guid><description>
&lt;!--
layout: blog
title: "A look into the Kubernetes Book Club"
slug: k8s-book-club
date: 2024-02-22
canonicalUrl: https://www.k8s.dev/blog/2024/02/22/k8s-book-club/
author: >
Frederico Muñoz (SAS Institute)
-->
&lt;!--
Learning Kubernetes and the entire ecosystem of technologies around it is not without its
challenges. In this interview, we will talk with [Carlos Santana
(AWS)](https://www.linkedin.com/in/csantanapr/) to learn a bit more about how he created the
[Kubernetes Book Club](https://community.cncf.io/kubernetes-virtual-book-club/), how it works, and
how anyone can join in to take advantage of a community-based learning experience.
-->
&lt;p>学习 Kubernetes 及其整个生态的技术并非易事。在本次采访中，我们的访谈对象是
&lt;a href="https://www.linkedin.com/in/csantanapr/">Carlos Santana (AWS)&lt;/a>，
了解他是如何创办 &lt;a href="https://community.cncf.io/kubernetes-virtual-book-club/">Kubernetes 读书会（Book Club）&lt;/a>的，
整个读书会是如何运作的，以及大家如何加入其中，进而更好地利用社区学习体验。&lt;/p>
&lt;!--
![Carlos Santana speaking at KubeCon NA 2023](csantana_k8s_book_club.jpg)
**Frederico Muñoz (FSM)**: Hello Carlos, thank you so much for your availability. To start with,
could you tell us a bit about yourself?
-->
&lt;p>&lt;img alt="Carlos Santana 在 KubeCon NA 2023 上演讲" src="https://kubernetes.io/zh-cn/blog/2024/02/22/k8s-book-club/csantana_k8s_book_club.jpg">&lt;/p>
&lt;p>&lt;strong>Frederico Muñoz (FSM)&lt;/strong>：你好 Carlos，非常感谢你能接受我们的采访。首先，你能介绍一下自己吗？&lt;/p>
&lt;!--
**Carlos Santana (CS)**: Of course. My experience in deploying Kubernetes in production six
years ago opened the door for me to join [Knative](https://knative.dev/) and then contribute to
Kubernetes through the Release Team. Working on upstream Kubernetes has been one of the best
experiences I've had in open-source. Over the past two years, in my role as a Senior Specialist
Solutions Architect at AWS, I have been assisting large enterprises build their internal developer
platforms (IDP) on top of Kubernetes. Going forward, my open source contributions are directed
towards [CNOE](https://cnoe.io/) and CNCF projects like [Argo](https://github.com/argoproj),
[Crossplane](https://www.crossplane.io/), and [Backstage](https://www.cncf.io/projects/backstage/).
-->
&lt;p>&lt;strong>Carlos Santana (CS)&lt;/strong>：当然可以。六年前，我在生产环境中部署 Kubernetes 的经验为我加入
&lt;a href="https://knative.dev/">Knative&lt;/a> 并通过 Release Team 为 Kubernetes 贡献代码打开了大门。
为上游 Kubernetes 工作是我在开源领域最好的经历之一。在过去的两年里，作为 AWS 的高级专业解决方案架构师，
我一直在帮助大型企业在 Kubernetes 之上构建他们的内部开发平台（IDP）。
未来我的开源贡献将主要集中在 &lt;a href="https://cnoe.io/">CNOE&lt;/a> 和 CNCF 项目，如
&lt;a href="https://github.com/argoproj">Argo&lt;/a>、&lt;a href="https://www.crossplane.io/">Crossplane&lt;/a> 和
&lt;a href="https://www.cncf.io/projects/backstage/">Backstage&lt;/a>。&lt;/p>
&lt;!--
## Creating the Book Club
**FSM**: So your path led you to Kubernetes, and at that point what was the motivating factor for
starting the Book Club?
-->
&lt;h2 id="创办读书会">创办读书会&lt;/h2>
&lt;p>&lt;strong>FSM&lt;/strong>：所以你的职业道路把你引向了 Kubernetes，那么是什么动机促使你开始创办读书会呢？&lt;/p>
&lt;!--
**CS**: The idea for the Kubernetes Book Club sprang from a casual suggestion during a
[TGIK](https://github.com/vmware-archive/tgik) livestream. For me, it was more than just about
reading a book; it was about creating a learning community. This platform has not only been a source
of knowledge but also a support system, especially during the challenging times of the
pandemic. It's gratifying to see how this initiative has helped members cope and grow. The first
book [Production
Kubernetes](https://www.oreilly.com/library/view/production-kubernetes/9781492092292/) took 36
weeks, when we started on March 5th 2021. Currently don't take that long to cover a book, one or two
chapters per week.
-->
&lt;p>&lt;strong>CS&lt;/strong>：Kubernetes 读书会的想法源于一次 &lt;a href="https://github.com/vmware-archive/tgik">TGIK&lt;/a> 直播中的一个临时建议。
对我来说，这不仅仅是读一本书，更是创办一个学习社区。这个社区平台不仅是知识的来源，也是一个支持系统，
特别是在疫情期间陪我度过了艰难时刻。读书会的这项倡议后来帮助许多成员学会了应对和成长，这让我感到很欣慰。
我们在 2021 年 3 月 5 日开始第一本书
&lt;a href="https://www.oreilly.com/library/view/production-kubernetes/9781492092292/">Production Kubernetes&lt;/a>，
花了 36 周时间。目前，一本书不会再花那么长时间了，如今每周会完成一到两章。&lt;/p>
&lt;!--
**FSM**: Could you describe the way the Kubernetes Book Club works? How do you select the books and how
do you go through them?
**CS**: We collectively choose books based on the interests and needs of the group. This practical
approach helps members, especially beginners, grasp complex concepts more easily. We have two weekly
series, one for the EMEA timezone, and I organize the US one. Each organizer works with their co-host
and picks a book on Slack, then sets up a lineup of hosts for a couple of weeks to discuss each
chapter.
-->
&lt;p>&lt;strong>FSM&lt;/strong>：你能介绍一下 Kubernetes 读书会是如何运作的吗？你们如何选书以及如何阅读它们？&lt;/p>
&lt;p>&lt;strong>CS&lt;/strong>：我们根据小组的兴趣和需求以集体的方式选书。这种实用的方法有助于成员们（特别是初学者）更容易地掌握复杂的概念。
我们每周有两次读书会应对不同的时区，一个针对 EMEA（欧洲、中东及非洲）时区，另一个是由我自己负责的美国时区。
每位组织者与他们的联合主持人在 Slack 上甄选一本书，然后安排几个主持人用几周时间讨论每一章。&lt;/p>
&lt;!--
**FSM**: If I’m not mistaken, the Kubernetes Book Club is in its 17th book, which is significant: is
there any secret recipe for keeping things active?
**CS**: The secret to keeping the club active and engaging lies in a couple of key factors.
-->
&lt;p>&lt;strong>FSM&lt;/strong>：如果我没记错的话，Kubernetes 读书会如今已经进行到了第 17 本书。这很了不起：有什么秘诀可以让读书这件事保持活跃吗？&lt;/p>
&lt;p>&lt;strong>CS&lt;/strong>：保持俱乐部活跃和吸引人参与的秘诀在于几个关键因素。&lt;/p>
&lt;!--
Firstly, consistency has been crucial. We strive to maintain a regular schedule, only cancelling
meetups for major events like holidays or KubeCon. This regularity helps members stay engaged and
builds a reliable community.
Secondly, making the sessions interesting and interactive has been vital. For instance, I often
introduce pop-up quizzes during the meetups, which not only tests members' understanding but also
adds an element of fun. This approach keeps the content relatable and helps members understand how
theoretical concepts are applied in real-world scenarios.
-->
&lt;p>首先，一贯性至关重要。我们努力保持定期聚会，只有在重大事件如节假日或 KubeCon 时才会取消聚会。
这种规律性有助于成员保持惯性参与，有助于建立一个可靠的社区。&lt;/p>
&lt;p>其次，让聚会有趣生动也非常重要。例如，我经常在聚会期间引入提问测验，不仅检测成员们的理解程度，还增加了一些乐趣。
这种方法使读书内容更加贴近实际，并帮助成员们理解理论概念在现实世界中的运用方式。&lt;/p>
&lt;!--
## Topics covered in the Book Club
**FSM**: The main topics of the books have been Kubernetes, GitOps, Security, SRE, and
Observability: is this a reflection of the cloud native landscape, especially in terms of
popularity?
-->
&lt;h2 id="读书会涵盖的话题">读书会涵盖的话题&lt;/h2>
&lt;p>&lt;strong>FSM&lt;/strong>：书籍的主要话题包括 Kubernetes、GitOps、安全、SRE 和可观测性：
这是否也反映了云原生领域的现状，特别是在受欢迎程度方面？&lt;/p>
&lt;!--
**CS**: Our journey began with 'Production Kubernetes', setting the tone for our focus on practical,
production-ready solutions. Since then, we've delved into various aspects of the CNCF landscape,
aligning our books with a different theme. Each theme, whether it be Security, Observability, or
Service Mesh, is chosen based on its relevance and demand within the community. For instance, in our
recent themes on Kubernetes Certifications, we brought the book authors into our fold as active
hosts, enriching our discussions with their expertise.
-->
&lt;p>&lt;strong>CS&lt;/strong>：我们的旅程始于《Production Kubernetes》，为我们专注于实用、生产就绪的解决方案定下了基调。
从那时起，我们深入探讨了 CNCF 领域的各个方面，根据不同的主题去选书。
每个主题，无论是安全性、可观测性还是服务网格，都是根据其相关性和社区需求来选择的。
例如，在我们最近关于 Kubernetes 考试认证的主题中，我们邀请了书籍的作者作为活跃现场的主持人，用他们的专业知识丰富了我们的讨论。&lt;/p>
&lt;!--
**FSM**: I know that the project had recent changes, namely being integrated into the CNCF as a
[Cloud Native Community Group](https://community.cncf.io/). Could you talk a bit about this change?
**CS**: The CNCF graciously accepted the book club as a Cloud Native Community Group. This is a
significant development that has streamlined our operations and expanded our reach. This alignment
has been instrumental in enhancing our administrative capabilities, similar to those used by
Kubernetes Community Days (KCD) meetups. Now, we have a more robust structure for memberships, event
scheduling, mailing lists, hosting web conferences, and recording sessions.
-->
&lt;p>&lt;strong>FSM&lt;/strong>：我了解到此项目最近有一些变化，即被整合到了 CNCF
作为&lt;a href="https://community.cncf.io/">云原生社区组（Cloud Native Community Group）&lt;/a>的一部分。你能谈谈这个变化吗？&lt;/p>
&lt;p>&lt;strong>CS&lt;/strong>：CNCF 慷慨地接受了读书会作为云原生社区组的一部分。
这是读书会发展过程中的重要一步，优化了读书会的运作并扩大了读书会的影响力。
这种拉齐对于增强读书会的管理能力至关重要，这点很像 Kubernetes Community Days (KCD) 聚会。
现在，读书会有了更稳健的会员结构、活动安排、邮件列表、托管的网络会议和录播系统。&lt;/p>
&lt;!--
**FSM**: How has your involvement with the CNCF impacted the growth and engagement of the Kubernetes
Book Club over the past six months?
**CS**: Since becoming part of the CNCF community six months ago, we've witnessed significant
quantitative changes within the Kubernetes Book Club. Our membership has surged to over 600 members,
and we've successfully organized and conducted more than 40 events during this period. What's even
more promising is the consistent turnout, with an average of 30 attendees per event. This growth and
engagement are clear indicators of the positive influence of our CNCF affiliation on the Kubernetes
Book Club's reach and impact in the community.
-->
&lt;p>&lt;strong>FSM&lt;/strong>：在过去的六个月里，你参与 CNCF 这件事对 Kubernetes 读书会的成长和参与度产生了什么影响？&lt;/p>
&lt;p>&lt;strong>CS&lt;/strong>：自从六个月前成为 CNCF 社区的一部分以来，我们在 Kubernetes 读书会中看到了一些显著的变化。
我们的会员人数激增至 600 多人，并在此期间成功组织并举办了超过 40 场活动。
更令人鼓舞的是，每场活动的出席人数都很稳定，平均约有 30 人参加。
这种增长和参与度清楚地表明了我们与 CNCF 的合作让 Kubernetes 读书会在社区中增强了影响力。&lt;/p>
&lt;!--
## Joining the Book Club
**FSM**: For anyone wanting to join, what should they do?
**CS**: There are three steps to join:
-->
&lt;h2 id="加入读书会">加入读书会&lt;/h2>
&lt;p>&lt;strong>FSM&lt;/strong>：若有人想加入读书会，他们应该怎么做？&lt;/p>
&lt;p>&lt;strong>CS&lt;/strong>：加入读书会只需三步：&lt;/p>
&lt;!--
- First, join the [Kubernetes Book Club Community](https://community.cncf.io/kubernetes-virtual-book-club/)
- Then RSVP to the
[events](https://community.cncf.io/kubernetes-virtual-book-club/)
on the community page
- Lastly, join the CNCF Slack channel
[#kubernetes-book-club](https://cloud-native.slack.com/archives/C05EYA14P37).
-->
&lt;ul>
&lt;li>首先加入 &lt;a href="https://community.cncf.io/kubernetes-virtual-book-club/">Kubernetes 读书会社区&lt;/a>&lt;/li>
&lt;li>然后注册参与在社区页面上列出的&lt;a href="https://community.cncf.io/kubernetes-virtual-book-club/">活动&lt;/a>&lt;/li>
&lt;li>最后加入 CNCF Slack 频道 &lt;a href="https://cloud-native.slack.com/archives/C05EYA14P37">#kubernetes-book-club&lt;/a>。&lt;/li>
&lt;/ul>
&lt;!--
**FSM**: Excellent, thank you! Any final comments you would like to share?
**CS**: The Kubernetes Book Club is more than just a group of professionals discussing books; it's a
vibrant community and amazing volunteers that help organize and host
[Neependra Khare](https://www.linkedin.com/in/neependra/),
[Eric Smalling](https://www.linkedin.com/in/ericsmalling/),
[Sevi Karakulak](https://www.linkedin.com/in/sevikarakulak/),
[Chad M. Crowell](https://www.linkedin.com/in/chadmcrowell/),
and [Walid (CNJ) Shaari](https://www.linkedin.com/in/walidshaari/).
Look us up at KubeCon and get your Kubernetes Book Club sticker!
-->
&lt;p>&lt;strong>FSM&lt;/strong>：太好了，谢谢你！最后你还有什么想法要跟大家分享吗？&lt;/p>
&lt;p>&lt;strong>CS&lt;/strong>：Kubernetes 读书会不仅仅是一个讨论书籍的专业小组，它是一个充满活力的社区，
有许多令人敬佩的志愿者帮助组织和主持聚会。我想借这次机会感谢几位志愿者：
&lt;a href="https://www.linkedin.com/in/neependra/">Neependra Khare&lt;/a>、
&lt;a href="https://www.linkedin.com/in/ericsmalling/">Eric Smalling&lt;/a>、
&lt;a href="https://www.linkedin.com/in/sevikarakulak/">Sevi Karakulak&lt;/a>、
&lt;a href="https://www.linkedin.com/in/chadmcrowell/">Chad M. Crowell&lt;/a>
和 &lt;a href="https://www.linkedin.com/in/walidshaari/">Walid (CNJ) Shaari&lt;/a>。
欢迎来 KubeCon 与我们相聚，还能领取你的 Kubernetes 读书会贴纸！&lt;/p></description></item><item><title>镜像文件系统：配置 Kubernetes 将容器存储在独立的文件系统上</title><link>https://kubernetes.io/zh-cn/blog/2024/01/23/kubernetes-separate-image-filesystem/</link><pubDate>Tue, 23 Jan 2024 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2024/01/23/kubernetes-separate-image-filesystem/</guid><description>
&lt;!--
layout: blog
title: 'Image Filesystem: Configuring Kubernetes to store containers on a separate filesystem'
date: 2024-01-23
slug: kubernetes-separate-image-filesystem
-->
&lt;!--
**Author:** Kevin Hannon (Red Hat)
-->
&lt;p>&lt;strong>作者:&lt;/strong> Kevin Hannon (Red Hat)&lt;/p>
&lt;p>&lt;strong>译者:&lt;/strong> &lt;a href="https://github.com/windsonsea">Michael Yao&lt;/a>&lt;/p>
&lt;!--
A common issue in running/operating Kubernetes clusters is running out of disk space.
When the node is provisioned, you should aim to have a good amount of storage space for your container images and running containers.
The [container runtime](/docs/setup/production-environment/container-runtimes/) usually writes to `/var`.
This can be located as a separate partition or on the root filesystem.
CRI-O, by default, writes its containers and images to `/var/lib/containers`, while containerd writes its containers and images to `/var/lib/containerd`.
-->
&lt;p>磁盘空间不足是运行或操作 Kubernetes 集群时的一个常见问题。
在制备节点时，你应该为容器镜像和正在运行的容器留足够的存储空间。
&lt;a href="https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/">容器运行时&lt;/a>通常会向 &lt;code>/var&lt;/code> 目录写入数据。
此目录可以位于单独的分区或根文件系统上。CRI-O 默认将其容器和镜像写入 &lt;code>/var/lib/containers&lt;/code>，
而 containerd 将其容器和镜像写入 &lt;code>/var/lib/containerd&lt;/code>。&lt;/p>
&lt;!--
In this blog post, we want to bring attention to ways that you can configure your container runtime to store its content separately from the default partition.
This allows for more flexibility in configuring Kubernetes and provides support for adding a larger disk for the container storage while keeping the default filesystem untouched.
One area that needs more explaining is where/what Kubernetes is writing to disk.
-->
&lt;p>在这篇博文中，我们想要关注的是几种不同方式，用来配置容器运行时将其内容存储到别的位置而非默认分区。
这些配置允许我们更灵活地配置 Kubernetes，支持在保持默认文件系统不受影响的情况下为容器存储添加更大的磁盘。&lt;/p>
&lt;p>需要额外讲述的是 Kubernetes 向磁盘在写入数据的具体位置及内容。&lt;/p>
&lt;!--
## Understanding Kubernetes disk usage
Kubernetes has persistent data and ephemeral data. The base path for the kubelet and local
Kubernetes-specific storage is configurable, but it is usually assumed to be `/var/lib/kubelet`.
In the Kubernetes docs, this is sometimes referred to as the root or node filesystem. The bulk of this data can be categorized into:
-->
&lt;h2 id="understanding-kubernetes-disk-usage">了解 Kubernetes 磁盘使用情况 &lt;/h2>
&lt;p>Kubernetes 有持久数据和临时数据。kubelet 和特定于 Kubernetes 的本地存储的基础路径是可配置的，
但通常假定为 &lt;code>/var/lib/kubelet&lt;/code>。在 Kubernetes 文档中，
这一位置有时被称为根文件系统或节点文件系统。写入的数据可以大致分类为：&lt;/p>
&lt;!--
- ephemeral storage
- logs
- and container runtime
This is different from most POSIX systems as the root/node filesystem is not `/` but the disk that `/var/lib/kubelet` is on.
-->
&lt;ul>
&lt;li>临时存储&lt;/li>
&lt;li>日志&lt;/li>
&lt;li>容器运行时&lt;/li>
&lt;/ul>
&lt;p>与大多数 POSIX 系统不同，这里的根/节点文件系统不是 &lt;code>/&lt;/code>，而是 &lt;code>/var/lib/kubelet&lt;/code> 所在的磁盘。&lt;/p>
&lt;!--
### Ephemeral storage
Pods and containers can require temporary or transient local storage for their operation.
The lifetime of the ephemeral storage does not extend beyond the life of the individual pod, and the ephemeral storage cannot be shared across pods.
-->
&lt;h3 id="ephemeral-storage">临时存储 &lt;/h3>
&lt;p>Pod 和容器的某些操作可能需要临时或瞬态的本地存储。
临时存储的生命周期短于 Pod 的生命周期，且临时存储不能被多个 Pod 共享。&lt;/p>
&lt;!--
### Logs
By default, Kubernetes stores the logs of each running container, as files within `/var/log`.
These logs are ephemeral and are monitored by the kubelet to make sure that they do not grow too large while the pods are running.
You can customize the [log rotation](/docs/concepts/cluster-administration/logging/#log-rotation) settings
for each node to manage the size of these logs, and configure log shipping (using a 3rd party solution)
to avoid relying on the node-local storage.
-->
&lt;h3 id="logs">日志 &lt;/h3>
&lt;p>默认情况下，Kubernetes 将每个运行容器的日志存储为 &lt;code>/var/log&lt;/code> 中的文件。
这些日志是临时性质的，并由 kubelet 负责监控以确保不会在 Pod 运行时变得过大。&lt;/p>
&lt;p>你可以为每个节点自定义&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/cluster-administration/logging/#log-rotation">日志轮换&lt;/a>设置，
以管控这些日志的大小，并（使用第三方解决方案）配置日志转储以避免对节点本地存储形成依赖。&lt;/p>
&lt;!--
### Container runtime
The container runtime has two different areas of storage for containers and images.
- read-only layer: Images are usually denoted as the read-only layer, as they are not modified when containers are running.
The read-only layer can consist of multiple layers that are combined into a single read-only layer.
There is a thin layer on top of containers that provides ephemeral storage for containers if the container is writing to the filesystem.
-->
&lt;h3 id="container-runtime">容器运行时 &lt;/h3>
&lt;p>容器运行时针对容器和镜像使用两个不同的存储区域。&lt;/p>
&lt;ul>
&lt;li>只读层：镜像通常被表示为只读层，因为镜像在容器处于运行状态期间不会被修改。
只读层可以由多个层组成，这些层组合到一起形成最终的只读层。
如果容器要向文件系统中写入数据，则在容器层之上会存在一个薄层为容器提供临时存储。&lt;/li>
&lt;/ul>
&lt;!--
- writeable layer: Depending on your container runtime, local writes might be
implemented as a layered write mechanism (for example, `overlayfs` on Linux or CimFS on Windows).
This is referred to as the writable layer.
Local writes could also use a writeable filesystem that is initialized with a full clone of the container
image; this is used for some runtimes based on hypervisor virtualisation.
The container runtime filesystem contains both the read-only layer and the writeable layer.
This is considered the `imagefs` in Kubernetes documentation.
-->
&lt;ul>
&lt;li>可写层：取决于容器运行时的不同实现，本地写入可能会用分层写入机制来实现
（例如 Linux 上的 &lt;code>overlayfs&lt;/code> 或 Windows 上的 CimFS）。这一机制被称为可写层。
本地写入也可以使用一个可写文件系统来实现，该文件系统使用容器镜像的完整克隆来初始化；
这种方式适用于某些基于 Hypervisor 虚拟化的运行时。&lt;/li>
&lt;/ul>
&lt;p>容器运行时文件系统包含只读层和可写层。在 Kubernetes 文档中，这一文件系统被称为 &lt;code>imagefs&lt;/code>。&lt;/p>
&lt;!--
## Container runtime configurations
### CRI-O
CRI-O uses a storage configuration file in TOML format that lets you control how the container runtime stores persistent and temporary data.
CRI-O utilizes the [storage library](https://github.com/containers/storage).
Some Linux distributions have a manual entry for storage (`man 5 containers-storage.conf`).
The main configuration for storage is located in `/etc/containers/storage.conf` and one can control the location for temporary data and the root directory.
The root directory is where CRI-O stores the persistent data.
-->
&lt;h2 id="container-runtime-configurations">容器运行时配置 &lt;/h2>
&lt;h3 id="cri-o">CRI-O&lt;/h3>
&lt;p>CRI-O 使用 TOML 格式的存储配置文件，让你控制容器运行时如何存储持久数据和临时数据。
CRI-O 使用了 &lt;a href="https://github.com/containers/storage">containers-storage 库&lt;/a>。
某些 Linux 发行版为 containers-storage 提供了帮助手册条目（&lt;code>man 5 containers-storage.conf&lt;/code>）。
存储的主要配置位于 &lt;code>/etc/containers/storage.conf&lt;/code> 中，你可以控制临时数据和根目录的位置。
根目录是 CRI-O 存储持久数据的位置。&lt;/p>
&lt;!--
```toml
[storage]
# Default storage driver
driver = "overlay"
# Temporary storage location
runroot = "/var/run/containers/storage"
# Primary read/write location of container storage
graphroot = "/var/lib/containers/storage"
```
-->
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-toml" data-lang="toml">&lt;span style="display:flex;">&lt;span>[storage]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#080;font-style:italic"># 默认存储驱动&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>driver = &lt;span style="color:#b44">&amp;#34;overlay&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#080;font-style:italic"># 临时存储位置&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>runroot = &lt;span style="color:#b44">&amp;#34;/var/run/containers/storage&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#080;font-style:italic"># 容器存储的主要读/写位置&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>graphroot = &lt;span style="color:#b44">&amp;#34;/var/lib/containers/storage&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
- `graphroot`
- Persistent data stored from the container runtime
- If SELinux is enabled, this must match the `/var/lib/containers/storage`
- `runroot`
- Temporary read/write access for container
- Recommended to have this on a temporary filesystem
-->
&lt;ul>
&lt;li>&lt;code>graphroot&lt;/code>
&lt;ul>
&lt;li>存储来自容器运行时的持久数据&lt;/li>
&lt;li>如果 SELinux 被启用，则此项必须是 &lt;code>/var/lib/containers/storage&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;code>runroot&lt;/code>
&lt;ul>
&lt;li>容器的临时读/写访问&lt;/li>
&lt;li>建议将其放在某个临时文件系统上&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;!--
Here is a quick way to relabel your graphroot directory to match `/var/lib/containers/storage`:
```bash
semanage fcontext -a -e /var/lib/containers/storage &lt;YOUR-STORAGE-PATH>
restorecon -R -v &lt;YOUR-STORAGE-PATH>
```
-->
&lt;p>以下是为你的 graphroot 目录快速重新打标签以匹配 &lt;code>/var/lib/containers/storage&lt;/code> 的方法：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>semanage fcontext -a -e /var/lib/containers/storage &amp;lt;你的存储路径&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>restorecon -R -v &amp;lt;你的存储路径&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
### containerd
The containerd runtime uses a TOML configuration file to control where persistent and ephemeral data is stored.
The default path for the config file is located at `/etc/containerd/config.toml`.
The relevant fields for containerd storage are `root` and `state`.
-->
&lt;h3 id="containerd">containerd&lt;/h3>
&lt;p>containerd 运行时使用 TOML 配置文件来控制存储持久数据和临时数据的位置。
配置文件的默认路径位于 &lt;code>/etc/containerd/config.toml&lt;/code>。&lt;/p>
&lt;p>与 containerd 存储的相关字段是 &lt;code>root&lt;/code> 和 &lt;code>state&lt;/code>。&lt;/p>
&lt;!--
- `root`
- The root directory for containerd metadata
- Default is `/var/lib/containerd`
- Root also requires SELinux labels if your OS requires it
- `state`
- Temporary data for containerd
- Default is `/run/containerd`
-->
&lt;ul>
&lt;li>&lt;code>root&lt;/code>
&lt;ul>
&lt;li>containerd 元数据的根目录&lt;/li>
&lt;li>默认为 &lt;code>/var/lib/containerd&lt;/code>&lt;/li>
&lt;li>如果你的操作系统要求，需要为根目录设置 SELinux 标签&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;code>state&lt;/code>
&lt;ul>
&lt;li>containerd 的临时数据&lt;/li>
&lt;li>默认为 &lt;code>/run/containerd&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;!--
## Kubernetes node pressure eviction
Kubernetes will automatically detect if the container filesystem is split from the node filesystem.
When one separates the filesystem, Kubernetes is responsible for monitoring both the node filesystem and the container runtime filesystem.
Kubernetes documentation refers to the node filesystem and the container runtime filesystem as nodefs and imagefs.
If either nodefs or the imagefs are running out of disk space, then the overall node is considered to have disk pressure.
Kubernetes will first reclaim space by deleting unusued containers and images, and then it will resort to evicting pods.
On a node that has a nodefs and an imagefs, the kubelet will
[garbage collect](/docs/concepts/architecture/garbage-collection/#containers-images) unused container images
on imagefs and will remove dead pods and their containers from the nodefs.
If there is only a nodefs, then Kubernetes garbage collection includes dead containers, dead pods and unused images.
-->
&lt;h2 id="kubernetes-node-pressure-eviction">Kubernetes 节点压力驱逐 &lt;/h2>
&lt;p>Kubernetes 将自动检测容器文件系统是否与节点文件系统分离。
当你分离文件系统时，Kubernetes 负责同时监视节点文件系统和容器运行时文件系统。
Kubernetes 文档将节点文件系统称为 nodefs，将容器运行时文件系统称为 imagefs。
如果 nodefs 或 imagefs 中有一个磁盘空间不足，则整个节点被视为有磁盘压力。
这种情况下，Kubernetes 先通过删除未使用的容器和镜像来回收空间，之后会尝试驱逐 Pod。
在同时具有 nodefs 和 imagefs 的节点上，kubelet 将在 imagefs
上对未使用的容器镜像执行&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/architecture/garbage-collection/#containers-images">垃圾回收&lt;/a>，
并从 nodefs 中移除死掉的 Pod 及其容器。
如果只有 nodefs，则 Kubernetes 垃圾回收将包括死掉的容器、死掉的 Pod 和未使用的镜像。&lt;/p>
&lt;!--
Kubernetes allows more configurations for determining if your disk is full.
The eviction manager within the kubelet has some configuration settings that let you control
the relevant thresholds.
For filesystems, the relevant measurements are `nodefs.available`, `nodefs.inodesfree`, `imagefs.available`, and `imagefs.inodesfree`.
If there is not a dedicated disk for the container runtime then imagefs is ignored.
Users can use the existing defaults:
-->
&lt;p>Kubernetes 提供额外的配置方法来确定磁盘是否已满。kubelet 中的驱逐管理器有一些让你可以控制相关阈值的配置项。
对于文件系统，相关测量值有 &lt;code>nodefs.available&lt;/code>、&lt;code>nodefs.inodesfree&lt;/code>、&lt;code>imagefs.available&lt;/code> 和
&lt;code>imagefs.inodesfree&lt;/code>。如果容器运行时没有专用磁盘，则 imagefs 被忽略。&lt;/p>
&lt;p>用户可以使用现有的默认值：&lt;/p>
&lt;!--
- `memory.available` &lt; 100MiB
- `nodefs.available` &lt; 10%
- `imagefs.available` &lt; 15%
- `nodefs.inodesFree` &lt; 5% (Linux nodes)
Kubernetes allows you to set user defined values in `EvictionHard` and `EvictionSoft` in the kubelet configuration file.
-->
&lt;ul>
&lt;li>&lt;code>memory.available&lt;/code> &amp;lt; 100MiB&lt;/li>
&lt;li>&lt;code>nodefs.available&lt;/code> &amp;lt; 10%&lt;/li>
&lt;li>&lt;code>imagefs.available&lt;/code> &amp;lt; 15%&lt;/li>
&lt;li>&lt;code>nodefs.inodesFree&lt;/code> &amp;lt; 5%（Linux 节点）&lt;/li>
&lt;/ul>
&lt;p>Kubernetes 允许你在 kubelet 配置文件中将 &lt;code>EvictionHard&lt;/code> 和 &lt;code>EvictionSoft&lt;/code> 设置为用户定义的值。&lt;/p>
&lt;!--
`EvictionHard`
: defines limits; once these limits are exceeded, pods will be evicted without any grace period.
`EvictionSoft`
: defines limits; once these limits are exceeded, pods will be evicted with a grace period that can be set per signal.
-->
&lt;dl>
&lt;dt>&lt;code>EvictionHard&lt;/code>&lt;/dt>
&lt;dd>定义限制；一旦超出这些限制，Pod 将被立即驱逐，没有任何宽限期。&lt;/dd>
&lt;dt>&lt;code>EvictionSoft&lt;/code>&lt;/dt>
&lt;dd>定义限制；一旦超出这些限制，Pod 将在按各信号所设置的宽限期后被驱逐。&lt;/dd>
&lt;/dl>
&lt;!--
If you specify a value for `EvictionHard`, it will replace the defaults.
This means it is important to set all signals in your configuration.
For example, the following kubelet configuration could be used to configure [eviction signals](/docs/concepts/scheduling-eviction/node-pressure-eviction/#eviction-signals-and-thresholds) and grace period options.
-->
&lt;p>如果你为 &lt;code>EvictionHard&lt;/code> 指定了值，所设置的值将取代默认值。
这意味着在你的配置中设置所有信号非常重要。&lt;/p>
&lt;p>例如，以下 kubelet
配置可用于配置&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/node-pressure-eviction/#eviction-signals-and-thresholds">驱逐信号&lt;/a>和宽限期选项。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>kubelet.config.k8s.io/v1beta1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>KubeletConfiguration&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">address&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;192.168.0.8&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">port&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#666">20250&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">serializeImagePulls&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#a2f;font-weight:bold">false&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">evictionHard&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">memory.available&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;100Mi&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">nodefs.available&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;10%&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">nodefs.inodesFree&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;5%&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">imagefs.available&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;15%&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">imagefs.inodesFree&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;5%&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">evictionSoft&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">memory.available&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;100Mi&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">nodefs.available&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;10%&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">nodefs.inodesFree&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;5%&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">imagefs.available&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;15%&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">imagefs.inodesFree&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;5%&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">evictionSoftGracePeriod&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">memory.available&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;1m30s&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">nodefs.available&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;2m&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">nodefs.inodesFree&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;2m&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">imagefs.available&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;2m&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">imagefs.inodesFree&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;2m&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">evictionMaxPodGracePeriod&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>60s&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!--
### Problems
The Kubernetes project recommends that you either use the default settings for eviction or you set all the fields for eviction.
You can use the default settings or specify your own `evictionHard` settings. If you miss a signal, then Kubernetes will not monitor that resource.
One common misconfiguration administrators or users can hit is mounting a new filesystem to `/var/lib/containers/storage` or `/var/lib/containerd`.
Kubernetes will detect a separate filesystem, so you want to make sure to check that `imagefs.inodesfree` and `imagefs.available` match your needs if you've done this.
-->
&lt;h3 id="problems">问题 &lt;/h3>
&lt;p>Kubernetes 项目建议你针对 Pod 驱逐要么使用其默认设置，要么设置与之相关的所有字段。
你可以使用默认设置或指定你自己的 &lt;code>evictionHard&lt;/code> 设置。 如果你漏掉一个信号，那么 Kubernetes 将不会监视该资源。
管理员或用户可能会遇到的一个常见误配是将新的文件系统挂载到 &lt;code>/var/lib/containers/storage&lt;/code> 或 &lt;code>/var/lib/containerd&lt;/code>。
Kubernetes 将检测到一个单独的文件系统，因此你要确保 &lt;code>imagefs.inodesfree&lt;/code> 和 &lt;code>imagefs.available&lt;/code> 符合你的需要。&lt;/p>
&lt;!--
Another area of confusion is that ephemeral storage reporting does not change if you define an image
filesystem for your node. The image filesystem (`imagefs`) is used to store container image layers; if a
container writes to its own root filesystem, that local write doesn't count towards the size of the container image. The place where the container runtime stores those local modifications is runtime-defined, but is often
the image filesystem.
If a container in a pod is writing to a filesystem-backed `emptyDir` volume, then this uses space from the
`nodefs` filesystem.
The kubelet always reports ephemeral storage capacity and allocations based on the filesystem represented
by `nodefs`; this can be confusing when ephemeral writes are actually going to the image filesystem.
-->
&lt;p>另一个令人困惑的地方是，如果你为节点定义了镜像文件系统，则临时存储报告不会发生变化。
镜像文件系统（&lt;code>imagefs&lt;/code>）用于存储容器镜像层；如果容器向自己的根文件系统写入，
那么这种本地写入不会计入容器镜像的大小。容器运行时存储这些本地修改的位置是由运行时定义的，但通常是镜像文件系统。
如果 Pod 中的容器正在向基于文件系统的 &lt;code>emptyDir&lt;/code> 卷写入，所写入的数据将使用 &lt;code>nodefs&lt;/code> 文件系统的空间。
kubelet 始终根据 &lt;code>nodefs&lt;/code> 所表示的文件系统来报告临时存储容量和分配情况；
当临时写入操作实际上是写到镜像文件系统时，这种差别可能会让人困惑。&lt;/p>
&lt;!--
### Future work
To fix the ephemeral storage reporting limitations and provide more configuration options to the container runtime, SIG Node are working on [KEP-4191](http://kep.k8s.io/4191).
In KEP-4191, Kubernetes will detect if the writeable layer is separated from the read-only layer (images).
This would allow us to have all ephemeral storage, including the writeable layer, on the same disk as well as allowing for a separate disk for images.
-->
&lt;h3 id="future-work">后续工作 &lt;/h3>
&lt;p>为了解决临时存储报告相关的限制并为容器运行时提供更多配置选项，SIG Node
正在处理 &lt;a href="http://kep.k8s.io/4191">KEP-4191&lt;/a>。在 KEP-4191 中，
Kubernetes 将检测可写层是否与只读层（镜像）分离。
这种检测使我们可以将包括可写层在内的所有临时存储放在同一磁盘上，同时也可以为镜像使用单独的磁盘。&lt;/p>
&lt;!--
### Getting involved
If you would like to get involved, you can
join [Kubernetes Node Special-Interest-Group](https://github.com/kubernetes/community/tree/master/sig-node) (SIG).
If you would like to share feedback, you can do so on our
[#sig-node](https://kubernetes.slack.com/archives/C0BP8PW9G) Slack channel.
If you're not already part of that Slack workspace, you can visit https://slack.k8s.io/ for an invitation.
-->
&lt;h3 id="getting-involved">参与其中 &lt;/h3>
&lt;p>如果你想参与其中，可以加入
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-node">Kubernetes Node 特别兴趣小组&lt;/a>（SIG）。&lt;/p>
&lt;p>如果你想分享反馈，可以分享到我们的
&lt;a href="https://kubernetes.slack.com/archives/C0BP8PW9G">#sig-node&lt;/a> Slack 频道。
如果你还没有加入该 Slack 工作区，可以访问 &lt;a href="https://slack.k8s.io/">https://slack.k8s.io/&lt;/a> 获取邀请。&lt;/p>
&lt;!--
Special thanks to all the contributors who provided great reviews, shared valuable insights or suggested the topic idea.
-->
&lt;p>特别感谢所有提供出色评审、分享宝贵见解或建议主题想法的贡献者。&lt;/p>
&lt;ul>
&lt;li>Peter Hunt&lt;/li>
&lt;li>Mrunal Patel&lt;/li>
&lt;li>Ryan Phillips&lt;/li>
&lt;li>Gaurav Singh&lt;/li>
&lt;/ul></description></item><item><title>Kubernetes 1.29 中的上下文日志生成：更好的故障排除和增强的日志记录</title><link>https://kubernetes.io/zh-cn/blog/2023/12/20/contextual-logging-in-kubernetes-1-29/</link><pubDate>Wed, 20 Dec 2023 09:30:00 -0800</pubDate><guid>https://kubernetes.io/zh-cn/blog/2023/12/20/contextual-logging-in-kubernetes-1-29/</guid><description>
&lt;!--
layout: blog
title: "Contextual logging in Kubernetes 1.29: Better troubleshooting and enhanced logging"
slug: contextual-logging-in-kubernetes-1-29
date: 2023-12-20T09:30:00-08:00
canonicalUrl: https://www.kubernetes.dev/blog/2023/12/20/contextual-logging/
-->
&lt;!--
**Authors**: [Mengjiao Liu](https://github.com/mengjiao-liu/) (DaoCloud), [Patrick Ohly](https://github.com/pohly) (Intel)
-->
&lt;p>&lt;strong>作者&lt;/strong>：&lt;a href="https://github.com/mengjiao-liu/">Mengjiao Liu&lt;/a> (DaoCloud), &lt;a href="https://github.com/pohly">Patrick Ohly&lt;/a> (Intel)&lt;/p>
&lt;p>&lt;strong>译者&lt;/strong>：&lt;a href="https://github.com/mengjiao-liu/">Mengjiao Liu&lt;/a> (DaoCloud)&lt;/p>
&lt;!--
On behalf of the [Structured Logging Working Group](https://github.com/kubernetes/community/blob/master/wg-structured-logging/README.md)
and [SIG Instrumentation](https://github.com/kubernetes/community/tree/master/sig-instrumentation#readme),
we are pleased to announce that the contextual logging feature
introduced in Kubernetes v1.24 has now been successfully migrated to
two components (kube-scheduler and kube-controller-manager)
as well as some directories. This feature aims to provide more useful logs
for better troubleshooting of Kubernetes and to empower developers to enhance Kubernetes.
-->
&lt;p>代表&lt;a href="https://github.com/kubernetes/community/blob/master/wg-structed-logging/README.md">结构化日志工作组&lt;/a>和
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-instrumentation#readme">SIG Instrumentation&lt;/a>，
我们很高兴地宣布在 Kubernetes v1.24 中引入的上下文日志记录功能现已成功迁移了两个组件（kube-scheduler 和 kube-controller-manager）
以及一些目录。该功能旨在为 Kubernetes 提供更多有用的日志以更好地进行故障排除，并帮助开发人员增强 Kubernetes。&lt;/p>
&lt;!--
## What is contextual logging?
[Contextual logging](https://github.com/kubernetes/enhancements/tree/master/keps/sig-instrumentation/3077-contextual-logging)
is based on the [go-logr](https://github.com/go-logr/logr#a-minimal-logging-api-for-go) API.
The key idea is that libraries are passed a logger instance by their caller
and use that for logging instead of accessing a global logger.
The binary decides the logging implementation, not the libraries.
The go-logr API is designed around structured logging and supports attaching
additional information to a logger.
-->
&lt;h2 id="what-is-contextual-logging">上下文日志记录是什么？ &lt;/h2>
&lt;p>&lt;a href="https://github.com/kubernetes/enhancements/tree/master/keps/sig-instrumentation/3077-contextual-logging">上下文日志记录&lt;/a>基于
&lt;a href="https://github.com/go-logr/logr#a-minimal-logging-api-for-go">go-logr&lt;/a> API。
关键思想是调用者将一个日志生成器实例传递给库，并使用它进行日志记录而不是访问全局日志生成器。
二进制文件而不是库负责选择日志记录的实现。go-logr API 围绕结构化日志记录而设计，并支持向日志生成器提供额外信息。&lt;/p>
&lt;!--
This enables additional use cases:
- The caller can attach additional information to a logger:
- [WithName](&lt;https://pkg.go.dev/github.com/go-logr/logr#Logger.WithName>) adds a "logger" key with the names concatenated by a dot as value
- [WithValues](&lt;https://pkg.go.dev/github.com/go-logr/logr#Logger.WithValues>) adds key/value pairs
When passing this extended logger into a function, and the function uses it
instead of the global logger, the additional information is then included
in all log entries, without having to modify the code that generates the log entries.
This is useful in highly parallel applications where it can become hard to identify
all log entries for a certain operation, because the output from different operations gets interleaved.
- When running unit tests, log output can be associated with the current test.
Then, when a test fails, only the log output of the failed test gets shown by go test.
That output can also be more verbose by default because it will not get shown for successful tests.
Tests can be run in parallel without interleaving their output.
-->
&lt;p>这一设计可以支持某些额外的使用场景：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>调用者可以为日志生成器提供额外的信息：&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://pkg.go.dev/github.com/go-logr/logr#Logger.WithName">WithName&lt;/a> 添加一个 “logger” 键，
并用句点（.）将名称的各个部分串接起来作为取值&lt;/li>
&lt;li>&lt;a href="https://pkg.go.dev/github.com/go-logr/logr#Logger.WithValues">WithValues&lt;/a> 添加键/值对&lt;/li>
&lt;/ul>
&lt;p>当将此经过扩展的日志生成器传递到函数中，并且该函数使用它而不是全局日志生成器时，
所有日志条目中都会包含所给的额外信息，而无需修改生成日志条目的代码。
这一特点在高度并行的应用中非常有用。在这类应用中，很难辨识某操作的所有日志条目，因为不同操作的输出是交错的。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>运行单元测试时，日志输出可以与当前测试相关联。且当测试失败时，go test 仅显示失败测试的日志输出。
默认情况下，该输出也可能更详细，因为它不会在成功的测试中显示。测试可以并行运行，而无需交错输出。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!--
One of the design decisions for contextual logging was to allow attaching a logger as value to a `context.Context`.
Since the logger encapsulates all aspects of the intended logging for the call,
it is *part* of the context, and not just *using* it. A practical advantage is that many APIs
already have a `ctx` parameter or can add one. This provides additional advantages, like being able to
get rid of `context.TODO()` calls inside the functions.
-->
&lt;p>上下文日志记录的设计决策之一是允许将日志生成器作为值附加到 &lt;code>context.Context&lt;/code> 之上。
由于日志生成器封装了调用所预期的、与日志记录相关的所有元素，
因此它是 context 的&lt;strong>一部分&lt;/strong>，而不仅仅是&lt;strong>使用&lt;/strong>它。这一设计的一个比较实际的优点是，
许多 API 已经有一个 &lt;code>ctx&lt;/code> 参数，或者可以添加一个 &lt;code>ctx&lt;/code> 参数。
进而产生的额外好处还包括比如可以去掉函数内的 &lt;code>context.TODO()&lt;/code> 调用。&lt;/p>
&lt;!--
## How to use it
The contextual logging feature is alpha starting from Kubernetes v1.24,
so it requires the `ContextualLogging` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) to be enabled.
If you want to test the feature while it is alpha, you need to enable this feature gate
on the `kube-controller-manager` and the `kube-scheduler`.
-->
&lt;h2 id="how-to-use-it">如何使用它 &lt;/h2>
&lt;p>从 Kubernetes v1.24 开始，上下文日志记录功能处于 Alpha 状态，因此它需要启用
&lt;code>ContextualLogging&lt;/code> &lt;a href="https://kubernetes.io/zh-cn/docs/reference/command-line-tools-reference/feature-gates/">特性门控&lt;/a>。
如果你想在该功能处于 Alpha 状态时对其进行测试，则需要在 &lt;code>kube-controller-manager&lt;/code> 和 &lt;code>kube-scheduler&lt;/code> 上启用此特性门控。&lt;/p>
&lt;!--
For the `kube-scheduler`, there is one thing to note, in addition to enabling
the `ContextualLogging` feature gate, instrumentation also depends on log verbosity.
To avoid slowing down the scheduler with the logging instrumentation for contextual logging added for 1.29,
it is important to choose carefully when to add additional information:
- At `-v3` or lower, only `WithValues("pod")` is used once per scheduling cycle.
This has the intended effect that all log messages for the cycle include the pod information.
Once contextual logging is GA, "pod" key/value pairs can be removed from all log calls.
- At `-v4` or higher, richer log entries get produced where `WithValues` is also used for the node (when applicable)
and `WithName` is used for the current operation and plugin.
-->
&lt;p>对于 &lt;code>kube-scheduler&lt;/code>，有一点需要注意，除了启用 &lt;code>ContextualLogging&lt;/code> 特性门控之外，
插桩行为还取决于日志的详细程度设置。
为了避免因 1.29 添加的上下文日志记录工具而降低调度程序的速度，请务必仔细选择何时添加额外的信息：&lt;/p>
&lt;ul>
&lt;li>在 &lt;code>-v3&lt;/code> 或更低日志级别中，每个调度周期仅使用一次 &lt;code>WithValues(&amp;quot;pod&amp;quot;)&lt;/code>。
这样做可以达到预期效果，即该周期的所有日志消息都包含 Pod 信息。
一旦上下文日志记录特性到达 GA 阶段，就可以从所有日志调用中删除 “pod” 键值对。&lt;/li>
&lt;li>在 &lt;code>-v4&lt;/code> 或更高日志级别中，会生成更丰富的日志条目，其中 &lt;code>WithValues&lt;/code> 也用于节点（如果适用），&lt;code>WithName&lt;/code> 用于当前操作和插件。&lt;/li>
&lt;/ul>
&lt;!--
Here is an example that demonstrates the effect:
-->
&lt;p>下面的示例展示了这一效果：&lt;/p>
&lt;blockquote>
&lt;p>I1113 08:43:37.029524 87144 default_binder.go:53] &amp;quot;Attempting to bind pod to node&amp;quot; &lt;strong>logger=&amp;quot;Bind.DefaultBinder&amp;quot;&lt;/strong> &lt;strong>pod&lt;/strong>=&amp;quot;kube-system/coredns-69cbfb9798-ms4pq&amp;quot; &lt;strong>node&lt;/strong>=&amp;quot;127.0.0.1&amp;quot;&lt;/p>
&lt;/blockquote>
&lt;!--
The immediate benefit is that the operation and plugin name are visible in `logger`.
`pod` and `node` are already logged as parameters in individual log calls in `kube-scheduler` code.
Once contextual logging is supported by more packages outside of `kube-scheduler`,
they will also be visible there (for example, client-go). Once it is GA,
log calls can be simplified to avoid repeating those values.
-->
&lt;p>这一设计的直接好处是在 &lt;code>logger&lt;/code> 中可以看到操作和插件名称。&lt;code>pod&lt;/code> 和 &lt;code>node&lt;/code> 已作为参数记录在
&lt;code>kube-scheduler&lt;/code> 代码中的各个日志调用中。一旦 &lt;code>kube-scheduler&lt;/code> 之外的其他包也支持上下文日志记录，
在这些包（例如，client-go）中也可以看到操作和插件名称。
一旦上下文日志记录特性到达 GA 阶段，就可以简化日志调用以避免重复这些值。&lt;/p>
&lt;!--
In `kube-controller-manager`, `WithName` is used to add the user-visible controller name to log output,
for example:
-->
&lt;p>在 &lt;code>kube-controller-manager&lt;/code> 中，&lt;code>WithName&lt;/code> 被用来在日志中输出用户可见的控制器名称，例如：&lt;/p>
&lt;blockquote>
&lt;p>I1113 08:43:29.284360 87141 graph_builder.go:285] &amp;quot;garbage controller monitor not synced: no monitors&amp;quot; &lt;strong>logger=&amp;quot;garbage-collector-controller&amp;quot;&lt;/strong>&lt;/p>
&lt;/blockquote>
&lt;!--
The `logger=”garbage-collector-controller”` was added by the `kube-controller-manager` core
when instantiating that controller and appears in all of its log entries - at least as long as the code
that it calls supports contextual logging. Further work is needed to convert shared packages like client-go.
-->
&lt;p>&lt;code>logger=”garbage-collector-controller”&lt;/code> 是由 &lt;code>kube-controller-manager&lt;/code>
核心代码在实例化该控制器时添加的，会出现在其所有日志条目中——只要它所调用的代码支持上下文日志记录。
转换像 client-go 这样的共享包还需要额外的工作。&lt;/p>
&lt;!--
## Performance impact
Supporting contextual logging in a package, i.e. accepting a logger from a caller, is cheap.
No performance impact was observed for the `kube-scheduler`. As noted above,
adding `WithName` and `WithValues` needs to be done more carefully.
-->
&lt;h2 id="performance-impact">性能影响 &lt;/h2>
&lt;p>在包中支持上下文日志记录，即接受来自调用者的记录器，成本很低。
没有观察到 &lt;code>kube-scheduler&lt;/code> 的性能影响。如上所述，添加 &lt;code>WithName&lt;/code> 和 &lt;code>WithValues&lt;/code> 需要更加小心。&lt;/p>
&lt;!--
In Kubernetes 1.29, enabling contextual logging at production verbosity (`-v3` or lower)
caused no measurable slowdown for the `kube-scheduler` and is not expected for the `kube-controller-manager` either.
At debug levels, a 28% slowdown for some test cases is still reasonable given that the resulting logs make debugging easier.
For details, see the [discussion around promoting the feature to beta](https://github.com/kubernetes/enhancements/pull/4219#issuecomment-1807811995).
-->
&lt;p>在 Kubernetes 1.29 中，以生产环境日志详细程度（&lt;code>-v3&lt;/code> 或更低）启用上下文日志不会导致 &lt;code>kube-scheduler&lt;/code> 速度出现明显的减慢，
并且 &lt;code>kube-controller-manager&lt;/code> 速度也不会出现明显的减慢。在 debug 级别，考虑到生成的日志使调试更容易，某些测试用例减速 28% 仍然是合理的。
详细信息请参阅&lt;a href="https://github.com/kubernetes/enhancements/pull/4219#issuecomment-1807811995">有关将该特性升级为 Beta 版的讨论&lt;/a>。&lt;/p>
&lt;!--
## Impact on downstream users
Log output is not part of the Kubernetes API and changes regularly in each release,
whether it is because developers work on the code or because of the ongoing conversion
to structured and contextual logging.
If downstream users have dependencies on specific logs,
they need to be aware of how this change affects them.
-->
&lt;h2 id="impact-on-downstream-users">对下游用户的影响 &lt;/h2>
&lt;p>日志输出不是 Kubernetes API 的一部分，并且经常在每个版本中都会出现更改，
无论是因为开发人员修改代码还是因为不断转换为结构化和上下文日志记录。&lt;/p>
&lt;p>如果下游用户对特定日志有依赖性，他们需要了解此更改如何影响他们。&lt;/p>
&lt;!--
## Further reading
- Read the [Contextual Logging in Kubernetes 1.24](https://www.kubernetes.dev/blog/2022/05/25/contextual-logging/) article.
- Read the [KEP-3077: contextual logging](https://github.com/kubernetes/enhancements/tree/master/keps/sig-instrumentation/3077-contextual-logging).
-->
&lt;h2 id="further-reading">进一步阅读 &lt;/h2>
&lt;ul>
&lt;li>参阅 &lt;a href="https://www.kubernetes.dev/blog/2022/05/25/contextual-logging/">Kubernetes 1.24 中的上下文日志记录&lt;/a> 。&lt;/li>
&lt;li>参阅 &lt;a href="https://github.com/kubernetes/enhancements/tree/master/keps/sig-instrumentation/3077-contextual-logging">KEP-3077：上下文日志记录&lt;/a>。&lt;/li>
&lt;/ul>
&lt;!--
## Get involved
If you're interested in getting involved, we always welcome new contributors to join us.
Contextual logging provides a fantastic opportunity for you to contribute to Kubernetes development and make a meaningful impact.
By joining [Structured Logging WG](https://github.com/kubernetes/community/tree/master/wg-structured-logging),
you can actively participate in the development of Kubernetes and make your first contribution.
It's a great way to learn and engage with the community while gaining valuable experience.
-->
&lt;h2 id="get-involved">如何参与 &lt;/h2>
&lt;p>如果你有兴趣参与，我们始终欢迎新的贡献者加入我们。上下文日志记录为你参与
Kubernetes 开发做出贡献并产生有意义的影响提供了绝佳的机会。
通过加入 &lt;a href="https://github.com/kubernetes/community/tree/master/wg-structured-logging">Structured Logging WG&lt;/a>，
你可以积极参与 Kubernetes 的开发并做出你的第一个贡献。这是学习和参与社区并获得宝贵经验的好方法。&lt;/p>
&lt;!--
We encourage you to explore the repository and familiarize yourself with the ongoing discussions and projects.
It's a collaborative environment where you can exchange ideas, ask questions, and work together with other contributors.
-->
&lt;p>我们鼓励你探索存储库并熟悉正在进行的讨论和项目。这是一个协作环境，你可以在这里交流想法、提出问题并与其他贡献者一起工作。&lt;/p>
&lt;!--
If you have any questions or need guidance, don't hesitate to reach out to us
and you can do so on our [public Slack channel](https://kubernetes.slack.com/messages/wg-structured-logging).
If you're not already part of that Slack workspace, you can visit [https://slack.k8s.io/](https://slack.k8s.io/)
for an invitation.
-->
&lt;p>如果你有任何疑问或需要指导，请随时与我们联系，你可以通过我们的&lt;a href="https://kubernetes.slack.com/messages/wg-structured-logging">公共 Slack 频道&lt;/a>联系我们。
如果你尚未加入 Slack 工作区，可以访问 &lt;a href="https://slack.k8s.io/">https://slack.k8s.io/&lt;/a> 获取邀请。&lt;/p>
&lt;!--
We would like to express our gratitude to all the contributors who provided excellent reviews,
shared valuable insights, and assisted in the implementation of this feature (in alphabetical order):
-->
&lt;p>我们要向所有提供精彩评论、分享宝贵见解并协助实施此功能的贡献者表示感谢（按字母顺序排列）：&lt;/p>
&lt;ul>
&lt;li>Aldo Culquicondor (&lt;a href="https://github.com/alculquicondor">alculquicondor&lt;/a>)&lt;/li>
&lt;li>Andy Goldstein (&lt;a href="https://github.com/ncdc">ncdc&lt;/a>)&lt;/li>
&lt;li>Feruzjon Muyassarov (&lt;a href="https://github.com/fmuyassarov">fmuyassarov&lt;/a>)&lt;/li>
&lt;li>Freddie (&lt;a href="https://github.com/freddie400">freddie400&lt;/a>)&lt;/li>
&lt;li>JUN YANG (&lt;a href="https://github.com/yangjunmyfm192085">yangjunmyfm192085&lt;/a>)&lt;/li>
&lt;li>Kante Yin (&lt;a href="https://github.com/kerthcet">kerthcet&lt;/a>)&lt;/li>
&lt;li>Kiki (&lt;a href="https://github.com/carlory">carlory&lt;/a>)&lt;/li>
&lt;li>Lucas Severo Alve (&lt;a href="https://github.com/knelasevero">knelasevero&lt;/a>)&lt;/li>
&lt;li>Maciej Szulik (&lt;a href="https://github.com/soltysh">soltysh&lt;/a>)&lt;/li>
&lt;li>Mengjiao Liu (&lt;a href="https://github.com/mengjiao-liu">mengjiao-liu&lt;/a>)&lt;/li>
&lt;li>Naman Lakhwani (&lt;a href="https://github.com/Namanl2001">Namanl2001&lt;/a>)&lt;/li>
&lt;li>Oksana Baranova (&lt;a href="https://github.com/oxxenix">oxxenix&lt;/a>)&lt;/li>
&lt;li>Patrick Ohly (&lt;a href="https://github.com/pohly">pohly&lt;/a>)&lt;/li>
&lt;li>songxiao-wang87 (&lt;a href="https://github.com/songxiao-wang87">songxiao-wang87&lt;/a>)&lt;/li>
&lt;li>Tim Allclai (&lt;a href="https://github.com/tallclair">tallclair&lt;/a>)&lt;/li>
&lt;li>ZhangYu (&lt;a href="https://github.com/Octopusjust">Octopusjust&lt;/a>)&lt;/li>
&lt;li>Ziqi Zhao (&lt;a href="https://github.com/fatsheep9146">fatsheep9146&lt;/a>)&lt;/li>
&lt;li>Zac (&lt;a href="https://github.com/249043822">249043822&lt;/a>)&lt;/li>
&lt;/ul></description></item><item><title>Kubernetes 1.29: 解耦污点管理器与节点生命周期控制器</title><link>https://kubernetes.io/zh-cn/blog/2023/12/19/kubernetes-1-29-taint-eviction-controller/</link><pubDate>Tue, 19 Dec 2023 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2023/12/19/kubernetes-1-29-taint-eviction-controller/</guid><description>
&lt;!--
layout: blog
title: "Kubernetes 1.29: Decoupling taint-manager from node-lifecycle-controller"
date: 2023-12-19
slug: kubernetes-1-29-taint-eviction-controller
-->
&lt;!--
**Authors:** Yuan Chen (Apple), Andrea Tosatto (Apple)
-->
&lt;p>&lt;strong>作者:&lt;/strong> Yuan Chen (Apple), Andrea Tosatto (Apple)&lt;/p>
&lt;p>&lt;strong>译者:&lt;/strong> Allen Zhang&lt;/p>
&lt;!--
This blog discusses a new feature in Kubernetes 1.29 to improve the handling of taint-based pod eviction.
-->
&lt;p>这篇博客讨论在 Kubernetes 1.29 中基于污点的 Pod 驱逐处理的新特性。&lt;/p>
&lt;!--
## Background
-->
&lt;h2 id="背景">背景&lt;/h2>
&lt;!--
In Kubernetes 1.29, an improvement has been introduced to enhance the taint-based pod eviction handling on nodes.
This blog discusses the changes made to node-lifecycle-controller
to separate its responsibilities and improve overall code maintainability.
-->
&lt;p>在 Kubernetes 1.29 中引入了一项改进，以加强节点上基于污点的 Pod 驱逐处理。
本文将讨论对节点生命周期控制器（node-lifecycle-controller）所做的更改，以分离职责并提高代码的整体可维护性。&lt;/p>
&lt;!--
## Summary of changes
-->
&lt;h2 id="变动摘要">变动摘要&lt;/h2>
&lt;!--
node-lifecycle-controller previously combined two independent functions:
-->
&lt;p>节点生命周期控制器之前组合了两个独立的功能：&lt;/p>
&lt;!--
- Adding a pre-defined set of `NoExecute` taints to Node based on Node's condition.
- Performing pod eviction on `NoExecute` taint.
-->
&lt;ul>
&lt;li>基于节点的条件为节点新增了一组预定义的污点 &lt;code>NoExecute&lt;/code>。&lt;/li>
&lt;li>对有 &lt;code>NoExecute&lt;/code> 污点的 Pod 执行驱逐操作。&lt;/li>
&lt;/ul>
&lt;!--
With the Kubernetes 1.29 release, the taint-based eviction implementation has been
moved out of node-lifecycle-controller into a separate and independent component called taint-eviction-controller.
This separation aims to disentangle code, enhance code maintainability,
and facilitate future extensions to either component.
-->
&lt;p>在 Kubernetes 1.29 版本中，基于污点的驱逐实现已经从节点生命周期控制器中移出，
成为一个名为污点驱逐控制器（taint-eviction-controller）的独立组件。
旨在拆分代码，提高代码的可维护性，并方便未来对这两个组件进行扩展。&lt;/p>
&lt;!--
As part of the change, additional metrics were introduced to help you monitor taint-based pod evictions:
-->
&lt;p>以下新指标可以帮助你监控基于污点的 Pod 驱逐：&lt;/p>
&lt;!--
- `pod_deletion_duration_seconds` measures the latency between the time when a taint effect
has been activated for the Pod and its deletion via taint-eviction-controller.
- `pod_deletions_total` reports the total number of Pods deleted by taint-eviction-controller since its start.
-->
&lt;ul>
&lt;li>&lt;code>pod_deletion_duration_seconds&lt;/code> 表示当 Pod 的污点被激活直到这个 Pod 被污点驱逐控制器删除的延迟时间。&lt;/li>
&lt;li>&lt;code>pod_deletions_total&lt;/code> 表示自从污点驱逐控制器启动以来驱逐的 Pod 总数。&lt;/li>
&lt;/ul>
&lt;!--
## How to use the new feature?
-->
&lt;h2 id="如何使用这个新特性">如何使用这个新特性？&lt;/h2>
&lt;!--
A new feature gate, `SeparateTaintEvictionController`, has been added. The feature is enabled by default as Beta in Kubernetes 1.29.
Please refer to the [feature gate document](/docs/reference/command-line-tools-reference/feature-gates/).
-->
&lt;p>名为 &lt;code>SeparateTaintEvictionController&lt;/code> 的特性门控已被添加。该特性在 Kubernetes 1.29 Beta 版本中默认开启。
详情请参阅&lt;a href="https://kubernetes.io/zh-cn/docs/reference/command-line-tools-reference/feature-gates/">特性门控&lt;/a>。&lt;/p>
&lt;!--
When this feature is enabled, users can optionally disable taint-based eviction by setting `--controllers=-taint-eviction-controller`
in kube-controller-manager.
-->
&lt;p>当这项特性启用时，用户可以通过在 &lt;code>kube-controller-manager&lt;/code> 通过手动设置
&lt;code>--controllers=-taint-eviction-controller&lt;/code> 的方式来禁用基于污点的驱逐功能。&lt;/p>
&lt;!--
To disable the new feature and use the old taint-manager within node-lifecylecycle-controller , users can set the feature gate `SeparateTaintEvictionController=false`.
-->
&lt;p>如果想禁用该特性并在节点生命周期中使用旧版本污点管理器，用户可以通过设置 &lt;code>SeparateTaintEvictionController=false&lt;/code> 来禁用。&lt;/p>
&lt;!--
## Use cases
-->
&lt;h2 id="使用案例">使用案例&lt;/h2>
&lt;!--
This new feature will allow cluster administrators to extend and enhance the default
taint-eviction-controller and even replace the default taint-eviction-controller with a
custom implementation to meet different needs. An example is to better support
stateful workloads that use PersistentVolume on local disks.
-->
&lt;p>该特性将允许集群管理员扩展、增强默认的污点驱逐控制器，并且可以使用自定义的实现方式替换默认的污点驱逐控制器以满足不同的需要。
例如：更好地支持在本地磁盘的持久卷中的有状态工作负载。&lt;/p>
&lt;!--
## FAQ
-->
&lt;h2 id="faq">FAQ&lt;/h2>
&lt;!--
**Does this feature change the existing behavior of taint-based pod evictions?**
-->
&lt;p>&lt;strong>该特性是否会改变现有的基于污点的 Pod 驱逐行为？&lt;/strong>&lt;/p>
&lt;!--
No, the taint-based pod eviction behavior remains unchanged. If the feature gate
`SeparateTaintEvictionController` is turned off, the legacy node-lifecycle-controller with taint-manager will continue to be used.
-->
&lt;p>不会，基于污点的 Pod 驱逐行为保持不变。如果特性门控 &lt;code>SeparateTaintEvictionController&lt;/code> 被关闭，
将继续使用之前的节点生命周期管理器中的污点管理器。&lt;/p>
&lt;!--
**Will enabling/using this feature result in an increase in the time taken by any operations covered by existing SLIs/SLOs?**
-->
&lt;p>&lt;strong>启用/使用此特性是否会导致现有 SLI/SLO 中任何操作的用时增加？&lt;/strong>&lt;/p>
&lt;!--
No.
-->
&lt;p>不会。&lt;/p>
&lt;!--
**Will enabling/using this feature result in an increase in resource usage (CPU, RAM, disk, IO, ...)?**
-->
&lt;p>&lt;strong>启用/使用此特性是否会导致资源利用量（如 CPU、内存、磁盘、IO 等）的增加？&lt;/strong>&lt;/p>
&lt;!--
The increase in resource usage by running a separate `taint-eviction-controller` will be negligible.
-->
&lt;p>运行单独的 &lt;code>taint-eviction-controller&lt;/code> 所增加的资源利用量可以忽略不计。&lt;/p>
&lt;!--
## Learn more
-->
&lt;h2 id="了解更多">了解更多&lt;/h2>
&lt;!--
For more details, refer to the [KEP](http://kep.k8s.io/3902).
-->
&lt;p>更多细节请参考 &lt;a href="http://kep.k8s.io/3902">KEP&lt;/a>。&lt;/p>
&lt;!--
## Acknowledgments
-->
&lt;h2 id="特别鸣谢">特别鸣谢&lt;/h2>
&lt;!--
As with any Kubernetes feature, multiple community members have contributed, from
writing the KEP to implementing the new controller and reviewing the KEP and code. Special thanks to:
-->
&lt;p>与任何 Kubernetes 特性一样，从撰写 KEP 到实现新控制器再到审核 KEP 和代码，多名社区成员都做出了贡献，特别感谢：&lt;/p>
&lt;ul>
&lt;li>Aldo Culquicondor (@alculquicondor)&lt;/li>
&lt;li>Maciej Szulik (@soltysh)&lt;/li>
&lt;li>Filip Křepinský (@atiratree)&lt;/li>
&lt;li>Han Kang (@logicalhan)&lt;/li>
&lt;li>Wei Huang (@Huang-Wei)&lt;/li>
&lt;li>Sergey Kanzhelevi (@SergeyKanzhelev)&lt;/li>
&lt;li>Ravi Gudimetla (@ravisantoshgudimetla)&lt;/li>
&lt;li>Deep Debroy (@ddebroy)&lt;/li>
&lt;/ul></description></item><item><title>Kubernetes 1.29：PodReadyToStartContainers 状况进阶至 Beta</title><link>https://kubernetes.io/zh-cn/blog/2023/12/19/pod-ready-to-start-containers-condition-now-in-beta/</link><pubDate>Tue, 19 Dec 2023 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2023/12/19/pod-ready-to-start-containers-condition-now-in-beta/</guid><description>
&lt;!--
layout: blog
title: "Kubernetes 1.29: PodReadyToStartContainers Condition Moves to Beta"
date: 2023-12-19
slug: pod-ready-to-start-containers-condition-now-in-beta
-->
&lt;!--
**Authors**: Zefeng Chen (independent), Kevin Hannon (Red Hat)
-->
&lt;p>&lt;strong>作者&lt;/strong>：Zefeng Chen (independent), Kevin Hannon (Red Hat)&lt;/p>
&lt;p>&lt;strong>译者&lt;/strong>：&lt;a href="https://github.com/windsonsea">Michael Yao&lt;/a>&lt;/p>
&lt;!--
With the recent release of Kubernetes 1.29, the `PodReadyToStartContainers`
[condition](/docs/concepts/workloads/pods/pod-lifecycle/#pod-conditions) is
available by default.
The kubelet manages the value for that condition throughout a Pod's lifecycle,
in the status field of a Pod. The kubelet will use the `PodReadyToStartContainers`
condition to accurately surface the initialization state of a Pod,
from the perspective of Pod sandbox creation and network configuration by a container runtime.
-->
&lt;p>随着最近发布的 Kubernetes 1.29，&lt;code>PodReadyToStartContainers&lt;/code>
&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/pod-lifecycle/#pod-conditions">状况&lt;/a>默认可用。
kubelet 在 Pod 的整个生命周期中管理该状况的值，将其存储在 Pod 的状态字段中。
kubelet 将通过容器运行时从 Pod 沙箱创建和网络配置的角度使用 &lt;code>PodReadyToStartContainers&lt;/code>
状况准确地展示 Pod 的初始化状态，&lt;/p>
&lt;!--
## What's the motivation for this feature?
-->
&lt;h2 id="这个特性的动机是什么">这个特性的动机是什么？&lt;/h2>
&lt;!--
Cluster administrators did not have a clear and easily accessible way to view the completion of Pod's sandbox creation
and initialization. As of 1.28, the `Initialized` condition in Pods tracks the execution of init containers.
However, it has limitations in accurately reflecting the completion of sandbox creation and readiness to start containers for all Pods in a cluster.
This distinction is particularly important in multi-tenant clusters where tenants own the Pod specifications, including the set of init containers,
while cluster administrators manage storage plugins, networking plugins, and container runtime handlers.
Therefore, there is a need for an improved mechanism to provide cluster administrators with a clear and
comprehensive view of Pod sandbox creation completion and container readiness.
-->
&lt;p>集群管理员以前没有明确且轻松访问的方式来查看 Pod 沙箱创建和初始化的完成情况。
从 1.28 版本开始，Pod 中的 &lt;code>Initialized&lt;/code> 状况跟踪 Init 容器的执行情况。
然而，它在准确反映沙箱创建完成和容器准备启动的方面存在一些限制，无法适用于集群中的所有 Pod。
在多租户集群中，这种区别尤为重要，租户拥有包括 Init 容器集合在内的 Pod 规约，
而集群管理员管理存储插件、网络插件和容器运行时处理程序。
因此，需要改进这个机制，以便为集群管理员提供清晰和全面的 Pod 沙箱创建完成和容器就绪状态的视图。&lt;/p>
&lt;!--
## What's the benefit?
1. Improved Visibility: Cluster administrators gain a clearer and more comprehensive view of Pod sandbox
creation completion and container readiness.
This enhanced visibility allows them to make better-informed decisions and troubleshoot issues more effectively.
-->
&lt;h2 id="这个特性有什么好处">这个特性有什么好处？&lt;/h2>
&lt;ol>
&lt;li>改进可见性：集群管理员可以更清晰和全面地查看 Pod 沙箱的创建完成和容器的就绪状态。
这种增强的可见性使他们能够做出更明智的决策，并更有效地解决问题。&lt;/li>
&lt;/ol>
&lt;!--
2. Metric Collection and Monitoring: Monitoring services can leverage the fields associated with
the `PodReadyToStartContainers` condition to report sandbox creation state and latency.
Metrics can be collected at per-Pod cardinality or aggregated based on various
properties of the Pod, such as `volumes`, `runtimeClassName`, custom annotations for CNI
and IPAM plugins or arbitrary labels and annotations, and `storageClassName` of
PersistentVolumeClaims.
This enables comprehensive monitoring and analysis of Pod readiness across the cluster.
-->
&lt;ol start="2">
&lt;li>指标收集和监控：监控服务可以利用与 &lt;code>PodReadyToStartContainers&lt;/code> 状况相关的字段来报告沙箱创建状态和延迟。
可以按照每个 Pod 的基数进行指标收集，或者根据 Pod 的各种属性进行聚合，例如
&lt;code>volumes&lt;/code>、&lt;code>runtimeClassName&lt;/code>、CNI 和 IPAM 插件的自定义注解，
以及任意标签和注解，以及 PersistentVolumeClaims 的 &lt;code>storageClassName&lt;/code>。
这样可以全面监控和分析集群中 Pod 的就绪状态。&lt;/li>
&lt;/ol>
&lt;!--
3. Enhanced Troubleshooting: With a more accurate representation of Pod sandbox creation and container readiness,
cluster administrators can quickly identify and address any issues that may arise during the initialization process.
This leads to improved troubleshooting capabilities and reduced downtime.
-->
&lt;ol start="3">
&lt;li>增强故障排查能力：通过更准确地表示 Pod 沙箱的创建和容器的就绪状态，
集群管理员可以快速识别和解决初始化过程中可能出现的任何问题。
这将提高故障排查能力，并减少停机时间。&lt;/li>
&lt;/ol>
&lt;!--
### What’s next?
Due to feedback and adoption, the Kubernetes team promoted `PodReadyToStartContainersCondition` to Beta in 1.29.
Your comments will help determine if this condition continues forward to get promoted to GA,
so please submit additional feedback on this feature!
-->
&lt;h3 id="后续事项">后续事项&lt;/h3>
&lt;p>鉴于反馈和采用情况，Kubernetes 团队在 1.29 版本中将 &lt;code>PodReadyToStartContainersCondition&lt;/code>
进阶至 Beta版。你的评论将有助于确定该状况是否继续并晋升至 GA，请针对此特性提交更多反馈！&lt;/p>
&lt;!--
### How can I learn more?
Please check out the
[documentation](/docs/concepts/workloads/pods/pod-lifecycle/) for the
`PodReadyToStartContainersCondition` to learn more about it and how it fits in relation to
other Pod conditions.
-->
&lt;h3 id="如何了解更多">如何了解更多？&lt;/h3>
&lt;p>请查看关于 &lt;code>PodReadyToStartContainersCondition&lt;/code>
的&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/pod-lifecycle/">文档&lt;/a>，
以了解其更多信息及其与其他 Pod 状况的关系。&lt;/p>
&lt;!--
### How to get involved?
This feature is driven by the SIG Node community. Please join us to connect with
the community and share your ideas and feedback around the above feature and
beyond. We look forward to hearing from you!
-->
&lt;h3 id="如何参与">如何参与？&lt;/h3>
&lt;p>该特性由 SIG Node 社区推动。请加入我们，与社区建立联系，分享你对这一特性及更多内容的想法和反馈。
我们期待倾听你的建议！&lt;/p></description></item><item><title>Kubernetes 1.29 新的 Alpha 特性：Service 的负载均衡器 IP 模式</title><link>https://kubernetes.io/zh-cn/blog/2023/12/18/kubernetes-1-29-feature-loadbalancer-ip-mode-alpha/</link><pubDate>Mon, 18 Dec 2023 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2023/12/18/kubernetes-1-29-feature-loadbalancer-ip-mode-alpha/</guid><description>
&lt;!--
layout: blog
title: "Kubernetes 1.29: New (alpha) Feature, Load Balancer IP Mode for Services"
date: 2023-12-18
slug: kubernetes-1-29-feature-loadbalancer-ip-mode-alpha
-->
&lt;!-- **Author:** [Aohan Yang](https://github.com/RyanAoh) -->
&lt;p>&lt;strong>作者：&lt;/strong> &lt;a href="https://github.com/RyanAoh">Aohan Yang&lt;/a>&lt;/p>
&lt;p>&lt;strong>译者：&lt;/strong> Allen Zhang&lt;/p>
&lt;!--
This blog introduces a new alpha feature in Kubernetes 1.29.
It provides a configurable approach to define how Service implementations,
exemplified in this blog by kube-proxy,
handle traffic from pods to the Service, within the cluster.
-->
&lt;p>本文介绍 Kubernetes 1.29 中一个新的 Alpha 特性。
此特性提供了一种可配置的方式用于定义 Service 的实现方式，本文中以
kube-proxy 为例介绍如何处理集群内从 Pod 到 Service 的流量。&lt;/p>
&lt;!--
## Background
-->
&lt;h2 id="背景">背景&lt;/h2>
&lt;!--
In older Kubernetes releases, the kube-proxy would intercept traffic that was destined for the IP
address associated with a Service of `type: LoadBalancer`. This happened whatever mode you used
for `kube-proxy`.
-->
&lt;p>在 Kubernetes 早期版本中，kube-proxy 会拦截指向 &lt;code>type: LoadBalancer&lt;/code> Service 关联
IP 地址的流量。这与你为 &lt;code>kube-proxy&lt;/code> 所使用的哪种模式无关。&lt;/p>
&lt;!--
The interception implemented the expected behavior (traffic eventually reaching the expected
endpoints behind the Service). The mechanism to make that work depended on the mode for kube-proxy;
on Linux, kube-proxy in iptables mode would redirecting packets directly to the endpoint; in ipvs mode,
kube-proxy would configure the load balancer's IP address to one interface on the node.
The motivation for implementing that interception was for two reasons:
-->
&lt;p>这种拦截实现了预期行为（流量最终会抵达服务后挂载的端点）。这种机制取决于 kube-proxy 的模式，在
Linux 中，运行于 iptables 模式下的 kube-proxy 会重定向数据包到后端端点；在 ipvs 模式下，
kube-proxy 会将负载均衡器的 IP 地址配置到节点的一个网络接口上。采用这种拦截有两个原因：&lt;/p>
&lt;!--
1. **Traffic path optimization:** Efficiently redirecting pod traffic - when a container in a pod sends an outbound
packet that is destined for the load balancer's IP address -
directly to the backend service by bypassing the load balancer.
-->
&lt;ol>
&lt;li>&lt;strong>流量路径优化：&lt;/strong> 高效地重定向 Pod 流量 - 当 Pod 中的容器发送指向负载均衡器 IP 地址的出站包时，
会绕过负载均衡器直接重定向到后端服务。&lt;/li>
&lt;/ol>
&lt;!--
2. **Handling load balancer packets:** Some load balancers send packets with the destination IP set to
the load balancer's IP address. As a result, these packets need to be routed directly to the correct backend (which
might not be local to that node), in order to avoid loops.
-->
&lt;ol start="2">
&lt;li>&lt;strong>处理负载均衡数据包：&lt;/strong> 有些负载均衡器发送的数据包设置目标 IP 为负载均衡器的 IP 地址。
因此，这些数据包需要被直接路由到正确的后端（可能不在该节点本地），以避免回环。&lt;/li>
&lt;/ol>
&lt;!--
## Problems
-->
&lt;h2 id="问题">问题&lt;/h2>
&lt;!--
However, there are several problems with the aforementioned behavior:
-->
&lt;p>然而，上述行为存在几个问题：&lt;/p>
&lt;!--
1. **[Source IP](https://github.com/kubernetes/kubernetes/issues/79783):**
Some cloud providers use the load balancer's IP as the source IP when
transmitting packets to the node. In the ipvs mode of kube-proxy,
there is a problem that health checks from the load balancer never return. This occurs because the reply packets
would be forward to the local interface `kube-ipvs0`(where the load balancer's IP is bound to)
and be subsequently ignored.
-->
&lt;ol>
&lt;li>&lt;strong>&lt;a href="https://github.com/kubernetes/kubernetes/issues/79783">源 IP（Source IP）&lt;/a>：&lt;/strong>
一些云厂商在传输数据包到节点时使用负载均衡器的 IP 地址作为源 IP。在 kube-proxy 的 ipvs 模式下，
存在负载均衡器健康检查永远不会返回的问题。原因是回复的数据包被转发到本地网络接口 &lt;code>kube-ipvs0&lt;/code>（绑定负载均衡器 IP 的接口）上并被忽略。&lt;/li>
&lt;/ol>
&lt;!--
2. **[Feature loss at load balancer level](https://github.com/kubernetes/kubernetes/issues/66607):**
Certain cloud providers offer features(such as TLS termination, proxy protocol, etc.) at the
load balancer level.
Bypassing the load balancer results in the loss of these features when the packet reaches the service
(leading to protocol errors).
-->
&lt;ol start="2">
&lt;li>&lt;strong>&lt;a href="https://github.com/kubernetes/kubernetes/issues/66607">负载均衡器层功能缺失&lt;/a>：&lt;/strong>
某些云厂商在负载均衡器层提供了部分特性（例如 TLS 终结、协议代理等）。
绕过负载均衡器会导致当数据包抵达后端服务时这些特性不会生效（导致协议错误等）。&lt;/li>
&lt;/ol>
&lt;!--
Even with the new alpha behaviour disabled (the default), there is a
[workaround](https://github.com/kubernetes/kubernetes/issues/66607#issuecomment-474513060)
that involves setting `.status.loadBalancer.ingress.hostname` for the Service, in order
to bypass kube-proxy binding.
But this is just a makeshift solution.
-->
&lt;p>即使新的 Alpha 特性默认关闭，也有&lt;a href="https://github.com/kubernetes/kubernetes/issues/66607#issuecomment-474513060">临时解决方案&lt;/a>，
即为 Service 设置 &lt;code>.status.loadBalancer.ingress.hostname&lt;/code> 以绕过 kube-proxy 绑定。
但这终究只是临时解决方案。&lt;/p>
&lt;!--
## Solution
-->
&lt;h2 id="解决方案">解决方案&lt;/h2>
&lt;!--
In summary, providing an option for cloud providers to disable the current behavior would be highly beneficial.
-->
&lt;p>总之，为云厂商提供选项以禁用当前这种行为大有裨益。&lt;/p>
&lt;!--
To address this, Kubernetes v1.29 introduces a new (alpha) `.status.loadBalancer.ingress.ipMode`
field for a Service.
This field specifies how the load balancer IP behaves and can be specified only when
the `.status.loadBalancer.ingress.ip` field is also specified.
-->
&lt;p>Kubernetes 1.29 版本为 Service 引入新的 Alpha 字段 &lt;code>.status.loadBalancer.ingress.ipMode&lt;/code> 以解决上述问题。
该字段指定负载均衡器 IP 的运行方式，并且只有在指定 &lt;code>.status.loadBalancer.ingress.ip&lt;/code> 字段时才能指定。&lt;/p>
&lt;!--
Two values are possible for `.status.loadBalancer.ingress.ipMode`: `"VIP"` and `"Proxy"`.
The default value is "VIP", meaning that traffic delivered to the node
with the destination set to the load balancer's IP and port will be redirected to the backend service by kube-proxy.
This preserves the existing behavior of kube-proxy.
The "Proxy" value is intended to prevent kube-proxy from binding the load balancer's IP address
to the node in both ipvs and iptables modes.
Consequently, traffic is sent directly to the load balancer and then forwarded to the destination node.
The destination setting for forwarded packets varies depending on how the cloud provider's load balancer delivers traffic:
-->
&lt;p>&lt;code>.status.loadBalancer.ingress.ipMode&lt;/code> 可选值为：&lt;code>&amp;quot;VIP&amp;quot;&lt;/code> 和 &lt;code>&amp;quot;Proxy&amp;quot;&lt;/code>。
默认值为 &lt;code>VIP&lt;/code>，即目标 IP 设置为负载均衡 IP 和端口并发送到节点的流量会被 kube-proxy 重定向到后端服务。
这种方式保持 kube-proxy 现有行为模式。&lt;code>Proxy&lt;/code> 用于阻止 kube-proxy 在 ipvs 和 iptables 模式下绑定负载均衡 IP 地址到节点。
此时，流量会直达负载均衡器然后被重定向到目标节点。转发数据包的目的值配置取决于云厂商的负载均衡器如何传输流量。&lt;/p>
&lt;!--
- If the traffic is delivered to the node then DNATed to the pod, the destination would be set to the node's IP and node port;
- If the traffic is delivered directly to the pod, the destination would be set to the pod's IP and port.
-->
&lt;ul>
&lt;li>如果流量被发送到节点然后通过目标地址转换（&lt;code>DNAT&lt;/code>）的方式到达 Pod，目的地应当设置为节点和 IP 和端口；&lt;/li>
&lt;li>如果流量被直接转发到 Pod，目的地应当被设置为 Pod 的 IP 和端口。&lt;/li>
&lt;/ul>
&lt;!--
## Usage
-->
&lt;h2 id="用法">用法&lt;/h2>
&lt;!--
Here are the necessary steps to enable this feature:
-->
&lt;p>开启该特性的必要步骤：&lt;/p>
&lt;!--
- Download the [latest Kubernetes project](https://kubernetes.io/releases/download/) (version `v1.29.0` or later).
- Enable the feature gate with the command line flag `--feature-gates=LoadBalancerIPMode=true`
on kube-proxy, kube-apiserver, and cloud-controller-manager.
- For Services with `type: LoadBalancer`, set `ipMode` to the appropriate value.
This step is likely handled by your chosen cloud-controller-manager during the `EnsureLoadBalancer` process.
-->
&lt;ul>
&lt;li>下载 &lt;a href="https://kubernetes.io/releases/download/">Kubernetes 最新版本&lt;/a>（&lt;code>v1.29.0&lt;/code> 或更新）。&lt;/li>
&lt;li>通过命令行参数 &lt;code>--feature-gates=LoadBalancerIPMode=true&lt;/code> 在 kube-proxy、kube-apiserver 和
cloud-controller-manager 开启特性门控。&lt;/li>
&lt;li>对于 &lt;code>type: LoadBalancer&lt;/code> 类型的 Service，将 &lt;code>ipMode&lt;/code> 设置为合适的值。
这一步可能由你在 &lt;code>EnsureLoadBalancer&lt;/code> 过程中选择的 cloud-controller-manager 进行处理。&lt;/li>
&lt;/ul>
&lt;!--
## More information
-->
&lt;h2 id="更多信息">更多信息&lt;/h2>
&lt;!--
- Read [Specifying IPMode of load balancer status](/docs/concepts/services-networking/service/#load-balancer-ip-mode).
- Read [KEP-1860](https://kep.k8s.io/1860) - [Make Kubernetes aware of the LoadBalancer behaviour](https://github.com/kubernetes/enhancements/tree/b103a6b0992439f996be4314caf3bf7b75652366/keps/sig-network/1860-kube-proxy-IP-node-binding#kep-1860-make-kubernetes-aware-of-the-loadbalancer-behaviour) _(sic)_.
-->
&lt;ul>
&lt;li>阅读&lt;a href="https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/#load-balancer-ip-mode">指定负载均衡器状态的 IPMode&lt;/a>。&lt;/li>
&lt;li>阅读 &lt;a href="https://kep.k8s.io/1860">KEP-1860&lt;/a> - &lt;a href="https://github.com/kubernetes/enhancements/tree/b103a6b0992439f996be4314caf3bf7b75652366/keps/sig-network/1860-kube-proxy-IP-node-binding#kep-1860-make-kubernetes-aware-of-the-loadbalancer-behaviour">让 Kubernetes 感知负载均衡器的行为&lt;/a> &lt;em>(sic)&lt;/em>。&lt;/li>
&lt;/ul>
&lt;!--
## Getting involved
-->
&lt;h2 id="联系我们">联系我们&lt;/h2>
&lt;!--
Reach us on [Slack](https://slack.k8s.io/): [#sig-network](https://kubernetes.slack.com/messages/sig-network),
or through the [mailing list](https://groups.google.com/forum/#!forum/kubernetes-sig-network).
-->
&lt;p>通过 &lt;a href="https://slack.k8s.io/">Slack&lt;/a> 频道 &lt;a href="https://kubernetes.slack.com/messages/sig-network">#sig-network&lt;/a>,
或者通过&lt;a href="https://groups.google.com/forum/#!forum/kubernetes-sig-network">邮件列表&lt;/a>联系我们。&lt;/p>
&lt;!--
## Acknowledgments
-->
&lt;h2 id="特别鸣谢">特别鸣谢&lt;/h2>
&lt;!--
Huge thanks to [@Sh4d1](https://github.com/Sh4d1) for the original KEP and initial implementation code.
I took over midway and completed the work. Similarly, immense gratitude to other contributors
who have assisted in the design, implementation, and review of this feature (alphabetical order):
-->
&lt;p>非常感谢 &lt;a href="https://github.com/Sh4d1">@Sh4d1&lt;/a> 的原始提案和最初代码实现。
我中途接手并完成了这项工作。同样我们也向其他帮助设计、实现、审查特性代码的贡献者表示感谢（按首字母顺序排列）：&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/aojea">@aojea&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/danwinship">@danwinship&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/sftim">@sftim&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/tengqm">@tengqm&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/thockin">@thockin&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/wojtek-t">@wojtek-t&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Kubernetes 1.29：修改卷之 VolumeAttributesClass</title><link>https://kubernetes.io/zh-cn/blog/2023/12/15/kubernetes-1-29-volume-attributes-class/</link><pubDate>Fri, 15 Dec 2023 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2023/12/15/kubernetes-1-29-volume-attributes-class/</guid><description>
&lt;!--
layout: blog
title: "Kubernetes 1.29: VolumeAttributesClass for Volume Modification"
date: 2023-12-15
slug: kubernetes-1-29-volume-attributes-class
-->
&lt;p>&lt;strong>译者&lt;/strong>：&lt;a href="https://github.com/carlory">Baofa Fan&lt;/a> (DaoCloud)&lt;/p>
&lt;!--
The v1.29 release of Kubernetes introduced an alpha feature to support modifying a volume
by changing the `volumeAttributesClassName` that was specified for a PersistentVolumeClaim (PVC).
With the feature enabled, Kubernetes can handle updates of volume attributes other than capacity.
Allowing volume attributes to be changed without managing it through different
provider's APIs directly simplifies the current flow.
You can read about VolumeAttributesClass usage details in the Kubernetes documentation
or you can read on to learn about why the Kubernetes project is supporting this feature.
-->
&lt;p>Kubernetes v1.29 版本引入了一个 Alpha 功能，支持通过变更 PersistentVolumeClaim（PVC）的
&lt;code>volumeAttributesClassName&lt;/code> 字段来修改卷。启用该功能后，Kubernetes 可以处理除容量以外的卷属性的更新。
允许更改卷属性，而无需通过不同提供商的 API 对其进行管理，这直接简化了当前流程。&lt;/p>
&lt;p>你可以在 Kubernetes 文档中，阅读有关 VolumeAttributesClass 的详细使用信息，或者继续阅读了解
Kubernetes 项目为什么支持此功能。&lt;/p>
&lt;h2 id="volumeattributesclass">VolumeAttributesClass&lt;/h2>
&lt;!--
The new `storage.k8s.io/v1alpha1` API group provides two new types:
-->
&lt;p>新的 &lt;code>storage.k8s.io/v1alpha1&lt;/code> API 组提供了两种新类型：&lt;/p>
&lt;p>&lt;strong>VolumeAttributesClass&lt;/strong>&lt;/p>
&lt;!--
Represents a specification of mutable volume attributes defined by the CSI driver.
The class can be specified during dynamic provisioning of PersistentVolumeClaims,
and changed in the PersistentVolumeClaim spec after provisioning.
-->
&lt;p>表示由 CSI 驱动程序定义的可变卷属性的规约。你可以在 PersistentVolumeClaim 动态制备时指定它，
并且允许在制备完成后在 PersistentVolumeClaim 规约中进行更改。&lt;/p>
&lt;p>&lt;strong>ModifyVolumeStatus&lt;/strong>&lt;/p>
&lt;!--
Represents the status object of `ControllerModifyVolume` operation.
-->
&lt;p>表示 &lt;code>ControllerModifyVolume&lt;/code> 操作的状态对象。&lt;/p>
&lt;!--
With this alpha feature enabled, the spec of PersistentVolumeClaim defines VolumeAttributesClassName
that is used in the PVC. At volume provisioning, the `CreateVolume` operation will apply the parameters in the
VolumeAttributesClass along with the parameters in the StorageClass.
-->
&lt;p>启用此 Alpha 功能后，PersistentVolumeClaim 的 &lt;code>spec.VolumeAttributesClassName&lt;/code> 字段指明了在 PVC 中使用的 VolumeAttributesClass。
在制备卷时，&lt;code>CreateVolume&lt;/code> 操作将应用 VolumeAttributesClass 中的参数以及 StorageClass 中的参数。&lt;/p>
&lt;!--
When there is a change of volumeAttributesClassName in the PVC spec,
the external-resizer sidecar will get an informer event. Based on the current state of the configuration,
the resizer will trigger a CSI ControllerModifyVolume.
More details can be found in [KEP-3751](https://github.com/kubernetes/enhancements/blob/master/keps/sig-storage/3751-volume-attributes-class/README.md).
-->
&lt;p>当 PVC 的 &lt;code>spec.VolumeAttributesClassName&lt;/code> 发生变化时，external-resizer sidecar 将会收到一个 informer 事件。
基于当前的配置状态，resizer 将触发 CSI ControllerModifyVolume。更多细节可以在
&lt;a href="https://github.com/kubernetes/enhancements/blob/master/keps/sig-storage/3751-volume-attributes-class/README.md">KEP-3751&lt;/a> 中找到。&lt;/p>
&lt;!--
## How to use it
If you want to test the feature whilst it's alpha, you need to enable the relevant feature gate
in the `kube-controller-manager` and the `kube-apiserver`. Use the `--feature-gates` command line argument:
-->
&lt;h2 id="如何使用它">如何使用它&lt;/h2>
&lt;p>如果你想在 Alpha 版本中测试该功能，需要在 &lt;code>kube-controller-manager&lt;/code> 和 &lt;code>kube-apiserver&lt;/code> 中启用相关的特性门控。
使用 &lt;code>--feature-gates&lt;/code> 命令行参数：&lt;/p>
&lt;pre tabindex="0">&lt;code>--feature-gates=&amp;#34;...,VolumeAttributesClass=true&amp;#34;
&lt;/code>&lt;/pre>&lt;!--
It also requires that the CSI driver has implemented the ModifyVolume API.
-->
&lt;p>它还需要 CSI 驱动程序实现 ModifyVolume API。&lt;/p>
&lt;!--
### User flow
If you would like to see the feature in action and verify it works fine in your cluster, here's what you can try:
-->
&lt;h3 id="用户流程">用户流程&lt;/h3>
&lt;p>如果你想看到该功能的运行情况，并验证它在你的集群中是否正常工作，可以尝试以下操作：&lt;/p>
&lt;!--
1. Define a StorageClass and VolumeAttributesClass
-->
&lt;ol>
&lt;li>
&lt;p>定义 StorageClass 和 VolumeAttributesClass&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>storage.k8s.io/v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>StorageClass&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>csi-sc-example&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">provisioner&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>pd.csi.storage.gke.io&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">parameters&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">type&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;hyperdisk-balanced&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">volumeBindingMode&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>WaitForFirstConsumer&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>storage.k8s.io/v1alpha1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>VolumeAttributesClass&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>silver&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">driverName&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>pd.csi.storage.gke.io&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">parameters&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">provisioned-iops&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;3000&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">provisioned-throughput&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;50&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ol>
&lt;!--
2. Define and create the PersistentVolumeClaim
-->
&lt;ol start="2">
&lt;li>
&lt;p>定义并创建 PersistentVolumeClaim&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>PersistentVolumeClaim&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>test-pv-claim&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">storageClassName&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>csi-sc-example&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">volumeAttributesClassName&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>silver&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">accessModes&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- ReadWriteOnce&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">resources&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">requests&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">storage&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>64Gi&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ol>
&lt;!--
3. Verify that the PersistentVolumeClaim is now provisioned correctly with:
-->
&lt;ol start="3">
&lt;li>
&lt;p>验证 PersistentVolumeClaim 是否已正确制备：&lt;/p>
&lt;pre tabindex="0">&lt;code>kubectl get pvc
&lt;/code>&lt;/pre>&lt;/li>
&lt;/ol>
&lt;!--
4. Create a new VolumeAttributesClass gold:
-->
&lt;ol start="4">
&lt;li>
&lt;p>创建一个新的名为 gold 的 VolumeAttributesClass：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>storage.k8s.io/v1alpha1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>VolumeAttributesClass&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>gold&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">driverName&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>pd.csi.storage.gke.io&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">parameters&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">iops&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;4000&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">throughput&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#b44">&amp;#34;60&amp;#34;&lt;/span>&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ol>
&lt;!--
5. Update the PVC with the new VolumeAttributesClass and apply:
-->
&lt;ol start="5">
&lt;li>
&lt;p>使用新的 VolumeAttributesClass 更新 PVC 并应用：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#008000;font-weight:bold">apiVersion&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>v1&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">kind&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>PersistentVolumeClaim&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">metadata&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">name&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>test-pv-claim&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb">&lt;/span>&lt;span style="color:#008000;font-weight:bold">spec&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">storageClassName&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>csi-sc-example&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">volumeAttributesClassName&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>gold&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">accessModes&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>- ReadWriteOnce&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">resources&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">requests&lt;/span>:&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#bbb"> &lt;/span>&lt;span style="color:#008000;font-weight:bold">storage&lt;/span>:&lt;span style="color:#bbb"> &lt;/span>64Gi&lt;span style="color:#bbb">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ol>
&lt;!--
6. Verify that PersistentVolumeClaims has the updated VolumeAttributesClass parameters with:
-->
&lt;ol start="6">
&lt;li>
&lt;p>验证 PersistentVolumeClaims 是否具有更新的 VolumeAttributesClass 参数：&lt;/p>
&lt;pre tabindex="0">&lt;code>kubectl describe pvc &amp;lt;PVC_NAME&amp;gt;
&lt;/code>&lt;/pre>&lt;/li>
&lt;/ol>
&lt;!--
## Next steps
* See the [VolumeAttributesClass KEP](https://kep.k8s.io/3751) for more information on the design
* You can view or comment on the [project board](https://github.com/orgs/kubernetes-csi/projects/72) for VolumeAttributesClass
* In order to move this feature towards beta, we need feedback from the community,
so here's a call to action: add support to the CSI drivers, try out this feature,
consider how it can help with problems that your users are having…
-->
&lt;h2 id="后续步骤">后续步骤&lt;/h2>
&lt;ul>
&lt;li>有关设计的更多信息，请参阅 &lt;a href="https://kep.k8s.io/3751">VolumeAttributesClass KEP&lt;/a>&lt;/li>
&lt;li>你可以在&lt;a href="https://github.com/orgs/kubernetes-csi/projects/72">项目看板&lt;/a>上查看或评论 VolumeAttributesClass&lt;/li>
&lt;li>为了将此功能推向 Beta 版本，我们需要社区的反馈，因此这里有一个行动倡议：为 CSI 驱动程序添加支持，
尝试此功能，考虑它如何帮助解决你的用户遇到的问题...&lt;/li>
&lt;/ul>
&lt;!--
## Getting involved
We always welcome new contributors. So, if you would like to get involved, you can join our [Kubernetes Storage Special Interest Group](https://github.com/kubernetes/community/tree/master/sig-storage) (SIG).
-->
&lt;h2 id="参与其中">参与其中&lt;/h2>
&lt;p>我们始终欢迎新的贡献者。因此，如果你想参与其中，可以加入我们的
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-storage">Kubernetes 存储特别兴趣小组&lt;/a> (SIG)。&lt;/p>
&lt;!--
If you would like to share feedback, you can do so on our [public Slack channel](https://app.slack.com/client/T09NY5SBT/C09QZFCE5).
-->
&lt;p>如果你想分享反馈意见，可以在我们的&lt;a href="https://app.slack.com/client/T09NY5SBT/C09QZFCE5">公共 Slack 频道&lt;/a> 上留言。&lt;/p>
&lt;!--
Special thanks to all the contributors that provided great reviews, shared valuable insight and helped implement this feature (alphabetical order):
-->
&lt;p>特别感谢所有为此功能提供了很好的评论、分享了宝贵见解并帮助实现此功能的贡献者（按字母顺序）：&lt;/p>
&lt;ul>
&lt;li>Baofa Fan (calory)&lt;/li>
&lt;li>Ben Swartzlander (bswartz)&lt;/li>
&lt;li>Connor Catlett (ConnorJC3)&lt;/li>
&lt;li>Hemant Kumar (gnufied)&lt;/li>
&lt;li>Jan Šafránek (jsafrane)&lt;/li>
&lt;li>Joe Betz (jpbetz)&lt;/li>
&lt;li>Jordan Liggitt (liggitt)&lt;/li>
&lt;li>Matthew Cary (mattcary)&lt;/li>
&lt;li>Michelle Au (msau42)&lt;/li>
&lt;li>Xing Yang (xing-yang)&lt;/li>
&lt;/ul></description></item><item><title>聚焦 SIG Testing</title><link>https://kubernetes.io/zh-cn/blog/2023/11/24/sig-testing-spotlight-2023/</link><pubDate>Fri, 24 Nov 2023 00:00:00 +0000</pubDate><guid>https://kubernetes.io/zh-cn/blog/2023/11/24/sig-testing-spotlight-2023/</guid><description>
&lt;!--
layout: blog
title: "Spotlight on SIG Testing"
slug: sig-testing-spotlight-2023
date: 2023-11-24
canonicalUrl: https://www.kubernetes.dev/blog/2023/11/24/sig-testing-spotlight-2023/
-->
&lt;p>&lt;strong>作者:&lt;/strong> Sandipan Panda&lt;/p>
&lt;p>&lt;strong>译者:&lt;/strong> &lt;a href="https://github.com/windsonsea">Michael Yao&lt;/a>&lt;/p>
&lt;!--
Welcome to another edition of the _SIG spotlight_ blog series, where we
highlight the incredible work being done by various Special Interest
Groups (SIGs) within the Kubernetes project. In this edition, we turn
our attention to [SIG Testing](https://github.com/kubernetes/community/tree/master/sig-testing#readme),
a group interested in effective testing of Kubernetes and automating
away project toil. SIG Testing focus on creating and running tools and
infrastructure that make it easier for the community to write and run
tests, and to contribute, analyze and act upon test results.
-->
&lt;p>欢迎阅读又一期的 “SIG 聚光灯” 系列博客，这些博客重点介绍 Kubernetes
项目中各个特别兴趣小组（SIG）所从事的令人赞叹的工作。这篇博客将聚焦
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-testing#readme">SIG Testing&lt;/a>，
这是一个致力于有效测试 Kubernetes，让此项目的繁琐工作实现自动化的兴趣小组。
SIG Testing 专注于创建和运行工具和基础设施，使社区更容易编写和运行测试，并对测试结果做贡献、分析和处理。&lt;/p>
&lt;!--
To gain some insights into SIG Testing, [Sandipan
Panda](https://github.com/sandipanpanda) spoke with [Michelle Shepardson](https://github.com/michelle192837),
a senior software engineer at Google and a chair of SIG Testing, and
[Patrick Ohly](https://github.com/pohly), a software engineer and architect at
Intel and a SIG Testing Tech Lead.
-->
&lt;p>为了深入了解 SIG Testing 的情况，
&lt;a href="https://github.com/sandipanpanda">Sandipan Panda&lt;/a>
采访了 Google 高级软件工程师兼 SIG Testing 主席
&lt;a href="https://github.com/michelle192837">Michelle Shepardson&lt;/a>
以及英特尔软件工程师、架构师兼 SIG Testing 技术负责人
&lt;a href="https://github.com/pohly">Patrick Ohly&lt;/a>。&lt;/p>
&lt;!--
## Meet the contributors
**Sandipan:** Could you tell us a bit about yourself, your role, and
how you got involved in the Kubernetes project and SIG Testing?
-->
&lt;h2 id="meet-the-contributors">会见贡献者 &lt;/h2>
&lt;p>&lt;strong>Sandipan:&lt;/strong> 你能简单介绍一下自己吗，谈谈你的职责角色以及你是如何参与
Kubernetes 项目和 SIG Testing 的？&lt;/p>
&lt;!--
**Michelle:** Hi! I'm Michelle, a senior software engineer at
Google. I first got involved in Kubernetes through working on tooling
for SIG Testing, like the external instance of TestGrid. I'm part of
oncall for TestGrid and Prow, and am now a chair for the SIG.
-->
&lt;p>&lt;strong>Michelle:&lt;/strong> 嗨！我是 Michelle，是 Google 高级软件工程师。
我最初是为 SIG Testing 开发工具（如 TestGrid 的外部实例）而参与到 Kubernetes 项目的。
我是 TestGrid 和 Prow 的轮值人员，现在也是这个 SIG 的主席。&lt;/p>
&lt;!--
**Patrick:** Hello! I work as a software engineer and architect in a
team at Intel which focuses on open source Cloud Native projects. When
I ramped up on Kubernetes to develop a storage driver, my very first
question was "how do I test it in a cluster and how do I log
information?" That interest led to various enhancement proposals until
I had (re)written enough code that also took over official roles as
SIG Testing Tech Lead (for the [E2E framework](https://github.com/kubernetes-sigs/e2e-framework)) and
structured logging WG lead.
-->
&lt;p>&lt;strong>Patrick:&lt;/strong> 你好！我在英特尔的一个团队中担任软件工程师和架构师，专注于开源云原生项目。
当我开始学习 Kubernetes 开发存储驱动时，我最初的问题是“如何在集群中进行测试以及如何记录信息？”
这个兴趣点引发了各种增强提案，直到我（重新）编写了足够多的代码，也正式担任了 SIG Testing 技术负责人
（负责 &lt;a href="https://github.com/kubernetes-sigs/e2e-framework">E2E 框架&lt;/a>）兼结构化日志工作组负责人。&lt;/p>
&lt;!--
## Testing practices and tools
**Sandipan:** Testing is a field in which multiple approaches and
tools exist; how did you arrive at the existing practices?
-->
&lt;h2 id="testing-practices-and-tools">测试实践和工具 &lt;/h2>
&lt;p>&lt;strong>Sandipan:&lt;/strong> 测试是一个存在多种方法和工具的领域，你们是如何形成现有实践方式的？&lt;/p>
&lt;!--
**Patrick:** I can’t speak about the early days because I wasn’t
around yet 😆, but looking back at some of the commit history it’s
pretty obvious that developers just took what was available and
started using it. For E2E testing, that was
[Ginkgo+Gomega](https://github.com/onsi/ginkgo). Some hacks were
necessary, for example around cleanup after a test run and for
categorising tests. Eventually this led to Ginkgo v2 and [revised best
practices for E2E testing](https://www.kubernetes.dev/blog/2023/04/12/e2e-testing-best-practices-reloaded/).
Regarding unit testing opinions are pretty diverse: some maintainers
prefer to use just the Go standard library with hand-written
checks. Others use helper packages like stretchr/testify. That
diversity is okay because unit tests are self-contained - contributors
just have to be flexible when working on many different areas.
Integration testing falls somewhere in the middle. It’s based on Go
unit tests, but needs complex helper packages to bring up an apiserver
and other components, then runs tests that are more like E2E tests.
-->
&lt;p>&lt;strong>Patrick:&lt;/strong> 我没法谈论早期情况，因为那时我还未参与其中 😆，但回顾一些提交历史可以明显看出，
当时开发人员只是看看有什么可用的工具并开始使用这些工具。对于 E2E 测试来说，使用的是
&lt;a href="https://github.com/onsi/ginkgo">Ginkgo + Gomega&lt;/a>。集成一些黑科技是必要的，
例如在测试运行后进行清理和对测试进行分类。最终形成了 Ginkgo v2
和&lt;a href="https://www.kubernetes.dev/blog/2023/04/12/e2e-testing-best-practices-reloaded/">重新修订的 E2E 测试最佳实践&lt;/a>。
关于单元测试，意见非常多样化：一些维护者倾向于只使用 Go 标准库和手动检查。
而其他人使用 stretchr/testify 这类辅助工具包。这种多样性是可以接受的，因为单元测试是自包含的：
贡献者只需在处理许多不同领域时保持灵活。集成测试介于二者之间，它基于 Go 单元测试，
但需要复杂的辅助工具包来启动 API 服务器和其他组件，然后运行更像是 E2E 测试的测试。&lt;/p>
&lt;!--
## Subprojects owned by SIG Testing
**Sandipan:** SIG Testing is pretty diverse. Can you give a brief
overview of the various subprojects owned by SIG Testing?
-->
&lt;h2 id="subprojects-owned-by-sig-testing">SIG Testing 拥有的子项目 &lt;/h2>
&lt;p>&lt;strong>Sandipan:&lt;/strong> SIG Testing 非常多样化。你能简要介绍一下 SIG Testing 拥有的各个子项目吗？&lt;/p>
&lt;!--
**Michelle:** Broadly, we have subprojects related to testing
frameworks, and infrastructure, though they definitely overlap. So
for the former, there's
[e2e-framework](https://pkg.go.dev/sigs.k8s.io/e2e-framework) (used
externally),
[test/e2e/framework](https://pkg.go.dev/k8s.io/kubernetes/test/e2e/framework)
(used for Kubernetes itself) and kubetest2 for end-to-end testing,
as well as boskos (resource rental for e2e tests),
[KIND](https://kind.sigs.k8s.io/) (Kubernetes-in-Docker, for local
testing and development), and the cloud provider for KIND. For the
latter, there's [Prow](https://docs.prow.k8s.io/) (K8s-based CI/CD and
chatops), and a litany of other tools and utilities for triage,
analysis, coverage, Prow/TestGrid config generation, and more in the
test-infra repo.
-->
&lt;p>&lt;strong>Michelle:&lt;/strong> 广义上来说，我们拥有与测试框架相关的子项目和基础设施，尽管它们肯定存在重叠。
我们的子项目包括：&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://pkg.go.dev/sigs.k8s.io/e2e-framework">e2e-framework&lt;/a>（外部使用）&lt;/li>
&lt;li>&lt;a href="https://pkg.go.dev/k8s.io/kubernetes/test/e2e/framework">test/e2e/framework&lt;/a>
（用于 Kubernetes 本身）&lt;/li>
&lt;li>kubetest2（用于端到端测试）&lt;/li>
&lt;li>boskos（用于 e2e 测试的资源租赁）&lt;/li>
&lt;li>&lt;a href="https://kind.sigs.k8s.io/">KIND&lt;/a>（在 Docker 中运行 Kubernetes，用于本地测试和开发）&lt;/li>
&lt;li>以及 KIND 的云驱动。&lt;/li>
&lt;/ul>
&lt;p>我们的基础设施包括：&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://docs.prow.k8s.io/">Prow&lt;/a>（基于 K8s 的 CI/CD 和 chatops）&lt;/li>
&lt;li>test-infra 仓库中用于分类、分析、覆盖率、Prow/TestGrid 配置生成等的其他工具和实用程序。&lt;/li>
&lt;/ul>
&lt;!--
*If you are willing to learn more and get involved with any of the SIG
Testing subprojects, check out the [SIG Testing README](https://github.com/kubernetes/community/tree/master/sig-testing#subprojects).*
-->
&lt;p>&lt;strong>如果你有兴趣了解更多并参与到 SIG Testing 的任何子项目中，查阅
&lt;a href="https://github.com/kubernetes/community/tree/master/sig-testing#subprojects">SIG Testing 的 README&lt;/a>。&lt;/strong>&lt;/p>
&lt;!--
## Key challenges and accomplishments
**Sandipan:** What are some of the key challenges you face?
-->
&lt;h2 id="key-challenges-and-accomplishments">主要挑战和成就 &lt;/h2>
&lt;p>&lt;strong>Sandipan:&lt;/strong> 你们面临的一些主要挑战是什么？&lt;/p>
&lt;!--
**Michelle:** Kubernetes is a gigantic project in every aspect, from
contributors to code to users and more. Testing and infrastructure
have to meet that scale, keeping up with every change from every repo
under Kubernetes while facilitating developing, improving, and
releasing the project as much as possible, though of course, we're not
the only SIG involved in that. I think another other challenge is
staffing subprojects. SIG Testing has a number of subprojects that
have existed for years, but many of the original maintainers for them
have moved on to other areas or no longer have the time to maintain
them. We need to grow long-term expertise and owners in those
subprojects.
-->
&lt;p>&lt;strong>Michelle:&lt;/strong> Kubernetes 从贡献者到代码再到用户等各方面看都是一个庞大的项目。
测试和基础设施必须满足这种规模，跟上 Kubernetes 每个仓库的所有变化，
同时尽可能地促进开发、改进和发布项目，尽管当然我们并不是唯一参与其中的 SIG。
我认为另一个挑战是子项目的人员配置。SIG Testing 有一些已经存在多年的子项目，
但其中许多最初的维护者已经转到其他领域或者没有时间继续维护它们。
我们需要在这些子项目中培养长期的专业知识和 Owner。&lt;/p>
&lt;!--
**Patrick:** As Michelle said, the sheer size can be a challenge. It’s
not just the infrastructure, also our processes must scale with the
number of contributors. It’s good to document best practices, but not
good enough: we have many new contributors, which is good, but having
reviewers explain best practices doesn’t scale - assuming that the
reviewers even know about them! It also doesn’t help that existing
code cannot get updated immediately because there is so much of it, in
particular for E2E testing. The initiative to [apply stricter linting to new or modified code](https://groups.google.com/a/kubernetes.io/g/dev/c/myGiml72IbM/m/QdO5bgQiAQAJ)
while accepting that existing code doesn’t pass those same linter
checks helps a bit.
-->
&lt;p>&lt;strong>Patrick:&lt;/strong> 正如 Michelle 所说，规模本身可能就是一个挑战。
不仅基础设施要与之匹配，我们的流程也必须与贡献者数量相匹配。
记录最佳实践是好的，但还不够好：我们有许多新的贡献者，这是好事，
但是让 Reviewer 靠人工解释最佳实践并不可行，这前提是 Reviewer 了解这些最佳实践！
如果现有代码不能被立即更新也无济于事，因为代码实在太多了，特别是对于 E2E 测试来说更是如此。
在接受现有代码无法通过同样的 linter 检查的同时，
&lt;a href="https://groups.google.com/a/kubernetes.io/g/dev/c/myGiml72IbM/m/QdO5bgQiAQAJ">为新代码或代码修改应用更严格的 lint 检查&lt;/a>对于改善情况会有所帮助。&lt;/p>
&lt;!--
**Sandipan:** Any SIG accomplishments that you are proud of and would
like to highlight?
-->
&lt;p>&lt;strong>Sandipan:&lt;/strong> 有没有一些 SIG 成就使你感到自豪，想要重点说一下？&lt;/p>
&lt;!--
**Patrick:** I am biased because I have been driving this, but I think
that the [E2E framework](https://github.com/kubernetes-sigs/e2e-framework) and linting are now in a much better shape than
they used to be. We may soon be able to run integration tests with
race detection enabled, which is important because we currently only
have that for unit tests and those tend to be less complex.
-->
&lt;p>&lt;strong>Patrick:&lt;/strong> 我有一些拙见，因为我一直在推动这个项目，但我认为现在
&lt;a href="https://github.com/kubernetes-sigs/e2e-framework">E2E 框架&lt;/a>和 lint 机制比以前好得多。
我们可能很快就能在启用竞争检测的情况下运行集成测试，这很重要，
因为目前我们只能对单元测试进行竞争检测，而那些往往不太复杂。&lt;/p>
&lt;!--
**Sandipan:** Testing is always important, but is there anything
specific to your work in terms of the Kubernetes release process?
-->
&lt;p>&lt;strong>Sandipan:&lt;/strong> 测试始终很重要，但在 Kubernetes 发布过程中，你的工作是否有任何特殊之处？&lt;/p>
&lt;!--
**Patrick:** [test flakes](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-testing/flaky-tests.md)…
if we have too many of those, development velocity goes down because
PRs cannot be merged without clean test runs and those become less
likely. Developers also lose trust in testing and just "retest" until
they have a clean run, without checking whether failures might indeed
be related to a regression in their current change.
-->
&lt;p>&lt;strong>Patrick:&lt;/strong> &lt;a href="https://github.com/kubernetes/community/blob/master/contributors/devel/sig-testing/flaky-tests.md">测试不稳定&lt;/a>……
如果我们有太多这样的不稳定测试，开发速度就会下降，因为我们无法在没有干净测试运行环境的情况下合并 PR，
并且这些环境会越来越少。开发者也会失去对测试的信任，只是“重新测试”直到有了一个干净的运行环境为止，
而不会检查失败是否确实与当前更改中的回归有关。&lt;/p>
&lt;!--
## The people and the scope
**Sandipan:** What are some of your favourite things about this SIG?
-->
&lt;h2 id="the-people-and-the-scope">人员和范围 &lt;/h2>
&lt;p>&lt;strong>Sandipan:&lt;/strong> 这个 SIG 中有哪些让你热爱的？&lt;/p>
&lt;!--
**Michelle:** The people, of course 🙂. Aside from that, I like the
broad scope SIG Testing has. I feel like even small changes can make a
big difference for fellow contributors, and even if my interests
change over time, I'll never run out of projects to work on.
-->
&lt;p>&lt;strong>Michelle:&lt;/strong> 当然是人 🙂。除此之外，我喜欢 SIG Testing 的宽广范围。
我觉得即使是小的改动也可以对其他贡献者产生重大影响，即使随着时间的推移我的兴趣发生变化，
我也永远不会缺少项目可供我参与。&lt;/p>
&lt;!--
**Patrick:** I can work on things that make my life and the life of my
fellow developers better, like the tooling that we have to use every
day while working on some new feature elsewhere.
**Sandipan:** Are there any funny / cool / TIL anecdotes that you
could tell us?
-->
&lt;p>&lt;strong>Patrick:&lt;/strong> 我的工作是为了让我和其他开发人员的工作变得更好，
比如建设在其他地方开发新特性时每天必须使用的工具。&lt;/p>
&lt;p>&lt;strong>Sandipan:&lt;/strong> 你们有没有任何好玩/酷炫/日常趣事可以告诉我们？&lt;/p>
&lt;!--
**Patrick:** I started working on E2E framework enhancements five
years ago, then was less active there for a while. When I came back
and wanted to test some new enhancement, I asked about how to write
unit tests for the new code and was pointed to some existing tests
which looked vaguely familiar, as if I had *seen* them before. I
looked at the commit history and found that I had *written* them! I’ll
let you decide whether that says something about my failing long-term
memory or simply is normal… Anyway, folks, remember to write good
commit messages and comments; someone will need them at some point -
it might even be yourself!
-->
&lt;p>&lt;strong>Patrick:&lt;/strong> 五年前，我开始致力于 E2E 框架的增强，然后在一段时间内参与活动较少。
当我回来并想要测试一些新的增强功能时，我询问如何为新代码编写单元测试，
并被指向了一些看起来有些熟悉的、好像以前&lt;strong>见过&lt;/strong>的现有测试。
我查看了提交历史，发现这些测试是我自己&lt;strong>编写的&lt;/strong>！
你可以决定这是否说明了我的长期记忆力衰退还是这很正常...
无论如何，伙计们，要谨记让每个 Commit 的消息和注释明确、友好；
某一刻会有人需要看这些消息和注释 - 甚至可能就是你自己！&lt;/p>
&lt;!--
## Looking ahead
**Sandipan:** What areas and/or subprojects does your SIG need help with?
-->
&lt;h2 id="looking-ahead">展望未来 &lt;/h2>
&lt;p>&lt;strong>Sandipan:&lt;/strong> 在哪些领域和/或子项目上，你们的 SIG 需要帮助？&lt;/p>
&lt;!--
**Michelle:** Some subprojects aren't staffed at the moment and could
use folks willing to learn more about
them. [boskos](https://github.com/kubernetes-sigs/boskos#boskos) and
[kubetest2](https://github.com/kubernetes-sigs/kubetest2#kubetest2)
especially stand out to me, since both are important for testing but
lack dedicated owners.
-->
&lt;p>&lt;strong>Michelle:&lt;/strong> 目前有一些子项目没有人员配置，需要有意愿了解更多的人参与进来。
&lt;a href="https://github.com/kubernetes-sigs/boskos#boskos">boskos&lt;/a> 和
&lt;a href="https://github.com/kubernetes-sigs/kubetest2#kubetest2">kubetest2&lt;/a> 对我来说尤其突出，
因为它们对于测试非常重要，但却缺乏专门的负责人。&lt;/p>
&lt;!--
**Sandipan:** Are there any useful skills that new contributors to SIG
Testing can bring to the table? What are some things that people can
do to help this SIG if they come from a background that isn’t directly
linked to programming?
-->
&lt;p>&lt;strong>Sandipan:&lt;/strong> 新的 SIG Testing 贡献者可以带来哪些有用的技能？
如果他们的背景与编程没有直接关联，有哪些方面可以帮助到这个 SIG？&lt;/p>
&lt;!--
**Michelle:** I think user empathy, writing clear feedback, and
recognizing patterns are really useful. Someone who uses the test
framework or tooling and can outline pain points with clear examples,
or who can recognize a wider issue in the project and pull data to
inform solutions for it.
-->
&lt;p>&lt;strong>Michelle:&lt;/strong> 我认为具备用户共情、清晰反馈和识别模式的能力非常有用。
有人使用测试框架或工具，并能用清晰的示例概述痛点，或者能够识别项目中的更广泛的问题并提供数据来支持解决方案。&lt;/p>
&lt;!--
**Sandipan:** What’s next for SIG Testing?
**Patrick:** Stricter linting will soon become mandatory for new
code. There are several E2E framework sub-packages that could be
modernised, if someone wants to take on that work. I also see an
opportunity to unify some of our helper code for E2E and integration
testing, but that needs more thought and discussion.
-->
&lt;p>&lt;strong>Sandipan:&lt;/strong> SIG Testing 的下一步是什么？&lt;/p>
&lt;p>&lt;strong>Patrick:&lt;/strong> 对于新代码，更严格的 lint 检查很快将成为强制要求。
如果有人愿意承担这项工作，我们可以对一些 E2E 框架的子工具包进行现代化改造。
我还看到一个机会，可以统一一些 E2E 和集成测试的辅助代码，但这需要更多的思考和讨论。&lt;/p>
&lt;!--
**Michelle:** I'm looking forward to making some usability
improvements for some of our tools and infra, and to supporting more
long-term contributions and growth of contributors into long-term
roles within the SIG. If you're interested, hit us up!
-->
&lt;p>&lt;strong>Michelle:&lt;/strong> 我期待为我们的工具和基础设施进行一些可用性改进，
并支持更多长期贡献者的贡献和成长，使他们在 SIG 中担任长期角色。如果你有兴趣，请联系我们！&lt;/p>
&lt;!--
Looking ahead, SIG Testing has exciting plans in store. You can get in
touch with the folks at SIG Testing in their [Slack channel](https://kubernetes.slack.com/messages/sig-testing) or attend
one of their regular [bi-weekly meetings on Tuesdays](https://github.com/kubernetes/community/tree/master/sig-testing#meetings). If
you are interested in making it easier for the community to run tests
and contribute test results, to ensure Kubernetes is stable across a
variety of cluster configurations and cloud providers, join the SIG
Testing community today!
-->
&lt;p>展望未来，SIG Testing 有令人兴奋的计划。你可以通过他们的
&lt;a href="https://kubernetes.slack.com/messages/sig-testing">Slack 频道&lt;/a>与 SIG Testing 的人员取得联系，
或参加他们定期举行的&lt;a href="https://github.com/kubernetes/community/tree/master/sig-testing#meetings">每两周的周二会议&lt;/a>。
如果你有兴趣为社区更轻松地运行测试并贡献测试结果，确保 Kubernetes
在各种集群配置和云驱动中保持稳定，请立即加入 SIG Testing 社区！&lt;/p></description></item></channel></rss>