写点什么

通过 Istio 重新实现微服务(四):跨服务跟踪和流量管理

  • 2019-05-27
  • 本文字数:6980 字

    阅读完需:约 23 分钟

通过 Istio 重新实现微服务(四):跨服务跟踪和流量管理

内置的特性

通过拦截所有的网络通信,Istio 能够得到一些指标和数据,这些指标和数据能够用来实现整个应用的可观察性。Kiali是一个开源的项目,它能够利用这些数据回答这样的问题:微服务是如何成为 Istio 服务网格的一部分的,它们是如何连接在一起的?

Kiali——可观察性

在安装 Istio 到我们的集群中之前,我们创建了一个用于 kiali 的 secret(还有另外一个用于 grafana),其中,我们将 user 和 password 都设置为 admin。要访问 Kiali 的 Admin UI,需要执行如下的命令:


$ kubectl port-forward \  $(kubectl get pod -n istio-system -l app=kiali \   -o jsonpath='{.items[0].metadata.name}') \  -n istio-system 20001
复制代码


打开http://localhost:20001/并使用“admin”(不含引号)作为 user 和 password 进行登录。这里很有多有用的特性,比如检查 Istio 组件的配置、拦截网络请求和响应所收集的信息构建的可视化服务,比如“谁调用了谁?”,“哪个版本的服务出现了故障?”等等。在进入下一步章节学习使用 Grafana 可视化指标之前,请花一些时间检验 Kiali 的功能。



图 10 Kiali——服务可观察性

Grafana——指标可视化

Istio 收集到的指标被放到了 Prometheus 中,并使用 Grafana 进行可视化。要访问 Grafana 的 Admin UI,请执行如下的命令并打开http://localhost:3000


$ kubectl -n istio-system port-forward \  $(kubectl -n istio-system get pod -l app=grafana \   -o jsonpath='{.items[0].metadata.name}') 3000

复制代码


在左上角点击 Home 菜单,并选择 Istio Service Dashboard,然后选择 sa-web-app 打头的服务,这样我们就会看到收集到的指标,如下图所示:



图 11 Grafana 指标的可视化


这是一个空的视图,一点也无法调动我们的兴致,管理层是不允许这样的。通过如下的命令,我们可以造一些负载出来:


$ while true; do \  curl -i http://$EXTERNAL_IP/sentiment -H "Content-type: application/json" \   -d '{"sentence": "I love yogobella"}' \  sleep .8; done
复制代码


现在,我们的图表漂亮多了,除此之外,我们还有一些非常棒的工具,Prometheus 能够用来监控,Grafana 能用来对指标进行可视化,有了它们之后,我们就能知道随着时间的推移服务的性能、健康状况以及是否有升级和降级。


最后,我们将会研究一下如何跨服务进行跟踪。

Jaeger——跟踪

我们需要跟踪系统的原因在于服务越多就越难以定位失败的原因。以下面图中这个简单的场景为例:



图 12 一个常见的请求失败


请求调用进来了,但是出现了失败,失败的原因是什么呢?是第一个服务失败还是第二个服务失败?两者都发生了异常,我们需要探查它们的日志。我们有多少次重复这样的经历了?在一定程度上讲,我们更像软件侦探,而不是开发人员。


这是微服务中一个非常普遍的问题,借助分布式的跟踪系统可以解决该问题,这种跟踪系统会在服务间传递一个唯一的 header 信息,然后这个信息会发送至分布式跟踪系统中,这样请求的跟踪信息就能汇总在一起了。样例如图 13 所示:



图 13 用于识别请求 span 的 TraceId


Istio 使用了 Jaeger Tracer,后者实现了 OpenTracing API,这是一个独立于供应商的框架。要访问 Jaegers UI,请执行如下的命令:


$ kubectl port-forward -n istio-system \  $(kubectl get pod -n istio-system -l app=jaeger \   -o jsonpath='{.items[0].metadata.name}') 16686
复制代码


