news 2026/9/9 21:03:43

Istio OpenTelemetry ALS 访问日志接入 Loki:Envoy Access Log 经 OTLP 写入 Grafana 的完整实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Istio OpenTelemetry ALS 访问日志接入 Loki:Envoy Access Log 经 OTLP 写入 Grafana 的完整实践

Istio OpenTelemetry ALS 访问日志接入 Loki:Envoy Access Log 经 OTLP 写入 Grafana 的完整实践

【免费下载链接】istioConnect, secure, control, and observe services.项目地址: https://gitcode.com/GitHub_Trending/is/istio

导读

本文基于 Istio 官方仓库 samples/open-telemetry/loki 示例,完整演示如何把 Istio 数据面(Envoy Sidecar)产生的访问日志通过OpenTelemetry ALS(Access Log Service,gRPC 访问日志服务)协议实时发送给 OpenTelemetry Collector,再由 Collector 转发写入Grafana Loki,最终在 Grafana 中实现日志检索。读完本文,你将掌握 extensionProviders(envoyOtelAls)声明、otel-collector 管道配置、Telemetry 访问日志策略下发,以及完整的验证与清理流程,可直接在本仓库基础上复制运行。

数据链路概览:Envoy 访问日志 --OTLP/gRPC(4317)--> otel-collector --loki exporter--> Loki(3100) --数据源--> Grafana


一、原理先行:Istio 的 OpenTelemetry ALS 是什么

Envoy 除了能把访问日志写到本地文件 /dev/stdout,还内置了 gRPC 类型的访问日志服务(ALS):sidecar 将每条请求日志打包后按流式 gRPC 推送到外部 collector。Istio 对 ALS 的支持有两类 provider:

  • envoyHttpAls/envoyTcpAls:走 Envoy 原生 HTTP/TCP gRPC ALS 协议;
  • envoyOtelAls:走 Envoy 的 OpenTelemetry 访问日志扩展(即envoy.access_loggers.open_telemetry),日志被编码为 OTLP Logs 后推送,可与生态中的 OTel Collector 无缝衔接。

在 Istio 源码 pilot/pkg/model/telemetry_logging.go 中可以看到该 provider 被处理的关键路径:

  • 常量OtelEnvoyALSName = "envoy.access_loggers.open_telemetry"与默认日志名OtelEnvoyAccessLogFriendlyName = "otel_envoy_accesslog"(telemetry_logging.go 定义);
  • openTelemetryLog()(telemetry_logging.go)根据 MeshConfig 中的 provider 定义生成 Envoy 的 OpenTelemetryAccessLogConfig,其中通过clusterLookupFn(即同文件LookupCluster())把service:port解析为 Envoy 可用的上游 cluster(BuildSubsetKey构建 outbound cluster);
  • buildOpenTelemetryAccessLogConfig()DisableBuiltinLabels: true,并把logFormat.labels转换为 OTLPKeyValueList写入日志 Attributes;
  • FilterStateObjectsToLog默认携带envoyWasmStateToLog中的上游/下游对端元数据(upstream_peerdownstream_peer及 wasm 相关 key),这正是 mTLS 场景下获取对端 workload 信息的基础。

因此在正式动手前,可以把“每个提供 OpenTelemetry 日志接入的第三方后端”理解成:先用 MeshConfig 声明一个被 Istio 认可的 extensionProvider,再用 Telemetry API 让某个作用域下的访问日志引用它


二、安装 Istio:通过 IstioOperator 声明 envoyOtelAls Provider

示例使用官方提供的 IOP(IstioOperator)清单安装 Istio,并把 OpenTelemetry ALS provider 写入网格配置:

istioctl install -f iop.yaml -y

iop.yaml 完整内容如下:

apiVersion: install.istio.io/v1alpha1 kind: IstioOperator spec: meshConfig: extensionProviders: - name: otel envoyOtelAls: service: opentelemetry-collector.istio-system.svc.cluster.local port: 4317 logFormat: labels: pod: "%ENVIRONMENT(POD_NAME)%" namespace: "%ENVIRONMENT(POD_NAMESPACE)%" cluster: "%ENVIRONMENT(ISTIO_META_CLUSTER_ID)%" mesh: "%ENVIRONMENT(ISTIO_META_MESH_ID)%"

逐字段说明:

