首页 资讯内容详情

你需要Kubernetes吗?

2020-10-22 75

作者 | Alex Hewson

译者 | 王者

策划 | 小智

近几年,Kubernetes 很火,我也从事与之相关的工作有数年时间。Kubernetes 的价值是什么?它适用于哪些场景?我们应该使用 Kubernetes 吗?...... 本文试图回答这些问题。

我经常从团队——无论是新团队还是成熟团队——那里听到一个问题:“我们应该将软件栈托管在 Kubernetes 上吗?”鉴于 Kubernetes 在科技界的名声大噪,很多人都认为应该这么做。

我从事 K8s 的相关工作有好几年了——通常是在非常强大而复杂的平台上,我认为实际情况会更加微妙一些。

在这篇文章中,我试着弄清楚这个问题。本文主要针对那些负责托管自己产品的初创公司和自给自足的团队,不过对于大型组织传统 IT 部门的人员来说,可能也有一定的价值。

1 Kubernetes 能为你带来什么

Kubernetes 不仅仅是 2018 年的一个流行词而已,它是一个健壮、高度可伸缩的系统,让你能在原语 (Pod、Service、Ingress 等) 基础上进行应用程序部署,然后尽其所能实现你想要的东西。在应用程序发生崩溃时,它会重新启动它们。如果你正在运行很多服务 (可能采用了微服务架构),并且追求效率、弹性和好的部署方法,那么它能为你做很多事情。

想要让你的服务具有基本程度的弹性?那就部署多个副本,然后在它们之间均衡流量。

如果你的工作负载具有“爆发”(例如大量的 API 流量) 的特点,可以在此基础上通过设置自动伸缩来增加必要的容量。这能为你节省很多钱,你不需要一直为峰值容量付费,只需要提供一个基本负载来保持平台运行,并在必要时提供更多副本。如果你可以将队列长度导入到系统中,那么自动伸缩功能也适用于基于队列的工作负载。

担心代码会出问题?那就配置就绪探针,在服务发生崩溃时,Kubernetes 会自动重启它们。对于硬件故障也是一样——我看到过一个集群,它有一半节点发生瘫痪,但仍然像什么都没发生一样继续运行。经过精心配置和维护的 Kubernetes 集群可以变得非常健壮。如果你有足够的资源,甚至可以尝试运行类似 Chaos Monkey 这样的工具,确保你的软件栈能容忍经常性的故障。

Kubernetes 可以与 CI 工作流很好地集成在一起。最常见的模式是将镜像推送到 Docker 注册表,然后启动 K8s 集群来加载它 (理想情况下,所有项目都是标准化的)。这可以根据具体情况通过修改部署来拉出新的标记,或者将标记指向新镜像,并触发 K8s 重新加载所有 Pod。在大多数情况下,部署可以是完全自动化的。如果你对测试很有信心,那就可以 100% 自动化 (也就是持续交付),如果不是很有信心,在构建之后进行手动检查仍然能帮你减轻痛苦。无论哪种方式,开发人员都应该能在没有 Kubernetes 专家帮助的情况下将大多数构建版本发布到集群中。

与 CI 类似,它可以帮你对应用程序的日志和监控进行标准化。这些并不是 Kubernetes 独有的,但不管怎样,使用一个集群将所有服务的数据收集到一起可以极大地减轻调试的痛苦。

我看到有人用 fluentd 将 JSON 结构的日志从应用程序传输到 AWS CloudWatch,并通过 Insights 进行查询,效果非常好。

最后,它可以极大地提高效率——不仅在托管层,而且还可以减少开发人员部署软件所需的时间。人力成本高于计算机成本,因此对大多数组织来说,这是最大的胜利。但 Kubernetes 并非魔法——我看到过一些漂亮、高效的集群,也看到了一些“纸老虎”。要想让 Kubernetes 为你省钱,必须用对它。

2 Kubernetes 适用于哪些场景

