如今,大多数应用程序架构都是默认分布式的:连接的微服务在云环境中的容器中运行。现在,无论大小的组织每天都要部署数千个容器——其规模之复杂几乎令人无法理解。绝大多数组织都依赖 Kubernetes(K8s)来编排、自动化和管理所有这些工作负载。
那么,当 Kubernetes 出事时会发生什么?
容错域是分布式系统的一个区域,当基础设施或网络服务的关键部分遇到问题时,该区域会受到影响。Kubernetes 是否成为下一个容错域?
思考与 Kubernetes 相关的应用程序故障的灾难是 DevOps 的噩梦。但在灾难中,也有机会:Kubernetes 有潜力通过成为设计高可用性(HA)应用程序以生存的容错域,帮助我们跨数据中心、云区域甚至云拥有相同的运维体验。
Kubernetes 作为通用操作系统
许多分布式应用程序需要尽可能靠近用户分布,所以假设我们想要构建一个三区域集群。
如果没有 Kubernetes,即使是在一个云中,也意味着要管理所有这些虚拟机,并在每个服务器上设置一组脚本来自我修复。如果服务器关闭或重新启动,我们必须编写一系列 Terraform 或 Ansible(或 Puppet 或 Chef 或 Pulumi)脚本来重新生成服务器。
然后,如果我们想跨云,我们必须以三种不同的方式完成所有这些工作!我们得知道 AWS 怎么做、Azure 怎么做、谷歌怎么做。
然而,使用 Kubernetes,我们只需要知道 AWS、Azure 或谷歌如何进入 Kubernete 集群,然后如何配置该集群,以便能够提供基础设施并能够相互通信,无论是通过专用网络、VPN 还是通过互联网的 TLS。一旦完成,其他管理工作基本上是相同的,无论基础设施位于何处。
Kubernetes 有效地提供了一个通用的操作系统,无论在哪里运行基础设施。它充当操作系统,抽象出运行的任何可用 zone、区域或云的复杂性。无论在哪里部署它,我们都有一种通用的操作语言,拥有 Kubernetes 所有强大的自愈能力。
这很好,但这也意味着 Kubernetes 成为容错域的可能:因为 K8s 集群的周长等于所处基础设施的周长,因此我们可以将每个 Kubernete 集群视为 HA 目的的数据中心或云区域。因此,如果区域或 Kubernetes 集群出现故障,应用程序将以相同的方式处理该故障。
通过使它们等效,我们减少了从可用性角度必须管理的维度数量。这大大简化了分布式应用程序环境,因为它成为我们必须仔细考虑的唯一容错域。
问题在于 Kubernetes 并没有真正被设计成一个容错域。
K8s 的下一代问题
这是我们现在需要解决的下一个大问题:为了能够轻松地将 Kubernetes 视为多区域/多站点集群的容错域,Kubernete 本身需要提供许多额外的构造来促进这种模式。
K8s 生态系统和社区已经花了相当长的时间来解决这个问题。这导致了为特定应用程序或应用程序栈专门构建多区域解决方案的各种不同方式,但目前还没有一种统一的策略或解决方案来解决这一问题。
这些定制解决方案领域中最重要的是网络和安全,但在基础设施、故障恢复、可观察性和监控领域也存在需求。网络至关重要,因为需要在集群之间建立连接,然后在这些集群之间进行服务发现和流量路由。安全性很重要,因为需要确保没有访问权限蔓延,需要一个中央信任机构。
网络
目前有跨集群通信平台,如 Cilium、Tigera 的 Project Calico、Submariner 和 Skupper。每种方法都有优缺点,但它们似乎都不是“一刀切”解决方案。
负载均衡和服务发现
一旦集群可以相互通信,它们就需要能够发现跨站点运行的不同服务的实例。而且需要全局负载均衡,允许用户被路由到最近的可用实例,而不管他们进入应用程序的位置。
安全
如果你管理的是 K8s 集群,一般来说,你将拥有相当低级别的安全权限。实际上,你需要在每个集群中拥有相同级别的安全权限,如果你在管理它时不太小心,那么最终可能会比特定集群中需要的安全性更高或更低。
不幸的是,K8s 中的安全管理通常仍然是一个相当手动的过程,并且随着应用程序的分布式程度越来越高,这变得越来越困难。
信任与身份
目前,跨多个 Kubernetes 集群共享单个信任和身份源是一项痛苦的工作,这会加剧在多个 Kubernetes 集群上运行应用程序时可能遇到的一些其他安全问题。当跨站点的 pod 之间进行交互时,这一点变得更加重要,管理员可能需要同时连接到多个 Kubernetes 集群以进行故障排除。
基础设施和性能
目前,提供 pod 的 Kubernetes 原语只允许你声明所获得的内容的“数量”,而不考虑基础设施的性能。例如,你可以要求 CPU 或特定大小的卷,但无法请求特定处理器或保证驱动器的性能特征。这意味着每个站点都必须仔细调整和监控,以确保没有性能热点或冷点。
故障恢复
无论一个系统如何分布式,仍然有可能发生环境设计不适合生存的灾难。减轻这种可能性的灾难恢复策略要求应用程序访问故障域之外的区域来存储和检索备份,这在 Kubernetes 和一般的云计算中都是一项非常重要的活动。
可观察性和监控
在运行多站点应用程序时,重要的是能够监控整个系统的运行状况、性能和行为,使管理员能够在问题发生之前进行干预,并进行容量规划,以管理系统上不断增加的需求。
以下介绍 CockroachDB 如何使用 Kubernetes 作为多区域集群或多站点集群的容错域。
控制平面
你可能不认为正在构建的应用程序是全局的,但它是全局的。跨两个或三个站点的部署与跨平面的多区域部署具有相同的挑战,因此应用程序必须使用相同的架构原语构建。
除非你有一个非常本地化的商业模式,否则你将以这种方式构建,无论是现在还是不久的将来。令人惊讶的是,一个活跃的工作负载越分散,在任何特定故障下生存的成本就越低。
例如,在传统的双站点灾难恢复场景中,如果数据中心或区域出现故障,你必须拥有 2 倍的资源才能继续运行。CockroachDB 分布在三个站点,只需要 1.5 倍的数据就可以在不中断的情况下运行。这是因为即使失去一个站点,仍有两个剩余站点。
当你将应用程序扩展到其他站点时,从站点故障中幸存下来的实际成本会下降得更多。例如,当分布在五个站点时,只需要提供 1.25 倍的基础设施,就可以在站点故障的情况下不间断地继续运行。
当部署多区域/多站点时,我们建议每个站点使用 Kubernetes 集群,然后跨这些站点部署 CockroachDB。由于缺乏这种下一代解决方案,我们不得不为托管 CockroachDB 服务做一些定制工作,以便能够将 Kubernetes 视为容错域。
我们在 CockroachDB 专用和无服务器中解决了这个问题,通过构建一个控制平面来管理这个问题。我们使用谷歌或 Amazon 中的网络允许在不同地区的 Kubernetes 集群之间进行路由,然后使用控制平面一致地应用所有安全设置,并进行检查以确保它们得到更新。它还为我们提供了同时支持数百个集群所需的各种可观察性信息,并帮助客户解决可能遇到的问题。
控制平面还做其他事情。我们创建了一个集中的密钥管理存储,这样管理员密钥就不必谨慎地发送到每个单独的区域。我们也花了很多时间思考持久性。
当最初构建 CockroachDB 数据库时,我们不断地讨论 Kubernetes,因为即使在单站点配置中,Cockroach DB 和 Kubernete 的结合使数据库具有比仅数据库更好的弹性。
如今,如果你看看我们的网站,我们几乎没有提到 Kubernetes。但在内部,这仍然是我们的首要任务:所有的 CockroachDB Dedicated、所有的 CockroachDB Serverless 无服务器,以及一些自托管集群都在 Kubernetes 中运行。控制平面处理复杂性。
结论
混合、多区域甚至多云部署不仅越来越普遍,而且对于需要横向扩展、保证可用性和最小化延迟的企业来说也越来越必要。Kubernetes 有潜力帮助我们在数据中心、云区域甚至云之间拥有相同的运维体验,成为我们设计 HA 应用程序的容错域。
我们认为,最好的方法是在每个位置都有一个 Kubernetes 集群,然后有某种共享机制将它们有效地连接在一起-能够共享安全配置信息并设置网络路由以及解决下一代问题所需的所有其他部分。
地球上的每一家软件即服务公司,以及每一家跨国公司,都有这个问题。发明允许 Kubernetes 分布在多个地区的机制,是整个 Kubernete 生态系统和社区目前面临的挑战。