然后通过http://localhost:16686打开 UI,选择 sa-web-app 服务,如果服务没有出现在下拉列表中的话,那么在页面进行一些活动,并点击刷新。随后点击 Find Traces 按钮,它只会展现最近的 trace,选择任意一条记录,所有的跟踪信息将会分别展示,如图 14 所示:



图 14 Jaeger-一个请求的跟踪信息


trace 展示了如下所述的信息:


  1. 传入 istio-ingressgateway 的请求(这是第一次与某个服务产生关联,所以会生成 Trace ID),随后网关将请求转发至 sa-web-app 服务;

  2. sa-web-app 服务中,请求会被 Envoy 容器捕获并生成一个 span child(这就是我们能够在 trace 中看到它的原因),然后会被转发至 sa-web-app 应用。

  3. 在这里,sentimentAnalysis 方法会处理请求。这些 trace 是由应用生成的,这意味着需要对代码进行一些修改;

  4. 在此之后,会发起针对 sa-logic 的 POST 请求。sa-web-app 需要将 Trace ID 传播下去;

  5. ……


注意:在第 4 步,我们的应用需要获取 Istio 生成的 header 信息,并将其向下传递给下一个请求,如下面的图片所示。



图 15 (A)Istio 传播 header 信息,(B)服务传播 header 信息


Istio 承担了主要的工作,它会为传入的请求生成 header 信息、为每个 sidecar 创建新的 span 并传递 span,但是,如果我们的服务不同时传播这些 header 信息的话,那么我们就会丢失请求的完整跟踪信息。


要传播的 header 信息如下所示:


x-request-idx-b3-traceidx-b3-spanidx-b3-parentspanidx-b3-sampledx-b3-flagsx-ot-span-context
复制代码


尽管这是一个很简单的任务,但依然有很多的库在简化这个过程,例如,在 sa-web-app 服务中,RestTemplate 客户端就进行了 instrument 操作,这样的话,我们只需要在依赖中添加 Jaeger 和 OpenTracing 就能传播 header 信息了。


在研究了开箱即用(以及部分开箱即用)的功能之后,我们看一下这里的主要话题,也就是细粒度路由、管理网络流量以及安全性等等。

流量管理

借助 Envoy,Istio 能够提供为集群带来很多新功能:


  • 动态请求路由:金丝雀发布、A/B 测试

  • 负载均衡:简单一致的 Hash 均衡

  • 故障恢复:超时、重试、断路器

  • 故障注入:延时、请求中断等。


在本文后面的内容中,我们将会在自己的应用中展示这些功能并在这个过程中介绍一些新的概念。我们要介绍的第一个概念就是 DestinationRules,并使用它们来实现 A/B 测试。

A/B 测试——Destination Rule 实践

A/B 测试适用于应用有两个版本的场景中(通常这些版本在视觉上有所差异),我们无法 100%确定哪个版本能够增加用户的交互,所以我们同时尝试这两个版本并收集指标。


为了阐述这种场景,我们部署前端的第二个版本(使用绿色按钮替换白色按钮)。执行如下的命令:


$ kubectl apply -f resource-manifests/kube/ab-testing/sa-frontend-green- deployment.yamldeployment.extensions/sa-frontend-green created
复制代码


绿色版本的部署 manifest 有两点差异:


  1. 镜像基于不同的标签:istio-green

  2. pod 添加了version: green标记。


因为两个 deployment 都有app: sa-frontend标记,所以 virtual service sa-external-services在将请求路由至sa-frontend服务时,会转发到这两者上面,并且会使用 round robin 算法进行负载均衡,这样会导致图 16 所示的问题。



图 16 请求的文件未找到


这里有文件没有找到的错误,这是因为在应用的不同版本中它们的名称不相同。我们验证一下:


