不!我们不使用 Kubernetes!

不!我们不使用 Kubernetes!
2021年07月22日 23:53 云头条

一篇关于《为什么使用Kubernetes扩展规模意味着“做几乎相同的事情,却来得更复杂”》的帖子在网上疯传,以至于刊登这篇文章的网站因流量过大而瘫痪。

作者是Ably公司的基础设施主管MaikZumstrull。

我们Ably运行着一个大规模的生产级基础设施,为我们的客户在全球的实时消息传递应用提供技术支持。与大多数科技公司一样,该基础设施主要依赖软件;而且与大多数科技公司一样,软件主要在Docker容器中部署和运行。

如果您一直关注技术领域,可能会立马想到这个问题:

“那么……你们使用 Kubernetes 吗?”

新老客户、对我们的平台感兴趣的开发人员以及面试Ably职位的求职者都提出过这个问题。有意思的是,甚至几个求职者放弃了工作机会,声称理由是我们不使用Kubernetes!

这也是我们在规划长期基础设施路线图时问自己的一个问题:我们是否应该在某个时候使用Kubernetes作为主要的部署平台?

为何是Kubernetes?

Kubernetes是最广为人知的系统,用于大规模编排容器化软件。虽然外头有不同的声音,但它仍基本上处于炒作周期的顶峰——常常让人觉得大家都在Kubernetes上运行,或至少大家都在谈论希望如何将一切转移到Kubernetes。Mesos的人气急剧下滑,Docker Swarm成了不受待见的话题;如果你仍在部署到普通的EC2实例,你很可能就是老古董。

Kubernetes优点多多。它是由大规模生产级工作负载方面经验丰富的工程师开发的,运用了来自谷歌的Borg编排系统的实用的可靠技术。它受到无数厂商的支持;这年头没有官方的Docker镜像和Kubernetes部署指南,都不好意思发布软件产品。

有点令人惊讶的是,Kubernetes从灵感源头Borg继承而来的初衷所剩无几,这个初衷就是将数量庞大的裸机系统转变成私有云环境。今天Kubernetes似乎主要部署在虚拟机上,最常见的是在公共云提供商上。公共云是当今许多组织部署Kubernetes的主要动因所在:它被视为统一的API层,使多云部署对您的DevOps人员而言很透明。

即使在单个云中,Kubernetes开发者体验也备受称道。开发人员已经很熟悉Docker, 而Kubernetes很容易让相同的容器在生产环境中运行。借助命名空间、内置的资源管理以及内置的虚拟网络功能或服务网格,它还允许部署由不同团队维护的多个交互服务,而不会相互干扰。

Ably做了什么?

Ably是公共云客户。我们的整个生产环境完全放在AWS上,目前没有使用别的云环境。我们在EC2实例上运行。机器总数在一天内随自动扩展机制而变化,但始终至少有数千台,横跨十个AWS区域。这些机器确实运行Docker,我们的的大部分软件部署在容器中。

Ably的云架构示意图,没有Kubernetes

我们不使用任何知名的运行时编排层。每个实例创建时,已经基于它所在的自动扩展组知道运行哪些容器。作为启动镜像一部分的每个实例上的小型自定义启动服务查看实例配置,提取合适的容器镜像,然后启动容器。

在实例的整个生命周期中,容器集是相同的。根本没有决定将实例从“核心”转换成“前端”或之类东西的调度器服务:想改变集群的配置,创建或销毁整个实例,不是被告知运行一组不同的容器。每个实例上都有轻量级监控服务:如果实例消亡,会重新生成所需的容器,如果运行的任何软件版本不再是该集群的首选版本,它会自行终止该实例。

至于流量处理方面,我们使用AWS网络负载均衡器(NLB)。由于一个自动扩展组对应一个生产级服务,我们可以使用普通的AWS方法:将一个NLB指向一个自动扩展组作为目标组,不需要额外的抽象层。

至于内部的服务到服务通信(可以称之为“服务网格”),我们使用……网络。由于服务不是在机器上任意混合,机器自动分配的IP地址足以满足我们的用途。

