☰
Envoy可观测性三件套落地指南:访问日志、指标监控与链路追踪
2026/10/7 4:07:38 网站建设 项目流程

上个月处理了一个线上事故,到现在印象还很深。入口网关集群的 5xx 突然上涨,CPU、内存、连接数看着都正常,但业务侧就是有请求打不通。更难受的是,网关的访问日志没配格式规范,指标只有机器层的CPU和内存,链路追踪压根没接,最后靠抓包手工看了一个下午才算定位。那次之后,我把 Envoy 的可观测性从“能跑就行”彻底重构成了“三件套齐全”,也就是日志、指标、链路追踪三件事同时落地。这篇内容就是那次重构的完整记录,从格式设计、采集方案、告警阈值到链路打通都有,适合正在做网关、服务网格或者 Sidecar 接入的运维和开发同学参考。

1. 先理清楚 Envoy 的可观测性到底在观测什么

很多人一上来就急着配 Prometheus、搞 Jaeger,结果发现告警不准、链路不全,最后变成一堆数据躺在那里没人看。问题的根源在于没有先想清楚每种数据回答什么问题,以及数据从哪来、在哪配置、能不能动态更新。

1.1 三种数据各回答什么问题

Envoy 的数据面会产出三种核心观测数据:访问日志、统计指标、分布式链路追踪。它们的定位分别对应三个问题:

  • 访问日志回答“某个具体请求发生了什么”。谁的请求、来了哪个域名、被路由到哪个集群、选中了哪台上游、返回什么状态码、耗时多少、有没有触发重试或熔断。关键时候它是最细颗粒度的证据。
  • 指标回答“整体趋势如何”。请求量、错误率、延迟分位数、活跃连接数、熔断器是否打开、健康检查是否在失败。它能告诉你系统正在变好还是变坏,是告警的主要数据源。
  • 链路追踪回答“请求的全链路视图”。从入口网关到内部服务的调用路径,每一跳的耗时分布,哪个环节最慢,哪些调用是失败的。它能把多个组件的日志串成一条线。

用生活化的类比:日志像每个航班的起降记录,指标像飞机仪表盘上的油量、高度、速度,链路追踪像一张完整航线图。做可观测性,就是要同时有记录、有仪表、有地图,缺一个都会在排障时抓瞎。

1.2 数据从哪产生、在哪个配置文件里控制

Envoy 的观测配置分散在三个位置,这里必须搞清楚,否则后面动配置的时候很容易触发重启事故。

第一是 bootstrap 静态配置,里面管的是stats_flush_interval、stats_config、stats_sinks,以及tracing的 provider 定义。这部分一旦启动后就不能通过 xDS 动态修改,改完必须重启实例。很多团队接链路追踪时没想清楚,上线后要换 zipkin 为 otel collector,结果发现要滚动重启整个网关,这就是配置规划没到位。

第二是 Listener 和 HttpConnectionManager(HCM)这一层,管理的是访问日志的开关和格式、请求 ID 的生成方式、采样率。这部分可以通过 LDS/RDS 动态下发,所以日志格式、采样策略可以在运行期调整,不需要重启,线上调整成本低很多。

第三是 Cluster 层,管理的是熔断、异常驱逐这些参数,它们本身不是观测配置,但会直接影响指标的含义,比如outlier_detection触发后的upstream_rq_5xx曲线会出现阶梯变化,在看指标时要能识别出来。

下面这张表是我自己整理的配置位置速查表,排查问题的时候能少走不少弯路。

观测能力配置位置是否可动态更新改动影响
访问日志开关与格式Listener / HCM是,通过LDS/RDS日志格式变化,采集端需要同步
指标 flush 间隔bootstrap stats_config否,需重启影响 Prometheus 抓取精度
指标 tag 拆分规则bootstrap stats_config否,需重启影响 label 维度
链路追踪 providerbootstrap tracing否,需重启影响全链路接入协议
链路采样率HCM tracing是,通过LDS影响成本与数据量