$ curl --silent http://$EXTERNAL_IP/ | tr '"' '\n' | grep main/static/css/main.c7071b22.css /static/js/main.059f8e9c.js$ curl --silent http://$EXTERNAL_IP/ | tr '"' '\n' | grep main/static/css/main.f87cd8c9.css/static/js/main.f7659dbb.js
复制代码


也就是说,index.html在请求某个版本的静态文件时,被负载均衡到了另外一个版本的 pod 上了,这样的话,就会理解为其他文件不存在。这意味着,对我们的应用来说,如果想要正常运行的话,就要引入一种限制“为 index.html 提供服务的应用版本,必须也要为后续的请求提供服务”。


我们会使用一致性 Hash 负载均衡(Consistent Hash Loadbalancing)来达成这种效果,这个过程会将同一个客户端的请求转发至相同的后端实例中,在实现时,会使用一个预先定义的属性,如 HTTP header 信息。使用 DestionatioRules 就能够让这一切变成现实。

DestinationRules

在 VirtualService 将请求路由至正确的服务后,借助 DestinationRules 我们能够为面向该服务实例的流量指定策略,如图 17 所示。



图 17 借助 Istio 资源进行流量管理


注意: 图 17 用非常易于理解的方式可视化地展现了 Istio 资源是如何影响网络流量的。但是,精确决定请求要发送至哪个实例是 Ingress Gateway 的 Envoy 完成的,它需要使用 CRD 来进行配置。


借助 Destination Rules 我们可以配置负载均衡使用一致哈希算法,从而确保相同的用户会由同一个服务实例提供响应。我们可以通过如下的配置实现这一点:


apiVersion: networking.istio.io/v1alpha3 kind: DestinationRulemetadata:  name: sa-frontendspec:  host: sa-frontend  trafficPolicy:      loadBalancer:        consistentHash:            httpHeaderName: version   # 1
复制代码


1.根据“version”头信息的内容生成 consistentHash


执行如下的命令应用该配置:


 $ kubectl apply -f resource-manifests/istio/ab-testing/destinationrule-sa- frontend.yaml destinationrule.networking.istio.io/sa-frontend created
复制代码


执行如下命令并校验在指定 version header 信息时会得到相同的文件:


$ curl --silent -H "version: yogo" http://$EXTERNAL_IP/ | tr '"' '\n' | grep main
复制代码


注意:在浏览器中,你可以使用chrome扩展为 version 设置不同的值。


DestinationRules 有很多其他负载均衡的功能,关于其细节,请参考官方文档


在更详细地探索 VirtualService 之前,通过如下的命令移除应用的 green 版本和 DestinationRules:


$ kubectl delete -f resource-manifests/kube/ab-testing/sa-frontend-green- deployment.yamldeployment.extensions "sa-frontend-green" deleted$ kubectl delete -f resource-manifests/istio/ab-testing/destinationrule-sa- frontend.yamldestinationrule.networking.istio.io "sa-frontend" deleted
复制代码

Shadowing———Virtual Services 服务实践

当我们想要在生产环境测试某项变更,但是不想影响终端用户的时候,可以使用影子(Shadowing)或镜像(Mirroring)技术,这样的话,我们能够将请求镜像至具有变更的第二个实例并对其进行评估。或者说更简单的场景,你的同事解决了一个最重要的缺陷,并提交了包含大量内容的 Pull Request,没人能够对其进行真正的审查。


为了测试这项特性,我们通过如下的命令创建 SA-Logic 的第二个实例(它是有缺陷的):


$ kubectl apply -f resource-manifests/kube/shadowing/sa-logic-service.buggy.yaml
复制代码


执行下面的命令校验所有的版本除了app=sa-logic之外都带有对应版本的标记:


$ kubectl get pods -l app=sa-logic --show-labelsNAME                              READY   LABELSsa-logic-568498cb4d-2sjwj         2/2    app=sa-logic,version=v1sa-logic-568498cb4d-p4f8c         2/2    app=sa-logic,version=v1sa-logic-buggy-76dff55847-2fl66   2/2    app=sa-logic,version=v2sa-logic-buggy-76dff55847-kx8zz   2/2    app=sa-logic,version=v2
复制代码


