第八篇:《可观测性(二):Envoy 访问日志与自定义指标》 在上一篇文章中我们学习了 Istio 可观测性的三大支柱——Kiali 拓扑、Jaeger 追踪和 Grafana 指标。但这些工具主要提供的是宏观视图和预置数据。当需要深入排查具体问题时Envoy 访问日志提供了每个请求的详细信息来源、目标、状态码、耗时等而自定义指标则能针对业务需求采集特定的监控数据。本文深入讲解如何配置 Envoy 访问日志包括 JSON 格式和 Trace ID 关联、如何使用 Telemetry API 精细化控制日志采集以及如何通过 Telemetry API 自定义 Prometheus 指标帮助你构建从“宏观监控”到“微观排查”的完整可观测性链路。一、Envoy 访问日志每个请求的“黑匣子”Envoy 访问日志记录了经过 Sidecar 代理的每一个请求的详细信息包括来源 IP、目标服务、HTTP 方法、路径、状态码、响应时间等。它是排查单次请求失败或延迟问题的第一手资料。1.1 启用访问日志Istio 提供了多种启用访问日志的方法Telemetry API 是当前推荐的方式。方法一使用 Telemetry API推荐创建一个 Telemetry 资源在 istio-system 命名空间中启用全局访问日志apiVersion:telemetry.istio.io/v1kind:Telemetrymetadata:name:mesh-logging-defaultnamespace:istio-systemspec:accessLogging:-providers:-name:envoy应用配置kubectl apply-f-EOF apiVersion: telemetry.istio.io/v1 kind: Telemetry metadata: name: mesh-logging-default namespace: istio-system spec: accessLogging: - providers: - name: envoy EOF方法二使用 MeshConfig备选如果使用 IstioOperator 安装也可以在配置中开启访问日志spec:meshConfig:accessLogFile:/dev/stdout启用后Envoy 会将访问日志输出到 istio-proxy 容器的标准输出可通过 kubectl logs 查看kubectl logspod-name-cistio-proxy1.2 配置 JSON 格式日志默认的访问日志是文本格式难以被日志采集系统如 ELK、Loki解析。推荐切换为 JSON 格式。通过 MeshConfig 配置 JSON 格式spec:meshConfig:accessLogFile:/dev/stdoutaccessLogEncoding:JSON设置 accessLogEncoding: JSON 后Envoy 会使用 Istio 默认的 JSON 模板输出日志。1.3 自定义日志格式与 Trace ID 关联默认的访问日志格式不包含 Trace ID导致日志和追踪数据难以关联。为了在排查问题时能从日志直接跳转到对应的 Trace需要在日志格式中增加 trace_id 和 span_id 字段。以下配置将访问日志格式化为 JSON并包含 trace_id 和 span_idapiVersion:install.istio.io/v1alpha1kind:IstioOperatorspec:meshConfig:accessLogFile:/dev/stdoutaccessLogEncoding:JSONaccessLogFormat:|{ timestamp: %START_TIME%, method: %REQ(:METHOD)%, path: %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%, protocol: %PROTOCOL%, response_code: %RESPONSE_CODE%, response_flags: %RESPONSE_FLAGS%, duration: %DURATION%, upstream_service_time: %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%, request_id: %REQ(X-REQUEST-ID)%, trace_id: %REQ(X-B3-TRACEID)%, span_id: %REQ(X-B3-SPANID)%, source_namespace: %ENVIRONMENT(POD_NAMESPACE)%, source_app: %ENVIRONMENT(APP)%, upstream_host: %UPSTREAM_HOST%, upstream_cluster: %UPSTREAM_CLUSTER% }关键字段解读 OpenTelemetry 用户如果使用 W3C Trace Contexttraceparent 头应将 trace_id 替换为 traceparent 字段。1.4 精细化控制Telemetry API 的高级用法Telemetry API 不仅支持全局开启还可以在命名空间或工作负载级别进行精细化控制。禁用特定工作负载的访问日志apiVersion:telemetry.istio.io/v1kind:Telemetrymetadata:name:disable-curl-loggingnamespace:defaultspec:selector:matchLabels:app:curlaccessLogging:-providers:-name:envoydisabled:true按流量方向过滤日志可以配置只记录入站流量mode: CLIENT或出站流量mode: SERVER减少日志量。spec:accessLogging:-providers:-name:envoyfilter:expression:request.method GET二、自定义 Prometheus 指标Istio 默认提供了丰富的标准指标如 istio_requests_total、istio_request_duration_milliseconds但业务场景往往需要自定义指标——例如按“用户类型”统计订单创建数、按“支付渠道”统计交易成功率等。从 Istio 1.18 开始推荐使用 Telemetry API 来定制遥测指标。2.1 使用 Telemetry API 定义自定义指标Telemetry API 的 metrics 字段允许定义自定义指标从请求中提取特定属性作为维度。以下示例定义了一个自定义 Counter 指标 myapp_requests_total按 response_code 和 destination_service 分组apiVersion:telemetry.istio.io/v1kind:Telemetrymetadata:name:mesh-metricsnamespace:istio-systemspec:metrics:-providers:-name:prometheusoverrides:-match:metric:REQUEST_COUNTtagOverrides:response_code:value:response.codedestination_service:value:destination.service.host⚠️ 注意高基数标签如 path、user_id会导致 Prometheus 指标爆炸严重影响性能。应谨慎选择维度优先使用有限的枚举值如 response_code、method。2.2 通过 EnvoyFilter 定义更复杂的自定义指标对于更复杂的指标定制需求可以使用 EnvoyFilter 直接配置 Envoy 的统计输出。以下示例定义了一个自定义指标 custom_requests_total包含 user_type 维度apiVersion:networking.istio.io/v1alpha3kind:EnvoyFiltermetadata:name:custom-metricsnamespace:istio-systemspec:configPatches:-applyTo:HTTP_FILTERmatch:context:SIDECAR_INBOUNDlistener:filterChain:filter:name:envoy.filters.network.http_connection_managerpatch:operation:MERGEvalue:stat_prefix:istiohttp_filters:-name:envoy.filters.http.routertyped_config:type:type.googleapis.com/envoy.extensions.filters.http.router.v3.Routerstats:-name:custom_requests_totaltags:-tag_name:user_typemetadata:kind:Requestkey:user_type三、日志、指标与追踪的关联排查问题的完整链路可观测性的三大信号——日志、指标和追踪——只有相互关联才能发挥最大价值指标告诉你“出问题了”如错误率飙升。追踪告诉你“哪里出了问题”如订单服务调用库存服务超时。日志告诉你“为什么出问题”如数据库连接超时的具体错误信息。而将它们串联起来的“线”就是 Trace ID。通过前面配置的包含 trace_id 的 JSON 访问日志排查流程可以这样串联Grafana 中发现 order-service 的错误率异常升高。跳转到 Jaeger筛选包含 order-service 的 Trace找到一条耗时异常的调用链。从 Jaeger 中复制该 Trace 的 Trace ID。在日志系统如 Loki 或 ELK中搜索该 Trace ID找到对应的 Envoy 访问日志查看具体的错误信息如 response_flags、response_code。text┌─────────────────────────────────────────────────────────────────┐│ 排查链路示例 ││ ││ Grafana 指标告警 ││ ↓ ││ Jaeger 追踪找到慢 Trace复制 Trace ID ││ ↓ ││ Loki/ELK 日志搜索用 Trace ID 过滤日志找到具体错误 ││ ↓ ││ 定位根因库存服务数据库连接超时 │└─────────────────────────────────────────────────────────────────┘四、小结Envoy 访问日志通过 Telemetry API 启用推荐使用 JSON 格式便于日志系统采集。Trace ID 关联在访问日志格式中包含 trace_id 和 span_id 字段实现日志与追踪的关联。自定义指标使用 Telemetry API 的 metrics 字段定义自定义 Prometheus 指标注意避免高基数标签。精细化控制Telemetry API 支持在命名空间和工作负载级别控制日志和指标的采集。三大信号关联指标发现问题→ 追踪定位服务→ 日志找出原因形成完整的可观测性闭环。