我需要库伯内斯吗?

2020-08-16 23:33:30

无论是新团队还是老牌团队,我经常听到的一个问题是“我们应该把我们的堆栈托管在Kubernetes上吗?”鉴于它在科技界引起的轩然大波,许多人认为是这样的。

我使用K8已经有几年了-通常是使用非常强大和复杂的平台-我认为真相更加微妙。

以下是我试图理清这一决定的尝试。它面向更广泛组织中的初创企业和自给自足的团队,负责托管他们自己的产品。它可能对大型商业组织中更传统的IT部门的人员也有价值。

库伯内斯不仅仅是2018年的流行语。它是一个健壮的、高度可伸缩的系统,允许您使用经过深思熟虑的原语(Pod、Service、Inress等)构建应用程序部署,然后尽最大努力使实际情况匹配。当应用程序崩溃时,它会重新启动它们。当整个底层机器消失时,它会试图替换它们。如果您正在运行许多服务(可能是作为微服务体系结构开发的),并且您正在寻找效率、弹性和部署的好故事,那么它可以为您做很多事情。

想要在你的服务中有基本程度的弹性吗?(是的,您需要)-在您的部署中运行多个副本,然后平衡它们之间的流量。

如果您的工作负载是“突发性的”(例如,大量API流量),您可以在此基础上构建自动伸缩功能,以便在需要时增加容量。这可以为您节省一大笔钱-而不是一直为峰值容量买单,而是提供一个基本负载量,以保持平台正常运行,并在需要时提供更多副本。如果您可以将队列长度导入到您的系统中,那么自动缩放也适用于基于队列的工作负载。

担心你的密码被破解吗?配置活跃度/就绪探头,Kubernetes会在出现故障时自动重启您的服务。同样,对于硬件故障-我看到丢失了一半节点的群集继续运行,就像什么都没发生一样。配置和维护良好的Kubernetes集群可以非常健壮。如果您有足够的资源,您甚至可以尝试运行一个类似于混乱猴子的工具,以确保您的堆栈能够容忍常规的故障。

Kubernetes具有与您的CI工作流集成的出色功能。我看到的最常见的模式是构建(理想情况下是跨所有项目标准化的),它将映像推送到Docker注册表,然后启动K8S集群来加载它。根据口味,可以通过修改部署来拉取新标签,或者将标签指向新映像并触发K8重新加载所有Pod。在大多数情况下(迁移会毁掉一切),部署可以完全自动化:如果您信任您的测试和功能标志,它可以是100%自动的(也就是连续交付);对于不那么勇敢的人,在构建之后执行手动审批步骤可以减轻痛苦。无论哪种方式,您的开发人员都应该能够在没有Kubernetes专家任何帮助的情况下将大多数构建发布到集群。

与CI类似,它可以帮助您标准化应用程序的日志记录和监控。这样做绝不是Kubernetes独有的,但是拥有一个集群范围的系统,将所有服务的数据收集到同一位置,可以极大地减轻调试的痛苦。我看到,使用Fluentd将JSON结构的日志记录输出从应用程序输送到AWS CloudWatch并通过Insights进行查询会产生特别好的效果。

最后,它可以极大地提高效率-无论是在托管层(即将尽可能多的应用程序塞到那些昂贵的EC2实例上),还是减少您的开发人员需要花费在部署软件上的时间。人类的成本比计算机高,所以对于大多数组织来说,第二个将是最大的胜利。但库伯内斯并不神奇--我见过一些美丽、高效的星团和一些完全耗油的星团。如果你投资于正确使用库伯内斯,你才会用Kubernetes省钱。

首先,考虑一下您的工作量。您需要运行哪些类型的应用程序?他们如何与彼此和外界交谈?根据经验,我想说以下属性使您的堆栈非常适合:

一般说来,您是否遵循微服务体系结构?如果您的世界只有一个应用程序,那么Kubernetes就没有什么价值。您需要将应用程序Docker化才能将它们部署到K8;从任何项目的第一天开始就这样做是让您自己思考服务之间边界的好方法。

您的服务是否通过HTTP向彼此和外部世界公开(可能是的,现在是2020年)?这将非常适合K8的型号,您可以使用一个正常的入口控制器来将它们放在前面。

您的应用程序是否适合负载平衡?没有本地状态(使用PostgreSQL/Redis/其他方式),通过已知端点进行通信,快速启动/关闭。这并不是说你不能在集群中保持像Redis缓存这样的短暂状态,但在许多情况下,你最好使用云提供商提供的盒装服务。

Kubernetes还非常适合于无头应用程序,如批处理(通过其Job控制器)和长期的队列使用者。