如果您不打算使用Kubernetes,为何使用Docker?

Docker仍是部署软件的一种相当方便的方式,软件用大量使用依赖项的语言(Node、Python和Ruby 等)编写时尤其如此。在这种情况下,可部署单元是复杂目录树中成千上万个相互依赖的文件,外加需要是源树快照的完全正确版本的执行运行时环境。

我们过去常将构建的软件作为简单的打包文件(又叫slug)来分发,每个实例上的管理服务负责下载和拆包它们。功能上,我们做的仍然一样,因为Docker镜像就是一堆捆绑了元数据JSON blob的打包文件,但是curl和tar已换成了docker pull。

(并非工程团队中的每个人都一致认为这是改进,那是另一篇博文探讨的话题。)

这种架构有多灵活?

资源管理

说到资源管理,我们根据服务的需求决定使用哪种类型的EC2实例。没必要弄清楚如何将较小的服务打包到较大的实例上;在弄清楚如何将小型虚拟机打包到大型物理机上这个方面,亚马逊至少比我们多十年的经验,所以我们让亚马逊处理这些细节。

Right Sizing(优化规模)如下:大多数软件服务只能有效地使用一定数量的资源。有两个线程的进程不需要16个CPU;一分钟只写入一次磁盘的进程不需要每秒可写入90000次的SSD存储;替代的CPU架构可能有更高的性价比。从众多AWS产品中挑选合适的组件让我们得以最大限度地减少开销和控制成本,最终为我们的客户降低每条消息的费用。

自动扩展

EC2实例组知道如何自动增加或减少组中的实例数量以满足需求。可用的工具类似Kubernetes。很显然,我们针对AWS设计的产品不会直接在其他任何云提供商上运行,但眼下我们不使用任何其他云提供商。

当然,仍可以手动管理容量。每个自动扩展组中所需的实例数量可以随时手动设置,自动扩展策略随后可以接过重任,根据系统负载高低来增减数量。

客户实际使用多少服务,我们收取多少费用。任何空闲容量的预算都出自我们的口袋,因此我们需要尽可能提高效率,同时即使在意外的负载高峰期间也能保证为我们的客户提供良好的服务水准。

入站流量

抛开我们遇到的具体的实施错误不谈,入站流量是各大云提供商都已解决的问题——也就是说,前提是您可以始终如一地将接受外部流量的服务映射到它正在运行的那群机器。

客户流量可能直接抵达我们的其中一个NLB,也可能先通过CloudFront绕道而行。从每个区域内运行的服务的角度来看,这没有什么区别。

无论在哪种情况下,在每个区域使用负载均衡器是实现横向扩展和灵活性的另一种手段——在这种情况下,可以处理连接数量的大幅度变化,比如重大体育赛事开始、吸引成千上万的观众时。

DevOps

为了确保我们的工程师能积极参与管理我们的生产级系统这项工作,开发人员可以设置单一的配置值——“该集群现在务必应运行这个组件的这个版本”,随着时间的推移,该服务的所有实例都将换成运行新版本的实例。

使用Kubernetes又如何?

如果我们将生产环境迁移到Kubernetes,我们的环境和流程会如何变化(但愿改进)?

鉴于我们的基础设施团队规模有限,唯一值得考虑的方案是,使用与AWS全面集成的托管Kubernetes。鉴于我们的产品需要全球部署,我们至少需要十个集群(十个区域各一个)。

如果我们将生产环境迁移到Kubernetes,Ably的架构会是这样子

资源管理

通过Kubernetes管理资源时,我们会使用大型实例(可能是最大的可用实例,即.metal类别),并将它们与容器一起打包,而不是使用大小适合每个服务的EC2实例。

打包服务器的一个小优点是使用现有机器上的空闲资源,而不是额外的机器以满足占用资源少的服务的需要。它还有这一个大缺点:在同一台机器上运行异构服务,因而争夺资源。这不是新的棘手问题:云提供商在虚拟机方面有同样的问题,名为“嘈杂的邻居”。然而,云提供商在其系统中拥有十年来的秘诀,可以尽量为客户缓解这个问题。在Kubernetes上,您得自行解决该问题。

