你需要一个服务网格——你有无数的微服务,并且正计划以云原生方式构建,以保护集群内的所有流量。市场上有很多服务网格,而且大部分都是免费的。你需要知道最适合你的。

那么,免费服务网格要花多少钱呢?答案比你想象的要复杂得多。与云和基础设施即服务世界中的许多事物一样,添加新工具通常会增加复杂性和成本,即使该工具本身是免费的。此外,还有隐藏的服务网格的部署和运维成本,一旦超出了rip-and-replace的范围,就会增加费用。

有许多意外成本增加的例子。首先,如果每个新的sidecar注入对控制平面(一个常见的服务网格问题)中的CPU需求有超过1倍的影响,那么随着添加新服务,成本可能会迅速上升,因为每个新服务都需要单独的sidecar。或者,假设你需要维护到集群外部运行的单片应用程序的API连接。如果服务网格没有此功能,那么你可能需要在服务网格的顶部保留一个单独的API网关。仅此一项就可能使成本、管理时间和风险翻一番。如果应用程序管理和控制的任何部分都依赖于用户数据报协议(UDP),该怎么办?不幸的是,大多数服务网格不支持这一点。你可能需要重构应用程序并切换控制方法以将其塞入服务网格。

选择服务网格之前要问的问题

显而易见的第一个问题是:“我需要一个服务网格吗?”在许多情况下,当你只需要管理少量的微服务,或者没有明确的安全要求(如端到端加密)时,服务网格可能会被过度使用,而且是不必要的。

如果你确定需要并且想要一个服务网格。首先,你应该读一读一个服务网格战场上的警示故事,来自HelloFresh的团队开始部署之旅时。

“在过去几个月里用Istio时,我们发现即使是较小的Istio全局配置也会对上游其他地方产生重大的连锁反应。在一个实例中,一个较小的全局配置更改导致Istio Pilot将新配置推送到1000多个连接的Istio代理。当代理加载此配置时,每个比平常多消耗了大约75mb的内存。虽然75mb听起来不算多,但当同一个工作节点上有几十个已连接的istio代理时,这个尖锐的峰值导致一些Kubernetes工作节点的可用内存不足,从而影响了节点上运行的pod。幸运的是,我们在部署之前发现了这一点。”

不过,这是一年多以前的事了,Kubernetes和Istio继续定期改进,因此许多技术问题今天可能更简单地得到解决。关键之处在于:他们选择的服务网格具有实际的成本影响,无论是在数据和CPU使用、变通方法和额外的计算基础设施方面,还是在故障排除和修复方面。对HelloFresh来说,一个合理的问题是:“你是否需要服务网格来管理在任何地方的所有服务,如果不需要,你所经历的一些挑战是否可以通过对服务网格足迹进行更多的选择来缓解?”

通过询问以下一系列问题,你可以评估服务网格选项的潜在隐藏成本:

1.运行控制平面需要多少个容器镜像?每个镜像必须有多大?

控制平面是一定的——你需要它来操作服务网格。但是,控制平面架构可能会产生重大影响,特别是运行控制平面所需的容器镜像的数量和大小。为什么这很重要?

数量:所需的容器镜像数量直接关系到网格想要对集群拥有多少所有权,这反过来又直接增加了成本。

大小:简单地说,容器越大,投入的资源就越多。

另外一个成本可能是维护应用程序所需服务级别所需的CPU类型。我们通常不考虑微服务的节点大小或类型,但Kubernetes集群中的重量级应用程序需要更多的计算资源,就像云中或裸金属上一样。对于开发环境,中端CPU可能就足够了。对于真正的生产环境,甚至是高可用性环境,你可能需要顶级CPU。

请记住,服务网格最终在硬件或虚拟硬件上运行,而容器镜像决定了该硬件的需求。

2.服务网格Ingress控制器的容量是多少?

Ingress控制器通常用于Kubernetes集群前面,以监控、管理和塑造入口和出口(南北)交通。尽管与服务网格一样,Ingress控制器并非都是平等创建的。与传统的数据中心负载均衡器一样,一些Ingress控制器的每秒连接或请求容量较低,这可能意味着更频繁地将Ingress控制器容器以较低的阈值自动缩放。

是的,Kubernetes被明确设计为自动缩放服务网格,但这应该是最后的手段。使用自动缩放,你可能需要定期支付现货云定价。这些费用很快就加起来了。当然,你可以切换到更高容量的Ingress控制器。一定要考虑这个限制;虽然有些服务网格彼此紧密集成,但并非所有服务网格都支持所有Ingress控制器,或者它们集成的方式可能会增加不必要的延迟。

3.sidecar能否满足服务需求?

