如果你已经使用 Kubernetes 一段时间了,则可能需要考虑计划定期升级。从 Kubernetes 1.19 开始,每个开源版本都提供一年的补丁。你需要升级到最新的可用次要版本或补丁版本才能获得安全性和错误修复。但是,如何在不停机的情况下升级基础架构的关键部分呢?本文将指导你了解在任何环境中升级 Kubernetes 时要考虑的常见模式。
我们不会深入研究执行升级的所有工具和注意事项。如果你使用的是集群管理工具或托管 Kubernetes 服务,你应该查阅你的文档以获得最适合你环境的选项。你还需要注意,某些工作负载和环境可能会限制你选择的升级策略。
我们将讨论集群升级的一些高级模式:
- 原地升级
- 蓝绿升级
- 滚动升级
- 金丝雀升级
这些模式类似于应用程序升级选项,但由于其潜在的影响可能需要考虑一些独特的因素。升级基础设施可能会产生相当大的成本,具体取决于升级需要多长时间以及你的规模有多大。
控制平面组件
Kubernetes 控制平面由 Kubernetes API Server、etcd 数据库、controller manager,、scheduler以及你的环境中可能拥有的任何其他控制器(例如云或ingress )组成。升级 API Server是升级集群的第一步。Kubernetes 将状态存储在 etcd 中,并且随着任何重大应用程序升级,你需要确保至少有一个备份,并且你已经验证可以恢复备份。在某些情况下,API Server升级可能还需要 etcd 升级。
数据平面组件
Kubernetes 数据平面由 kubelet、容器运行时以及你在集群工作负载中使用的任何网络、日志记录或存储驱动程序组成。对于许多集群,至少需要 kube-proxy 和 CNI 插件更新。你的数据平面组件可以小于等于你的 API Server版本。理想情况下,你的主机操作系统、容器运行时和数据平面组件可以相互独立升级。将这些组件解耦,将确保你可以在出现错误修复、新功能或安全补丁时快速升级。
Kubernetes 托管服务
如果你使用Amazon Elastic Kubernetes Service (EKS)等托管 Kubernetes 服务,则会为你处理控制平面升级。如果你使用的是托管数据平面服务,例如托管节点组 (MNG),你的数据平面升级也应该由你的云提供商自动处理。
即使使用托管服务,你仍然有责任验证已安装在集群中的工作负载、附加控制器和第三方插件(例如 CNI)。在测试或开发环境中升级集群之前,应测试这些组件的 API 兼容性。
在所有这些升级策略中,你应该避免在集群升级期间进行应用程序升级。如果可能,请保持你的工作负载使用相同的版本,以最大限度地减少可能错误地归因于 Kubernetes 升级的故障。还要尽量减少其他潜在问题,例如scheme升级或应用程序 API 兼容性。
对于任何 Kubernetes 升级,你应该按以下顺序升级组件:
- 控制平面
- 数据平面和节点
- 附加组件
- 工作负载
这些升级模式将帮助你决定如何升级最适合你的集群和环境的组件。
01 原地升级In-Place Upgrade
执行原地升级时,你必须格外小心,确保组件保持健康,因为你是在当前服务于生产流量的集群上执行工作。原地升级可以包括包更新(例如 yum、apt)、配置管理自动化(例如 Ansible、Chef)或 VM/容器镜像更改。理想情况下,你的升级将是脚本化和自动化的(包括回滚),但如果这是你第一次升级,在开发或测试环境中手动进行升级可能会有所帮助。
原地升级意味着所有组件将大致同时升级。如果你通过配置管理更改所需的 API Server版本并推送新配置,则所有 API Server在收到新配置后都会升级。这与我们稍后讨论的滚动升级不同。
原地升级的主要好处是:
- 在任何规模下,它都是最快的。
- 如果手动完成,则可以更好地控制组件和升级过程。
- 它很容易适用于多种环境(本地或云)。
- 从基础设施成本的角度来看,它是最便宜的。
根据你的流程、规模和工具,原地升级可能是能够编写脚本的最直接的方法。脚本可以在本地或在开发集群中进行测试,而无需重新配置集群管理员团队可能无法访问的资源——例如负载均衡器或 DNS。
如果要使用此方法进行升级,原地升级还需要考虑以下限制:
- 如果你的所有 API Server或控制器同时升级,则可能导致停机。
- 如果你想从 Kubernetes 1.16 迁移到 1.20,你必须将整个集群四次升级到每个次要版本。
- 验证每个步骤可能是一个手动过程,这可能会增加额外的时间和出错的机会。
- 你应该在失败的情况下测试回滚计划,因为某些升级无法轻松恢复。(例如,scheme更改)。
02 蓝/绿升级
蓝/绿集群升级需要你使用新版本的 Kubernetes 创建第二个集群。你需要部署新的控制平面和数据平面,然后将所有工作负载复制到新集群,然后再将流量从旧集群切换到新集群。你可以使用蓝/绿来更新集群的每个组件,但整体集群升级更易于部署和回滚。
好消息是,设置新集群通常比升级集群更容易。关于如何将工作负载部署到新集群,你有多种选择。如果你的工作负载已经是 GitOps 或持续交付的一部分,你可以在升级之前或期间将部署同时转到新集群和旧集群。如果你没有自动部署,你可以使用Velero 之类的工具来备份你现有的工作负载并将它们部署到新集群。
创建新的“Green”集群可以让你对新版本按预期工作充满信心,并让你控制何时切换版本。新集群还可用于验证自动化工具,例如 Terraform 模块或 GitOps 存储库。你可以随时通过 DNS 或负载均衡器进行更改,甚至可以在维护时段或低利用率期间进行更改。
蓝/绿升级的主要好处是:
- 在发送流量之前预先验证所有组件是否正常。
- 你可以一次升级多个版本(例如,从 1.16 直接升级到 1.20)。
- 你可以更改可能难以测试的基础架构的其他部分(例如,切换区域、添加区域、更改实例类型)。
- 回滚是最安全和最容易的。
蓝/绿部署要考虑的缺点包括:
- 这是基础架构成本中最昂贵的策略,因为你必须在迁移期间运行两倍的计算容量。
- 如果你有数千个工作程序节点,你可能无法获得运行完整的第二个集群所需的所有计算容量。
- 如果你有多个并发集群升级,则此策略很难扩展到数十个或数百个集群。
- 除非你有备用服务器,否则在没有虚拟化的情况下在本地实现蓝/绿并不容易。
- 如果你有很多端点要更新,一次切换所有流量可能并不容易。负载均衡器可能需要预先调整并预热缓存。请注意 DNS 生存时间 (TTL),它可能会或可能不会用于分散负载。
- 一次切换所有集群流量需要跨团队协调迁移到新集群;以及工程周期来验证工作负载的规模是否正确。
当你拥有较少数量的集群或少于几百个工作节点时,蓝/绿可能是一个很好的策略。它允许你跳过版本并且回滚是安全的,但它可能会需要更多的基础设施支出和协调时间。
03 滚动升级
如果你熟悉 Kubernetes 部署策略,你就会熟悉滚动升级。滚动升级将部署组件的一个升级为新副本,然后缩减一个旧副本。它将继续这种模式,直到所有旧组件都被删除。滚动升级的增量性质比原地升级和蓝/绿策略有一些优势。
与原地升级类似,你需要一次升级 Kubernetes 的一个次要版本。当需要升级多个版本时,这可能是额外的工作,但它是唯一受支持的选项。根据你要升级的组件,你可以使用不同的工具来升级每个组件。
对于像控制平面这样的资源,你可能希望将带有升级的 API Server的新服务器添加到控制平面,然后关闭旧服务器。如果你使用的是 AWS,则可以更改 Auto Scaling 组启动配置 AMI 并一次替换一个实例。其他控制平面组件(例如调度程序)可能在集群内作为容器运行,因此你可以使用标准的 Kubernetes 滚动部署升级来升级这些组件。
与蓝/绿相比,滚动升级的主要区别在于你的外部流量路由(DNS 和负载均衡器)将保持指向同一位置。在进行生产集群升级之前,你需要确保在不同的集群或环境中测试所有附加组件和工作负载。
请注意,AWS 托管节点组、kOps、Cluster-API和许多其他 Kubernetes 集群管理工具使用滚动升级策略。好处包括:
- 与原地升级相比,更安全的更新和回滚。
- 成本低于蓝色/绿色,并且资源耗尽的可能性较小。
- 如果出现问题,可以在升级过程中暂停。
- 可以在本地环境模拟。
滚动升级是最常见的自动化工具。它们在速度和成本之间取得了很好的平衡,也减少手动工作和风险。
升级生产集群时,你现有的所有工作负载仍将被部署;只要你测试了它们的兼容性,你的升级就应该是可自动化的。
使用滚动升级时的进一步考虑包括:
- 滚动升级可能会很慢,具体取决于你的规模。
- 在升级期间,你可能需要协调控制器、守护进程或插件升级。
- 你可能无法进行集群范围的更改,例如添加可用区或更改架构。
04 金丝雀升级
Canary 应用程序部署一次为应用程序的新版本提供少量流量。Canary 升级可以被认为是具有蓝/绿优势的滚动升级。
通过 Canary 升级,你将使用要部署的版本创建一个新的 Kubernetes 集群。然后添加一个小型数据平面并将你现有的应用程序以较小的规模部署到新集群。通过负载均衡器配置、DNS 循环或服务网格将新的集群工作负载添加到现有的生产流量中。
现在,你可以监控流向新集群的流量,慢慢扩展新集群中的工作负载并缩减旧集群中的工作负载。你可以一次完成一项工作,并且可以根据自己的习惯缓慢或快速完成。如果任何单个工作负载开始出现错误,你可以缩减新集群中的单个工作负载,使其自动使用旧集群。
Canary 集群升级的好处包括:
- 新集群更容易创建和验证。
- 你可以在升级期间跳过次要 Kubernetes 版本(例如,1.16 到 1.20)。
- 可以在每个团队的基础上选择加入应用程序部署。
- 由于增加的流量使用,错误的影响最小。
- 你可以在升级期间进行大型基础架构更改。
- 集群从小规模开始,因此基础设施成本较低,你可以在扩展时预热缓存和负载均衡器。
如果你想进行较大的更改(例如更改架构)或者你想添加额外的可用区,那么 Canary 是一个不错的选择。通过启动较小的集群并根据工作负载增加它,你可以确保在新实例更高效或工作负载请求和限制发生变化时不会过度配置基础设施。
与任何事情一样,需要权衡取舍。使用金丝雀部署时,你应该注意以下一些问题:
- 回滚应用程序可能需要手动干预来更改负载均衡器或缩小新集群的规模。
- 调试应用程序可能更难,因为你需要知道发生了哪些集群错误。
- 如果你有数十个或数百个集群,随着集群的升级,你的集群数量可能会增加 50% 或更多。
- Canary 是最复杂的升级策略,但它受益于自动化部署、健康检查和性能监控。
结论
无论你选择哪种升级策略,重要的是要了解它们的工作原理以及随着 Kubernetes 使用量的增长可能出现的任何问题。你需要有一个升级策略,因为 Kubernetes 有频繁的发布和偶尔的错误。
与新版本保持同步可能是你的基础设施安全流程的重要组成部分,并使应用程序能够快速利用新功能。如果你部署了 Kubernetes 并迁移了所有工作负载,而没有考虑如何升级,那么现在是开始计划的最佳时机。
如果你没有运行自己的 Kubernetes 集群的业务需求,我强烈建议你使用可用的托管 Kubernetes 选项之一。选择托管控制平面和数据平面可以为你每年节省数天或数周的规划和升级时间。每个托管选项可能执行不同的升级,但它们都允许你专注于工作负载和业务价值,而不是控制平面高可用性或数据平面兼容性。