关于istio:Envoy-Istio-性能指标与原理初探

28次阅读

共计 21153 个字符,预计需要花费 53 分钟才能阅读完成。

💂 对于封面:
置信很多人听过《London Bridge Is Falling Down》这个儿歌,有人也晓得这个是英国传统的儿童游戏歌曲。但很多人和我一样,认为 “London Bridge” 就是封面中的塔桥。直到明天,我才晓得,”London Bridge” 并不是 “Tower Bridge”。所以,封面不是 “London Bridge”。无论喜爱与否,一个时代的符号走到了起点,愿安定。

📚 摘录阐明:
本文摘自一本我在写作中的开源书《Istio & Envoy 底细》中 Istio 与 Envoy 指标 一节。如果说你看到的转载图片不清,可回到原书。

  • Istio 与 Envoy 指标概述
  • Envoy 指标

    • Envoy 指标概述

      • Tag
      • 指标数据类型
    • 指标释义

      • cluster manager
      • http connection manager(HCM)
      • listeners
      • server
      • watch dog
      • Event loop
    • 配置阐明

      • config.bootstrap.v3.Bootstrap
      • config.metrics.v3.StatsConfig
      • config.metrics.v3.StatsMatcher
  • Istio 指标

    • Istio 本人的 Metrics

      • 规范指标阐明

        • Metrics
        • Prometheus 的 Labels
      • 应用

        • istio-proxy 与利用的 Metrics 整合输入
        • 定制:为 Metrics 减少维度
        • 定制:退出 request / response 元信息维度
      • 工作原理

        • istio stat filter 应用
        • istio stat Plugin 实现
    • Envoy 内置的 Metrics

      • 定制 Envoy 内置的 Metrics
      • 原理
    • 总结:Istio-Proxy 指标地图

Istio 与 Envoy 指标概述

指标监控,可能是 DevOps 监控最重要的一环。但同时也可能是最难的一环。你能够从网上找到各种零碎和中间件的 Grafana 监控仪表盘,它们大都设计得很漂亮得体,让人感觉监控曾经白璧无瑕。

然而,不晓得你是否与我有同样的经验:在零碎遇到问题时,手头有一大堆指标和监控仪表盘。

  • 却不晓得哪个指标才是问题相干的。
  • 或者是,问题曾经有个方向定位,却发现这个方向上,基本没有记录指标。

事件究竟是要人来解决,再多的数据,如果:

  • 不去了解这些数据背地的意义
  • 不去被动剖析本人的利用场景和部署环境须要什么数据,只是零碎默认给什么就用什么

那么指标越多,越让人迷失在茫茫指标的陆地中。

作为一个混后端江湖多年的老程(老程序员),总有很多货色不懂,却难以启齿的。其中一个就是一些具体指标的意义。举个两个例子:

  1. 我之前定位一个 Linux 下的网络问题,用了一个叫 nstat 的工具,它输入了十分多的指标,但很多会发现,有些指标是死活找不到阐明文档的。这也是开源软件始终以来的问题,变动快,文档跟不上,甚至谬误或过期未更新。
  2. 我之前定位一个 Linux 下的 TCP 连贯问题,用了一个叫 ss 的工具,它输入的神指标,也是搜索引擎也无能为力去解释。最初不得不看原码。还好,我把调查结果记录到 Blog 中:《可能是最残缺的 TCP 连贯衰弱指标工具 ss 的阐明》,心愿对起初人有一些参考作用吧。

故事说完了,回到本书的配角 Istio 与 Envoy 上。它们的指标阐明文档比下面的老爷车开源软件好一些。起码根本每个指标都有一行文字说明,尽管文字一样十分短且含糊。

Istio 的 istio-proxy 的数据面指标是 基于 Envoy 的指标构架实现的。所以,前面我将先说 Envoy 的指标架构。

如果你和我一样,是个急性子。那么下图就是 Istio & Envoy 的指标地图了。它阐明了指标产生在什么中央。前面内容会一步步推导出这个地图。

图:Envoy@Istio 的指标。用 Draw.io 关上

Envoy 指标

Envoy 指标概述