首先,分析一下你的工作负载。你需要运行什么类型的应用程序?它们之间以及与外部世界之间是如何通信的?根据我的经验,我认为可以通过以下这些属性来判断是否可以使用 Kubernetes:

  • 你采用的是微服务架构吗?如果你只有一个应用程序,那么使用 Kubernetes 就没有什么价值。你需要容器化应用程序,然后将它们部署到 K8s 上。从项目开始时就这样做有助于你思考服务之间的边界。

  • 你的服务是否通过 HTTP 对外公开?这很适合 K8s 的模型,你可以在服务前面使用 ingress 控制器。

  • 你的应用程序适合进行负载均衡吗?没有本地状态 (使用 PostgreSQL/Redis/ 其他),通过已知端点通信,可以快速启动 / 关闭。这并不是说你不能在集群中保留像 Redis 缓存这样的短寿命状态,在很多情况下,你最好是使用云提供商提供的服务。

  • Kubernetes 也非常适用于 headless 应用程序,如批处理 (通过作业控制器) 和长时间运行的队列消费者客户端应用程序。

  • 内存 (以及在一定程度上 CPU) 使用情况是可预测的吗?Kubernetes 会尝试在相同的物理机器上托管应用程序,因此,如果其中一台机器出现故障并消耗了所有内存,那么其他工作负载可能会被随机终止。根据我的经验,这是 Kubernetes 集群最大的不稳定性来源。如果了解应用程序的资源使用情况,就可以设置好 resources.requests 和 resources.limits,保证它们总有足够的内存,不会影响其他应用程序。

相反,对于下面这些工作负载,我认为不应该使用 Kubernetes:

  • 静态网站。通常,你会将内容打包成基于 Nginx 的镜像,并通过集群的 ingress 控制器来公开它。这是一种糟糕的托管静态内容的方式:所有的 Nginx 副本都需要维护,效率很低。当然,你也可以把它放在 CDN 后面,但既然你要这么做,为什么不托管在云服务上呢?

  • 托管不受信任的代码。它们可能是客户提供的应用程序或有安全问题的第三方代码,例如 Wordpress 或来自 NPM 不可靠的库。默认情况下,Kubernetes 提供的用于隔离工作负载的特性并不是很好。你可以添加 Calico 之类的东西来控制网络访问,但这很容易出错,而且你的安全模型总是 100% 依赖于容器运行时。默认情况下 (Docker,基于 Linux cgroup),这为应用程序提供了一个巨大的攻击面:如果你的集群运行的代码被黑,攻击者就很容易访问集群的其余部分。cgroup 的替代品 (例如 Kata Container) 正在做一些有趣的工作,但它还不够主流,不能推荐给普通用户。

即使 Kubernetes 不太适用于你的工作负载,你仍然可以选择使用它 (例如,可以使用卷来保存生命周期较长的状态),只是你要花费大量的时间。不管怎样,其中有很多都是不好的实践,只会进一步伤害你。

3 没有银弹

Kubernetes 并非一颗银弹。它有助于将托管应用程序的复杂性转移到自己设计的层中,但不会让它们消失。你必须始终做好保护和维护平台的工作。

要让集群对工作负载发挥效用,需要大量的附加组件。有些几乎人人都在使用,有些则有点小众,比如 Nginx ingress 控制器、cert-manager 和 cluster-autoscaler,在没有足够的容量时可用来添加额外的节点。拥有一组有用的定制工具会让你的集群变得像一片雪花一样,所以需要对其进行管理。

此外,它们需要定期更新,有时可能会发生故障。像 Helm 或 Terraform 这样的配置管理工具几乎是不可缺少的:手动维护集群存在较大风险,如果没有声明性设置,你将永远无法以完全相同的方式启动另一个集群。在维护或替换成更成熟的集群时,这样会导致无穷无尽的问题。

在 Kubernetes 上部署重要的软件栈时,总是需要进行一定程度的管理。任何人都可以随心所欲地部署你的集群,这只会导致混乱。最终,你将看到很多命名不一致的应用程序分散在几十个 (更糟糕的是一个) 名称空间中,而没有人知道它们是如何组合在一起的。那么恭喜你,你用“新口味的意大利面基础设施替代了旧口味的意大利面基础设施”,只是换成了更好看的盘子而已。

我见过的最成功的 Kubernetes 实现,是基础设施专家与开发人员一起确保工作负载配置良好、标准化、相互保护并定义了通信模式。他们对部署在基础设施中的应用程序进行初始设置,并集成到构建 / 发布系统中,这样开发团队就可以在没有帮助的情况下发布新版本。在很多方面,这反映了组织文化——如果工程糟糕,沟通混乱,责任不明,那么托管环境也会反映出这些问题。在最好的情况下,这会导致不可靠,在最坏的情况下,这是一种不可靠、不可维护、代价高昂的混乱。

4 自有 Kubernetes 集群的成本

