💂 对于封面:
置信很多人听过《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 监控仪表盘,它们大都设计得很漂亮得体,让人感觉监控曾经白璧无瑕。
然而,不晓得你是否与我有同样的经验:在零碎遇到问题时,手头有一大堆指标和监控仪表盘。
- 却不晓得哪个指标才是问题相干的。
- 或者是,问题曾经有个方向定位,却发现这个方向上,基本没有记录指标。
事件究竟是要人来解决,再多的数据,如果:
- 不去了解这些数据背地的意义
- 不去被动剖析本人的利用场景和部署环境须要什么数据,只是零碎默认给什么就用什么
那么指标越多,越让人迷失在茫茫指标的陆地中。
作为一个混后端江湖多年的老程(老程序员),总有很多货色不懂,却难以启齿的。其中一个就是一些具体指标的意义。举个两个例子:
- 我之前定位一个 Linux 下的网络问题,用了一个叫
nstat
的工具,它输入了十分多的指标,但很多会发现,有些指标是死活找不到阐明文档的。这也是开源软件始终以来的问题,变动快,文档跟不上,甚至谬误或过期未更新。 - 我之前定位一个 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 指标与外来的连贯 / 申请无关。它们由
listener
、HTTP connection manager(HCM)
、TCP proxy filter
等产生。 - Upstream:Upstream 指标与内向的连贯 / 申请无关。它们由
connection pool
、router filter
、tcp proxy filter
等产生。 - Server:
Server
指标信息形容 Envoy 服务器实例的运作状况。服务器失常运行工夫或调配的内存量等统计信息。
在最简略场景下,单个 Envoy Proxy 通常波及 Downstream
和 Upstream
统计数据。这两种指标反映了取该 网络节点
的运行状况。来自整个网格的统计数据提供了每个 网络节点
和整体网络健康状况的十分具体的汇总信息。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_interval
或stats_flush_on_admin
只能设置之一。Duration 必须至多为 1 毫秒,最多为 5 分钟。 - stats\_flush\_on\_admin
(bool) 仅当在治理界面(admin interface)
上查问时才将统计信息刷新到sink
。如果设置,则不会创立刷新计时器。只能设置stats_flush_on_admin
或stats_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 aCOUNTER
incremented for every request handled by an Istio proxy. - Request Duration (
istio_request_duration_milliseconds
): This is aDISTRIBUTION
which measures the duration of requests. - Request Size (
istio_request_bytes
): This is aDISTRIBUTION
which measures HTTP request body sizes. - Response Size (
istio_response_bytes
): This is aDISTRIBUTION
which measures HTTP response body sizes. - gRPC Request Message Count (
istio_request_messages_total
): This is aCOUNTER
incremented for every gRPC message sent from a client. - gRPC Response Message Count (
istio_response_messages_total
): This is aCOUNTER
incremented for every gRPC message sent from a server.
对于 TCP 流量,Istio 生成以下指标:
- Tcp Bytes Sent (
istio_tcp_sent_bytes_total
): This is aCOUNTER
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 aCOUNTER
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 aCOUNTER
incremented for every opened connection. - Tcp Connections Closed (
istio_tcp_connections_closed_total
): This is aCOUNTER
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 andsource
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 tounknown
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
- 应用以下命令将以下 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…