字段取值作用
extensionProviders[].nameotelprovider 的全局唯一名称,Telemetry 资源通过该名称引用
envoyOtelAls.serviceopentelemetry-collector.istio-system.svc.cluster.local接收 OTLP 日志的后端服务全限定名。Istio 侧LookupCluster()会先在服务注册表(ServiceIndex)中解析该名字,找不到对应 Service 时 ALS 不会被正确配置,并会在 pilot 日志中记录could not find cluster ...错误(见 telemetry_logging.go)
envoyOtelAls.port4317后端 OTLP gRPC 接收端口
logFormat.labels一组静态键 + Envoy 命令操作符每个 key 都会成为写入 OTLP Attributes 的标签;value 使用 Envoy 的%ENVIRONMENT(VAR)%命令操作符读取 istio-proxy 容器环境变量

关于上面 4 个 label 的环境变量来源:

  • POD_NAMEPOD_NAMESPACE:sidecar 注入器为 istio-proxy 容器注入的运行时信息;
  • ISTIO_META_CLUSTER_IDISTIO_META_MESH_ID:Istio 注入时写入 istio-proxy 的网格元数据环境变量,分别标识集群与网格。

这些 label 会在后续 collector 配置中被挑选为 Loki 的流标签(见第四节),实现“按 Pod / 命名空间 / 集群 / 网格维度切分与检索日志”。同类 provider 的合法性校验(如 service 是否可解析、字段约束)由 pilot 在推送 xDS 前通过 pkg/config/validation/agent/extensionprovider.go 中的ValidateExtensionProviderEnvoyOtelAls()完成。


三、Setup Loki:安装 Loki 后端

仓库在 addons 目录提供了可直接使用的 Loki 清单(由官方 Loki Helm Chart 渲染而来,版本 3.6.11):

kubectl apply -f samples/addons/loki.yaml -n istio-system

对 samples/addons/loki.yaml 中与本实验强相关的要点:

  • 单实例 StatefulSet模式运行(-target=all),镜像docker.io/grafana/loki:3.6.11
  • 对外 Service 名为loki,监听:
    • HTTP3100(对外提供/loki/api/v1/push写入接口与查询接口,Service 端口名http-metrics);
    • gRPC9095(内部组件通信);
  • 数据以filesystem对象存储写入/var/loki,并通过 volumeClaimTemplates 申请 10Gi PVC;
  • 额外附带loki-memberlist(无头服务,7946)与loki-headless等配套 Service,便于后续扩展为分布式模式。

安装后,collector 将通过http://loki.istio-system.svc:3100/loki/api/v1/push推送日志(详见下一节配置)。


四、Setup otel-collector:部署 OpenTelemetry Collector 并串联到 Loki

创建一个otel-collector后端,配置了 OTLP 接收器、属性处理与 Loki 导出器:

kubectl apply -f otel.yaml -n istio-system

samples/open-telemetry/loki/otel.yaml 在单个文件中声明了 ConfigMap、Service、Deployment 三类资源。先看核心的 collector 配置(ConfigMap 的data.opentelemetry-collector-config):

receivers: otlp: protocols: grpc: http: processors: batch: attributes: actions: - action: insert key: loki.attribute.labels value: pod, namespace,cluster,mesh exporters: loki: endpoint: "http://loki.istio-system.svc:3100/loki/api/v1/push" logging: loglevel: debug extensions: health_check: service: extensions: - health_check pipelines: logs: receivers: [otlp] processors: [attributes] exporters: [loki, logging]

配置语义拆解:

  • receivers.otlp:同时开启 gRPC(4317)与 HTTP 两种 OTLP 协议接收,Envoy 的 ALS 通过 gRPC 4317 上报;
  • processors.attributes:通过action: insert插入特殊 keyloki.attribute.labels,其值为逗号分隔的pod, namespace,cluster,mesh。这是 OTel Loki exporter 的约定:只有被列进loki.attribute.labels的日志属性,才会被提升为 Loki 的 label(索引字段),其余属性只作为非索引的日志内容。这里列出的四个 key 与第二节 iop.yaml 中logFormat.labels的四个 key(pod/namespace/cluster/mesh)一一对应,从而让每条访问日志都携带可索引的 Pod、命名空间、集群与网格维度;
  • exporters.loki:指向 Loki 单实例的 HTTP Push APIhttp://loki.istio-system.svc:3100/loki/api/v1/push
  • exporters.loggingloglevel: debug表示同时把每条日志原样打印到 collector 的 stdout,便于无需接入 Grafana 时快速排障(这也是 README 中“查看 ALS 输出”的直接手段);
  • service.pipelines.logs:把otlp → attributes → loki/logging串成一条完整 logs 管道;health_check扩展为存活探针提供端点。

