最近,我怀着对微服务治理的热情,开始学习和使用Istio服务网格。
Istio这几年很火,特别是在Kubernetes和云原生领域,几乎是人人都在讨论。它号称是下一代微服务治理的标准,由Google、IBM、Lyft等公司联合开发,能提供流量管理、安全、可观测性等强大功能,而且对业务代码零侵入。
我们团队的微服务,一直面临着服务治理的问题。服务发现、负载均衡、熔断降级、限流重试、安全通信、链路追踪、监控告警……这些功能,我们都是用SDK的方式集成到业务代码里的,维护成本很高,而且多语言支持困难。我本来以为,引入Istio之后,这些问题就能迎刃而解,微服务治理就能变得简单而优雅。
结果没想到,Istio的学习曲线这么陡,概念这么多,配置这么复杂,坑这么多,让我屡屡碰壁,差点放弃。
今天,我想记录一下我Istio服务网格从入门到(差点)放弃的经历,包括我为什么学Istio、学习过程中遇到的困难、我是怎么克服的、以及我对Istio的一些看法。
需要说明的是,目前(2018年5月)Istio还处于0.x版本,1.0还没发布(预计今年年中发布),还在快速发展中,API和功能可能还会变化。本文基于目前的版本和我的使用经验,可能会有不准确的地方,仅供参考。
一、我为什么学Istio
先说说我为什么想学Istio。
我们团队的微服务架构,已经跑了两年多了,有十几个微服务,用Java和Go两种语言开发。随着服务数量的增多,微服务治理的问题越来越突出:
1. 服务治理逻辑和业务逻辑耦合
我们的服务治理功能(熔断、限流、重试、负载均衡等),都是用SDK的方式集成到业务代码里的。比如,Java服务用Netflix的Hystrix做熔断,Ribbon做负载均衡;Go服务用自己实现的一套库。这些治理逻辑,和业务逻辑混在一起,业务代码不够纯粹,维护成本很高。
而且,不同语言的SDK,功能和行为不一致,治理策略不统一。比如,Java服务的熔断阈值和Go服务的不一样,导致整个系统的治理策略很混乱。
2. 多语言支持困难
我们的微服务用Java和Go两种语言开发,每种语言都需要一套SDK。如果以后再加新的语言(比如Python、Node.js),又要重新实现一套SDK,成本很高。而且,不同语言的SDK质量参差不齐,很难保证一致性。
3. 升级困难
SDK的升级,需要每个服务都重新编译、重新部署,成本很高。如果SDK有bug或者需要加新功能,要推动所有服务升级,是一件很麻烦的事情。
4. 高级流量管理功能缺失
我们想做灰度发布、A/B测试、流量镜像等高级流量管理功能,但是用SDK的方式很难实现。这些功能,需要在流量入口层做统一的控制,SDK做起来很麻烦,而且效果不好。
5. 安全和可观测性不足
服务之间的通信,没有统一的加密和认证,安全性不够。监控和链路追踪,也是每个服务自己埋点,不统一,排查问题很麻烦。
就在这个时候,Istio进入了我的视野。Istio的设计理念,正好解决了我们的这些痛点:
- 零侵入:通过Sidecar代理,把治理逻辑从业务代码里抽离出来,业务代码只关注业务逻辑。
- 多语言无关:不管服务用什么语言开发,都可以用同一套治理方案。
- 统一的控制平面:有统一的控制平面,可以统一配置和管理所有服务的治理策略。
- 强大的流量管理:支持灰度发布、A/B测试、流量镜像、故障注入等高级流量管理功能。
- 内置的安全和可观测性:内置了服务间通信的加密、身份认证、监控指标收集、分布式追踪等功能。
看到这些特性,我很兴奋,觉得Istio就是我们要找的微服务治理方案。于是,我开始了Istio的学习和实践之旅。
二、入门:概念多到让人头大
最开始学Istio的时候,我被它的各种概念搞得头大。
Istio的概念真的很多,而且每个概念都有专门的CRD(Custom Resource Definition),配置起来很复杂。比如:
- VirtualService:虚拟服务,用来配置路由规则,比如根据请求头、权重等把流量路由到不同的服务版本。
- DestinationRule:目标规则,用来配置目标服务的策略,比如负载均衡策略、连接池、异常检测、熔断等。
- Gateway:网关,用来配置网格入口的流量,比如对外暴露的端口、协议、TLS证书等。
- ServiceEntry:服务入口,用来把网格外部的服务加入到网格内部的服务注册表中,让网格内的服务可以访问外部服务。
- EnvoyFilter:Envoy过滤器,用来直接配置Envoy代理的过滤器,实现更高级的功能。
- Policy:策略,用来配置网格的策略,比如限流、配额等。
- MeshPolicy:网格策略,用来配置整个网格的安全策略,比如是否启用mTLS。
- Sidecar:Sidecar配置,用来调整Sidecar代理的配置,比如限制Sidecar转发的端口、协议等。
这些概念,每个都不简单,而且它们之间还有复杂的关系。比如,一个请求进来,先经过Gateway,然后匹配VirtualService的路由规则,路由到目标服务,然后应用DestinationRule的策略,最后由Sidecar代理转发到实际的服务实例。
最开始,我根本搞不清这些概念之间的关系,配置一个简单的路由规则,都要查半天文档,改好几次才能成功。
而且,Istio的文档,虽然内容很丰富,但是组织得不太好,很多概念的解释不够清晰,例子也不够多。对于新手来说,光看文档,很难快速上手。
那段时间,我每天都在看文档、看博客、看例子,试图理解这些概念。花了大概一周的时间,才大概搞清楚了核心概念和它们之间的关系。
三、部署:复杂到让人崩溃
搞清楚了概念之后,我开始尝试部署Istio。本以为部署是最简单的一步,结果没想到,部署才是噩梦的开始。
Istio的部署,比我想象的复杂得多。它不是一个单一的组件,而是由很多组件组成的:
- Envoy:Sidecar代理,每个服务实例旁边都有一个,负责流量转发和治理。
- Pilot:负责流量管理,把路由规则和服务发现信息分发给Envoy。
- Mixer:负责策略执行和遥测数据收集,比如限流、配额、监控指标、日志等。
- Citadel:负责安全,管理证书和密钥,实现服务间的mTLS通信。
- Ingress Gateway:入口网关,负责网格入口的流量。
- Egress Gateway:出口网关,负责网格出口的流量。
这些组件,每个都需要单独部署和配置,而且它们之间还有复杂的依赖关系。部署的时候,要注意组件的版本、配置、资源限制等,任何一个地方出问题,整个Istio都可能不正常。
我最开始是在本地的Minikube上部署的,按照官方文档一步步来,结果部署了好几次才成功。不是这个组件启动失败,就是那个组件连不上,各种报错。
后来,我在测试环境的Kubernetes集群上部署,又遇到了很多问题:
- 资源不足:Istio的组件很多,每个组件都需要一定的CPU和内存资源。我们的测试集群资源有限,部署了Istio之后,资源很紧张,经常出现Pod被驱逐的情况。
- 网络问题:Istio的Sidecar代理,会拦截所有的进出流量,这对集群的网络配置有一定要求。我们的集群网络插件是Flannel,和Istio有一些兼容性问题,折腾了很久才解决。
- mTLS问题:Istio默认启用了mTLS(双向TLS),服务之间的通信都是加密的。但是,我们有些老服务,不支持mTLS,接入Istio之后,服务之间调用失败。后来,我们花了很多时间,才把mTLS的策略配置好,让新老服务都能正常通信。
- Sidecar注入问题:Istio通过自动注入Sidecar的方式,把Envoy代理注入到每个服务的Pod里。但是,自动注入有时候会失败,或者注入的配置不对,导致服务启动失败。我们踩了很多坑,才搞清楚自动注入的机制和配置方法。
部署Istio,前前后后花了我将近两周的时间,才在测试环境跑起来。那段时间,我每天都在查问题、改配置、重新部署,差点就放弃了。
四、使用:配置复杂,调试困难
部署好之后,我开始尝试使用Istio的各种功能。本以为部署好了,使用起来就简单了,结果没想到,使用才是更大的挑战。
1. 配置复杂
Istio的配置,真的很复杂。一个简单的功能,可能需要写很多YAML配置。
比如,我想做一个简单的灰度发布,把10%的流量路由到新版本的服务。我需要:
- 部署新版本的服务,给它打一个特定的标签(比如version: v2)。
- 配置DestinationRule,定义服务的子集(subset),把不同版本的服务归到不同的子集里。
- 配置VirtualService,定义路由规则,把10%的流量路由到v2子集,90%的流量路由到v1子集。
这还只是最简单的灰度发布。如果要做基于请求头的路由、基于权重的A/B测试、流量镜像、故障注入等更复杂的功能,配置就更复杂了。
而且,Istio的配置,是通过CRD(Custom Resource Definition)来实现的,每个CRD都有很多字段,很多字段的含义和用法,文档里解释得不够清楚,需要反复试错才能搞明白。
2. 调试困难
Istio的调试,也很困难。因为流量是经过Sidecar代理转发的,出了问题,你不知道是业务代码的问题,还是Sidecar代理的问题,还是控制平面的问题。
比如,服务A调用服务B失败了,可能的原因有:
- 服务B本身挂了,或者业务代码有bug。
- 服务B的Sidecar代理配置不对,或者挂了。
- 服务A的Sidecar代理配置不对,路由规则有问题。
- Pilot没有把最新的配置分发给Envoy。
- mTLS证书有问题,服务之间无法建立安全连接。
- 网络策略或者防火墙阻止了流量。
- ……
这么多可能的原因,排查起来很麻烦。你需要查看业务日志、Sidecar代理的日志、Pilot的日志、Mixer的日志,还要用Istio提供的命令行工具(istioctl)查看配置和状态,有时候还要直接看Envoy的配置和统计信息。
最开始,我遇到问题,根本不知道从哪里下手排查,花了很多时间才找到原因。后来,用得多了,才慢慢积累了一些排查经验。
3. 性能开销
Istio的性能开销,也是一个需要考虑的问题。因为每个服务实例旁边都有一个Sidecar代理,所有的流量都要经过Sidecar代理转发,这会增加一定的延迟和资源消耗。
根据官方的测试数据,Istio的Sidecar代理,会增加几毫秒到几十毫秒的延迟(取决于配置和场景),每个Sidecar代理会占用一定的CPU和内存资源。对于延迟不敏感的场景,这个开销可以接受;但是对于延迟敏感的场景(比如高频交易、实时通信等),这个开销可能就需要仔细评估了。
我们在测试环境做了简单的压测,发现接入Istio之后,服务的平均延迟增加了大概10-20毫秒,CPU和内存的使用率也有所增加。对于我们的场景来说,这个开销可以接受,但是对于一些性能要求更高的场景,可能就需要权衡了。
4. 生态还不成熟
目前(2018年5月),Istio还处于0.x版本,生态还不够成熟。很多第三方工具和平台,对Istio的支持还不够好。比如,我们用的监控系统(Prometheus+Grafana),虽然Istio能导出监控指标,但是现成的Dashboard还不够完善,需要自己配置。链路追踪(Jaeger/Zipkin)的集成,也有一些坑,踩了很久才搞定。
而且,Istio的版本更新很快,API和功能经常变化,文档和例子有时候跟不上版本的更新,学习和使用的成本比较高。
五、坚持:慢慢找到感觉
就在我快要放弃的时候,发生了一件事情,让我坚持了下来。
那天,我需要做一个灰度发布,把一个新版本的服务,先放量10%,观察一段时间,没问题再逐步放量。以前,用SDK的方式,做灰度发布很麻烦,需要改代码、重新部署,而且效果不好。
用Istio,我只需要改一下VirtualService的配置,把10%的流量路由到新版本,几分钟就搞定了。而且,灰度发布的过程中,可以实时观察新版本的监控指标和错误率,如果有问题,随时可以把流量切回去,非常方便。
那一刻,我真正体会到了Istio的威力。以前需要花几天时间、改很多代码才能做到的事情,用Istio,几分钟就搞定了,而且更优雅、更可靠。
从那以后,我不再那么急躁了,开始静下心来,慢慢学习和使用Istio。我发现,只要搞清楚了核心概念,掌握了配置方法,积累了排查经验,Istio用起来还是很顺手的。
我总结了一些学习和使用Istio的经验:
- 先搞清楚核心概念:VirtualService、DestinationRule、Gateway这些核心概念,一定要搞清楚,它们是Istio的基础。
- 从简单的例子开始:不要一开始就搞复杂的配置,先从最简单的路由规则开始,慢慢增加复杂度。
- 善用istioctl工具:istioctl是Istio的命令行工具,能查看配置、状态、日志等,是排查问题的好帮手。
- 看Envoy的日志和配置:很多问题,需要看Envoy代理的日志和配置才能找到原因。要学会查看Envoy的访问日志、错误日志、配置信息。
- 从小范围开始试点:不要一开始就把所有服务都接入Istio,先选一两个非核心服务试点,跑通了再逐步扩大范围。
- 关注社区和文档:Istio发展很快,要关注社区的动态和文档的更新,及时了解新功能和最佳实践。
慢慢地,我开始找到感觉了。现在,我已经能比较熟练地配置Istio的各种功能,遇到问题也能比较快地排查和解决了。我们的测试环境,已经有几个服务接入了Istio,运行得还不错。
六、我对Istio的一些看法
用了一段时间Istio之后,我对它有了一些自己的看法。
Istio的优点:
- 零侵入,多语言无关:这是Istio最大的优点。通过Sidecar代理,把治理逻辑从业务代码里抽离出来,业务代码只关注业务逻辑,而且不管用什么语言开发,都可以用同一套治理方案。
- 强大的流量管理:Istio的流量管理功能非常强大,支持灰度发布、A/B测试、流量镜像、故障注入、超时重试、熔断限流等高级功能,而且配置灵活,能满足各种复杂的流量管理需求。
- 内置的安全和可观测性:Istio内置了mTLS、身份认证、授权等安全功能,以及监控指标收集、分布式追踪、访问日志等可观测性功能,不需要额外集成,开箱即用。
- 统一的控制平面:有统一的控制平面,可以统一配置和管理所有服务的治理策略,治理策略的升级和变更,不需要修改业务代码,不需要重新部署服务。
- 和Kubernetes深度集成:Istio和Kubernetes深度集成,利用Kubernetes的CRD、Service、Pod等机制,部署和使用都比较方便。
Istio的缺点:
- 学习曲线陡:Istio的概念多,配置复杂,学习成本比较高,新手需要花不少时间才能上手。
- 部署和运维复杂:Istio的组件多,部署和运维比较复杂,对团队的Kubernetes和运维能力有一定要求。
- 性能开销:Sidecar代理会增加一定的延迟和资源消耗,对于延迟敏感的场景,需要仔细评估。
- 生态还不够成熟:目前Istio还处于0.x版本,生态还不够成熟,第三方工具的支持还不够完善,版本更新快,API和功能经常变化。
- 调试困难:因为流量经过Sidecar代理,出了问题排查起来比较麻烦,需要一定的经验和工具支持。
Istio适合什么场景?
根据我的经验,Istio适合以下场景:
- 大规模微服务架构:服务数量多,治理需求复杂,用SDK的方式维护成本高。
- 多语言微服务:服务用多种语言开发,需要统一的治理方案。
- 需要高级流量管理:需要灰度发布、A/B测试、流量镜像等高级流量管理功能。
- 对安全和可观测性要求高:需要统一的服务间安全通信、监控、链路追踪等。
- 已经在使用Kubernetes:Istio和Kubernetes深度集成,在Kubernetes上使用最方便。
不适合什么场景?
- 小型项目或单体应用:服务数量少,治理需求简单,用Istio有点杀鸡用牛刀。
- 团队运维能力不足:Istio的部署和运维比较复杂,如果团队没有足够的Kubernetes和运维能力,可能hold不住。
- 对延迟极度敏感:如果系统对延迟极度敏感(比如高频交易),Sidecar代理的延迟开销可能不可接受。
- 生产环境要求绝对稳定:目前Istio还没到1.0,还在快速发展中,如果生产环境要求绝对稳定,建议等1.0发布、更成熟之后再用。
七、写在最后
Istio服务网格,从入门到(差点)放弃,我经历了很多,也学到了很多。
Istio是一个很强大的工具,它的设计理念(零侵入、多语言无关、统一控制平面、强大的流量管理)代表了微服务治理的发展方向。但是,它也有很多缺点,学习曲线陡,部署运维复杂,性能有开销,生态还不够成熟。
对于我来说,虽然学习和使用Istio的过程很痛苦,踩了很多坑,差点放弃,但是坚持下来之后,我觉得是值得的。Istio确实能解决我们微服务治理的很多痛点,让微服务治理变得更简单、更优雅。
当然,Istio不是银弹,不是所有场景都适合用。在决定是否引入Istio之前,要仔细评估自己的需求、团队的能力、系统的特点,看看Istio是不是真的适合。不要盲目追新,看到别人用就跟着用,结果踩了一堆坑,还没解决实际问题。
而且,目前Istio还处于0.x版本,还在快速发展中。如果你想在生产环境大规模使用,建议等1.0发布、更成熟之后再用。如果只是想学习和试点,可以现在就开始,提前了解和积累经验。
最后,用一句话来总结我使用Istio的感受:"Istio,入门很难,坑很多,但是坚持下来,你会发现它确实能解决微服务治理的很多痛点。它不是银弹,但是代表了微服务治理的发展方向,值得学习和关注。"
愿每一个在微服务治理道路上探索的朋友,都能找到适合自己的方案,构建出稳定、可靠、易治理的微服务系统。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录