1.3 日志作用域这个概念先掰扯清楚

热词里有个“日志作用域”,在 Envoy 语境里其实有两条线索,很多人混在一起理解。

一条是 access log 的生效范围。访问日志可以在 HCM 上配置,代表对所有进入该监听器的请求生效;也可以在 VirtualHost 或 Route 级别覆盖,代表只对特定域名、特定路径生效。实际业务里常见做法是全局配置一份完整格式,然后对健康检查路径、静态资源路径单独加 filter 降噪。我见过有人为了排查某个接口,直接在 Route 里加了一条 debug 级别的详细日志,查完再移除,这种用法就是作用域的实际价值。

另一条是 Envoy 内部 error log 的日志级别。它通过--log-level启动参数控制,也可以在运行时通过 admin 接口的/logging动态调整。注意这条日志讲的是 Envoy 自身的运行情况,比如配置文件解析失败、上游连接异常、内部断言错误,和业务访问日志是两套完全独立的东西。热词里提到“日志面板”,通常就是指 admin 页面里的 logging 管理面板,可以按 logger 名称逐项调整级别,排查期间开到 debug,结束必须调回,不然磁盘会被内部日志打爆。

这两条作用域在排障时有一个连贯的使用逻辑:先看访问日志确认请求走到了哪里,再看内部日志确认 Envoy 处理的哪个环节出了问题,最后用链路数据串起来。顺序反了容易陷入“一直在看日志却不知道在看什么”的状态。

2. 访问日志落地:格式、采样与采集

访问日志是排障的第一现场。很多团队刚开始接入 Envoy 时根本不配 access log,或者用默认的 CLF 格式扔到 stdout,等人去 grep。这种做法在小流量下勉强能用,流量一起来就是灾难。这块的完整落地包括格式设计、采样策略、磁盘保护、采集链路四个部分。

2.1 日志格式设计:从 CLF 到 JSON

Envoy 默认不输出访问日志,要在 HCM 里显式配置。最简单的写法是用默认的 CLF 格式,但我不推荐任何人直接用默认格式,它适合人眼看,不适合机器解析,字段多了以后还会漏字段。我的习惯是从第一天就用 JSON 格式,每一个字段都是明确的 key,采集端解析、检索、告警都能直接复用。

下面是一个可用的 JSON access log 配置,放在 HCM 的http_filters前后都可以,字段按需要增删:

access_log: - name: envoy.access_loggers.file typed_config: "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog path: /var/log/envoy/access.log log_format: json_format: start_time: "%START_TIME%" req_method: "%REQ(:METHOD)%" req_path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%" req_host: "%REQ(:AUTHORITY)%" req_user_agent: "%REQ(USER-AGENT)%" upstream_host: "%UPSTREAM_HOST%" upstream_cluster: "%UPSTREAM_CLUSTER%" response_code: "%RESPONSE_CODE%" response_code_details: "%RESPONSE_CODE_DETAILS%" duration_ms: "%DURATION%" bytes_sent: "%RESPONSE_BYTES_SIZE%" bytes_received: "%REQUEST_BODY_BYTES%" trace_id: "%REQ(X-REQUEST-ID)%" route_name: "%ROUTE_NAME%" upstream_response_time: "%RESPONSE_DURATION%"

有两个字段我想特别强调。%UPSTREAM_HOST%一定要保留,线上 5xx 如果集中在一台上游,靠这个字段就能立刻锁定目标机器。%RESPONSE_CODE_DETAILS%是 Envoy 自己生成的状态码说明,比如via_upstream、upstream_reset_before_response_started、local_rate_limit,比裸看状态码有价值得多,能直接告诉你这个 4xx/5xx 到底是业务返回的还是网络层重置的。

格式定了以后,下一步就该考虑降噪。访问日志会记录所有请求,包括健康检查、探针、静态资源。我的建议是加一个过滤条件,只记录需要关心的请求。比如下面的配置只记录非健康检查且状态码不小于 400 的请求,配合采样参数使用效果更好:

access_log: - name: envoy.access_loggers.file typed_config: "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog path: /var/log/envoy/access.log log_format: json_format: response_code: "%RESPONSE_CODE%" req_path: "%REQ(:PATH)%" upstream_cluster: "%UPSTREAM_CLUSTER%" duration_ms: "%DURATION%" filter: status_code_filter: comparison: op: GE value: default_value: 400

2.2 采样与磁盘保护:日志是成本,不是越多越好

有人觉得日志越全越好,这个想法在 Envoy 这里要吃大亏。访问日志单条 JSON 大约 300 字节左右,如果是 1000 QPS 的入口网关,一天就是 300 × 1000 × 86400,约 25GB。这个量级在排障时基本没法直接 grep,在存储侧也是不小的成本。

所以我强烈建议给访问日志加采样。Envoy 的 access_log 支持sampled参数,写在 access_log 条目上,0.01 表示只记录 1% 的请求。实际操作中,我会按两个维度分策略:错误请求永远全量采样,正常请求按比例采样。比如先在全局配置sampled: 0.1,再用 status_code_filter 保证错误请求一定会被记录,因为 filter 是在采样之后进行过滤的,这个细节要自己测一下,不同版本行为有差异,我的经验是 v1.26+ 中采样后再过滤会出现“错误请求也被采样掉”的情况,所以更稳妥的做法是配置两条 access_log:一条全量但不落盘,一条采样后落盘。看起来浪费配置,但换来的是错误请求一条不漏。

磁盘保护是另一个容易忽略的点。Envoy 的 file access logger 本身不负责日志轮转,需要靠外部 logrotate 或容器化平台的日志轮转机制处理。我在生产环境用的是独立路径/var/log/envoy/配合 logrotate,按天切割、保留 7 天。这里要提醒一句,不要把 access.log 直接写到根分区或和系统日志混在一起,日志膨胀会把整个磁盘打满,最后连 ssh 都登不上去。

2.3 Filebeat 采集与解析:过滤、状态与常见坑

日志写进了文件,下一步就是采集。我没有用 Envoy 自带的 gRPC access log service(ALS)直接推到 Kafka,主要原因是团队已经有一套基于 Elasticsearch 的日志平台,Filebeat 是最成熟稳定的一条链路,不需要额外改 Envoy 配置。

Filebeat 采集配置的核心是filestream输入,注意 8.x 已经不建议用老的log输入了,filestream 对文件轮转和位置跟踪做得更好。一个可用的配置:

filebeat.inputs: - type: filestream id: envoy-access-log paths: - /var/log/envoy/access.log parsers: - ndjson: target: "" add_error_key: true message_key: req_path fields: log_source: envoy_access fields_under_root: true output.elasticsearch: hosts: ["es01:9200"] index: "envoy-access-%{+yyyy.MM.dd}"

用ndjsonparser 可以自动把 JSON 每一行拆开成独立字段,fields_under_root把自定义的log_source提升到根级,方便后续按来源过滤。这里有一个很容易翻车的点:Filebeat 解析失败时默认会丢弃有问题的行,配置add_error_key: true可以保留错误标记,排查格式变更时能很快看出来。

Filebeat 的 offset 状态也是一个常见的坑。它把已读位置存在data/registry/filebeat/log.json里,如果容器被重建但状态目录没持久化,Filebeat 会从文件头重新读取,导致日志重复入库。反过来,如果文件被轮转但状态没跟上,也可能漏日志。我在 K8s 里会把 Filebeat 的 data 目录做成 emptyDir 以外的持久化卷,避免频繁重复。

2.4 内部日志的运维:admin 接口和级别控制

Envoy 自身的错误日志和访问日志一定要区分看待。内部日志通过--log-level info控制,运行期可以在 admin 接口上用POST /logging?level=debug调整。admin 接口默认监听 9901 端口,我在生成环境会把它绑定到内网地址,加一层访问控制,绝不直接暴露公网。