Envoy 的次要指标之一是使网络易于了解。Envoy 会依据其配置形式产生大量统计信息。一般来说,统计数据 (指标) 分为三类:

  • Downstream:Downstream 指标与外来的连贯 / 申请无关。它们由 listenerHTTP connection manager(HCM)TCP proxy filter 等产生。
  • Upstream:Upstream 指标与内向的连贯 / 申请无关。它们由 connection poolrouter filtertcp proxy filter等产生。
  • ServerServer 指标信息形容 Envoy 服务器实例的运作状况。服务器失常运行工夫或调配的内存量等统计信息。

在最简略场景下,单个 Envoy Proxy 通常波及 DownstreamUpstream 统计数据。这两种指标反映了取该 网络节点 的运行状况。来自整个网格的统计数据提供了每个 网络节点 和整体网络健康状况的十分具体的汇总信息。Envoy 的文档对这些指标有一些简略的阐明。

Tag

Envoy 的指标还有两个子概念,反对在指标中应用:标签 (tags)/ 维度(dimensions)。这里的 tags 对等于 Prometheus 指标的 label。意义上,能够了解为:分类维度。

Envoy 的 指标 由标准的字符串来标识。这些字符串的动静局部(子字符串)被提取成为 标签(tag)。能够通过指定 tag 提取规定(Tag Specifier configuration.) 来定制 tag。

举个例子:

### 1. 原始的 Envoy 指标 ###

$ kubectl exec fortio-server -c istio-proxy -- curl 'localhost:15000/stats'

# 返回:cluster.outbound|8080||fortio-server-l2.mark.svc.cluster.local.external.upstream_rq_2xx: 300

# 其中:# - `outbound|8080||fortio-server-l2.mark.svc.cluster.local` 局部是 upstream cluster 的名字。能够正则提取作为 tag。# - `2xx` 局部是 HTTP Status Code 的分类。能够正则提取作为 tag。下文将有这个提取规定的配置阐明。### 2. 给 Prometheus 的指标 ###
$ kubectl exec fortio-server -c istio-proxy -- curl 'localhost:15000/stats?format=prometheus' | grep 'outbound|8080||fortio-server-l2' | grep 'external.upstream_rq'

# 返回:envoy_cluster_external_upstream_rq{response_code_class="2xx",cluster_name="outbound|8080||fortio-server-l2.mark.svc.cluster.local"} 300

指标数据类型

Envoy 收回三种类型的值作为统计信息:

  • 计数器(Counters):无符号整数,只会减少而不会缩小。例如,总申请。
  • 仪表(Gauges):减少和缩小的无符号整数。例如,以后流动的申请。
  • 直方图(Histograms):作为指标流的一部分的无符号整数,而后由收集器聚合以最终产生汇总的百分位值(percentile,即平时说的 P99/P50/Pxx)。例如,Upsteam 响应工夫。

在 Envoy 的外部实现中,Counters 和 Gauges 被分批并定期刷新以进步性能。Histograms 在接管时写入。

指标释义

从指标的产出地点来划分,能够分为:

  • cluster manager : 面向 upstream 的 L3/L4/L7 层指标
  • http connection manager(HCM):面向 upstream & downstream 的 L7 层指标
  • listeners : 面向 downstream 的 L3/L4 层指标
  • server(全局)
  • watch dog

上面我只抉择了局部要害的性能指标来简略阐明。

cluster manager

Envoy 文档:cluster manager stats

下面文档曾经说得比拟具体了。我只补充一些在性能调优时须要关注的方面。那么,个别须要关注什么指标?

咱们从驰名的 Utilization Saturation and Errors (USE) 方法学来剖析。

利用率(Utilization):

  • upstream_cx_total (Counter): 连接数
  • upstream_rq_active

饱和度(Saturation):

  • upstream_rq_time (Histogram): 响应工夫
  • upstream_cx_connect_ms (Histogram)
  • upstream_cx_rx_bytes_buffered
  • upstream_cx_tx_bytes_buffered
  • upstream_rq_pending_total
  • upstream_rq_pending_active (Gauge)

谬误(Error):

  • upstream_cx_connect_fail (Counter): 连贯失败数
  • upstream_cx_connect_timeout (Counter): 连贯超时数
  • upstream_cx_overflow (Counter): 集群连贯断路器溢出的总次数
  • upstream_cx_pool_overflow
  • upstream_cx_destroy_local_with_active_rq
  • upstream_cx_destroy_remote_with_active_rq
  • upstream_rq_timeout
  • upstream_rq_retry
  • upstream_rq_rx_reset
  • upstream_rq_tx_reset

