如果你已经在使用 Docker 了,那么下一步很自然的就是要应用 Kubernetes。
在开发同一应用程序时,5 个软件工程师设计的解决方案,与 50 个、500 个软件工程师设计的肯定不同。因此,如果你是在一个小团队中,Kubernetes 可能不是一个好的选择,它会带来很多痛苦,但好处却微乎其微。
为什么这么说呢?
Kubernetes 应用存在哪些问题?
Kubernetes 有大量的活动部件——概念、子系统、过程、机器、代码,这就意味着会有大量的问题。
多机器
Kubernetes 是一个分布式系统:有一台控制工作机器的主机器,工作被安排在不同的工作机器上。然后,每台机器在容器中运行工作。
如果你的工作只需要两台机器或者虚拟机来完成,那么使用 Kubernetes,你可能就需要扩展,需要 3 个、4 个或者更多的虚拟机。
多代码
截至 2020 年 3 月初,Kubernetes 的代码库中已有超过 58 万行 Go 代码。 这是实际的代码行数,没有计算注释或空白行,也没计算供应商的包。
2019 年的安全审查 这样描述其代码库:
……Kubernetes 的代码库有很大的改进空间。该代码库庞大而复杂,大部分代码只包含很少的文档和大量的依赖关系,包括 Kubernetes 外部的系统。在代码库中有很多逻辑重新实现的情况,可以集中到支持库中,从而降低复杂性,简化补丁,并减少代码库中不同区域的文档负担。
坦率来讲,Kubernetes 与其它大型项目没有什么不同,如果想要应用程序不奔溃且更好的运行,那么研究代码是必须要做的工作。
复杂性
Kubernetes 是一个复杂的系统,包含许多不同的服务、系统和部件。
在运行单个应用程序之前,你需要以下高度简化的架构:
K8s 文档中的概念文档包含许多这样的讲解说明:
在 Kubernetes 中,EndpointSlice 包含对一组网络端点的引用。在指定选择器时,EndpointSlice 控制器自动为 Kubernetes 服务创建 EndpointSlice。这些 EndpointSlices 将包含任何与服务选择器匹配的 Pod 引用。EndpointSlice 通过唯一的服务和端口组合将网络端点分组。
在默认情况下,EndpointSlice 控制器管理的每个 EndpointSlice 的端点不超过 100 个。在这个范围内,EndpointSlice 应该与端点和服务进行 1:1 的映射,并且具有类似的性能。
仅仅这一段文字中就包含了很多的概念,例如 EndpointSlice、服务、选择器、Pod 和端点。但在实际应用中,有时你根本都用不到这些功能。
默认情况下,发送到 ClusterIP 或 NodePort 服务的流量可能被路由到该服务的任何后端地址。从 Kubernetes 1.7 开始,就可以将“外部”流量路由到在接收流量的节点上运行的 Pods,但这不支持 ClusterIP 服务,而且,也不可能实现更复杂的拓扑结构(如分区路由)。服务拓扑特性解决了这个问题,它允许服务创建者根据源节点和目标节点的节点标签定义流量路由策略。
安全审查是这样评价 Kubernetes 的:
Kubernetes 是一个庞大的系统,操作非常复杂。评估团队发现 Kubernetes 的配置和部署非常复杂,某些组件的默认设置令人困惑、缺少操作控制和隐式定义的安全控制。
另外,Kubernetes 的开发复杂性也很高,当你越多的使用 Kubernetes,就会越难进行平常的开发,需要了解各种概念之后才能运行代码,如 Pod、部署、服务等。同样测试时,也需要通过 VM 或嵌套的 Docker 容器启动完整的 Kubernetes 系统。
由于应用程序很难在本地运行,开发也就更困难了,所以各种各样的解决方案也就应运而生了,从过渡环境,到将本地进程代理到集群,再到将远程进程代理到本地机器……
虽然解决方案很多,但是有些方案也不完善,所以我认为最好也是最简单的解放方案是不使用 Kubernetes。
微服务
当系统允许运行多服务时,很容易就会编写许多服务。其实,这并不是个好主意。
首先,分布式应用程序很难编写,服务越多,问题就会越多。
其次,分布式应用程序很难调试,可能需要新的工具和日志记录来调试。
微服务其实是一种组织层面的扩展技术,当 500 名开发人员在共同开发一个网站时,不同的开发团队需要独立工作,这时支付大规模分布式系统的成本是有意义的,如果是一个 5 人团队,微服务是没有意义的。
Kubernetes 是不是就没用了呢?
上面讲了这么多 Kubernetes 应用时的问题,那是不是说明 Kubernetes 完全没用呢?当然不是。
扩展性
如果你需要大规模的扩展,Kubernetes 可能会很有用。
你可以得到最多 416 个 vCPU 和 8TiB RAM 的云 VM,虽然会很贵,但也很简单。
你可以使用像 Heroku 这样的服务来扩展许多简单的 Web 应用程序。
不过,大多数应用程序不需要扩展太多,一些合理的优化就足够了。
许多 Web 应用程序的扩展其瓶颈通常是数据库,而不是 Web 工作进程。
可靠性
活动部件越多,就意味着出错的机会越多。
Kubernetes 内置了很多特性(健康检查、滚动部署),可以使得可靠性变得更简单,例如,Nginx 可以对工作进程执行健康检查,使用 docker-autoheal 或类似的东西自动重启进程。
如果你关心的是停机时间,那么第一个想法不应该是“如何将部署停机时间从 1 秒减少到 1 毫秒”,而应该是“如何确保数据库模式更改不会妨碍我在事情搞砸时进行回滚”。
如果你只是想要一个可靠的 Web 工作进程,不存在单机故障点,那么有很多方法可以做到这一点,不必使用 Kubernetes。
最佳实践?
没有所谓的最佳实践,只有针对特定情况的最佳实践。
我们不能仅仅因为某件事很流行,就认为它是正确的选择。在某些情况下,Kubernetes 是一个非常好的主意,但在另一些情况下,这是一种毫无益处的时间陷阱。
在我看来,除非你的应用程序真的复杂到必须使用 Kubernetes,否则使用其它工具也可以很好的完成工作,例如单机 Docker Compose、类似 Heroku 的系统、用于计算管道的 Snakemake 等等。
原文链接:
https://pythonspeed.com/articles/dont-need-kubernetes
评论 4 条评论