因为sa-logic服务的目标是带有app=sa-logic标记的 pod,所以传入的请求会在所有的实例间进行负载均衡,如图 18 所示:



图 18 Round Robin 负载均衡


但是,我们想要将请求路由至 version v1 的实例并镜像至 version v2,如图 19 所示:



图 19 路由至 v1 并镜像至 v2


这可以通过组合使用 VirtualService 和 DestinationRule 来实现,Destination Rule 声明子集,而 VirtualService 路由至特定的子集。

通过 Destination Rule 声明子集

我们通过如下的配置定义子集:


apiVersion: networking.istio.io/v1alpha3 kind: DestinationRulemetadata:  name: sa-logicspec:  host: sa-logic   # 1  subsets:  - name: v1   # 2      labels:        version: v1  # 3  - name: v2      labels:      version: v2

复制代码


  1. host 定义这个规则只适用于路由至 sa-logic 服务的请求;

  2. 当路由至子集实例时所使用子集名称;

  3. 以键值对形式定义的标记,将实例定义为子集的一部分。


通过执行如下的命令应用该配置:


$ kubectl apply -f resource-manifests/istio/shadowing/sa-logic-subsets- destinationrule.yamldestinationrule.networking.istio.io/sa-logic created
复制代码


在子集定义完之后,我们可以继续配置 VirtualService,让针对 sa-logic 的请求遵循如下的规则:


  1. 路由至名为 v1 的子集;

  2. 镜像至名为 v2 的子集。


这可以通过如下的 manifest 实现:


apiVersion: networking.istio.io/v1alpha3 kind: VirtualServicemetadata:  name: sa-logicspec:  hosts:    - sa-logic  http:  - route:    - destination:        host: sa-logic        subset: v1    mirror:      host: sa-logic      subset: v2

复制代码


所有的配置都很具有表述性,我们不再赘述,接下来看一下它的实际效果:


$ kubectl apply -f resource-manifests/istio/shadowing/sa-logic-subsets-shadowing- vs.yamlvirtualservice.networking.istio.io/sa-logic created
复制代码


通过执行如下命令生成一些负载:


$ while true; do curl -v http://$EXTERNAL_IP/sentiment \   -H "Content-type: application/json" \  -d '{"sentence": "I love yogobella"}'; \  sleep .8; done
复制代码


在 Grafana 检查结果,你会发现有缺陷的版本会出现 60%的请求失败,但是这些失败都不会影响终端用户,因为他们是由当前活跃的服务来提供响应的。



图 20 sa-logic 服务的成功率


在本节中,我们第一次看到如何将 VirtualService 用到服务的 envoy 上,当 sa-web-app 发起对 sa-logic 的请求时,会经过 sidecar envoy,借助我们配置的 VirtualService,将会路由至 sa-logic 的 v1 子集并镜像至 v2 子集。

金丝雀部署

金丝雀(Canary)部署指的是让少量用户使用应用新版本的一个过程,借助这一过程能够验证新版本是否存在问题,然后能够确保以更高的质量发布给更多的受众。


我们继续使用sa-logic带有缺陷的子集来阐述金丝雀发布。


首先,我们大胆地将 20%的用户发送至带有缺陷的版本(这就是金丝雀发布),并将 80%的用户发送至正常的服务,这可以通过如下的 VirtualService 来实现:


apiVersion: networking.istio.io/v1alpha3 kind: VirtualServicemetadata:  name: sa-logicspec:  hosts:    - sa-logic  http:  - route:    - destination:    host: sa-logic    subset: v1    weight: 80         # 1  - destination:    host: sa-logic    subset: v2      weight: 20         # 1
复制代码