其它:

  • upstream_rq_total (Counter): TPS (吞吐)
  • upstream_cx_destroy_local (Counter): Envoy 被动断开的连贯计数
  • upstream_cx_destroy_remote (Counter): Envoy 被动断开的连贯计数
  • upstream_cx_length_ms (Histogram)

http connection manager(HCM)

Envoy 文档:http connection manager(HCM) stats

能够认为,这是面向 downstream & 局部 upstream 的 L7 层指标

利用率(Utilization):

  • downstream_cx_total
  • downstream_cx_active
  • downstream_cx_http1_active
  • downstream_rq_total
  • downstream_rq_http1_total
  • downstream_rq_active

饱和度(Saturation):

  • downstream_cx_rx_bytes_buffered
  • downstream_cx_tx_bytes_buffered
  • downstream_flow_control_paused_reading_total
  • downstream_flow_control_resumed_reading_total

谬误(Error):

  • downstream_cx_destroy_local_active_rq
  • downstream_cx_destroy_remote_active_rq
  • downstream_rq_rx_reset
  • downstream_rq_tx_reset
  • downstream_rq_too_large
  • downstream_rq_max_duration_reached
  • downstream_rq_timeout
  • downstream_rq_overload_close
  • rs_too_large

其它:

  • downstream_cx_destroy_remote
  • downstream_cx_destroy_local
  • downstream_cx_length_ms

listeners

Envoy 文档:listener stats

能够认为,这是 downstream 的 L3/L4 层的指标。

利用率(Utilization):

  • downstream_cx_total
  • downstream_cx_active

饱和度(Saturation):

  • downstream_pre_cx_active

谬误(Error):

  • downstream_cx_transport_socket_connect_timeout
  • downstream_cx_overflow
  • no_filter_chain_match
  • downstream_listener_filter_error
  • no_certificate

其它:

  • downstream_cx_length_ms

server

Envoy 根底信息指标

Envoy 文档:server stats

利用率(Utilization):

  • concurrency

谬误(Error):

  • days_until_first_cert_expiring

watch dog

Envoy 文档: Watchdog

Envoy 还包含一个可配置的看门狗零碎,它能够在 Envoy 没有响应时减少统计数据并选择性地终止服务器。零碎有两个独立的看门狗配置,一个用于主线程,一个用于工作线程;因为不同的线程有不同的工作负载。这些统计数据有助于从高层次上了解 Envoy 的事件循环是否因为它正在做太多工作、阻塞或没有被操作系统调度而没有响应。

饱和度(Saturation):

  • watchdog_mega_miss(Counter): mega 未命中数
  • watchdog_miss(Counter): 未命中数

如果你对 watchdog 机制的趣味,能够参考:

https://github.com/envoyproxy…
https://github.com/envoyproxy…

#### Event loop
Envoy 文档: Event loop

Envoy 架构旨在通过在大量线程上运行事件循环来优化可扩展性和资源利用率。“main” 线程负责管制面解决,每个 “worker” 线程分担数据面的一部分工作。Envoy 公开了两个统计信息来监控所有这些线程事件循环的性能。

跑一轮循环的耗时:事件循环的每次迭代都会执行一些工作。工作数量会随着负载的变动而变动。然而,如果一个或多个线程具备异样长尾循环执行耗时,则可能存在性能问题。例如,负责可能在工作线程之间调配不均,或者插件中可能存在长时间阻塞操作妨碍了工作进度。

轮询提早:在事件循环的每次迭代中,事件调度程序都会轮询 I/O 事件,并在某些 I/O 事件就绪 或 产生 超时 时“唤醒”线程,以先产生者为准。在 超时 的状况下,咱们能够测量轮询后预期唤醒工夫与理论唤醒工夫的差值;这种差别称为“ 轮询提早 ”。看到一些小的 轮询提早 是失常的,通常等于内核调度程序的“工夫片(time slice”)”或“量子(quantum)”——这取决于运行 Envoy 的操作系统 —— 但如果这个数字大大高于其失常察看到的基线,它示意内核调度程序可能产生提早。