如果你正在大规模运行应用程序,那么 Kubernetes 能为你节省很多钱。可以看看一些特性,比如自动伸缩 (集群和副本集) 和 Spot 实例池 (EC2) 或抢占式 VM(谷歌)。

有一个优秀的工具生态系统可以帮助任何一个工程师搭建出一个玩具集群来测试他们的应用程序。从某种程度上说,这样很好,因为学习曲线变得不那么陡峭,但在你意识到需要多大规模之前,Kubernetes 就已经进入到生产环境中,并成为业务的关键部分。它的故障模式很复杂,要充分利用它需要很多专业技能。让一个没有经验的开发团队匆忙搭建一个集群(使用 Kops 是一种反模式)就是一场灾难:刚开始几个月或许没问题,但如果你需要做出重大变更,重新配置集群或排除故障,你的好日子就到头了。

从头构建 K8s 集群就像是自己编译内核:这是一种很好的学习方式,但对于运行生产应用程序来说则是很糟糕的方法。相反,你应该使用已有的解决方案,如 AWS EKS 或谷歌的 GKE。比我们还要聪明的人花了大量时间做出这些东西,即使你每个月为此付出几百美元也是值得的。

即使使用已有的 Kubernetes 解决方案,你也需要专业技能。控制平面是亚马逊提供的,但迟早你会在节点上触发一些错误,通常是在业务最繁忙的时候。你必须准备好资源,并为之支付费用。Kubernetes 的发布周期很短,所以你至少需要每年更新一次集群,并定期修改它的 API,这是一项很重要的工作。任何一个附加组件都需要维护。如果你是一个轻量级的在线小商店,使用临时资源就可以了,但请相信我,当你所有的容器在凌晨 4 点因为一个线程错误而崩溃时,你不得不向别人求助。

所有这些都让我相信,有效利用 Kubernetes 是有一个规模大小和复杂性的阈值的。如果你运行的是少量 (比如少于 5 个) 简单的服务,那么就不值得这么麻烦了。它真正的亮点在于那些具有高度部署复杂性的环境、动态的工作负载或者通过对工具进行标准化可以大幅降低复杂性 / 成本的场景。

5 那么,我应该怎么办?

毫不惊喜地说,答案是“视情况而定”。

如果你只有屈指可数的几个服务,不希望它们成倍增长,那么可能有更简单、更便宜的方式来托管它们。可以看看 AWS 的 ECS(特别是与 Fargate 一起使用的 ECS),把你的 API 或批处理作业重构成 Lambdas/Cloud Function,甚至可以使用简单的 PaaS 提供商 (如 Heroku) 来托管你的应用程序。尽管听起来似乎有些过时,但不要小看了这些运行在 Linux 机器上的低流量应用程序所带来的价值和健壮性。

安全性和合规需求可能会影响你的决策。如果必须在本地托管工作负载,则可能会有较大的运维开销,尽管这并不妨碍使用 Kubernetes,但传统的解决方案可能更适合你。如果你需要使用一组附加组件,但为了合规性,你不得不检查它们的每一个部分,那么这样做可能不现实。

我见过很多创业公司,他们认为自己需要 Kubernetes,但实际上并不需要,结果他们投入大量资源。仔细考虑一下你是否真的需要这些,以及你是否负担得起成本。如果你的需求和能够从中得到的好处是相当的,那就去做吧。如果不是,那么可以考虑是否在将来采用 Kubernetes,并将其加入到技术决策中。在一开始就用 Docker 打包应用程序 (Docker -compose 对于开发和生产来说都很有价值),并仔细考虑是否需要存储本地状态。

另一方面,评估未来的增长空间也很重要。如果你现在只有几个简单的服务,可能不需要 K8s。但是,它们是否会在未来变成几十个?如果是的话,你的团队是否应该开始学习管理这种复杂性的技能?当双翼飞机可以满足载客量的时候,你不会想要建造一架 747,但是,当 300 名乘客出现在登机口时,“骆驼”战斗机就没有多大用处了。

总而言之,基础设施决策通常与软件架构决策有关。不要让你的基础设施成为事后才去考虑的事情,不要忘了你需要的越多需要付出的成本也就越高。如果你需要的话,在复杂的系统上投入是值得的,但在投入之前要三思!

  • 评论列表 (0条)

 暂无评论,快来抢沙发吧~

发布评论

零下20°

酷站推荐℃

Hot 推荐

New 推荐