内存(以及较小范围的CPU)使用情况是否可预测?Kubernetes将尝试在相同的物理机上托管您的应用程序,因此如果其中一个应用程序出现故障并消耗了所有RAM,其他工作负载可能会被随机终止。根据我的经验,这是Kubernetes集群上最大的不稳定性来源。如果您了解应用程序的资源使用情况,您可以声明一个资源.请求和资源.限制,以保证它们总是获得所需的内存,并且不会对邻居造成不良影响。

如果您正在大规模运行应用程序,Kubernetes可以为您节省一大笔钱。了解自动缩放(针对集群和副本集)和Spot实例池(EC2)或可抢占VM(Google)等功能。在一个大环境中,单凭这一点就可能做出正确的决定。

存在一个优秀工具的生态系统,可以帮助任何工程师提出一个玩具集群来测试他们的应用程序。从某种程度上说,这很棒-学习曲线开始得很平缓-但对Kubernetes来说,在你意识到承诺的规模之前,悄悄进入生产并成为你业务的关键部分太容易了。它有复杂的故障模式,最大限度地利用它需要大量的专业技能。让一个缺乏经验的开发团队匆忙拼凑一个集群(使用KOPS是一种常见的反模式)会导致灾难:它在几个月内会工作得很好,但如果您需要进行重大更改、重新配置集群或排除合并失败的故障,那么您将面临一个糟糕的时期。

从头开始构建一个K8S集群就像编译您自己的内核:这是一个很好的未雨绸缪的活动,可以了解事情是如何工作的,但是运行生产应用程序的方式却非常糟糕。相反,你应该运行像AWS EKS或Google的GKE这样的盒装解决方案。比我聪明得多的人投入了大量的时间来做好这些事情,利用这些努力是有意义的,即使你需要每月支付几百美元才能做到这一点。

即使使用盒装Kubernetes发行版,也需要专业技能。控制平面是Amazon的问题,但是您迟早会设法在节点上触发一些模糊的bug,通常是在您的业务最繁忙的时候。您必须准备好投入资源来运行系统,并且愿意支付这些资源。Kubernetes的发布周期很短,因此您每年至少需要升级一次集群,并且定期更改其API,这可能是一项非常重要的工作。您运行的任何附加组件也需要维护。如果你是一个有轻量级要求的小商店,兼职资源就可以了,但相信我,当你的所有容器在凌晨4点因为一个隐蔽的线程错误而爆炸时,你将需要有人来求助。

所有这些让我相信,有效使用Kubernetes存在一个大小/复杂度的阈值。如果你只运行少量的简单的、要求不高的服务(比方说<;5),可能就不值得麻烦了。它真正闪耀的地方是需要管理的部署复杂性很高、工作负载动态的环境,或者可以通过标准化您的软件工具来大幅降低复杂性/成本的环境。

正如你可能对一篇2000字的文章的结论所期望的那样,答案是“视情况而定”。如果您还没有,绘制一张架构图会很有帮助。

如果您只有一小部分不期望成倍增长的服务,那么可能有更简单、更便宜的方式来托管您的技术堆栈。看看AWS ECS(特别是与Fargate结合使用),将您的API或批处理作业重写为lambdas/Cloud函数,甚至使用Heroku这样的简单PaaS提供商托管您的应用程序。尽管听起来很复古,但不要忽视在几个维护良好的Linux邮箱上运行简单的低流量应用程序所带来的价值和健壮性。

安全和合规性要求可能会影响您的决策。如果必须在内部托管工作负载,您可能会看到很大的运营开销,虽然这并不排除使用Kubernetes,但更传统的解决方案可能更适合您。如果您需要使用一组附加组件,但是遵从性要求您审查您运行的每一个软件,那么这种努力可能不太现实。

我见过很多初创公司,他们认为自己需要Kubernetes,但实际上他们并不需要,结果却投入了大量资源。仔细想想你是否需要所有的力量,你是否能负担得起很好地实施它。如果你的需求证明了你的承诺是合理的,那么就去做吧。如果不是这样,考虑一下你将来可能选择的Kubernetes,并将其纳入你的技术决策中,让你的选择变得更加开放。从第一天开始在Docker中运行您的应用程序(使用docker-compose it对于开发和生产一样有价值),并在让您的应用程序存储本地状态之前仔细考虑。

另一方面,重要的是要衡量未来的增长空间。如果你现在只有几个简单的服务,你可能不需要K8。但是,它们是否即将变异为几十个,如果是这样,您的组织现在是否应该开始获得管理这种复杂性的技能?当双翼飞机可以做到的时候,你不会想要制造一架747,但另一方面,当300名乘客出现在登机口时,Sopwith Camel不会有太大的用处。

总而言之,基础设施决策通常取决于您对软件体系结构所做的选择。不要让您的基础设施成为事后的想法,不要忘记,您需要的基础设施越多,拥有成本就越高。如果需要,投资复杂的系统是可以的,但在这样做之前要仔细考虑一下承诺。