DockOne微信分享(二一六):基于Istio的灰度平台实践


【编者的话】Istio目前是Service Mesh最受欢迎的实现方式,流量管理是Istio一个非常核心的功能。本次分享主要介绍在Kubernetes平台上面基于Istio的流量管理做灰度发布、灰度测试的实践以及遇到的各种坑。

Service Mesh是什么?

服务网格(Service Mesh)是致力于解决服务间通讯的基础设施层。它负责在现代云原生应用程序的复杂服务拓扑来可靠地传递请求。实际上,Service Mesh 通常是通过一组轻量级网络代理(Sidecar proxy),与应用程序代码部署在一起来实现,而无需感知应用程序本身。

可能一句话很难理解Service Mesh到底是什么。我们通过两个抽象的场景来看Service Mesh是怎么发展的。

第一个是服务通讯的发展,当我们有一个需求是两个服务之间进行通讯。
1.jpg

最原始应该就是通过网线互联这种最简单的方式。

随着计算机变得越来越便宜和越来越流行,连接数量和通过它们的数据量急剧增加。随着人们越来越依赖网络系统,工程师需要确保他们构建的软件符合用户所需的服务质量,出现了网络层。如图1

此时就对我们的程序提出了挑战,比如说流量控制。

想象一种场景,计算机A以给定的速率向计算机B发送字节,但不能保证B将以一致且足够快的速度处理接收的字节。例如,B可能忙于并行运行其他任务,或者数据包可能无序到达,而B被阻止等待应该首先到达的数据包。这意味着不仅A不具备B的预期性能,而且还可能使事情变得更糟,因为它可能会使B超载,现在必须将所有这些传入的数据包排队等待处理。

当出现这种问题时,最简单的就是在业务里面实现流量控制的逻辑。如图2。

技术飞速发展,很快TCP/IP出现,将流控制和许多其他问题纳入网络堆栈本身。这意味着该段代码仍然存在,但它已从您的应用程序提取到您的操作系统提供的底层网络层。

我们发现,随着技术的发展,公共的东西越来越下沉。

第二个场景,是微服务时代的一个场景,微服务时代给我们带来了很多机遇和新的挑战。

新的机遇比如说我们可以让服务的职责更单一,发布更迅速。

挑战就像是我们图1中的问题,服务发现和熔断。
2.jpg

最开始遇到这样的问题,开始的方式依旧是在我们的代码中,编写对应的逻辑来做。如图1。

随着技术发展,有了专门的库来把公共的东西抽象出来,我们只需要做一个依赖。如图2 。

与我们在网络堆栈中看到的类似,非常希望将大规模分布式服务所需的功能提取到底层平台中。

人们使用更高级别的协议(如HTTP)编写非常复杂的应用程序和服务,甚至不考虑TCP如何控制其网络上的数据包。这种情况是我们对微服务所需要的,其中从事服务工作的工程师可以专注于他们的业务逻辑,避免浪费时间编写自己的服务基础架构代码或管理整个机队的库和框架。如图3。

而这样的实现方式比较困难,于是后续有一个新的方式。Sidecar,它是重新启动一个进程,来拦截所有的流量。于是有了图4这种部署方式。

当我们有很多服务部署的时候,就看到的整体部署图就变成了很多sidecar之间的通讯。那么又一个新的挑战,就是sidecar应该如何管理。那么control plane就变成了一个不可或缺的组件。用来管理我们的sidecar。

于是有了最终Service Mesh的架构图。
3.jpg

Istio是什么?

简单说是一种Service Mesh架构的实现。

官网的描述为Istio 提供一种简单的方式来为已部署的服务建立网络,该网络具有负载均衡、服务间认证、监控等功能,只需要对服务的代码进行很少或不需要做任何改动。想要让服务支持Istio,只需要在您的环境中部署一个特殊的sidecar代理,使用Istio控制平面功能配置和管理代理,拦截微服务之间的所有网络通信。

Istio各模块的职责:
4.jpg

Istio的架构图:
5.jpg

为什么要用Istio?
  • Cloud Native云原生趋势
  • 多语言:Java、Python、Go
  • 强大的流量管理


为什么选择Istio?
  • Google加持。
  • 一个非常活跃的开源项目。
  • 更新频次。2月开始到现在更新了18个版本。
  • 最近一次KubeCon大会上,Istio是一个出现频次非常高的词。
  • 国内各大云平台的首选,阿里,腾讯,华为,蚂蚁金服……


Istio测试环境实践

为什么又有一个测试环境?
  1. 跟线上环境结构不同。线上结构是通过git group拆分namespace。测试环境在同一个namespace下跑所有服务。
  2. 多环境。现在测试环境有2个,每个里面跑所有的基础服务,导致pod数很多,有段时间,测试环境的Pod总数比生产还要多。但是流量却少很多。
  3. 多语言。现在主要是Java技术栈,和部分的Python,未来还有Go技术栈。Java技术栈的话,Spring Cloud做服务发现,熔断,负载等功能是没有问题,但是在多个技术栈的时候,我们就需要再做很多事情来兼容。
  4. 流量管理。就是需要更加强大的流量管理,比如灰度发布,基于比例的流量策略。


现在的流量管理方式:
6.jpg

8.png

当有A-B-C-D的一个调用链时,当B有新版本V2发布,会把B老版本替换。导致所有的人员测试的流量都是相同的服务,这样的测试环境就变得很不稳定,上游服务可能会受到下游服务发布的影响。