Service 与 Deployment 部分的关键点:

spec: ports: - name: grpc-opencensus port: 55678 - name: grpc-otlp # Default endpoint for OpenTelemetry receiver. port: 4317 selector: app: opentelemetry-collector
spec: template: metadata: labels: app: opentelemetry-collector sidecar.istio.io/inject: "false" # do not inject spec: containers: - command: - "/otelcol-contrib" - "--config=/conf/opentelemetry-collector-config.yaml" env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: docker.io/otel/opentelemetry-collector-contrib:0.73.0
  • Service 暴露4317(OTLP gRPC)与55678两个端口;其中grpc-otlp: 4317正是 iop.yaml 中envoyOtelAls.port指向的接收端点;
  • Deployment 镜像使用otel/opentelemetry-collector-contrib:0.73.0(contrib 发行版才内置 loki exporter 等丰富组件);
  • 通过sidecar.istio.io/inject: "false"明确禁止给 collector 自身注入 sidecar,避免“访问日志后端自己也在被采集”的循环与干扰;
  • 通过 fieldRef 注入POD_NAMEPOD_NAMESPACE环境变量;配置以 ConfigMap 卷挂载到/conf/opentelemetry-collector-config.yaml

补充:仓库中的姊妹示例 samples/open-telemetry/als/README.md 演示了最小化的纯 stdout 版本——collector 只包含otlp → batch → logging管道,不接 Loki;当你想先验证 ALS 通道本身是否打通时,可先跑那个精简版。


五、Apply Telemetry API:把访问日志路由到 otel Provider

Istio 的访问日志通过telemetry.istio.io/v1Telemetry资源按作用域(mesh / namespace / workload)启用。示例添加一条全局策略,让网格内所有 sidecar 把访问日志发送到前面声明的otelprovider:

kubectl apply -f telemetry.yaml

telemetry.yaml 完整内容:

apiVersion: telemetry.istio.io/v1 kind: Telemetry metadata: name: mesh-logging namespace: istio-system spec: accessLogging: - providers: - name: otel

要点:

  • 资源位于istio-system(根命名空间)且未限定selector,因此这是一条全网格生效的访问日志策略;
  • spec.accessLogging[].providers[].name: otel引用的正是 iop.yaml 中注册的 extensionProvider 名称;Istio 生成 xDS 时,会按 pilot/pkg/model/telemetry_logging.go 中telemetryAccessLog()的 switch 逻辑把该 provider 展开为 Envoy 的envoy.access_loggers.open_telemetry过滤器,填入 cluster(collector 服务)与 logName(默认otel_envoy_accesslog)等信息。

六、验证 ALS 输出:发起流量并观察日志

6.1 启动示例服务

按 httpbin 示例说明 启动httpbinfortio两个服务。若命名空间已启用自动注入,直接 apply 清单即可:

kubectl apply -f httpbin.yaml # 位于 samples/httpbin/ kubectl apply -f samples/httpbin/sample-client/fortio-deploy.yaml

否则需先为 istio-proxy 手动注入,例如:

kubectl apply -f <(istioctl kube-inject -f httpbin.yaml) kubectl apply -f <(istioctl kube-inject -f samples/httpbin/sample-client/fortio-deploy.yaml)

6.2 从 fortio 请求 httpbin

kubectl exec -it deploy/fortio -- fortio curl httpbin:8000/ip

此时该请求经过 fortio 与 httpbin 两侧的 Envoy,两侧的访问日志都会通过 ALS 上报给 otel-collector。

6.3 查看 collector 的 stdout 输出

由于 collector 配置了logging/loglevel: debug导出器,日志会同时打印到其标准输出:

kubectl logs -l app=opentelemetry-collector -n istio-system --tail=-1

正常时你会看到类似 OTLP LogRecord 的结构化输出,其中包含请求方法、路径、响应码以及前面配置的podnamespaceclustermesh属性。若看不到任何日志,可按以下顺序排查:

  1. 确认istioctl install -f iop.yaml后 provider 已注册:istioctl manifest generate -f iop.yaml或查看 istiod 日志;
  2. 确认 Telemetry 资源已生效(kubectl get telemetry -n istio-system);
  3. 确认 otel-collector 与 Loki 的 Service 均能解析(kubectl get svc -n istio-system);
  4. 查看 istiod 日志中是否存在could not find cluster for open telemetry provider类错误——这对应源码中LookupCluster()失败的分支。