能够通过将 enable_dispatcher_stats 设置为 true 来启用这些统计信息。

  • main 线程的事件调度器有一个以 server.dispatcher. 为根的统计树。
  • 每个 worker 线程的事件调度器都有一个以 listener_manager.worker_<id>.dispatcher. 为根的统计树。

每棵树都有以下统计信息:

Name Type Description
loop_duration_us Histogram 以微秒为单位的事件循环持续时间
poll_delay_us Histogram 以微秒为单位的轮询提早

请留神,此处不包含任何辅助 (非 main 与 worker) 线程。

Watch Dog 和 Event loop 都是解决与监控事件处理提早与时效的工具,这里有很多细节和故事,甚至能够说到 Linux Kernel。心愿本书前面有工夫,能够和大家一起学习和剖析这些乏味的细节。

配置阐明

如果你认真看过本书的前言中的 {ref}`index: 本书不是什么 `,说好的不是“使用手册”,为何又讲起配置来了?好吧,我只能说,从理解应用办法动手,再学实现,比间接一来就源码的办法更好让人类入门。本节参考:[Envoy 文档](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/metrics/v3/stats.proto)

config.bootstrap.v3.Bootstrap

Envoy 文档:config.bootstrap.v3.Bootstrap proto

{"node": {...},
  "static_resources": {...},
  "dynamic_resources": {...},
  "cluster_manager": {...},
  "stats_sinks": [],
  "stats_config": {...},
  "stats_flush_interval": {...},
  "stats_flush_on_admin": ...,
...
}
什么是 `stats sink`?本书不作阐明。Istio 默认没定制相干配置。以下只说关注的局部配置。
  • stats\_config
    (config.metrics.v3.StatsConfig) 用于外部解决统计信息的配置。
  • stats\_flush\_interval
    (Duration) 刷新 stats sink 的工夫距离。。出于性能起因,Envoy 不会实时刷新 counter,仅定期刷新 counter 和 gauge。如果未指定,则默认值为 5000 毫秒。stats_flush_intervalstats_flush_on_admin 只能设置之一。Duration 必须至多为 1 毫秒,最多为 5 分钟。
  • stats\_flush\_on\_admin
    (bool) 仅当在 治理界面(admin interface) 上查问时才将统计信息刷新到 sink。如果设置,则不会创立刷新计时器。只能设置 stats_flush_on_adminstats_flush_interval 之一。

config.metrics.v3.StatsConfig

Envoy 文档:config-metrics-v3-statsconfig

{"stats_tags": [],
  "use_all_default_tags": {...},
  "stats_matcher": {...},
  "histogram_bucket_settings": []}
  • stats_tags – 维度提取规定 (对应 Prometheus 的 label 提取)
    ( 多个 config.metrics.v3.TagSpecifier ) 每个 指标名称字符串 都通过这些标签规定独立解决。当一个标签匹配时,第一个捕捉组不会立刻从名称中删除,所以前面的 TagSpecifiers 也能够反复匹配同一部分。在实现所有标签匹配后,再剪裁 指标名称字符串 的匹配局部,并作为 stats sink 的指标名,例如 Prometheus 的指标名。
  • use_all_default_tags
    (BoolValue) 应用 Envoy 中指定的所有默认标签正则表达式。这些能够与 stats_tags 中指定的自定义标签联合应用。它们将在自定义标签之前进行解决。Istio 默认为 false.
  • stats_matcher
    (config.metrics.v3.StatsMatcher) 指定 Envoy 要产出哪些指标。反对 蕴含 / 排除 规定指定。如果未提供,则所有指标都将产出。阻止某些指标集的统计能够进步一点 Envoy 运行性能。

config.metrics.v3.StatsMatcher

Envoy 文档:config-metrics-v3-statsmatcher

用于禁用 / 开启统计指标计算与产出的配置。

{
  "reject_all": ...,
  "exclusion_list": {...},
  "inclusion_list": {...}
}
  • reject_all
    (bool) 如果 reject_all 为 true,则禁用所有统计信息。如果 reject_all 为 false,则启用所有统计信息。
  • exclusion_list
    (type.matcher.v3.ListStringMatcher) 排除列表
  • inclusion_list
    (type.matcher.v3.ListStringMatcher) 蕴含列表
本节参考了:https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/observability/statistics

下一节,将以 Istio 如何应用下面的配置为例,举例说明。

Istio 指标

Istio 本人的 Metrics

规范指标阐明

