前面我们学习了 Istio 中的流量管理功能,本节我们来学习如何配置 Istio来自动收集网格中的服务遥测。Istio为网格内所有的服务通信生成详细的遥测数据,这种遥测技术提供了服务的可观察性,使运维人员能够排查故障、维护和优化应用程序,而不会给服务的开发人员带来任何额外的负担。通过 Istio,运维人员可以全面了解到受监控的服务如何与其他服务以及Istio组件进行交互。
网站会自动生成以下类型的遥测数据,以提供对整个服务网格的可观察性:
主机名 | IP | 角色 |
---|---|---|
k8s-master | eth0:10.1.1.100、docker:172.17.100.0/24 | K8S-master |
k8s-node1 | eth0:10.1.1.120、docker:172.17.120.0/24 | K8S-node |
k8s-node2 | eth0:10.1.1.130、docker:172.17.130.0/24 | K8S-node |
nginx-proxy | eth0:10.1.1.11 | 代理节点 |
由于微服务之间的调用关系错综复杂,排查问题就更加困难了,为了使服务之间的关系更加清晰明了,了解应用的行为和状态,我们有必要使用一些可视化的方案来观测我们的微服务应用,其中 Kiali 就是这样的一个工具。Kiali 是一个基于 Istio 的服务网格的管理控制台。它提供了仪表盘、可观察性,并让我们通过强大的配置和验证能力来操作网格。它通过推断流量拓扑来显示服务网格,并显示网格的健康状况。Kiali 提供了详细的指标,强大的验证,Grafana 访问,以及与 Jaeger 的分布式追踪的强大集成。
在安装 Kiali时,需要使用Istio的addons
文件夹中的 kiali.yaml
文件。
$ cd /opt/istio/samples/addons/
# 创建kiali
$ kubectl apply -f /opt/istio/samples/addons/kiali.yaml
注意,如果你看到任何错误,例如在版本 monitoringkiali.io/v1alpha
中没有匹配的 MonitoringDashboard
,请重新运行 kubectl apply
命令。问题是,在安装 CRD(自定义资源定义)和由该 CRD 定义的资源时,可能存在一个匹配条件。
我们可以用 istioctl dashboard kiali
打开 Kiali。
本次使用另外一种方法:
#可以看到kiali这个service的类型为ClusterIP,外部环境访问不了
$ kubectl get svc -n istio-system kiali
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kiali ClusterIP 192.168.97.86 <none> 20001/TCP,9090/TCP 25s
#修改kiali这个service的类型为NodePort,这样外部环境就可以访问kiali了
#把type: ClusterIP 修改为 type: NodePort即可
# kubectl edit service kiali -n istio-system
# 或者通过Ingress实现
cat > /opt/istio/samples/addons/kiali-ingress.yaml <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kiali
namespace: istio-system
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: kiali.od.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kiali
port:
number: 20001
EOF
# 应用Ingress配置清单
$ kubectl -f /opt/istio/samples/addons/kiali-ingress.yaml
将100.1.1.11
绑定本地hosts文件
,访问 http://kiali.od.com/
Istio 使用 Prometheus 来监控指标,跟踪 Istio 和网格中的应用程序的健康状况。
要安装 Prometheus,我们可以使用 Istio 安装包中 /samples/addons
文件夹中的示例安装。
$ cd /opt/istio/samples/addons/
# 创建Prometheus
$ kubectl apply -f /opt/istio/samples/addons/prometheus.yaml
$ kubectl get deploy -n istio-system
要打开 Prometheus 仪表板,我们可以使用 Istio CLI 中的 dashboard
命令:
$ istioctl dashboard prometheus
http://localhost:9090
这里我们使用另外一种方法:
#修改prometheus这个service的类型为NodePort,这样外部环境就可以访问prometheus了
#把type: ClusterIP 修改为 type: NodePort即可
#$ kubectl edit service prometheus -n istio-system
# 或者通过Ingress访问
$ cat > /opt/istio/samples/addons/prometheus-ingress.yaml <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: prometheus-ui
namespace: istio-system
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: prometheus.od.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: prometheus
port:
number: 9090
EOF
$ kubectl apply -f /opt/istio/samples/addons/prometheus-ingress.yaml
将100.1.1.11
绑定本地hosts文件
,访问 http://prometheus.od.com
我们也可以来筛选一些关于 productpage 服务的指标数据,比如查询请求 productpage 服务的总次数:
istio_requests_total{destination_service="productpage.bookinfo.svc.cluster.local"}
# 或
istio_requests_total{destination_service_name="productpage"}
请求 reviews 服务 V3 版本的总次数,可以使用下面的 proml 语句,该语句返回所有请求 reviews 服务 V3 版本的当前总次数:
istio_requests_total{destination_service="reviews.bookinfo.svc.cluster.local",destination_version="v3"}
# 或
istio_requests_total{destination_service_name="reviews",destination_version="v3"}
过去 5 分钟 productpage 服务所有实例的正常请求频率
rate(istio_requests_total{destination_service_name=~"productpage.*",response_code="200"}[5m])
Grafana 是一个用于分析和监控的开放平台。Grafana 可以连接到各种数据源,并使用图形、表格、热图等将数据可视化。通过强大的查询语言,你可以定制现有的仪表盘并创建更高级的可视化。
通过 Grafana,我们可以监控 Istio 安装和服务网格中运行的应用程序的健康状况。
我们可以使用 grafana.yaml
来部署带有预配置仪表盘的 Grafana 示例安装。该 YAML 文件在 Istio 安装包的 /samples/addons
下。
确保在部署 Grafana 之前部署 Promeheus 插件,因为 Grafana 使用 Prometheus 作为其数据源。
运行下面的命令来部署 Grafana 和预配置的仪表盘:
$ cd /opt/istio/samples/addons/
# 创建Grafana
$ kubectl apply -f /opt/istio/samples/addons/grafana.yaml
$ kubectl get deploy -n istio-system
这个 Grafana 安装不打算在生产中运行,因为它没有经过性能或安全方面的调整。
Kubernetes 将 Grafana 部署在 istio-system
命名空间。要访问 Grafana,我们可以使用 istioctl dashboard
命令。
istioctl dashboard grafana
我们使用另外一种方法:
#修改prometheus这个service的类型为NodePort,这样外部环境就可以访问prometheus了
#把type: ClusterIP 修改为 type: NodePort即可
#$ kubectl edit service grafana -n istio-system
# 或者通过Ingress访问
$ cat > /opt/istio/samples/addons/grafana-ing.yaml <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: grafana
namespace: istio-system
spec:
rules:
- host: grafana.od.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: grafana
port:
number: 3000
EOF
将100.1.1.11
绑定本地hosts文件
,访问 http://grafana.od.com
点击搜索框和 istio 文件夹,查看已安装的仪表盘,如下图所示。
Istio 控制平面仪表盘(Istio Control Plane Dashboard)
从 Istio 控制平面仪表盘,我们可以监控 Istio 控制平面的健康和性能。
Istio Control Plane Dashboard 仪表盘将向我们展示控制平面的资源使用情况(内存、CPU、磁盘、Go routines),以及关于 Pilot、Envoy 和 Webhook 的信息。
Istio 网格仪表盘(Istio Mesh Dashboard)
网格仪表盘为我们提供了在网格中运行的所有服务的概览。仪表盘包括全局请求量、成功率以及 4xx 和 5xx 响应的数量。
Istio 性能仪表盘(Istio Performance Dashboard)
性能仪表盘向我们展示了 Istio 主要组件在稳定负载下的资源利用率。
Istio 服务仪表盘(Istio Service Dashboard)
服务仪表盘允许我们在网格中查看服务的细节。
我们可以获得关于请求量、成功率、持续时间的信息,以及显示按来源和响应代码、持续时间和大小的传入请求的详细图表。
Istio Wasm 扩展仪表盘(Istio Wasm Extension Dashboard)
Istio Wasm 扩展仪表盘显示与 WebAssembly 模块有关的指标。从这个仪表盘,我们可以监控活动的和创建的 Wasm 虚拟机,关于获取删除 Wasm 模块和代理资源使用的数据。
Istio 工作负载仪表盘(Istio Workload Dashboard)
这个仪表盘为我们提供了一个工作负载的详细指标分类。
日志也是应用可观测性中一个非常重要的方式,也是我们传统调试应用非常重要的手段,在 Istio 中使用 Sidecar 容器对请求进行了拦截,无疑也增大了调试难度,但是同时 Istio 也可以监测到网格内的服务通信的流转情况,并生成详细的遥测日志数据,任何请求与事件的元信息都可以获取到,所以我们也非常有必要来查看下 Istio中的代理日志数据。Istio 最简单的日志类型是 Envoy 的访问日志
,Envoy 代理打印访问日志信息到标准输出,然后我们就可以通过 kubectl logs
命令打印出来查看了
默认情况下 Istio 已经开启了 Envoy 访问日志,我们也可以通过 istioctl install
命令来配置日志:
$ kubectl get istiooperators -n istio-system installed-state -oyaml
....
meshConfig:
accessLogFile: /dev/stdout
....
默认情况下日志就是输出到stdout 上的 TEXT 文本格式,为了方便显示,这里我们将其设置为 JSON 格式,如果要想修改访问日志的格式可以设置 accessLogFormat 属性,具体的访问日志格式可以查看 Envoy 官方文档了解配置规则。
配置项 | 说明 | ||||||
---|---|---|---|---|---|---|---|
accessLogFile | 访问日志的日志文件路径,例如/dev/stdout,空值表示禁用该日志; | ||||||
accessLogFormat | 访问日志的日志格式,空值表示使用默认的日志格式; | ||||||
accessLogEncoding | 访问日志编码格式,支持TEXT和JSON两种,默认为TEXT; | ||||||
level | 访问日志级别,默认warning;可选trace\ | debug\ | info\ | warning\ | error\ | critical\ | off |
$ istioctl install --set profile=demo --set meshConfig.accessLogFile="/dev/stdout" --set meshConfig.accessLogEncoding="JSON"
$ kubectl get istiooperators -n istio-system installed-state -oyaml
....
meshConfig:
accessLogEncoding: JSON
accessLogFile: /dev/stdout
....
将日志格式设置为JSON后,此时输出的日志内容进行格式化如下:
{
"upstream_cluster": "outbound|9080||reviews.bookinfo.svc.cluster.local",
"start_time": "2023-03-03T04:59:48.441Z",
"upstream_service_time": "949",
"response_code_details": "via_upstream",
"request_id": "0071de46-2937-97bf-aaa7-4ab9dacc363d",
"method": "GET",
"requested_server_name": null,
"protocol": "HTTP/1.1",
"route_name": "default",
"downstream_local_address": "192.168.100.231:9080",
"response_flags": "-",
"bytes_received": 0,
"x_forwarded_for": null,
"downstream_remote_address": "172.7.130.7:33286",
"bytes_sent": 442,
"response_code": 200,
"upstream_local_address": "172.7.130.7:43992",
"upstream_transport_failure_reason": null,
"path": "/reviews/0",
"authority": "reviews:9080",
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36",
"duration": 949,
"connection_termination_details": null,
"upstream_host": "172.7.100.7:9080"
}
日志信息中有五个重要的字段,也就是所谓的Envoy 流量五元组:
Downstream (下游)
,Envoy 发出请求流量到B用户叫做 Upstream (上游)
,在处理Downstream
和 Upstream
过程中,分别会涉及2个流量端点,即请求的发起端和接收端;UPSTREAM_CLUSTER
,并根据负载均衡规则,从这个集合中选择一个 host 作为流量转发的接收端点,这个 host 就是 UPSTREAMLHOST
。这就是 Envoy请求处理的流量五元组信息,这是 Envoy 日志里最重要的部分,通过Envoy 流量五元组
我们可以准确的观测流量从哪里来
和到哪里去
。还有一个非常重要的属性:response_flags
,一些请求的错误标志会被赋值给该字段,用于调试请求的时候非常有用。常见错误标志有如下几种:
相比传统的单体应用,微服务的一个主要变化是将应用中的不同模块拆分为了独立的服务,在微服务架构下,原来进程内的方法调用成为了跨进程的远程方法调用。相对于单一进程内的方法调用而言,跨进程调用的调试和故障分析是非常困难的,难以使用传统的代码调试程序或者日志打印来对分布式的调用过程进行查看和分析。一个来自客户端的请求在其业务处理过程中很有可能需要经过多个微服务,我们如果想要对该请求的端到端调用过程进行完整的分析,则必须将该请求经过的所有进程的相关信息都收集起来并关联在一起,这就是分布式追踪,也是应用可观测性中非常重要的手段。
Istio支持通过 Envoy 代理进行分布式追踪。代理会代表其代理的应用程序自动生成跟踪范围,只需要应用程序转发适当的请求上下文。
随着分布式追踪技术的发展,社区推出了 OpenTracing
这个规范,提供了标准的 API 规范、框架以及一些公共的库。目前比较知名的追踪工具基本上都通过 OpenTracing
进行实现,比如 Jaeger
、Zipkin
等
我们这里主要来给大家介绍比较流行的 Jaeger。Jaeger 是由 Uber 开源的分布式追踪系统,采用 Go 语言编写,主要借鉴了 Google Dapper
论文和 Zipkin
的设计兼容 OpenTracing
以及 Zipkin
踪格式,目前已成为 CNCF
基金会的开源项目。
image.png
Span
的组合
Jaeger 的架构:
核心组件:
接下来我们把 Jaeger 集成到 Istio。首先,确认 Istio 开启了追踪选项,可以使用如下命令开启:
# 默认就是开启的
$ istioctl install <flags-you-used-to-install-Istio> --set values.tracing.enabled=true
我们可以使用官方提供的配置文件快速将 Jaeger 集成到 Istio 中:
$ cd /opt/istio/samples/addons/
# 创建Grafana
$ kubectl apply -f /opt/istio/samples/addons/jaeger.yaml
$ kubectl get deploy -n istio-system
然后使用如下命令启动 Jaeger 的Web UI:
istioctl dashboard jaeger
这里我们使用另外一种方法:
#修改jaeger这个service的类型为NodePort,这样外部环境就可以访问jaeger了
#把type: ClusterIP 修改为 type: NodePort即可
#$ kubectl edit service jaeger-collector -n istio-system
# 或者通过Ingress访问
$ cat > /opt/istio/samples/addons/jaeger-ingress.yaml <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: jaeger
namespace: istio-system
spec:
rules:
- host: jaeger.od.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: tracing
port:
number: 80
EOF
$ kubectl apply -f /opt/istio/samples/addons/jaeger-ingress.yaml
将100.1.1.11
绑定本地hosts文件
,访问 http://jaeger.od.com
然后访问 Bookinfo 应用页面生成一些 trace 数据后,到 Jaeger 查询 trace 数据:
点击任意 Span 可以查看其详细 trace 数据:
通过System Architecture
查看调用视图