在生产排查时,内部日志级别通常保持 info 就够了。只有在定位配置热更新问题、上游连接异常这类场景下,才临时调到 debug。调完之后记得切回来,否则可能一个小时产生几百 MB 的 debug 日志。热词里有“日志分析”,落到 Envoy 场景,最实用的习惯是定期看一眼/logging面板下有没有 error 级别的持续输出,这些往往预示着配置错误或连接池异常,比业务指标更能提前暴露隐患。

3. 指标监控与告警阈值:从 stats 到 Prometheus

日志解决了个案,指标解决趋势。Envoy 自带的 stats 体系非常成熟,但第一次接触的人会被它的字段数量吓到。一个什么都没做的网关,光/stats输出的指标就有几千行。这些指标不是都要盯,关键是理解模型、会接、会定阈值。

3.1 stats 模型先过一遍

Envoy 的 stats 有三种基础类型:Counter 是单调递增计数,适合统计总请求量、总错误量;Gauge 是可变数值,适合统计当前活跃连接数;Histogram 是分位数统计,适合统计延迟。Prometheus 接入后,Counter 会变成_total,Histogram 会展开成多个_bucket和_sum、_count。

指标命名一般以cluster.、listener.、http.开头。比如cluster.ratings.upstream_rq_5xx是 ratings 集群的 5xx 响应数,listener.ingress_http.downstream_cx_active是入口监听器当前的活跃连接数。我这里提醒一个必改的配置:stats_config里要打开use_all_listener_tags,否则多个 listener 的指标会被合并,端口标签会丢失,排障时根本分不清是哪个入口在报错。

还有一个参数是stats_flush_interval,默认 5 秒。Prometheus 抓取时,如果抓取间隔大于 flush 间隔,会漏掉一部分中间峰值。我的经验是把stats_flush_interval设为 5s,Prometheusscrape_interval也设为 5s,两者匹配,否则会出现明明 QPS 在涨但曲线是平的这种怪象。

3.2 Prometheus 接入方式:两种路径都讲

Prometheus 接入 Envoy 有两种主流方式。第一种是用 admin 端点/stats/prometheus,Prometheus 直接抓取。这种最简单,但要小心 admin 端口的暴露风险。第二种是新建一个内部 listener 专门暴露 metrics。我在生产上更推荐第二种,虽然配置多几行,但可以把抓取链路和 admin 管理面分离。

一个精简的内部 listener 方式:

static_resources: listeners: - name: envoy_metrics_listener address: socket_address: address: 0.0.0.0 port_value: 9901 filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: metrics route_config: name: local_route virtual_hosts: - name: admin domains: ["*"] routes: - match: prefix: "/stats/prometheus" route: cluster: prometheus_stats http_filters: - name: envoy.filters.http.router clusters: - name: prometheus_stats connect_timeout: 0.25s type: static load_assignment: cluster_name: prometheus_stats endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 127.0.0.1 port_value: 9901

Prometheus 侧的抓取配置:

scrape_configs: - job_name: envoy metrics_path: /stats/prometheus scrape_interval: 5s static_configs: - targets: ["envoy-metrics:9901"] labels: component: ingress-gateway

注意这里的静态集群其实还是把请求转发到 admin 的/stats/prometheus,但通过独立的 listener 收口后,就不需要把 admin 端口暴露给 Prometheus 了,网络策略也可以收敛到一条。

3.3 必盯指标与阈值经验值

指标不是全采就完事,关键是要给核心指标定告警阈值。我自己整理了一套最小清单,按优先级分三档。

第一档是业务健康类,直接决定是否被 pager:

指标含义经验阈值
cluster.*.upstream_rq_5xx / cluster.*.upstream_rq_total5xx 错误率连续 5 分钟 > 1% 告警,> 5% 高优
cluster.*.upstream_rq_timeP99上游服务延迟分位数按业务基线,超过基线 P99 的 2 倍告警
cluster.*.upstream_rq_retry / cluster.*.upstream_rq_total重试率重试率 > 10% 且持续 5 分钟告警
cluster.*.upstream_cx_active活跃连接数增长速率 > 基线 2 倍告警
listener.*.downstream_cx_active入口活跃连接数增长速率异常告警