参考:https://istio.io/latest/docs/…

Metrics

对于 HTTP、HTTP/2 和 GRPC 流量,Istio 默认生成以下指标:

  • Request Count (istio_requests_total): This is a COUNTER incremented for every request handled by an Istio proxy.
  • Request Duration (istio_request_duration_milliseconds): This is a DISTRIBUTION which measures the duration of requests.
  • Request Size (istio_request_bytes): This is a DISTRIBUTION which measures HTTP request body sizes.
  • Response Size (istio_response_bytes): This is a DISTRIBUTION which measures HTTP response body sizes.
  • gRPC Request Message Count (istio_request_messages_total): This is a COUNTER incremented for every gRPC message sent from a client.
  • gRPC Response Message Count (istio_response_messages_total): This is a COUNTER incremented for every gRPC message sent from a server.

对于 TCP 流量,Istio 生成以下指标:

  • Tcp Bytes Sent (istio_tcp_sent_bytes_total): This is a COUNTER which measures the size of total bytes sent during response in case of a TCP connection.
  • Tcp Bytes Received (istio_tcp_received_bytes_total): This is a COUNTER which measures the size of total bytes received during request in case of a TCP connection.
  • Tcp Connections Opened (istio_tcp_connections_opened_total): This is a COUNTER incremented for every opened connection.
  • Tcp Connections Closed (istio_tcp_connections_closed_total): This is a COUNTER incremented for every closed connection.
Prometheus 的 Labels
  • Reporter: This identifies the reporter of the request. It is set to destination if report is from a server Istio proxy and source if report is from a client Istio proxy or a gateway.
  • Source Workload: This identifies the name of source workload which controls the source, or“unknown”if the source information is missing.
  • Source Workload Namespace: This identifies the namespace of the source workload, or“unknown”if the source information is missing.
  • Source Principal: This identifies the peer principal of the traffic source. It is set when peer authentication is used.
  • Source App: This identifies the source application based on app label of the source workload, or“unknown”if the source information is missing.
  • Source Version: This identifies the version of the source workload, or“unknown”if the source information is missing.
  • Destination Workload: This identifies the name of destination workload, or“unknown”if the destination information is missing.
  • Destination Workload Namespace: This identifies the namespace of the destination workload, or“unknown”if the destination information is missing.
  • Destination Principal: This identifies the peer principal of the traffic destination. It is set when peer authentication is used.
  • Destination App: This identifies the destination application based on app label of the destination workload, or“unknown”if the destination information is missing.
  • Destination Version: This identifies the version of the destination workload, or“unknown”if the destination information is missing.
  • Destination Service: This identifies destination service host responsible for an incoming request. Ex: details.default.svc.cluster.local.
  • Destination Service Name: This identifies the destination service name. Ex:“details”.
  • Destination Service Namespace: This identifies the namespace of destination service.
  • Request Protocol: This identifies the protocol of the request. It is set to request or connection protocol.
  • Response Code: This identifies the response code of the request. This label is present only on HTTP metrics.
  • Connection Security Policy: This identifies the service authentication policy of the request. It is set to mutual_tls when Istio is used to make communication secure and report is from destination. It is set to unknown when report is from source since security policy cannot be properly populated.
  • Response Flags: Additional details about the response or connection from proxy. In case of Envoy, see %RESPONSE_FLAGS% in Envoy Access Log for more detail.
  • Canonical Service: A workload belongs to exactly one canonical service, whereas it can belong to multiple services. A canonical service has a name and a revision so it results in the following labels.

    source_canonical_service
    source_canonical_revision
    destination_canonical_service
    destination_canonical_revision
  • Destination Cluster: This identifies the cluster of the destination workload. This is set by: global.multiCluster.clusterName at cluster install time.
  • Source Cluster: This identifies the cluster of the source workload. This is set by: global.multiCluster.clusterName at cluster install time.
  • gRPC Response Status: This identifies the response status of the gRPC. This label is present only on gRPC metrics.

应用

istio-proxy 与利用的 Metrics 整合输入

图:istio-proxy 与利用的 Metrics 整合输入。用 Draw.io 关上

参考:https://istio.io/v1.14/docs/o…

Istio 可能齐全通过 prometheus.io annotations 来管制抓取。尽管 prometheus.io annotations 不是 Prometheus 的外围局部,但它们已成为配置抓取的事实标准。

