这篇文章发布已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已不正确。
使用更新的 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 补丁版本尽可能安全和无干扰,因此新的 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,他们帮助以不仅使 Kubernetes 受益的方式推动了这些改进,而且使所有 Go 用户受益。