第二档是容量饱和类,不直接报错,但预示着即将出问题:

指标含义经验阈值
cluster.*.upstream_cx_overflow连接池溢出次数出现即关注,配合熔断器检查
cluster.*.lb_healthy_panic进入 panic 模式出现即高优告警
cluster.*.circuit_breakers.*.remaining熔断器剩余容量低于 20% 告警
cluster.*.health_check.*.failure健康检查失败数持续失败告警

第三档是资源类,一般是机器或容器层监控,但 Envoy 自身的server.*指标也要带一个:

  • server.live是否在存活
  • server.uptime是否被频繁重启

阈值不能光用固定值。我在实践中感受最深的是,固定阈值在小流量集群上极度不友好,流量低时任何波动都是成倍的。所以我的方案是告警表达式里尽量用“比值+基线”的组合,比如:

sum(rate(envoy_cluster_upstream_rq_5xx[5m])) / sum(rate(envoy_cluster_upstream_rq_total[5m])) > 0.01

延迟 P99 的表达式:

histogram_quantile(0.99, sum(rate(envoy_cluster_upstream_rq_time_bucket[5m])) by (le) ) > 0.5

这里的0.5秒是示例值,真实要根据业务接口压测结果来定。而且要注意,不同接口的延迟差异很大,聚合到一个表达式里会导致误报,生产上建议按 Route 或 Cluster 拆分。

3.4 指标口径与告警风暴:几个容易翻车的地方

告警规则写完,不代表就能躺平。我踩过几个比较深的坑,每次都是线上告警风暴后总结出来的。

第一个坑是 label 变化导致告警断裂。Envoy 集群重命名后,所有以cluster.<名字>开头的指标 label 都会变化,旧的告警规则会因为找不到指标而变成无数据。所以集群命名规范必须提前定死,比如业务线-服务-环境,上线后禁止改名。

第二个坑是 histogram 桶的精度。Prometheus 的histogram_quantile是基于 bucket 估算的,如果 Envoy 上报的 bucket 边界不适合你的业务延迟范围,P99 会严重失真。比如业务延迟大部分在 20ms 左右,但 bucket 在 100ms 以下只有一个点,算出来的 P99 可能直接跳到 100ms。需要根据业务延迟分布调整 bucket 边界。

第三个坑是告警太多等于没有告警。刚配完的那一周,我收到了上百条告警通知,全是各种细碎指标的抖动。后来把所有观察类告警全部降级成 warning,只有 pager 级别的保留,错误率、可用性、容量三类。这样处理之后,告警反而被重视了。

4. 链路追踪:把请求串起来看

日志和指标能定位“哪里出了问题”,但回答不了“为什么慢”。链路追踪的作用是把一次请求经过的每个组件串起来,看清每一跳的耗时和状态。Envoy 是数据面的第一跳,也是最后一跳,它在链路追踪里的角色很特殊。

4.1 Envoy 在 trace 里的角色是什么

很多人以为接入了 Envoy 就自动有了应用全链路追踪,这是个误解。Envoy 本身不做业务埋点,它做的是三件事:生成或透传 trace 上下文、生成入口的 server span 和上游调用的 client span、在 span 上记录结果信息。应用服务如果没接 SDK,链路到服务内部就会断掉,Envoy 只能看到“请求到了我这,转给了某台机器,花了多少毫秒”,看不到业务代码内部的调用过程。

所以落地链路追踪的时候,要跟应用团队约定:入口网关由 Envoy 负责打 span,下游服务接入 zipkin/otel 的 SDK 并透传 trace header。没有这个约定,后期排查链路断裂会非常痛。我见过最典型的场景是运维把 Envoy 的 trace 配好后,开发反馈说“链路还是断的”,最后查下来是应用框架把 b3 header 给过滤掉了。