1.权重声明了请求要转发到目的地或目的地子集的百分比。


通过下面的命令,更新上述的sa-logic virtual service:


$ kubectl apply -f resource-manifests/istio/canary/sa-logic-subsets-canary-vs.yamlvirtualservice.networking.istio.io/sa-logic configured
复制代码


我们马上可以看到有些请求失败了:


$ while true; do \  curl -i http://$EXTERNAL_IP/sentiment -H "Content-type: application/json" \   -d '{"sentence": "I love yogobella"}' \  --silent -w "Time: %{time_total}s \t Status: %{http_code}\n" -o /dev/null; \   sleep .1; doneTime: 0.153075s      Status: 200Time: 0.137581s      Status: 200Time: 0.139345s      Status: 200Time: 30.291806s    Status: 500
复制代码


VirtualServices 实现了金丝雀发布,借助这种方法,我们将潜在的损失降低到了用户群的 20%。非常好!现在,当我们对代码没有确切把握的时候,就可以使用 Shadowing 技术和金丝雀发布。

超时和重试

代码不仅仅会有缺陷,在“分布式计算的8个谬误”中,排名第一的就是“网络是可靠的”。网络实际上是不可靠的,这也是我们需要超时和重试的原因。


为了便于阐述,我们将会继续使用有缺陷版本的sa-logic,其中随机的失败模拟了网络的不可靠性。


带有缺陷的服务版本会有三分之一的概率在生成响应时耗费过长的时间,三分之一的概率遇到服务器内部错误,其余的请求均能正常完成。


为了降低这些缺陷的影响并给用户带来更好的用户体验,我们会采取如下的措施:


  • 如果服务耗时超过了 8 秒钟,将会超时;

  • 对于失败的请求进行重试。


这可以通过如下的资源定义来实现:


apiVersion: networking.istio.io/v1alpha3 kind: VirtualServicemetadata:  name: sa-logicspec:  hosts:    - sa-logic  http:  - route:    - destination:        host: sa-logic        subset: v1      weight: 50    - destination:        host: sa-logic        subset: v2      weight: 50  timeout: 8s  # 1  retries:    attempts: 3  # 2    perTryTimeout: 3s  # 3

复制代码


  1. 请求有 8 秒钟的超时;

  2. 它会尝试 3 次;

  3. 如果耗时超过 3 秒钟就将本次尝试标记为失败。


这是一种优化:用户的等待不会超过 8 秒钟,如果失败的话,我们将会重试三次,这样的话增加了获取成功响应的概率。


通过如下命令应用更新后的配置:


$ kubectl apply -f resource-manifests/istio/retries/sa-logic-retries-timeouts- vs.yamlvirtualservice.networking.istio.io/sa-logic configured
复制代码


查阅 Grafana 中的图表,看成功率是否有所提升(参见图 21)。



图 21 在使用超时和重试功能之后,带来了成功率的提升


在进入下一节之前,通过如下命令移除掉sa-logic-buggy和 VirtualService:


$ kubectl delete deployment sa-logic-buggydeployment.extensions "sa-logic-buggy" deleted$ kubectl delete virtualservice sa-logicvirtualservice.networking.istio.io "sa-logic" deleted
复制代码




系列回顾


通过 Istio 重新实现微服务 (一):认识 Istio


通过 Istio 重新实现微服务 (二):Istio 实践


通过 Istio 重新实现微服务 (三):使用 Istio 代理运行应用


2019-05-27 10:236185

评论

发布
暂无评论
发现更多内容

AI技术的英语背诵APP开发

北京木奇科技有限公司

AI技术开发 软件外包公司 AI英语学习

一行代码引发 12G 内存 5 分钟爆仓!SeaTunnel Kafka 连接器"内存溢出"元凶抓到了

白鲸开源

kafka 开源 内存 数据同步 Apache SeaTunnel

文心快码升级至3.5S版本,强化多智能体自协同能力

Comate编码助手

