本文介绍如何使用 OpenTelemetry 对 Istio 进行链路追踪。通过 Istio 的链路追踪功能,可以可视化服务调用关系和依赖、监控微服务的健康状态、识别系统中的性能瓶颈以及排查分布式系统中的故障。
前提条件
集群已安装 Istio 且 Istio 版本 ≥ v1.19。
已部署 OpenTelemetry Collector。Istio 调用链需要通过 OpenTelemetry Collector 转发上报至可观测链路 OpenTelemetry 版。如您的集群中尚未部署 OpenTelemetry Collector,请参考 通过 OpenTelemetry Collector 转发 进行部署。
获取可观测链路 OpenTelemetry 版的接入点和鉴权信息。详情请参考 接入和鉴权说明。
接入步骤
1、设置 Istio 链路数据上报方式
Istio 可以通过 gRPC 或 HTTP 协议导出 Trace 数据到 OpenTelemetry Collector。请选择以下两种方式中的一种进行配置。
使用 gRPC 协议
运行以下内容,Istio 的 Trace 数据将通过 OTLP/HTTP 导出到 OpenTelemetry Collector。
创建配置文件istio-otel-config.yaml。
cat > istio-otel-config.yaml <<EOF apiVersion: install.istio.io/v1alpha1 kind: IstioOperator spec: meshConfig: defaultConfig: tracingServiceName: APP_LABEL_AND_NAMESPACE enableTracing: true extensionProviders: - name: otel-tracing opentelemetry: port: 4317 service: <service-name>.<namespace>.svc.cluster.local resource_detectors: environment: {} EOF
使用 HTTP 协议
运行以下内容,Istio 的 Trace 数据将通过 OTLP/HTTP 导出到 OpenTelemetry Collector。
创建配置文件istio-otel-config.yaml。
cat > istio-otel-config.yaml <<EOF apiVersion: install.istio.io/v1alpha1 kind: IstioOperator spec: meshConfig: enableTracing: true extensionProviders: - name: otel-tracing opentelemetry: port: 4318 service: opentelemetry-collector.observability.svc.cluster.local http: path: "/v1/traces" timeout: 5s headers: - name: "custom-header" value: "custom value" resource_detectors: environment: {} EOF
说明需要将配置中的
service
地址替换为您环境中 OpenTelemetry Collector 的实际服务地址,<service-name>为 OpenTelemetry Collector 的服务名称,<namespace> 为OpenTelemetry Collector 所在命名空间的名称。例如:opentelemetry-collector.observability.svc.cluster.local
。Istio 提供了配置选项 tracingServiceName 来控制应用名称的生成方式,有三种选项。
APP_LABEL_AND_NAMESPACE
(默认值):使用<app标签>.<命名空间>
格式。CANONICAL_NAME_ONLY
:仅使用工作负载的规范名称,如 Deployment 的名称。CANONICAL_NAME_AND_NAMESPACE
:使用<规范名称>.<命名空间>
格式。
使用该配置文件安装。
istioctl install -y -f istio-otel-config.yaml
2、为 Istio 开启链路追踪
配置完链路数据上报后,还需要开启 Istio 链路数据采集功能并设置采样比例。运行以下命令来启用链路追踪。
创建配置文件istio-telemetry.yaml。
cat > istio-telemetry.yaml <<EOF apiVersion: telemetry.istio.io/v1 kind: Telemetry metadata: name: otel-demo spec: tracing: - providers: - name: otel-tracing randomSamplingPercentage: 100 EOF
说明randomSamplingPercentage
表示追踪采样率,取值 0-100,设置为 100 表示记录所有请求的追踪数据。在生产环境中,建议根据实际流量情况调整该值。应用配置。
kubectl apply -f istio-telemetry.yaml
完成以上配置后,当服务间有调用发生时,Istio 就会自动生成链路数据,并通过 OpenTelemetry Collector 转发到可观测链路 OpenTelemetry 版。
3、查看 Istio 调用链
前往可观测链路 OpenTelemetry 版控制台查看 Istio 的调用链。
实践教程
接下来将通过以下示例演示如何采集 Istio 的调用链,并上报至可观测链路 OpenTelemetry 版。
1、安装 Istio
curl -L https://istio.io/downloadIstio | sh -
cd istio-1.25.2
export PATH=$PWD/bin:$PATH
2、安装 OpenTelemetry Collector
创建otel.yaml,需要替换 <gRPC-Endpoint> 和 <gRPC-Token> 为前提条件中获取的接入点和鉴权 Token。
cat > otel.yaml <<EOF apiVersion: v1 kind: ConfigMap metadata: name: opentelemetry-collector-conf labels: app: opentelemetry-collector data: opentelemetry-collector-config: | receivers: otlp: protocols: grpc: http: processors: batch: exporters: otlp: endpoint: "<gRPC-Endpoint>" headers: Authentication: "<gRPC-Token>" tls: insecure: true logging: loglevel: debug extensions: health_check: port: 13133 service: extensions: - health_check pipelines: logs: receivers: [otlp] processors: [batch] exporters: [logging] traces: receivers: - otlp exporters: - logging - otlp --- apiVersion: v1 kind: Service metadata: name: opentelemetry-collector labels: app: opentelemetry-collector spec: ports: - name: grpc-opencensus port: 55678 protocol: TCP targetPort: 55678 - name: grpc-otlp # Default endpoint for OpenTelemetry receiver. port: 4317 protocol: TCP targetPort: 4317 - name: http-otlp # HTTP endpoint for OpenTelemetry receiver. port: 4318 protocol: TCP targetPort: 4318 selector: app: opentelemetry-collector --- apiVersion: apps/v1 kind: Deployment metadata: name: opentelemetry-collector spec: selector: matchLabels: app: opentelemetry-collector strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 1 type: RollingUpdate template: metadata: labels: app: opentelemetry-collector sidecar.istio.io/inject: "false" # do not inject spec: containers: - command: - "/otelcol" - "--config=/conf/opentelemetry-collector-config.yaml" env: - name: POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.namespace image: otel/opentelemetry-collector:0.54.0 imagePullPolicy: IfNotPresent name: opentelemetry-collector ports: - containerPort: 4317 protocol: TCP - containerPort: 4318 protocol: TCP - name: grpc-opencensus containerPort: 55678 protocol: TCP resources: limits: cpu: "2" memory: 4Gi requests: cpu: 200m memory: 400Mi terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - name: opentelemetry-collector-config-vol mountPath: /conf dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler terminationGracePeriodSeconds: 30 volumes: - configMap: defaultMode: 420 items: - key: opentelemetry-collector-config path: opentelemetry-collector-config.yaml name: opentelemetry-collector-conf name: opentelemetry-collector-config-vol EOF
创建命名空间 observability。
kubectl create namespace observability
部署 OpenTelemetry Collector。
kubectl apply -f otel.yaml -n observability
3、设置 Istio 链路追踪
在集群中运行以下命令,Istio 的 Trace 数据将通过 OTLP/HTTP 导出到 OpenTelemetry Collector。
cat <<EOF | istioctl install -y -f - apiVersion: install.istio.io/v1alpha1 kind: IstioOperator spec: meshConfig: enableTracing: true extensionProviders: - name: otel-tracing opentelemetry: port: 4317 service: opentelemetry-collector.observability.svc.cluster.local resource_detectors: environment: {} EOF
运行以下命令启用 Istio 链路追踪。
kubectl apply -f - <<EOF apiVersion: telemetry.istio.io/v1 kind: Telemetry metadata: name: otel-demo spec: tracing: - providers: - name: otel-tracing randomSamplingPercentage: 100 EOF
4、部署 Demo
为 default 命名空间添加自动注入标签。
Istio 将自动为该命名空间中新创建的 Pod 注入 sidecar 代理(istio-proxy 容器)。
kubectl label namespace default istio-injection=enabled
部署 istio 自带的 Demo(在下载好的 istio 目录中运行)。
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
查看容器组和服务状态。
kubectl get pods kubectl get services
验证应用是否可访问。
kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>" # 预期输出 <title>Simple Bookstore App</title>
5、创建 Demo 服务的对外访问入口
创建 Demo 应用的入口网关配置。
kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
export INGRESS_NAME=istio-ingressgateway export INGRESS_NS=istio-system export INGRESS_HOST=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.status.loadBalancer.ingress[0].ip}') export INGRESS_PORT=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.spec.ports[?(@.name=="http2")].port}') export SECURE_INGRESS_PORT=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.spec.ports[?(@.name=="https")].port}') export TCP_INGRESS_PORT=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.spec.ports[?(@.name=="tcp")].port}') export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT # 查看生成的访问地址 echo $GATEWAY_URL # 输出示例:192.168.1.100:80
验证 Demo 访问地址。
curl -s "http://${GATEWAY_URL}/productpage" | grep -o "<title>.*</title>" # 预期输出 <title>Simple Bookstore App</title>
6、查看调用链
使用以下命令连续访问 10 次 productpage 页面,以生成测试流量。
for i in $(seq 1 10); do curl -s -o /dev/null "http://$GATEWAY_URL/productpage"; done
前往可观测链路 OpenTelemetry 版控制台查看 Istio 的调用链。
常见问题
问题:控制台未查询到 Istio 的链路数据。
解决方法:
可查看 OpenTelemetry Collector 日志,确认 OpenTelemetry Collector 正常运行并接收到了 Istio 上报的数据。
kubectl logs <collector-pod-name> -n <namespace>
预期输出:
检查 sidecar 是否注入成功。
kubectl get pod -n default -o custom-columns=NAME:.metadata.name,CONTAINERS:.spec.containers[*].name
如果 CONTAINERS 中不包含 istio-proxy 容器,说明注入失败。注入失败的原因可能是:为命名空间设置
istio-injection=enabled
自动注入标签时,Pod 已经创建。该标签只对新创建的 Pod 生效,已存在的 Pod 不受影响,需要重启 Pod 后才会生效。检查 Telemetry 资源是否正确配置。
使用以下命令检查 Telemetry 配置。
kubectl get telemetry otel-demo -o yaml
查看 Istio 的 ConfigMap 配置中与 OpenTelemetry 相关的部分是否正确。
kubectl get cm istio -n istio-system -o yaml | grep -A 10 extensionProviders