4.2 tracing provider 配置示例与采样策略

Envoy 的 tracing provider 是在 bootstrap 里静态配置的,这点和日志、指标都不同,改 provider 必须重启实例。我用的是 zipkin 协议对接 Jaeger,配置如下,注意不同小版本字段名会有差别,这是 1.26 左右的写法:

tracing: http: name: envoy.tracers.zipkin typed_config: "@type": type.googleapis.com/envoy.config.trace.v3.ZipkinConfig collector_cluster: zipkin collector_endpoint: /api/v2/spans collector_endpoint_version: HTTP_JSON shared_span_context: false

在 HCM 里还要加采样率。注意 HCM 的 tracing 配置是可以动态更新的,所以采样率可以随时调整:

tracing: random_sampling: percent: 1

采样率怎么定,要看成本和需求的平衡。全链路 100% 采样带来的存储成本可能比日志还高,尤其 QPS 大的网关。我的经验是入口 1% 采样就足够保障可用性类排查了,如果某次线上事故需要针对特定用户、特定接口抓取全量链路,可以临时调到 100%,排查完再调回去。这里有一个体系设计的概念,就是头部采样和尾部采样:Envoy 只能做头部采样,也就是在请求入口就决定采不采样;真正理想的方案是配合链路后端做尾部采样,先全量接收再按需保留异常链路,但成本会高一个量级。小团队不必一上来就上尾部采样。

4.3 用 trace_id 把日志、指标、链路串成一个闭环

链路追踪最大的价值不是看那张拓扑图,而是让日志可以围绕一次请求组织起来。

Envoy 会为每个请求生成x-request-id,配置 zipkin 后还会生成 traceId。我在访问日志里专门留了trace_id字段,取的是%REQ(X-REQUEST-ID)%。这样整个排障路径就是闭环的:

  1. 先从 Prometheus 上看到某条路由的 5xx 上涨。
  2. 进 Jaeger 按 service 和时间段找到异常 trace。
  3. 拿到 traceId 后,去 ES 里搜访问日志,看到 Envoy 记录的response_code、upstream_host、duration_ms。
  4. 如果请求走到了下游,拿同一个 traceId 去下游服务的日志平台查应用日志。

这个闭环做好之后,排障时间可以从小时级降到分钟级。实际落地时有个小技巧:Elasticsearch 里给trace_id字段建 keyword 索引,否则精确搜索会退化成全文本搜索,慢得没法用。

还有一个经验是,日志里不光记 traceId,最好把upstream_host也记下来。因为 Envoy 会重试请求到不同的上游,单看一份日志可能看不出哪台机器有问题,但结合 trace 就可以确认某次重试是不是打到了同一条不健康的链路上。

4.4 常见链路断链原因:先查这几个地方

链路断链是接入后最普遍的问题,我整理了一个排查顺序,照着检查基本能覆盖 80% 的场景。

第一查协议头。Envoy 用的 zipkin 传播头是 b3,全称x-b3-traceid、x-b3-spanid、x-b3-parentspanid、x-b3-sampled。应用 SDK 是否读取和透传了这些头,是链路能不能连续的第一前提。有的框架默认会清洗未知 header,需要显式放行。

第二查采样一致性。如果入口 Envoy 采样率是 1%,但下游服务自己的采样率是 100%,就会出现 traceId 一样的 span 只有一部分的情况。反过来入口采了但下游没采,链路也会断。最好全局统一一套采样配置,或者用服务端尾部采样。

第三查 span 的 parentId。进入 Jaeger 后,如果一个 trace 里有多个根 span,说明客户端和服务端没有共享上下文,通常是因为shared_span_context配置不一致,或者应用端自己起了新的 root span。我在配置 Envoy 时用shared_span_context: false,是为了避免冲突,但这个字段要结合下游 SDK 行为一起确定。

第四查版本兼容。zipkin v1 和 v2 的 span 格式有差异,Jaeger 的默认端口虽然是 9411,但不同版本支持的 endpoint 不同。如果配置里写的是/api/v1/spans而 Jaeger 只收 v2,链路会显示“服务在线但无数据”。

