引入 Kubernetes 时不能太草率,因为它不一定适合你。本篇文章探讨了在使用 Kubernetes 前应该考虑的一些因素。
过去几年,Docker 成为一种非常受欢迎的应用程序构建、交付和运行方式。使用 Docker,只需一次构建应用程序,即可随处运行。虽然这是软件开发方式的一次巨大飞跃,但它也带来一些新挑战。对初学者而言,在 Docker 容器和主机间建立网络连接不是一件简单的事。这与我们过去传统的联网方法有很大不同,它要求具备一定的技能才能做好。
另一个挑战是存储。默认情况下,Docker volumes 被绑定到它们的主机。这意味着,如果我们希望运行一个服务的多个实例,并让它们共享 volume,就不得不设置好复制机制或配置成使用云存储服务。
虽然 Docker 被视为一项了不起的技术,但缺少一个能将所有技术联系在一起的组件。而 Kubernetes 正是那个组件。尤其是通过 Azure、AWS 等云平台提供的全托管形式,Kubernetes 解决了所有这些问题,并通过一系列概念将它们从最终用户那里抽象出来。
Kubernetes,也被称为 k8s,它由谷歌开发,用于解决在全球范围内运行成千上万个应用程序时所面临的问题。最近一两年,k8s 的采用正快速增长,有越来越多的公司寻找精通 k8s 的工程师。Kubernetes 虽然在 Spotify、ING 和许多其他公司的实施取得令人惊叹的成功,但它并非所有公司的终极解决方案。
https://kubernetes.io/case-studies/spotify/
https://kubernetes.io/case-studies/ing/
事实上,在生产环境中运行 Kubernetes 也会带来一些严重问题。在这篇文章,我们将探讨在决定使用 Kubernetes 前应考虑的一些因素。
1. 学习曲线
Kubernetes 有自己的运行机制。它是围绕几个概念设计的,熟悉其中的大多数概念是在生产环境中运行 Kubernetes 的必要条件。所以,这就引入了一个相当陡峭的学习曲线。不仅是对于系统管理员,对于开发人员也是如此。
https://kubernetes.io/docs/concepts/
下面这个图展示了 Kubernetes 架构的高级概述
Kubernetes 架构(Kubernetes Components,CC-BY 4.0)
https://kubernetes.io/docs/concepts/overview/components/
所有这些管理器、调度器和服务器负责全天候运行你的应用程序,即 k8s 中的工作负载。它们各司其职,并实现了 Kubernetes 的一个或多个概念。
在使用 Docker 或从事比较传统的系统管理工作时,你不一定会用到这些概念。每次,你在集群部署一个新的应用程序时,Kubernetes 都会为你的应用程序创建最少数量的以下对象:
- 表示应用程序的Deployment对象;
- ReplicaSet用于扩展与部署相关的Pod;
- 可选,一个或多个Service处理部署的网络需求;
- 表示实际容器的一个或多个Pod。这是 Kubernetes 架构中的最小组件。
如你所见,对一个不熟悉 Kubernetes 的人来说,这可能是很大的负担。更重要的是,这些对象中的每一种都有无数种配置方式,可以极大改变它们的行为。
事实上,启动和运行 Kubernetes 并正确配置它的所有组件,这需要大量时间。托管 Kubernetes 供应商承担了大量底层的配置和集成,但是,有一些工作将不可避免地渗透到开发人员那里,至少,他们需要基本熟练地使用 Kubernetes 才能正确完成工作。
你不一定非得需要 Kubernetes 来运行应用程序,它只是运行生产软件的众多选项之一。
你应该仔细衡量一下,迁移成本(学习曲线的增加和配置开销)和迁移好处。
2. 应用程序需要扩展吗?
Kubernetes 的一个关键特性是能对应用程序的各个部分进行扩展。流量会自动在各个Pod间路由和分配,如果配置完成,Kubernetes 甚至可以自动为你缩放Pod。
如果一个应用程序有一个或多个热点组件需要处理突发事件,那这个特性就很有价值。例如,在推出新扩展或新特性时,在线游戏的身份验证服务可能会出现登录请求突然增加的情况。或者是那些在发行后变得非常受欢迎并需要快速扩展基础设施的游戏,就无需担心网络、存储等问题。
《精灵宝可梦 Go》便是这样一款游戏,它在发行后不久便吸引了大量玩家。于是,它们广泛使用 Kubernetes 来为全世界大量玩家提供服务。
https://scotch.io/@pavan-belagatti/pokemon-go-a-successful-kubernetes-story
然而,对大多数其他应用程序来说,单个服务成为整个环境的瓶颈问题,通过优化而不是扩展解决更好。当然,在这个问题上,你可以多用几个Pod,并祈祷问题会消失——也就是说,只要没有达到存储层的限制,你就可以简单地通过扩展Pod来解决问题,达到了,就不行了。
不要误解我的意思——能动态地扩展部署是一个很大优点。但是,在我见过的绝大多数情况下,为解决瓶颈而扩大部署只是治标不治本。
此外,除了能使用 Kubernetes 扩展应用程序外,还有许多其他方法。Heroku、Azure 和 AWS 都提供了动态运行和扩展应用程序的方法。例如,Azure Web App 有横向扩展选项,这与在 Kubernetes 中运行多个Pod并在前置一个负载均衡器的效果是一样的。
如果扩展能力是吸引你转向 Kubernetes 的原因,那么首先要考虑下其他不太需要维护的选项。
3. 运行微服务
Kubernetes 主要用于运行许多小型的工作负载,这些工作负载一起组成一个应用程序。如前一节所述,其关键特性之一是独立扩展基础设施的各个部分,而不需要扩展整个应用程序。这些架构(通常被称为微服务架构)在 Kubernetes 上蓬勃发展。其架构支持简单的服务发现,以及整个拓扑中各个组件间的轻松交互。
因此,这里要考虑的不是在 Kubernetes 上运行微服务是否是一个好主意,而是微服务是否是特定应用程序恰当的架构原则。虽然微服务架构通常比传统的单体架构更受欢迎,但它们也给开发人员带来巨大负担。比如,Uber 支付体验平台放弃微服务,转而使用宏服务,这一事情引起网友热议。
让每个独立的服务各自都有定义好的职责是一种合理的架构选择。下一步,将这些职责划分为不同服务似乎是合乎逻辑的,但也可以不必如此。为了让开发人员可以分析和修复微服务环境中的 Bug,他们需要能访问构成该环境的大部分(如果不是全部的话)服务。
这让整个应用程序更加难以有效地工作。由于开发人员不能仅在他们的开发机器上运行应用程序,因此,你需要引入一整套工具来分析解决问题。考虑每个环境的分布式日志记录、消息队列和性能监视。
这对开发人员生产力的影响不是很明显。同样,这样做可能是值得的,特别是对于拥有许多开发团队的大型组织来说,每个开发团队都在他们自己的微服务上工作,是全局的一部分。然而,对于较小的公司和团队,微服务架构的成本要高得多。Kubernetes 并不一定使这些问题更容易处理。事实上,它甚至可能让情况变得更糟糕。
如果启用微服务架构是吸引你使用 Kubernetes 的原因,那么请仔细考虑一下,职责分离是不是一个可以用代码解决的问题,而不是通过在基础设施中引入 Kubernetes 等大型组件来解决它。
4. 小结
在考虑 Kubernetes 是否适合你的项目或组织时,我们讨论了一些需要考虑的因素。Kubernetes 最初是由谷歌设计来解决谷歌所面临的问题。这些问题涉及到在生产环境中运行大量的工作负载,而其伸缩需求对于我们这些普通人来说是不可想象的。
谷歌只有一家。当然,除了谷歌,你可能会遇到与谷歌在设计 Kubernetes 时相同的问题,而你成功的机会却很小。在决定将 Kubernetes 作为你的业务基础前,你非常有必要考虑下,在一段较长时间内,它对你的组织、开发团队和平台稳定性的影响。这项技术仍然相对较新,精通 Kubernetes 的工程师相对较少。
这并不是说 Kuberneets 是解决问题的错误方法。此前,我参与过一些项目,它们依赖 Kubernetes 向终端用户提供价值,而且规模很大,这是其他类似技术难以匹敌的。最重要的是,尽管关于 Kubernetes 的许多宣传是真的,但在引入 Kubernetes 时还是不能草率。
它有时候很合适——但并不总是很合适。