在旧世界的云应用程序甚至是单体应用程序中,代理的速度直接影响到应用程序架构。速度较慢、容量较低、可扩展性较差的代理可能意味着你需要部署更多代理。对于高性能、低延迟的应用程序来说,快速、可扩展的代理过去是好的,现在仍然是。在Kubernetes中,sidecar包含代理。

有些sidecar使用的语言不是专为网络或超级性能应用程序交付和流量管理而设计的,因此性能存在很大差异,加上在某些流量阈值下容易翻车。在其他情况下,编写sidecar的团队可能没有太多的经验来创建能够处理网络规模流量和需求高峰的“防弹”代理。sidecar的性能越差,你就需要更多的sidecar和服务来跟上流量高峰和一般负载。

你还可能为一个步履蹒跚的代理支付比预期更多的费用,这可能会在停止流量的同时,仍然在Kubernetes仪表板上显示为工作正常。一个步履蹒跚的代理可能会额外引入尾部延迟,这不会出现在平均值中,但会导致一些客户不满意。

4.多集群还是多租户?

多个集群可以以每小时每个集群的最低速率快速累加。如果你正在运行许多服务,但希望不同的团队保持对其服务的控制,那么多个集群将有麻烦。

这就是说,多租户——将资源隔离在更大的集群中——有其自身的挑战。从表面上看,将更多的应用程序和开发团队放到集群中看起来确实更便宜,因为它允许你更好地优化存储和CPU的使用。尽管多租户可能会给DevOps和DevSecOps团队带来沉重的负担,同时还会增加迫使他们创建和维护额外功能的复杂性。例如,对于多租户,在建立基于角色的访问控制(RBAC)时,可能需要在命名空间级别在租户之间创建分段。然后,如果一个团队对网络、安全或其他配置进行更改,则必须考虑潜在的风险,从而将所有应用程序暴露在可能导致整个集群的威胁中。

5.服务网格需要多少CRD?

在Kubernetes中,CRD是“自定义资源定义”。在这个集群和服务网格的世界中,资源是Kubernetes API中的端点,允许你存储API对象。默认Kubernetes安装中包含许多资源,但Kubernetes还允许你创建CRD以实现更多自定义或定制功能。

大多数服务网格需要在Kubernetes环境中创建一些CRD,以连接到集群并提供功能。然而,太多的CRD就像太多的代码。每个CRD都包含指向每个API版本的API路径。如果服务网格需要许多CRD,这可能会快速产生级联复杂性。由于CRD的数量通常与服务网格实现的功能数量成正比,因此更多的CRD可以转化为更具挑战性的配置,通常是针对未使用的功能,以及维护服务网格及其服务的应用程序。

6.是否需要专门的员工来运行服务网格?如果是,有多少人?

如上所述,复杂性需要更多的管理和对工具的更多关注。对你来说,需要一个专注的员工,他们的主要工作是保持你的服务网络平稳运行,这可能是一个危险的信号。考虑到优秀平台运维和DevOps人才的成本,这将立即在预算中增加六位数的费用。这也违背了Kubernetes和服务网格“左移”的整个理念,即让应用程序团队和服务所有者更多地控制自己的命运。最后,它表明服务网格选择是复杂的、脆弱的,并且可能成为单点故障。

7.服务网格是否将你锁定在特定的软件或云中?

Kubernetes的目的是允许你将容器化应用程序移动到任何环境,对吗?对于Kubernetes层来说,这可能比服务网格更真实。每个云都有一个Kubernetes服务和一些依赖关系,这使得在服务之间移动应用程序有点困难。不幸的是,服务网格层上的依赖关系往往更不宽容,而且往往带有很重的观点:如何与集群集成,或者不集成;对整个集群拥有多少所有权;是否将新的Kubernetes工具用于重复功能等。

虽然大多数主要的服务网格都遵循称为SMI规范的服务网格接口标准,但不同的云在如何调整它们的可伸缩性、安全工具和解决方案以及可观察性处理方面存在差异。例如,一些服务网格具有非常深的可观察性钩子,需要重大配置甚至数据模式更改才能有效地移植到其他云。一个好的做法是尝试对服务网格选择中可能遇到的所有类型的锁定和可移植性挑战进行编目。理想情况下,挑战越少,你可以保留的可选性就越多。如果你确实需要在一个或多个云中进行大规模构建,那么你应该了解在成本和灵活性方面将付出的锁定代价。

结论:了解隐藏成本

以上所有内容都取决于你的特定服务网格计划和应用程序的需求。对于大多数团队来说,在将服务网格部署到生产环境之前广泛测试驱动服务网格是一个不错的想法,这与提前花一些时间定义你希望通过服务网格选择解决的用例一样。虽然这是一个理想化的工作流程,但有十几个服务网格存在,并且测试它们都需要花费大量的时间,因此尝试一个你永远不会使用的附加功能是没有意义的——提前想好服务网格的问题。