5. 实战中那些绕不开的坑

三段数据体系都落地之后,还有一堆运维层面的坑,单独拿出来分享。这些坑不是文档里会告诉你的,但几乎每个团队都会踩。

5.1 日志没写出来的排查路径

环境配好发现日志文件永远是空的,首先检查 HCM 里有没有真的挂上 access_log。很多人是在旧版本配置里写的access_log_path,升级到 v3 API 后这个字段已经废弃,配置直接静默失效。

其次检查文件路径的权限。Envoy 进程在容器里通常以非 root 用户运行,如果挂载的日志目录权限是 755 而目录属主是 root,会写失败。我的做法是在镜像里预先创建/var/log/envoy并chown给 envoy 用户,或者直接写到 stdout 由容器运行时接管。

第三个原因是 filter 过滤太狠。我见过有人把status_code_filter配成了只记录 500,结果排查 400 问题时日志里什么都没有。回答“为什么没日志”之前,先问自己在 filter 里写了什么。

5.2 指标为空的排查方法

/stats/prometheus能打开,但 Prometheus 里看到up是 1,target 却拿不到数据,这类问题通常和 flush 间隔、tag 配置有关。如果指标页面能打开但只有envoy_server_*少数几个指标,大概率是 admin 端口权限或路径重定向的问题。

还有一个容易被忽略的点:cluster_name里带有特殊字符时,Envoy 生成的 metrics name 会出现转义,比如.变成_。如果 Prometheus 规则里写的是原始 cluster 名,会匹配不上。解决方法是先在/stats/prometheus页面上搜一下实际的 metrics 名字,再写规则。

5.3 日志重复、乱序、延迟

Filebeat 重复读日志,我刚才提到了 registry 状态的持久化问题。还有一个更隐蔽的场景:logrotate 把旧文件改名后,Filebeat 的 filestream 输入如果没有正确处理close_inactive和ignore_older,会在文件轮转瞬间产生重复读取或丢失。我在轮转配置里会保证create 0644 envoy envoy,让 Filebeat 对 old 文件和新文件都有明确的 inode 跟踪。

日志乱序则要区分接收端还是发送端的问题。Envoy 写文件是有序的,但 Filebeat 多线程输出到 ES 时可能出现乱序。如果需要严格排序,单条日志里一定要带%START_TIME%时间字段,ES 侧用时间字段排序,而不是依赖摄入时间。

5.4 一个速查表备查

把上面这些经验汇总成一张速查表,贴在团队 wiki 里很有用:

现象可能原因排查动作
access.log 为空HCM 未配置 access_log 或配置了旧字段检查配置中的access_log是否存在
access.log 写入失败目录权限不足ls -l /var/log/envoy,调整属主
Filebeat 重复入库registry 状态丢失检查 Filebeat data 目录持久化
Prometheus 指标缺失cluster 名特殊字符或 tag 未拆分在 /stats/prometheus 里搜实际名称
告警无数据label 变化导致旧规则失效确认 cluster 名称和 namespace 标签
链路全断应用未透传 b3 header检查应用框架的 header 白名单
链路部分断采样率不一致或 span 根节点多个统一采样率,检查 shared_span_context
traceId 和日志对不上日志里取错了 header 字段确认%REQ(X-REQUEST-ID)%与 trace 工具的实际值

这套速查表是当时踩坑后整理的,现在每次 Envoy 升级或者团队新增成员,都会先过一遍这些场景。可观测性的价值不在配置本身,而在于这些配置能不能在你需要的时候,最快地把真相带到你面前。

我自己最大的体会是:可观测性不是一次性工程,而是一个持续演进的基础设施。先保证日志和指标可用,再逐步把链路、告警、采样策略调优;不要试图第一天就做到完美,那是永远等不到的。先从一份规范的 JSON 访问日志、一套能响的告警开始,剩下的坑,等踩到了再填。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询