AI辅助编程 AI 编程 文心快码 文心快码Zulu

AI在英语培训中的应用

北京木奇科技有限公司

软件外包公司 AI英语学习 AI英语

恒拓高科BeeWorks亮相鸿蒙 HEC 生态大会,重构数字化协作免费新体验

BeeWorks

即时通讯 IM 私有化部署

千万许可黑洞?VMware 升级后,我们的IT预算差点崩盘

智驱前线

为什么舆情监测离不开海外社交媒体分析?

沃观Wovision

社交媒体 沃观Wovision 舆情监测系统 海外舆情监测

实测有效|用 SeaTunnel 免费实现 MySQL→Oracle 实时同步,步骤超细

白鲸开源

MySQL oracle 大数据 数据同步 Apache SeaTunnel

AI 在研发效能中的实际应用效果|《DevData 2025 研发效能基准报告》

思码逸研发效能

研发效能 研发效能度量 研发效能管理 智能编程 思码逸

【浪潮海岳inDatax数据中台专栏】数据门户-灵活多样的数据共享方案

inBuilder低代码平台

企业如何选择适合自己的私有化视频会议产品?

BeeWorks

即时通讯 IM 私有化部署

积极响应“人工智能+”行动,和鲸助力打造气象数据查询智能体示范应用,让风云“智慧可测”

ModelWhale

气象 数据查询 气象数据 人工智能+

Apache服务器自动化运维与安全加固脚本详解

qife122

日志分析 Apache安全

限时赠书|Altair 助力高校数据科学教育:中山大学教授发布RapidMiner 权威教材

Altair RapidMiner

人工智能 AI 数据分析 制造业 RapidMiner

喜报!白鲸开源 CEO 荣登「2025 中国数智化转型升级先锋人物」榜

白鲸开源

大数据 科技 DataOps 白鲸开源

融云十周年:于时代的「十字路口」,相信持续精进的力量

融云 RongCloud

深入解析Web Components:Shadow DOM实战指南

qife122

前端开发 Web Components

WebGL开发数字孪生项目

北京木奇科技有限公司

数字孪生 软件外包公司 webgl开发

WAVE SUMMIT深度学习开发者大会2025举行 文心大模型X1.1发布

Comate编码助手

百度 文心大模型 AI 编程 文心快码 文心大模型X1.1

MyEMS:开源能源管理的破局者

开源能源管理系统

开源 开源能源管理系统

融云:当年搞出了「飞信」的师傅,如今竟扛着 200 多个国家的聊天、弹幕和日常?

融云 RongCloud

Jira 官宣停售 Data Center ,中国企业又双叒要迁移了?!

万事ONES

Jira Atlassian 国产化替代 ONES研发管理

如何轻松掌握三维模型层次结构,快来试试结构树功能!

在路上

cad cad看图 CAD看图王

海外舆情监测系统的价值与玩法

沃观Wovision

跨境贸易 出海 舆情监测系统 海外舆情监测

GreatSQL分页查询优化案例实战

GreatSQL

一次缓存引发的文件系统数据不一致问题排查与深度解析

阿里技术

缓存 问题 故障排查 解析

数据湖变“数据沼泽”?TDengine IDMP 让 AI 秒懂数据

TDengine

tdengine 时序数据库 工业数据

秒开CAD装配体!制造业三维模型浏览/测量 / 剖切 / 爆炸一步到位

在路上

cad

阅读破10万的学Go建议,不管初学Go还是进阶都值得一看!

王中阳Go

Go

以Data+AI赋能产业,Kyligence荣膺2025中国数智化转型升级创新服务企业奖

Kyligence

从苹果新品发布会看海外红人营销的流量密码

Wolink

苹果 出海 海外营销推广 沃链Wolink 达人营销

通过 Istio 重新实现微服务(四):跨服务跟踪和流量管理_文化 & 方法_Rinor Maloku_InfoQ精选文章