6.4 通过 Grafana 查询 Loki

如需在 Grafana 中检索日志,先部署 addons 中的 Grafana:

kubectl apply -f samples/addons/grafana.yaml -n istio-system istioctl dashboard grafana

然后在 Grafana 中把 Loki 添加为数据源(地址为http://loki.istio-system.svc:3100),即可使用 LogQL 按podnamespace等标签过滤、检索这些访问日志(Grafana 与 Loki 数据源的对接用法可查阅 Grafana 官方数据源文档)。


七、清理

按以下顺序删除示例资源并卸载 Istio:

kubectl delete -f otel.yaml -n istio-system kubectl delete telemetry mesh-logging -n istio-system istioctl uninstall --purge -y

如需连同 Loki、Grafana 一并清理,可补充:

kubectl delete -f samples/addons/loki.yaml -n istio-system kubectl delete -f samples/addons/grafana.yaml -n istio-system kubectl delete -f httpbin.yaml kubectl delete -f samples/httpbin/sample-client/fortio-deploy.yaml

八、小结与仓库导航

本实验展示了 Istio 可观测性中“访问日志外送”的一条标准链路:MeshConfig 声明 extensionProvider(envoyOtelAls)→ Telemetry 按作用域开启 accessLogging → Envoy 以 OTLP/gRPC 上报 → otel-collector 加工 → Loki 存储 → Grafana 查询。其中“按 Pod/命名空间/集群/网格给日志打标签”的做法,对多集群、多租户网格的日志归类与排障尤其实用。

建议结合仓库源码继续深入的关键文件:

  • 示例清单:iop.yaml、otel.yaml、telemetry.yaml;
  • Loki 后端清单:samples/addons/loki.yaml;
  • 流量生成样例:samples/httpbin/README.md 与 samples/httpbin/sample-client/fortio-deploy.yaml;
  • 核心实现:pilot/pkg/model/telemetry_logging.go(openTelemetryLog/buildOpenTelemetryAccessLogConfig/LookupCluster);
  • Provider 校验:pkg/config/validation/agent/extensionprovider.go(ValidateExtensionProviderEnvoyOtelAls);
  • 精简对照版:samples/open-telemetry/als/README.md。

掌握本文链路后,把exporters.loki.endpoint换成其他 Loki 网关、或把 collector 换成自建接收端,即可平滑迁移到生产级日志平台。

【免费下载链接】istioConnect, secure, control, and observe services.项目地址: https://gitcode.com/GitHub_Trending/is/istio

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 21:03:08

Android歌词渐变:用LinearGradient实现卡拉OK式进度高亮

简介&#xff1a;一份Android自定义View源码&#xff0c;实现歌词风格的文字颜色渐变效果&#xff0c;面向需要为TextView添加动态渐变文字的移动开发者。项目通过GradientTextView对文本着色&#xff0c;以两种颜色平滑过渡&#xff0c;适合音乐播放器歌词、字幕强调等场景&am…

作者头像 李华
网站建设 2026/9/9 21:02:21

diagram-design:现代前端可视化表达系统核心技术解析

1. 什么是 diagram-design&#xff1a;不是画图工具&#xff0c;而是现代前端工程中的可视化表达系统 “diagram-design”这个词乍看像某个软件功能名&#xff0c;但实际它早已脱离单一工具范畴&#xff0c;演变成一套融合设计思维、前端工程能力与领域建模逻辑的 可视化表达系…

作者头像 李华
网站建设 2026/9/9 21:02:13

CSS Position 定位完全指南:5种取值、踩坑与实战秘籍

一、Position 的 5 种取值全景&#xff1a;每个值到底在干嘛先聊一个很多人一开始就懵的地方。position属性在 CSS 里其实就管一件事&#xff1a;这个元素到底按什么规则落位。默认情况下&#xff0c;页面上所有元素都遵循文档流——就是你不管写多长&#xff0c;它都老老实实从…

作者头像 李华
网站建设 2026/9/9 20:59:57

MCP Server工程结构实战:从模块化到基础设施的工业级设计

最近连续做了几个 MCP Server 的项目&#xff0c;从最早的“能跑就行”到后来被线上问题逼着重构&#xff0c;我最大的感受是&#xff1a;MCP Server 这个玩意儿&#xff0c;协议本身不复杂&#xff0c;真正决定项目成败的&#xff0c;是工程结构。说得直白一点&#xff0c;MCP…

作者头像 李华