本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
使用更新的 Go 版本保持 Kubernetes 安全
问题所在
自 v1.19(2020 年发布)以来,Kubernetes 项目为每个小版本提供了 12-14 个月的补丁发布支持。这使用户能够以年度升级周期来验证和采用 Kubernetes 版本,并获得为期一年的安全修复。
Go 项目每年发布两次新的小版本,并为最近的两个小版本提供安全修复,从而为每个 Go 版本提供大约一年的支持。尽管每个新的 Kubernetes 小版本在首次发布时都使用受支持的 Go 版本构建,但该 Go 版本在 Kubernetes 小版本支持期结束前就已停止支持,而且自 v1.19 以来延长的 Kubernetes 补丁支持期更是拉大了这一差距。
在撰写本文时,所有 Go 补丁版本中略多于一半(88/171)包含针对具有潜在安全影响问题的修复。尽管其中许多问题与 Kubernetes 无关,但有些是相关的,因此使用能够接收这些修复的受支持 Go 版本仍然很重要。
一个显而易见的解决方案是简单地将 Kubernetes 的发布分支更新到新的 Go 小版本。然而,Kubernetes 会避免在补丁版本中引入不稳定的变更,历史上,这阻止了将现有的发布分支更新到新的 Go 小版本,因为有些变更被认为过于复杂、有风险或具有破坏性,无法包含在补丁版本中。例如:
- Go 1.6:默认启用 http/2
- Go 1.14:EINTR 处理问题
- Go 1.17:放弃 x509 CN 支持,ParseIP 变更
- Go 1.18:默认禁用 x509 SHA-1 证书支持
- Go 1.19:放弃当前目录的 LookPath 行为
其中一些变更可以在 Kubernetes 代码中轻松缓解,一些只能通过用户指定的 GODEBUG
环境变量来禁用,而另一些则需要侵入性的代码更改或根本无法避免。由于这种不一致性,Kubernetes 的发布分支通常会停留在一个 Go 小版本上,并面临着在每个 Kubernetes 小版本支持周期的最后几个月里无法获取相关 Go 安全修复的风险。
当相关的 Go 安全修复仅在较新的 Kubernetes 小版本中可用时,用户将不得不在 12-14 个月支持期结束前从旧的 Kubernetes 小版本升级,才能获得这些修复。如果用户没有准备好进行升级,这可能导致 Kubernetes 集群存在漏洞。即使用户可以应对意外的升级,这种不确定性也使得 Kubernetes 的年度支持在规划上不够可靠。
解决方案
我们很高兴地宣布,自 2023 年 1 月起,受支持的 Kubernetes 版本和受支持的 Go 版本之间的差距已经得到解决。
在过去的一年里,我们与 Go 团队密切合作,以解决采用新 Go 版本时遇到的困难。这促成了一次讨论、一个提案、一次在 GopherCon 上的演讲,以及一个旨在改善 Go 向后兼容性的设计,确保新的 Go 版本可以与之前的 Go 版本保持至少两年(四个 Go 版本)的兼容运行时行为。这使得像 Kubernetes 这样的项目能够将发布分支更新到受支持的 Go 版本,而不会让用户面临行为变更。
拟议的改进有望在 Go 1.21 中包含,并且 Go 团队已在 2022 年末的一个 Go 1.19 补丁版本中提供了有针对性的兼容性改进。这些更改使得 Kubernetes 1.23+ 能够在 2023 年 1 月更新到 Go 1.19,同时避免了任何面向用户的配置或行为更改。所有受支持的 Kubernetes 发布分支现在都使用受支持的 Go 版本,并且可以获取包含可用安全修复的新 Go 补丁版本。
展望未来,Kubernetes 维护者仍然致力于使 Kubernetes 补丁版本尽可能安全且无干扰,因此,在现有的 Kubernetes 发布分支更新到新的 Go 小版本之前,该版本必须满足几个要求:
- 新的 Go 版本必须已发布至少 3 个月。这为 Go 社区的采用以及问题或回归报告留出了时间。
- 新的 Go 版本必须在一个新的 Kubernetes 小版本中已使用至少 1 个月。这确保了所有 Kubernetes 的版本发布阻塞性测试在新 Go 版本上都能通过,并为 Kubernetes 社区对发布候选版本和新小版本的早期采用提供反馈时间。
- 不得存在已知会影响 Kubernetes 的、相对于先前 Go 版本的回归问题。
- 默认情况下必须保留运行时行为,无需 Kubernetes 用户/管理员采取任何操作。
- 像
k8s.io/client-go
这样的 Kubernetes 库必须保持与每个小版本最初使用的 Go 版本的兼容性,因此消费者不必为了获取库的补丁版本而更新 Go 版本(尽管鼓励他们使用受支持的 Go 版本进行构建,Go 1.21 中计划的兼容性改进使这一点变得更加容易)。
所有这些工作的目标是,在不引起注意的情况下使 Kubernetes 补丁版本更安全、更可靠,并使 Kubernetes 小版本在其整个支持生命周期内都能安全使用。
非常感谢 Go 团队,特别是 Russ Cox,他帮助推动了这些改进,这将使所有 Go 用户受益,而不仅仅是 Kubernetes。