此选项默认启用,但能够通过在 装置 期间传递 --set meshConfig.enablePrometheusMerge=false 来禁用。启用后,将向所有数据立体 pod 增加适当的 prometheus.io annotations 以设置抓取。如果这些正文曾经存在,它们将被笼罩。应用此选项,Envoy sidecar 会将 Istio 的指标与应用程序指标合并。合并后的指标将从 /stats/prometheus:15020 中抓取。

此选项以明文模式公开所有指标。

定制:为 Metrics 减少维度

参考:https://istio.io/latest/docs/…

如,减少端口、与 HTTP HOST 头 维度。

1.

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  values:
    telemetry:
      v2:
        prometheus:
          configOverride:
            inboundSidecar:
              metrics:
                - name: requests_total
                  dimensions:
                    destination_port: string(destination.port)
                    request_host: request.host
            outboundSidecar:
              metrics:
                - name: requests_total
                  dimensions:
                    destination_port: string(destination.port)
                    request_host: request.host
            gateway:
              metrics:
                - name: requests_total
                  dimensions:
                    destination_port: string(destination.port)
                    request_host: request.host
  1. 应用以下命令将以下 annotation 利用到所有注入的 pod,其中蕴含要提取到 Prometheus 工夫序列 的维度列表:

仅当您的维度不在 [DefaultStatTags 列表] 中时才须要此步骤(https://github.com/istio/isti…)

apiVersion: apps/v1
kind: Deployment
spec:
  template: # pod template
    metadata:
      annotations:
        sidecar.istio.io/extraStatTags: destination_port,request_host

要在网格范畴内启用额定 Tag,您能够将 extraStatTags 增加到网格配置中:

meshConfig:
  defaultConfig:
    extraStatTags:
     - destination_port
     - request_host

参考 : https://istio.io/latest/docs/…

定制:退出 request / response 元信息维度

能够把 request 或 repsonse 里一些根底信息 退出到 指标的维度。如,URL Path,这在须要为雷同服务分隔统计不同 REST API 的指标时,相当有用。

参考 : https://istio.io/latest/docs/…

工作原理

istio stat filter 应用

Istio 在本人的定制版本 Envoy 中,退出了 stats-filter 插件,用于计算 Istio 本人想要的指标:

$ k -n istio-system get envoyfilters.networking.istio.io stats-filter-1.14 -o yaml
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  annotations:
  labels:
    install.operator.istio.io/owning-resource-namespace: istio-system
    istio.io/rev: default
    operator.istio.io/component: Pilot
    operator.istio.io/version: 1.14.3
  name: stats-filter-1.14
  namespace: istio-system
spec:
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: SIDECAR_OUTBOUND
      listener:
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
            subFilter:
              name: envoy.filters.http.router
      proxy:
        proxyVersion: ^1\.14.*
    patch:
      operation: INSERT_BEFORE
      value:
        name: istio.stats
        typed_config:
          '@type': type.googleapis.com/udpa.type.v1.TypedStruct
          type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
          value:
            config:
              configuration:
                '@type': type.googleapis.com/google.protobuf.StringValue
                value: |
                  {
                    "debug": "false",
                    "stat_prefix": "istio"
                  }
              root_id: stats_outbound
              vm_config:
                code:
                  local:
                    inline_string: envoy.wasm.stats
                runtime: envoy.wasm.runtime.null
                vm_id: stats_outbound
  - applyTo: HTTP_FILTER
    match:
      context: SIDECAR_INBOUND
      listener:
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
            subFilter:
              name: envoy.filters.http.router
      proxy:
        proxyVersion: ^1\.14.*
    patch:
      operation: INSERT_BEFORE
      value:
        name: istio.stats
        typed_config:
          '@type': type.googleapis.com/udpa.type.v1.TypedStruct
          type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
          value:
            config:
              configuration:
                '@type': type.googleapis.com/google.protobuf.StringValue
                value: |
                  {
                    "debug": "false",
                    "stat_prefix": "istio",
                    "disable_host_header_fallback": true,
                    "metrics": [
                      {
                        "dimensions": {"destination_cluster": "node.metadata['CLUSTER_ID']",
                          "source_cluster": "downstream_peer.cluster_id"
                        }
                      }
                    ]
                  }
              root_id: stats_inbound
              vm_config:
                code:
                  local:
                    inline_string: envoy.wasm.stats
                runtime: envoy.wasm.runtime.null
                vm_id: stats_inbound
  - applyTo: HTTP_FILTER
    match:
      context: GATEWAY
      listener:
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
            subFilter:
              name: envoy.filters.http.router
      proxy:
        proxyVersion: ^1\.14.*
    patch:
      operation: INSERT_BEFORE
      value:
        name: istio.stats
        typed_config:
          '@type': type.googleapis.com/udpa.type.v1.TypedStruct
          type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
          value:
            config:
              configuration:
                '@type': type.googleapis.com/google.protobuf.StringValue
                value: |
                  {
                    "debug": "false",
                    "stat_prefix": "istio",
                    "disable_host_header_fallback": true
                  }
              root_id: stats_outbound
              vm_config:
                code:
                  local:
                    inline_string: envoy.wasm.stats
                runtime: envoy.wasm.runtime.null
                vm_id: stats_outbound
  priority: -1
istio stat Plugin 实现

https://github.com/istio/prox…

内置的 Metric:

const std::vector<MetricFactory>& PluginRootContext::defaultMetrics() {
  static const std::vector<MetricFactory> default_metrics = {
      // HTTP, HTTP/2, and GRPC metrics
      MetricFactory{"requests_total", MetricType::Counter,
                    [](::Wasm::Common::RequestInfo&) -> uint64_t {return 1;},
                    static_cast<uint32_t>(Protocol::HTTP) |
                        static_cast<uint32_t>(Protocol::GRPC),
                    count_standard_labels, /* recurrent */ false},
      MetricFactory{"request_duration_milliseconds", MetricType::Histogram,
                    [](::Wasm::Common::RequestInfo& request_info) -> uint64_t {
                      return request_info.duration /* in nanoseconds */ /
                             1000000;
                    },
                    static_cast<uint32_t>(Protocol::HTTP) |
                        static_cast<uint32_t>(Protocol::GRPC),
                    count_standard_labels, /* recurrent */ false},
      MetricFactory{"request_bytes", MetricType::Histogram,
                    [](::Wasm::Common::RequestInfo& request_info) -> uint64_t {return request_info.request_size;},
                    static_cast<uint32_t>(Protocol::HTTP) |
                        static_cast<uint32_t>(Protocol::GRPC),
                    count_standard_labels, /* recurrent */ false},
      MetricFactory{"response_bytes", MetricType::Histogram,
                    [](::Wasm::Common::RequestInfo& request_info) -> uint64_t {return request_info.response_size;},
                    static_cast<uint32_t>(Protocol::HTTP) |
                        static_cast<uint32_t>(Protocol::GRPC),
                    count_standard_labels, /* recurrent */ false},
...

https://github.com/istio/prox…

void PluginRootContext::report(::Wasm::Common::RequestInfo& request_info,
                               bool end_stream) {

...
  map(istio_dimensions_, outbound_, peer_node_info.get(), request_info);

  for (size_t i = 0; i < expressions_.size(); i++) {if (!evaluateExpression(expressions_[i].token,
                            &istio_dimensions_.at(count_standard_labels + i))) {
      LOG_TRACE(absl::StrCat("Failed to evaluate expression: <",
                             expressions_[i].expression, ">"));
      istio_dimensions_[count_standard_labels + i] = "unknown";
    }
  }

  auto stats_it = metrics_.find(istio_dimensions_);
  if (stats_it != metrics_.end()) {for (auto& stat : stats_it->second) {if (end_stream || stat.recurrent_) {stat.record(request_info);
      }
      LOG_DEBUG(absl::StrCat("metricKey cache hit", ", stat=", stat.metric_id_));
    }
    cache_hits_accumulator_++;
    if (cache_hits_accumulator_ == 100) {incrementMetric(cache_hits_, cache_hits_accumulator_);
      cache_hits_accumulator_ = 0;
    }
    return;
  }
...
}                                  

对于 Istio 的指标原理,这是一个很好的参考文章:https://blog.christianposta.c…

Envoy 内置的 Metrics

Istio 默认用 istio-agent 去整合 Envoy 的 metrics。
而 Istio 默认关上的 Envoy 内置 Metrics 很少:

见:https://istio.io/latest/docs/…

cluster_manager
listener_manager
server
cluster.xds-grpc

定制 Envoy 内置的 Metrics

参考:https://istio.io/latest/docs/…

如果要配置 Istio Proxy 以记录 其它 Envoy 原生的指标,您能够将 ProxyConfig.ProxyStatsMatcher 增加到网格配置中。例如,要全局启用断路器、重试和上游连贯的统计信息,您能够指定 stats matcher,如下所示:

代理须要重新启动以获取统计匹配器配置。

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  meshConfig:
    defaultConfig:
      proxyStatsMatcher:
        inclusionRegexps:
          - ".*circuit_breakers.*"
        inclusionPrefixes:
          - "upstream_rq_retry"
          - "upstream_cx"

您还能够应用 proxy.istio.io/config annotation 为个别代码指定配置。例如,要配置与下面雷同的统计信息,您能够将 annotation 增加到 gateway proxy 或 workload,如下所示:

metadata:
  annotations:
    proxy.istio.io/config: |-
      proxyStatsMatcher:
        inclusionRegexps:
        - ".*circuit_breakers.*"
        inclusionPrefixes:
        - "upstream_rq_retry"
        - "upstream_cx"

原理

上面,看看 Istio 默认配置下,如何配置 Envoy。

istioctl proxy-config bootstrap fortio-server | yq eval -P  > envoy-config-bootstrap-default.yaml

输入:

bootstrap:
...
  statsConfig:
    statsTags: # 从指标名中抓取 Tag(prometheus label)
      - tagName: cluster_name
        regex: ^cluster\.((.+?(\..+?\.svc\.cluster\.local)?)\.)
      - tagName: tcp_prefix
        regex: ^tcp\.((.*?)\.)\w+?$
      - tagName: response_code
        regex: (response_code=\.=(.+?);\.;)|_rq(_(\.d{3}))$
      - tagName: response_code_class
        regex: _rq(_(\dxx))$
      - tagName: http_conn_manager_listener_prefix
        regex: ^listener(?=\.).*?\.http\.(((?:[_.[:digit:]]*|[_\[\]aAbBcCdDeEfF[:digit:]]*))\.)
...
    useAllDefaultTags: false
    statsMatcher:
      inclusionList:
        patterns: # 抉择要记录的指标
          - prefix: reporter=
          - prefix: cluster_manager
          - prefix: listener_manager
          - prefix: server
          - prefix: cluster.xds-grpc ## 只记录 xDS cluster. 即不记录用户本人服务的 cluster !!!
          - prefix: wasm
          - suffix: rbac.allowed
          - suffix: rbac.denied
          - suffix: shadow_allowed
          - suffix: shadow_denied
          - prefix: component

这时,如果批改 pod 的定义为:

    annotations:
      proxy.istio.io/config: |-
        proxyStatsMatcher:
          inclusionRegexps:
          - "cluster\\..*fortio.*" #proxy upstream(outbound)
          - "cluster\\..*inbound.*" #proxy upstream(inbound,这里个别就是指到同一 pod 中运行的利用了)
          - "http\\..*"
          - "listener\\..*"

产生新的 Envoy 配置:

 "stats_matcher": {
   "inclusion_list": {
     "patterns": [
       {"prefix": "reporter="},
       {"prefix": "cluster_manager"},
       {"prefix": "listener_manager"},
       {"prefix": "server"},
       {"prefix": "cluster.xds-grpc"},
 

       {
         "safe_regex": {"google_re2": {},
           "regex": "cluster\\..*fortio.*"
         }
       },
       {
         "safe_regex": {"google_re2": {},
           "regex": "cluster\\..*inbound.*"
         }
       },
       {
         "safe_regex": {"google_re2": {},
           "regex": "http\\..*"
         }
       },
       {
         "safe_regex": {"google_re2": {},
           "regex": "listener\\..*"
         }
       },

总结:Istio-Proxy 指标地图

要做好监控,首先要深刻理解指标原理。而要理解指标原理,当然要晓得指标是产生流程中的什么地位,什么组件。看完下面对于 Envoy 与 Istio 的指标阐明后。能够大略失去以下论断:

图:Envoy@Istio 的指标。用 Draw.io 关上

本节的试验环境阐明见于:https://istio-insider.mygraph…

正文完
 0