一种可能的方法是在使用Kubernetes时,尝试保留“一个虚拟机,一个服务”模式。Kubernetes minion不必一模一样,它们可以是不同大小的虚拟机,Kubernetes调度约束条件可用来在每个minion上就运行一个逻辑服务。不过这提出了一个问题:如果您在特定的EC2实例组上运行固定的容器集,为什么要多一个Kubernetes层而不是就这么做?

自动扩展

说到改用Kubernetes,服务的自动扩展看起来很相似:公开自定义的“当前利用率”指标,定有根据需要添加或删除容器的规则。当然,只有集群节点上有可用容量时,Kubernetes集群才能启动额外的服务pod。正因为如此,我们需要部署拥有大量空闲容量的节点,并添加集群自动扩展器(Cluster Autoscaler),以便按需创建更多节点。

对于集群自动扩展器而言,扩展集群比较简单——“没有所需的空闲容量时,添加节点”。然而,缩小集群变得复杂起来:您最终面临的可能是基本上空闲的节点,但这不是空节点。剩余的pod需要迁移到其他节点以创建一个空节点,然后终止该节点以缩小集群。

自动扩展方面的结论是,它应该仍像现在一样运作,但是我们将解决两个自动扩展问题而不是一个自动扩展问题,而且它们都比我们现在面临的一个问题来得复杂。按需或计划的容量管理(手动干预)会稍微复杂一点,因为我们先要确保有足够的Kubernetes节点,然后确保有足够的pod用于所需的服务。

入站流量

换成Kubernetes的话,入站流量会很轻松。EKS团队在这方面做出了几个值得称道的设计选择:如果集群以这种方式配置,每个pod收到一个与VPC(EC2的虚拟网络层)完全集成的由AWS管理的 IP 地址。集群内运行的东西可直接访问这些IP地址。

当Ingress(入站)或Service(服务)部分被添加到服务的Kubernetes规范时,控制器会自动创建AWS负载均衡器,并将它们直接指向合适的pod集。总的来说,这不会比我们现在公开流量路由实例的方式来得复杂。

当然,这里隐藏的缺点是这种出色的集成程度完全是AWS特有的。对于任何尝试使用Kubernetes来实现多云的人来说,它不是很有帮助。

DevOps

在Kubernetes环境中,软件版本管理在功能上与我们现在拥有的非常相似。我们的开发人员将在Kubernetes部署中指定新的目标版本,pod就会进行滚动替换,而不是在我们的自定义配置系统中指定新的目标版本,所有EC2实例就会自动进行滚动替换。

但还有其他好处吗?

前面部分可以总结如下:我们所做的事大部分一样,却来得更复杂了。如果在Kubernetes上运行带来我们讨论如何移植现有基础设施时没有考虑到的附带好处,这么做可能是值得的。不妨看一下通常被称为是Kubernetes优点的另几个好处,看看它们是否对我们有帮助。

多云就绪

每个人都应该拥有多云战略!除非它不该拥有。

我们发觉自己属于“不该拥有”这个群体,目前并未奉行该策略。我们也不完全相信Kubernetes是实现多云就绪的好方法。一旦服务需要访问自个集群外的服务,或者需要从自个集群外可以访问,或者使用任何类型的持久存储,各大云提供商之间的差异确实很重要,Kubernetes无法成功地抽取掉这些差异、以至于您的开发人员不必关心。

如果您仍需要一种策略来部署到AWS上的Kubernetes,需要另一种相似但不同的策略来部署到GCP上的Kubernetes,那么采用相似但不同的策略来部署到AWS和GCP、不用Kubernetes会困难得多吗?

混合云就绪

我们认为,管理混合云或本地环境(或换句话说,管理您自己的物理机器)是部署Kubernetes的正当理由。说来也巧,这也是最初设计Borg以实现的目标。如果我们准备开始构建自己的物理数据中心而不是使用公共云资源,我们在其中安装的几乎肯定是裸机Kubernetes集群。

