经验分享:HelloFresh在生产中运行Istio的经验教训 - Craig Huber


在HelloFresh,我们运行数百种微服务,这些微服务可以完成从供应链管理和付款到保存客户偏好的所有工作。大规模运行微服务并非没有挑战,许多公司开始经历复杂性的痛苦。像许多其他微服务采用者一样,我们发现随着服务数量的增长,越来越难以理解所有这些服务之间的交互。当微服务领域出现问题时,很难确定问题可能在堆栈中的哪个位置。在2019年初,我们开始研究解决此问题的方法,并得出结论认为服务网格,尤其是Istio是最佳选择。

Istio
Istio是围绕Envoy代理构建的服务网格,用于管理和控制流量,安全服务并查看它们之间发生的事情。此外,Istio还可以与Jaeger,Grafana,Kiali和Prometheus等其他常见基础结构和监视组件配合使用。由于我们已经将所有工作负载转移到Kubernetes / EKS,并且已经使用了上述工具,因此Istio非常适合我们。我们花了几个月的时间在暂存和生产工作负载上部署和配置Istio,到2019年12月,我们已经在生产服务之外部署了最后一辆sidecar代理。这一系列博客文章将解释我们在这段时间中学到的所有内容,并将涵盖一些未必在文档中突出显示的经验教训。

专注于您的需求
Istio可以做很多事情。纵观其带来的功能数量可能是压倒性的,但Istio的核心确实做四件事:连接性,可观察性,安全性和流量控制。早些时候,我们决定将精力集中在提供可观察性和弹性上。我们的策略是首先实现可观察性和复原力的构建基块,并在适应该基准后将其转移到其他功能上。
在Istio中,这意味着选择能够实现可观察性和可靠性的核心功能集。为了提高弹性,我们启用了“断路”,“异常检测”,“重试”(必要时)和“超时”。我们以一种使开发人员可以选择他们想要实现的功能的方式启用它们,但是具有公司标准接口(更多内容请参见下文)。实际上,我们为大多数服务添加了sidecar代理(Envoy),网关,虚拟服务和目标规则。
这里的建议是,对于大多数公司而言,Istio可能过于复杂而无法一次全部推出所有功能。因此,首先关注一个或两个方面,然后再添加其余方面。

集中式Istio模板
我们使用Helm chart部署所有服务。通常,要在全公司范围内创建虚拟服务和目标规则,我们将必须使用适当的Istio相关Helm模板来更新每个git repo。但是,我们编写了一个Helm插件,该插件可加载包含Istio虚拟服务,目标规则,网关资源的集中式Helm模板。该插件将这些模板与项目特定的值结合使用,以生成完整的图表。然后,应用程序团队可以在维护模板的同时配置值文件以满足他们的需求。为了为所有人启用Istio,我们要做的就是创建模板,而团队只需更新其helm 值即可。我们创建了一个简单的界面,通过以下值来控制Istio的所有方面:


是否使用边车sidecar代理?
最终,在考虑并确定要推出的功能以及开发人员如何与之交互之后,我们开始进行测试。在Istio中,这意味着将代理Sidecar添加到应用程序Pod。Istio通过在应用程序旁边注入基于Envoy的Sidecar代理进行工作,该应用程序拦截去往和来自Pod的所有入站和出站呼叫。然后,可以将Sidecar代理配置为控制或保护通过它的流量,但也可以收集遥测指标和跟踪信息,以供Prometheus和Jaeger使用。
首先,我们选择不向每个新pod中注入边车,因此我们全局禁用了自动注入:

global:
  proxy:
    autoinject: disabled

同样,并不是我们需要为每个Kubernetes命名空间注入sidecar,因此我们通过向启用了istio的命名空间添加以下标签来限制可能具有sidecar的命名空间:

istio-injection: "enabled"


有了这两部分之后,我们就可以通过在Pod中添加以下注释,逐个应用地推出Istio:

sidecar.istio.io/inject: "true"

Istio可以在应用程序级别上彻底改变预期的行为。在盲目地将它部署到任何地方之前,您需要对在哪个应用程序上运行进行有意识的选择。另外,并非每个应用程序都与Istio兼容,因此请务必先检查

分阶段推出
在HelloFresh,我们将团队分为小队和部落。每个部落都有自己的Kubernetes命名空间。如上所述,我们按名称空间启用sidecar注入名称空间,然后按应用程序启用。在为Istio启用应用程序之前,我们举办了研讨会,以使小队了解其应用程序发生的变化。由于我们采用“您构建,拥有它”的模型,因此,团队可以在进行故障排除时了解流量。不仅如此,它还提高了公司内部的知识水平。我们还创建了与Istio相关的OKR,以跟踪我们的进度并实现我们的Istio采用目标。

缩放控制平面
每个新的边车都会给Istio控制平面增加更多的负载。Pilot连接到每个istio-proxy,每个istio-proxy都针对每个请求(减去一些缓存)使用Mixer进行检查并报告,因此这些控制平面组件变得非常关键。在将每个名称空间迁移到Istio之前,我们都已监控并调整了控制平面。在继续增加负载之前,这为我们提供了一个很好的检查点。我们必须定期调整每个控制平面组件的副本数,CPU和内存请求/限制。
另外,我们还要关注每个istio-proxy消耗的内存量。请记住,尽管Envoy代理是相对轻量级的,但是运行数千个请求并不是免费的,并且会增加大量的内存占用。我们已经在使用Kubernetes集群自动缩放器,因此我们的集群会自动缩放,
同样,所有生成的日志,指标和跟踪都会给我们的Graylog,Jaeger和Prometheus基础架构带来额外的负担。通常,我们必须在日志记录基础架构,Jaeger,Cassandra数据库中增加更多的容量,并在将更多名称空间加入Istio之前扩展Prometheus Pod。