本文已发布超过一年。较旧的文章可能包含过时内容。请检查页面中的信息自发布以来是否已不准确。
使用更新的 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 小版本中可用时,用户必须在旧的 Kubernetes 小版本 12-14 个月的支持期结束之前升级,才能获得这些修复。如果用户未准备好进行此类升级,可能会导致 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 补丁发布尽可能安全且非破坏性,因此,新的 Go 小版本在现有 Kubernetes 发布分支更新使用它之前,必须满足以下几个要求:
- 新的 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。