Istio 通过整合很多开源工具,如 Kiali、Grafana、Prometheus、 Jaeger,来完成对微服务应用的监控和调式。这些工具开箱即用,Istio 默认安装,且完成了配置。
1.1 使用 Kiali 观测微服务
由于微服务之间的调用关系错综复杂,排查问题就更加困难了,为了使服务之间的关系更加清晰明了,了解应用的行为和状态,我们有必要使用一些可视化的方案来观测我们的微服务应用,其中 Kiali 就是这样的一个工具。
Kiali 是 Istio 的一个可观测工具,提供服务拓扑展示服务网格的结构,提供网格的健康状态视图,配置信息验证功能,此外还具有服务网格配置的功能。
默认情况下,Kiali 服务已经安装了,可以通过 istioctl 命令来访问,比如我们可以使用如下命令来打开 kiali 的 web UI (Kiali Service 类型未修改),然后就可以通过 44759 端口访问到 kiali 服务了:
$ istioctl dashboard kiali --address=0.0.0.0
http://localhost:44759/kiali
也可以通过修改 Kiali 的服务为 NodePort 类型来访问。
默认的用户名和密码存储在名为 kiali 的 Secret 对象之中,需要将其中的 username 与 passphrase 做 base64 解码获得用户名和密码(admin/admin):
$ kubectl get secret -n istio-system kiali -o yaml
apiVersion: v1
data:
passphrase: YWRtaW4=
username: YWRtaW4=
kind: Secret
......
(1) 可以在 Graph 页面下面查看微服务应用的整个调用链:
(2) 在 Istio Config 模块下面可以查看整个网格中的配置校验情况:
红色标记的表示验证未通过的配置,可以点击进去编辑错误的配置。
(3) 在 Istio Config 模块下创建 Istio 资源配置:
1.2 使用 Jaeger 进行分布式追踪
(1) 启用 Jaeger 追踪服务
这里安装 Istio 的时候使用的是 demo 这个 profile:
默认情况下已经安装了 Jaeger,查看:
$ kubectl get pods -l app=jaeger -n istio-system
NAME READY STATUS RESTARTS AGE
istio-tracing-8584b4d7f9-vmcdx 1/1 Running 0 40d
$ kubectl get svc -l app=jaeger -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
jaeger-agent ClusterIP None <none> 5775/UDP,6831/UDP,6832/UDP 40d
jaeger-collector ClusterIP 10.97.9.74 <none> 14267/TCP,14268/TCP,14250/TCP 40d
jaeger-collector-headless ClusterIP None <none> 14250/TCP 40d
jaeger-query ClusterIP 10.105.127.27 <none> 16686/TCP 40d
tracing ClusterIP 10.101.132.125 <none> 80/TCP 40d
zipkin ClusterIP 10.108.118.19 <none> 9411/TCP 40d
如果没有安装可以在使用 istioctl 命令初始化的时候添加
--set values.tracing.enabled=true
参数进行开启:$ istioctl manifest apply --set values.tracing.enabled=true
也可以使用命令将集群中现有的 Jaeger 服务关联到 Istio:
$ istioctl manifest apply --set values.global.tracer.zipkin.address=<jaeger-collector-service>.<jaeger-collector-namespace>:9411
(2) 访问 Jaeger 的 Dashboard
通过 tracing 这个 Service 来访问 Jaeger 的 Dashboard 页面,同样为了方便测试将其修改为 NodePort 类型:
$ kubectl edit svc tracing -n istio-system
......
spec:
type: NodePort
......
service/tracing edited
$ kubectl get svc tracing -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
tracing NodePort 10.101.132.125 <none> 80:31755/TCP 40d
修改完成后就可以在浏览器中通过 http://<NodeIP>:31755
访问 Jaeger 的 Dashboard 页面了:
(3) 测试 Jaeger 的流量追踪功能
通过访问 BookInfo 应用来产生流量,在 Jaeger 的 Dashboard 中测试这个请求生成的追踪数据。
- 在左侧 Servcie 区域选择一个我们要追踪的服务,比如 details.default,点击 “Find Traces” 按钮查看追踪结果:
- 点击列表项目还可以查看追踪详细信息,记录了一次请求涉及到的 Services、深度、Span 总数、请求总时长等信息,也可以对下方的单项服务展开,观察每一个服务的请求耗时和详情:
- 还可以切换 Trace 的显示方式为 Graph,在右上角点击 Trace Timeline 切换为 Trace Graph 模式,该模式下可以更加清晰查看到每一个调用详细信息:
- Jaeger 还可以展示服务依赖,点击顶部的 Dependencies 菜单查看,该页面可以查看服务的完整依赖调用关系:
- 还可以对比两个 Trace,在顶部 Compare 菜单中,输入两个不同的 Trace ID 即可进行对比,这可以帮助我们发现不同 Trace 之间的差异:
:::info 注意:Istio 默认提供的 Jaeger 采用内存的存储方式,Pod 被销毁后数据也就丢失了。在生产环境中需要单独配置持久化存储数据库,具体可查看 Jaeger 官方文档。 :::
1.3 查看 Envoy 日志进行 Debug 分析
Istio 借助 Envoy 可以监测到网格内的服务通信的流转情况,同时我们也可以通过访问 Envoy 的日志来进行调试分析。
Envoy 代理会打印访问日志信息到标准输出,然后我们就可以通过 kubectl logs
命令打印出来查看了。
(1) 启动 Envoy 日志
(2) 修改 Envoy 日志格式
可以通过 Istio 的 ConfigMap 配置来修改日志的格式:
- 默认情况下日志就是输出到 stdout 上的 TEXT 文本格式,为了方便显示,这里我们将其设置为 JSON 格式;
如果要想修改访问日志的格式可以设置 accessLogFormat 属性,具体的访问日志格式可以查看 Envoy 官方文档了解配置规则。
$ kubectl edit cm istio -n istio-system
apiVersion: v1
data:
mesh: |-
accessLogEncoding: JSON
accessLogFile: /dev/stdout
accessLogFormat: ""
outboundTrafficPolicy:
mode: REGISTRY_ONLY
defaultConfig:
......
(3) 测试
访问 BookInfo 服务,同时来查看 productpage 的 sidecar 日志:
- 收到3条 JSON 格式的日志,productpage 服务会调用 details 与 reviews 服务,所以我们可以看到一条访问 /reviews/0 与 /details/0 的 outbound 请求,和最终的 /productpage 的 inbound 请求记录。 ```shell $ kubectl get pods -l app=productpage NAME READY STATUS RESTARTS AGE productpage-v1-5f96867467-nsclh 2/2 Running 0 8d
$ kubectl logs -f productpage-v1-5f96867467-nsclh -c istio-proxy {“useragent”:”Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36”,”response_code”:”200”,”response_flags”:”-“,”start_time”:”2020-07-19T06:48:44.074Z”,”method”:”GET”,”request_id”:”6df02877-0e8d-99f4-a9ee-0f9479d648dd”,”upstream_host”:”10.244.8.180:9080”,”x_forwarded_for”:”-“,”requested_server_name”:”-“,”bytes_received”:”0”,”istio_policy_status”:”-“,”bytes_sent”:”178”,”upstream_cluster”:”outbound|9080||details.default.svc.cluster.local”,”downstream_remote_address”:”10.244.8.227:47244”,”authority”:”details:9080”,”path”:”/details/0”,”protocol”:”HTTP/1.1”,”upstream_service_time”:”17”,”upstream_local_address”:”10.244.8.227:42248”,”duration”:”18”,”upstream_transport_failure_reason”:”-“,”route_name”:”default”,”downstream_local_address”:”10.109.179.166:9080”} {“user_agent”:”Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36”,”response_code”:”200”,”response_flags”:”-“,”start_time”:”2020-07-19T06:48:44.104Z”,”method”:”GET”,”request_id”:”6df02877-0e8d-99f4-a9ee-0f9479d648dd”,”upstream_host”:”10.244.8.182:9080”,”x_forwarded_for”:”-“,”requested_server_name”:”-“,”bytes_received”:”0”,”istio_policy_status”:”-“,”bytes_sent”:”295”,”upstream_cluster”:”outbound|9080||reviews.default.svc.cluster.local”,”downstream_remote_address”:”10.244.8.227:36718”,”authority”:”reviews:9080”,”path”:”/reviews/0”,”protocol”:”HTTP/1.1”,”upstream_service_time”:”20”,”upstream_local_address”:”10.244.8.227:42884”,”duration”:”21”,”upstream_transport_failure_reason”:”-“,”route_name”:”default”,”downstream_local_address”:”10.99.31.144:9080”} {“bytes_sent”:”4183”,”upstream_cluster”:”inbound|9080|http|productpage.default.svc.cluster.local”,”downstream_remote_address”:”10.244.0.0:0”,”authority”:”k8s.qikqiak.com:32193”,”path”:”/productpage”,”protocol”:”HTTP/1.1”,”upstream_service_time”:”70”,”upstream_local_address”:”127.0.0.1:36436”,”duration”:”71”,”upstream_transport_failure_reason”:”-“,”route_name”:”default”,”downstream_local_address”:”10.244.8.227:9080”,”user_agent”:”Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36”,”response_code”:”200”,”response_flags”:”-“,”start_time”:”2020-07-19T06:48:44.061Z”,”method”:”GET”,”request_id”:”6df02877-0e8d-99f4-a9ee-0f9479d648dd”,”upstream_host”:”127.0.0.1:9080”,”x_forwarded_for”:”10.244.0.0”,”requested_server_name”:”outbound.9080..productpage.default.svc.cluster.local”,”bytes_received”:”0”,”istio_policy_status”:”-“}
:::info
这里我们查询的容器名 `istio-proxy` 其实就是 `Envoy sidecar` 代理,Envoy 将请求和响应日志都进行了打印并输出至 stdout ,所以可以通过 kubectl logs 查询。
:::
<a name="tfKIp"></a>
#### (4) 分析日志
- 为了方便查看,这里我们将第一条日志进行格式化,如下所示:
![](https://cdn.nlark.com/yuque/0/2021/png/1471554/1623739545405-66c0c2a0-de42-40db-9667-258135736ab7.png#clientId=u3861bdd5-8274-4&from=paste&id=ua6c49bcc&margin=%5Bobject%20Object%5D&originHeight=1080&originWidth=1416&originalType=url&ratio=2&status=done&style=shadow&taskId=ue4159f88-ef36-43e9-80b8-0255a192ccc)
- Envoy 流量模型中重要的几个信息:
- DownStream:请求的发起端;
- downstream_local_address
- downstream_remote_address
- UpStream:请求的接收端;
- upstream_cluster:符合条件的转发目的主机的集合;
- upstream_host:从 upstream_cluster 集合中选择一个 host 作为流量转发的接收端点;
- upstream_local_address
- request_id:用于链路追踪,可以将一条请求在不同的服务中的调用串联起来;
- response_flags:查看当前请求的状态,用于调试请求的时候非常有用:
- UH:upstream cluster 中没有健康的 host,503;
- UF:upstream 连接失败,503;
- UO:upstream overflow(熔断);
- NR:没有路由配置,404;
- URX:请求被拒绝因为限流或最大连接次数;
:::info
**注意:**
- 当 Pod 被销毁后,旧的日志将不复存在,也无法通过 kubectl logs 就行查看了。
- 如果要查看历史的的日志数据,我们可以使用 EFK 方案将日志进行收集
:::
<a name="RHB3O"></a>
### 1.4 使用 Prometheus 收集监控指标
默认情况下 Istio 就部署了用于收集监控指标的 Prometheus 应用:
```shell
$ kubectl get pods -n istio-system -l app=prometheus
NAME READY STATUS RESTARTS AGE
prometheus-6dd77d88cf-nmsl7 2/2 Running 0 32d
$ kubectl get svc -n istio-system -l app=prometheus
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
prometheus ClusterIP 10.98.118.202 <none> 9090/TCP 32d
为了测试方便我们可以将 Prometheus 的 Service 更改为 NodePort 类型:
$ kubectl edit svc prometheus -n istio-system
......
spec:
type: NodePort
......
$ kubectl get svc -n istio-system -l app=prometheus
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
prometheus NodePort 10.98.118.202 <none> 9090:31128/TCP 32d
然后我们就可以通过 http://<NodeIP>:31128
访问 Prometheus 页面,默认情况下就已经有了很多抓取任务了:
默认就已经收集了很多网格的指标,包括服务级别和代理级别(sidecar)的数据,自 Istio 1.5 起,Istio 标准指标由 Envoy 代理直接获取,之前是通过 Mixer 组件生成的。
1.5 使用 Grafana 可视化系统监控
Istio 网格中默认通过 Prometheus 收集了很多服务和代理相关的指标数据,此外 Istio 还默认开启了 Grafana 工具,我们可以通过 Grafana 来可视化查看网格的监控状态。
$ kubectl get pods -n istio-system -l app=grafana
NAME READY STATUS RESTARTS AGE
grafana-74dc798895-mns2v 1/1 Running 0 32d
$ kubectl get svc -n istio-system -l app=grafana
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
grafana ClusterIP 10.96.52.254 <none> 3000/TCP 32d
同样我们这里将 grafana 的 Service 对象修改为 NodePort 类型的服务:
$ kubectl edit svc grafana -n istio-system
......
spec:
type: NodePort
......
$ kubectl get svc -n istio-system -l app=grafana
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
grafana NodePort 10.96.52.254 <none> 3000:30692/TCP 32d
然后就可以通过 http://<NodeIP>:30692
访问 Grafana 应用了:
默认情况下 Grafana 中就已经导入了 Istio 的几个 Dashboard:
- Mesh Dashboard:主要是查看应用的数据,包括网格数据总览、服务视图、工作负载视图等
- Performance Dashboard:主要是用于查看 Istio 本身的监控数据。