另一种选择是尝试构建基于虚拟化技术的私有云,许多组织选择这么做。然而,我们凭以往构建这种环境的经验就知道,这绝不是一种省钱或轻松的选择。

不过,我们没准备开始搞自己的数据中心。我们仍需要将规模扩大数倍,那样自己搭建硬件的好处才能证明在我们的工程部门设立物理基础设施小组的成本是合理的。

基础设施即代码

基础设施即代码是我们已经在做的事情,使用CloudFormation、Terraform以及我们自己的自定义工具。为Kubernetes编写YAML文件不是管理基础设施即代码的唯一方法,在许多情况下,这甚至不是最合适的方法。

拥有庞大而活跃的社区

使用Kubernetes的一个常被提及的好处是有庞大的用户社区可以交流问题和建议。但是您无需运行Kubernetes即可访问庞大的用户和开发者社区。云计算还有许多其他方面的社区,我们非常积极地参与其中。使用AWS的技术人员组成的社区比Kubernetes开发者和用户社区更庞大,两者有明显的重叠。我们部署的许多其他技术(比如Cassandra)也大受欢迎。我们在Kubernetes人群面前并不觉得孤独。

要承认的一点是,在许多情况下,使用用户社区庞大且快速增长的产品实际上没有帮助。Ably SRE的几位工程师之前曾在Kubernetes团队工作过,大量新手用户很难找到Kubernetes 相关问题方面的有用信息。很多人使用Kubernetes,但据我们的经验,很少有人深入了解,因此通过用户群如此庞大的社区排除问题比您想象的要困难得多。

大量供应商进入这个领域也带来了巨大的技术变化,Kubernetes核心中的功能被快速添加或更改,以适应人们试图销售的新的第三方附加组件。庞大而活跃的社区有利也有弊。

Kubernetes的另外弊端

复杂性,对,复杂性。若想迁移到Kubernetes,仅仅为了保持Kubernetes集群顺利运行,组织就需要整个工程团队,其前提是使用托管的Kubernetes服务,而且可以依靠另外的基础设施工程师来维护在组织的实际产品或服务基础上的其他支持性服务。

比如说,上面提到的那些用于网络和入站流量的AWS EKS服务。那些服务并不随带EKS。您需要创建一个EKS集群,然后在其上面安装和配置那些服务。还有另外一些服务。

如果我们走服务提供商这条路,这显然会为我们减少一些工作,但这有其自身的弊端。我们已经讨论了这种充满活力的Kubernetes市场带来的技术变化,因此从一家供应商换成另一家供应商绝非易事。选择供应商不是轻松的选择,本身就是对架构方面的承诺。

这个问题不是AWS的托管Kubernetes产品所特有的,整个行业都这样。关键不是EKS团队做得不好,而是即使拥有真正精心维护的托管Kubernetes架构,从基本集群到可靠的生产环境仍有很多工作要做。

结束语

尽管我们承认Kubernetes是一种设计精良的产品,但我们目前并未使用或计划使用它。倒不是说部署Kubernetes永远没有意义,只是眼下对我们来说没有意义。

经过认真的成本效益评估后,采用如此昂贵的组件似乎只会转移我们的一些问题,而不是真正解决它们。

在我们看来,Kubernetes对于目前全力投入到Kubernetes的许多公司来说没有意义,但选择权在它们。如果您看到本文,贵组织目前试图决定在多大程度上需要Kubernetes,但愿我们的观点会帮助您为自己的团队做出正确的决定。

我们的生产级系统肯定面临问题和技术债务,就像别人的一样。我们列出了想要改进的方面,我们在招聘更多的工程师帮助改进。然而,最终,“迁移到Kubernetes”不是要改进的其中一项。

没人想要再管理 Kubernetes 了 !

因 DNS 和 Kubernetes 导致 GitHub 故障 4 个半小时:7 月 13 日故障报告

美国空军:Kubernetes和容器为纳税人省下了100年的钱!

谷歌开源 Skaffold:简化 Kubernetes 开发

财经自媒体联盟更多自媒体作者

新浪首页 语音播报 相关新闻 返回顶部