我们期望的流量方式:
9.jpg

我们期望的方式是,当B发布新版本V2时,跟B老版本同时运行,只是对应测试B-V2的测试人员的流量会打到B-V2服务。而其他人的流量依然走A-B-C-D。

我们测试环境的部分实现细节:
10.jpg

配置如图:
11.jpg

常见问题

Pod显示2/2问题?Pod日志看不了了,提示:
12.jpg

Error from server (BadRequest): a container name must be specified for pod spring-account-admin-normal-dcd6544cd-ckxjr, choose one of: [istio-proxy account-admin]

因为:

需要选择container。

需要-c参数来指定container名称。

Consul取消注册问题?原来使用Consul做服务发现,当停Pod时,没有从Consul上注销。

因为:在业务container关闭的时候,envoy也关闭了。所以访问失败了。issue#7136。

解决:preStop脚本,在Envoy关闭时,会检查是否有非Envoy的进程在运行。如果有,也会超时重试。等待业务服务的优雅停机。

容器启动顺序问题?Pod启动的时候,连接consul timeout问题。

因为:主要是因为服务启动的顺序问题。当Pod中业务container启动的时候,Envoy也在启动,但是initContainer已经启动完毕,iptables已经配置好了。所以请求打不出去了

解决:我们在容器启动的时候,加了超时重试。

访问外网问题。在部署完istio之后,我们所有请求外网的url都返回失败。

因为:Istio的iptables规则。是拦截所有的请求。

解决:通过配置Istio的参数global.proxy.includeIPRanges来指定Envoy拦截的流量。只拦截Service IP段流量。

渐进式升级Istio怎么做?

主要是兼容之前的请求链路。

原来通过Consul服务发现,本地找到Consul中存储的服务实例,即Pod IP。通讯的时候使用Pod IP。

需要灰度的流量需要修改为Kubernetes的服务发现,即使用Service IP进行通讯,Envoy也只拦截service ip的流量。即区分SVC的IP段,和Pod的IP段。这样当业务不改动代码时,还是走原来的请求链路,需要使用灰度功能时,可以修改代码,来支持灰度测试。

Prometheus内存撑爆问题。有一次测试环境一上午不能用。

因为:开箱即用的Prometheus。

解决:Resources limits。

gRPC Not Started问题,有一次升级完gRPC Starter支持keep header之后,gRPC的请求偶发的出现gRPC Not Started异常。

因为:需要使用header中数据分流,线程中gRPC调用,header丢失。

解决:添加容错。

Q&A

Q:如何判断check、quota下放istio-proxy引入的问题?
A:得通过压测了,看性能损耗了。我们后续会加入Mixer的功能再压测一轮。现在做的压测还是不开Mixer功能的场景下压的。因为我们线上目前还不打算开Mixer。

Q:能否给个demo?
A:目前还没有开放在外面的demo。可以给些思路,请问你想要什么要的功能的demo?没实践过,听理论总是有点虚!可以实践一下。我们主要是用的Istio(Envoy)的流量管理的功能。主要是要配置Istio的流量管理策略。给业务人员再给他们配置yaml文件,学习成本太大,所以做了可视化,有按流量,按用户,自定义三种方式。主要是把页面配置编译成yaml流量配置。

Q:Istio每个服务中得到的访问IP都是127.0.0.1,这个该怎么搞?能拿到real client ip?
A:kubectl get svc应该可以查到clusterip,接着Q3,app拿到外面访问的address都是127.0.0.1的。
嗯,是有这个问题,我们也遇到了,目前还没有解决方案。Envoy的日志中是可以拿到的,后续需要看看怎么带过去。

Q:服务的应用运行日志在Istio中如何获取或者查看,例如log4j控制台的输出?
A:应用运行日志就在应用容器上看啊。我们是通过标准输出收集到了InfluxDB中。

Q:Envoy的CPU、内存的request、limit一般配置多少?
A:我们压测的是默认的Envoy的资源限制。没有修改默认的资源限制。
resources:
  limits:
    cpu: "2"
    memory: 1Gi
  requests:
    cpu: 100m
    memory: 128Mi

Q:里面在配合Spring Clund有必要吗?
A:感觉没必要,重复了,Istio让程序员更关注业务,将维护管理分离
我们之后会陆续用Istio的方式替换之前在Spring Cloud上的实现。

Q:有配合Alibaba Nacos试试吗实验落地的最好,consul.etcd选哪个好点?
A:没有使用过Alibaba Nacos,我们未来会走Kubernetes的服务发现,所以会选择etcd吧。

Q:Spring Cloud向Istio迁移好迁移吗?
A:比较好迁移。我们遇到的问题主要就是通讯的问题。涉及到Feign和gRPC两种。需要升级一下starter,传递一下header。因为我们的流量标签是在header中传递。还有一个重要的就是分享里提到的,服务发现问题。因为要做渐进式升级,不能一下就给所有的服务上Istio,边缘服务先上,热门服务后上,所以要兼容之前的服务发现(Consul),同时有两个服务发现机制的时候会有些问题。

以上内容根据2019年7月16日晚微信群分享内容整理。分享人史海洋,水滴公司效能平台负责人,目前负责公司效能平台开发,目前主要研究DevOps、Cloud Native。DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiese,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

0 个评论

要回复文章请先登录注册