
统一观测系列文章回顾:
Nginx Ingress 网关简介
Cloud Native
在 Kubernetes 集群中,我们通常使用 “Nginx Ingress” 实现集群南北向流量的代理转发,Nginx Ingress 基于集群内 Ingress 资源配置生成具体的路由规则。Ingress 资源负责对外公开服务的管理,一般这类服务通过 HTTP 协议进行访问。通过 Nginx Ingress + Ingress 资源可以实现以下场景:


工作负载资源
入口请求流量
包括集群范围全局的流量、某个 Ingress 规则转发的流量、某个 Service 的流量,以及对应的成功率/错误率、延迟,乃至请求来源的地址、设备等信息的分析与统计。针对“入口请求流量监控”,一般建议关注 “RED” 指标,即:请求速率(Rate)、请求失败数(Errors)、请求延迟(Duration)。可通过本文最佳实践实现接入。
Nginx Ingress 网关监控实现方式
Cloud Native
▷▶︎ 基于 Exporter 指标
Kubernetes 基于开源 Nginx 实现的 Nginx Ingress 发行版一大特色是其每个进程都扮演着 Exporter 角色,实现遵循 Prometheus 协议格式的自监控指标,如:
nginx_ingress_controller_requests{canary="",controller_class="k8s.io/ingress-nginx",controller_namespace="kube-system",controller_pod="nginx-ingress-controller-6fdbbc5856-pcxkz",host="my.otel-demo.com",ingress="my-otel-demo",method="GET",namespace="default",path="/",service="my-otel-demo-frontend",status="200"} 2.401964e+06nginx_ingress_controller_requests{canary="",controller_class="k8s.io/ingress-nginx",controller_namespace="kube-system",controller_pod="nginx-ingress-controller-6fdbbc5856-pcxkz",host="my.otel-demo.com",ingress="my-otel-demo",method="GET",namespace="default",path="/",service="my-otel-demo-frontend",status="304"} 111nginx_ingress_controller_requests{canary="",controller_class="k8s.io/ingress-nginx",controller_namespace="kube-system",controller_pod="nginx-ingress-controller-6fdbbc5856-pcxkz",host="my.otel-demo.com",ingress="my-otel-demo",method="GET",namespace="default",path="/",service="my-otel-demo-frontend",status="308"} 553545nginx_ingress_controller_requests{canary="",controller_class="k8s.io/ingress-nginx",controller_namespace="kube-system",controller_pod="nginx-ingress-controller-6fdbbc5856-pcxkz",host="my.otel-demo.com",ingress="my-otel-demo",method="GET",namespace="default",path="/",service="my-otel-demo-frontend",status="404"} 55nginx_ingress_controller_requests{canary="",controller_class="k8s.io/ingress-nginx",controller_namespace="kube-system",controller_pod="nginx-ingress-controller-6fdbbc5856-pcxkz",host="my.otel-demo.com",ingress="my-otel-demo",method="GET",namespace="default",path="/",service="my-otel-demo-frontend",status="499"} 2nginx_ingress_controller_requests{canary="",controller_class="k8s.io/ingress-nginx",controller_namespace="kube-system",controller_pod="nginx-ingress-controller-6fdbbc5856-pcxkz",host="my.otel-demo.com",ingress="my-otel-demo",method="GET",namespace="default",path="/",service="my-otel-demo-frontend",status="500"} 64nginx_ingress_controller_requests{canary="",controller_class="k8s.io/ingress-nginx",controller_namespace="kube-system",controller_pod="nginx-ingress-controller-6fdbbc5856-pcxkz",host="my.otel-demo.com",ingress="my-otel-demo",method="GET",namespace="default",path="/",service="my-otel-demo-frontendproxy",status="200"} 59599nginx_ingress_controller_requests{canary="",controller_class="k8s.io/ingress-nginx",controller_namespace="kube-system",controller_pod="nginx-ingress-controller-6fdbbc5856-pcxkz",host="my.otel-demo.com",ingress="my-otel-demo",method="GET",namespace="default",path="/",service="my-otel-demo-frontendproxy",status="304"} 15nginx_ingress_controller_requests{canary="",controller_class="k8s.io/ingress-nginx",controller_namespace="kube-system",controller_pod="nginx-ingress-controller-6fdbbc5856-pcxkz",host="my.otel-demo.com",ingress="my-otel-demo",method="GET",namespace="default",path="/",service="my-otel-demo-frontendproxy",status="308"} 15709nginx_ingress_controller_requests{canary="",controller_class="k8s.io/ingress-nginx",controller_namespace="kube-system",controller_pod="nginx-ingress-controller-6fdbbc5856-pcxkz",host="my.otel-demo.com",ingress="my-otel-demo",method="GET",namespace="default",path="/",service="my-otel-demo-frontendproxy",status="403"} 235nginx_ingress_controller_requests{canary="",controller_class="k8s.io/ingress-nginx",controller_namespace="kube-system",controller_pod="nginx-ingress-controller-6fdbbc5856-pcxkz",host="e-commerce.
使用开源或阿里云 Prometheus Agent 配合服务发现策略即可完成指标抓取与上报,通过 PromQL 实现分析、告警配置,或通过 Grafana 实现指标数据可视化展现。但这种监控实现方式在生产实践中存在不少问题。
问题 1:暴露太多不实用的 Histogram 指标
nginx_ingress_controller_request_size_bucket:对每个请求体大小的分桶采样; nginx_ingress_controller_bytes_sent_bucket:对每个响应体大小的分桶采样。
默认情况下,如果不在 Prometheus 的 metric_relabel_configs 采集配置中执行 drop 操作,这些指标都会被抓取、上报,占用大量带宽与存储资源。
问题 2:Pull 模式拉取太多不活跃的时间线
问题 3:Ingress Path 不可扩展、下钻
问题 4:缺少地理、设备信息的分析
访问网站的用户分布在全国哪几个省市?其中, Top10 的城市是哪些? 用户通过移动端还是 PC 端访问网站?其中,移动端有多少是 iOS 机型,有多少是 Android 机型?
这些数据也是 Nginx Ingress 自身暴露的指标中所未体现的。
问题 5:Kubernetes 官方 Grafana 大盘布局不够聚焦

我不关注 Ingress Controller 的连接数,这是 HTTP 请求下层的概念 我不关注 Controller 级别的成功率,我更关注贯穿 Ingress Host、Service、URI 路径上的成功率 我不关注 Ingress Controller 的配置被 Reload 了多少次 我不关注 Ingress Controller 上一次配置拉取失败 我不关注 Ingress 证书到期时间 ……
因此,提供一张聚焦、好用的大盘,也是实现 “Nginx Ingress 网关监控” 无法回避的事情。
▷▶︎ 基于访问日志统计
172.16.0.20 - [172.16.0.20] - - [24/Mar/2023:17:58:26 +0800] "POST api/cart HTTP/1.1" 500 32 "-" "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/3.0)" 475 0.003 [default-my-otel-demo-frontend-8080] 172.16.0.17:8080 32 0.003 500 8f4dafe7280e421e9f6ca01efeacaf2d my.otel-demo.com []172.16.0.20 - [172.16.0.20] - - [24/Mar/2023:17:58:26 +0800] "GET api/products/HQTGWGPNH4 HTTP/1.1" 200 758 "-" "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/3.0)" 334 0.001 [default-my-otel-demo-frontend-8080] 172.16.0.17:8080 758 0.002 200 e90aa6e5ffb7dfc03c0d576eb145fa29 my.otel-demo.com []172.16.0.20 - [172.16.0.20] - - [24/Mar/2023:17:58:26 +0800] "POST api/cart HTTP/1.1" 500 32 "-" "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/3.0)" 475 0.003 [default-my-otel-demo-frontend-8080] 172.16.0.17:8080 32 0.002 500 dd7b9f42dbe53e72efe8768b1811525a my.otel-demo.com []172.16.0.20 - [172.16.0.20] - - [24/Mar/2023:17:58:26 +0800] "GET api/products/L9ECAV7KIM HTTP/1.1" 200 752 "-" "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/3.0)" 334 0.002 [default-my-otel-demo-frontend-8080] 172.16.0.17:8080 752 0.001 200 883fec15467ed2e243a22345a0df9ed9 my.otel-demo.com []172.16.0.20 - [172.16.0.20] - - [24/Mar/2023:17:58:26 +0800] "POST api/cart HTTP/1.1" 500 32 "-" "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/3.0)" 475 0.007 [default-my-otel-demo-frontend-8080] 172.16.0.17:8080 32 0.008 500 08ae27b3de3e112c47572255f3702af0 my.otel-demo.com []172.16.0.20 - [172.16.0.20] - - [24/Mar/2023:17:58:26 +0800] "POST api/checkout HTTP/1.1" 200 315 "-" "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/3.0)" 765 0.194 [default-my-otel-demo-frontend-8080] 172.16.0.17:8080 315 0.194 200 4ed16b7f57394004d1d90383ce43a137 my.otel-demo.com []172.16.0.20 - [172.16.0.20] - - [24/Mar/2023:17:58:26 +0800] "GET api/products/6E92ZMYYFZ HTTP/1.1" 200 493 "-" "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/3.0)" 334 0.002 [default-my-otel-demo-frontend-8080] 172.16.0.17:8080 493 0.002 200 674e2ae6c941f48a0bcaf0a7c57821c1 my.otel-demo.com []172.16.0.20 - [172.16.0.20] - - [24/Mar/2023:17:58:26 +0800] "GET api/products/66VCHSJNUP HTTP/1.1" 200 515 "-" "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/3.0)" 334 0.001 [default-my-otel-demo-frontend-8080] 172.16.0.17:8080 515 0.002 200 245e689b406613eed45937d56c11339e my.otel-demo.com []172.16.0.20 - [172.16.0.20] - - [24/Mar/2023:17:58:26 +0800] "GET api/products/0PUK6V6EV0 HTTP/1.1" 200 438 "-" "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/3.0)" 334 0.001 [default-my-otel-demo-frontend-8080] 172.16.0.17:8080 438 0.002 200 b6d2416865d34f601c460a2b382806b7 my.otel-demo.com []172.16.0.20 - [172.16.0.20] - - [24/Mar/2023:17:58:26 +0800] "POST api/checkout HTTP/1.1" 200 321 "-" "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/3.0)" 772 0.214 [default-my-otel-demo-frontend-8080] 172.16.0.17:8080 321 0.214 200 63d8d6405b0d9a0ee65d6c1a13342f10 my.otel-demo.com []
目前 ACK 默认的 Nginx Ingress 所打印的访问日志包含以下信息:
请求时间 请求来源 IP 请求方法,如:GET 请求路径,如:/api/cart 响应状态码 请求体长度 响应体长度 请求耗时 请求上游服务名,如:default-my-otel-demo-frontend-8080 请求 User-Agent,如:Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/3.0) 请求头携带的 Host 域名,如:my.otel-demo.com,这有助于确定流量是从哪个 Ingress 路由规则进来的
基于这些信息,只需在 K8s 环境里部署一个采集器,通过预聚合计算方式即可实现入口流量 RED 指标统计,并通过可控的技术手段规避基于 Exporter 指标实施监控的几大问题:
“暴露太多不实用的 Histogram 指标”——制作一组精益指标,裁剪不需要的指标项,满足大部分统计分析场景需要; “Pull 模式拉取太多不活跃的时间线”——抛弃计数器模型,使用滚动窗口计算 Gauge 指标,窗口间数据独立,使用 RemoteWrite 方式推送,避免历史堆积时间线的重复上报; “Ingress Path”不可扩展、下钻——预聚合逻辑可使用 CR 配置扩展,通过建立新的匹配规则实现下钻; “缺少地理、设备信息的分析”——预聚合过程通过 GeoIP、UserAgent 分析等手段实现数据富化; “Kubernetes 官方 Grafana 大盘布局不够聚焦”——建立新的入口观测大盘,优化布局与信息结构,提升大盘的价值与体验。
Nginx Ingress 网关监控指标模型
Cloud Native
▷▶︎ 通用请求量指标(ingress_requests)
指标名:ingress_requests
指标类型:Gauge
聚合周期:30s
指标说明:表示一个聚合周期内在标签对应维度上被统计到的请求量数值

指标名:ingress_geoip_requests
指标类型:Gauge
聚合周期:30s
指标说明:表示一个聚合周期内在标签对应维度上被统计到的请求量数值,标签中富化了地理信息

注:我们刻意裁剪了标签中 URI、Method、Status Code 等几个维度信息,该指标常见的使用场景中,请求路径的粒度至服务(Service)级即可满足,更细的粒度需要更昂贵的存储,且使用价值较低。
指标名:ingress_user_agent_requests
指标类型:Gauge
聚合周期:30s
指标说明:表示一个聚合周期内在标签对应维度上被统计到的请求量数值,标签中富化了设备信息

注:我们刻意裁剪了标签中 URI、Method、Status Code 等几个维度信息,该指标常见的使用场景中,请求路径的粒度至服务(Service)级即可满足,更细的粒度需要更昂贵的存储,且使用价值较低。
指标名:ingress_request_time
指标类型:GaugeHistogram
聚合周期:30s
指标说明:表示一个聚合周期内在标签对应维度上被统计到的请求延迟分桶值

注:请留意当前指标类型并非常见的 Histogram 类型——每个桶的数值为计数器模型,而是 GaugeHistogram 类型——每个桶的数值为当前聚合周期内观察到的一种“瞬时值”,因此如果要对这种指标进行分位数计算,参考表达式:histogram_quantile(0.95,sum(sum_over_time(ingress_request_time_bucket{...}[1m])) by (le))。
指标名:ingress_request_size
指标类型:Gauge
聚合周期:30s
指标说明:表示一个聚合周期内在标签对应维度上被统计到的请求报文总字节数

注:我们刻意裁剪了标签中 URI、Method、Status Code 等几个维度信息,该指标常见的使用场景中,请求路径的粒度至服务(Service)级即可满足,更细的粒度需要更昂贵的存储,且使用价值较低。
指标名:ingress_response_size
指标类型:Gauge
聚合周期:30s
指标说明:表示一个聚合周期内在标签对应维度上被统计到的响应报文总字节数——受 Nginx Ingress 实现限制,这里只能统计到响应体的字节数,不包含响应头的大小

注:我们刻意裁剪了标签中 URI、Method、Status Code 等几个维度信息,该指标常见的使用场景中,请求路径的粒度至服务(Service)级即可满足,更细的粒度需要更昂贵的存储,且使用价值较低。
Nginx Ingress 网关监控接入
Cloud Native
▷▶︎ 方法一:实现 ACK 集群默认安装的 Nginx Ingress 网关监控
第一步:进入阿里云 Prometheus 监控集成中心

第二步:填写安装参数
如果您在 ACK 集群创建后没有对 Nginx Ingress 执行任何变更操作(如:更改命名空间、IngressClass 标识名等),可在这步直接点击“确定”提交安装。 如果您正在接入的是自建、第 N 套 Nginx Ingress 网关,请参见下文“实现自建/多套 Nginx Ingress 网关监控”进行接入。
注:启用当前监控将在您的 K8s 集群中部署一个采集器工作负载(DaemonSet),资源限制为 0.5 核/512MB ,可以结合网关实际流量规模进行资源限制的调整,请通过 kubectl edit daemonset -narms-prom arms-vector 命令进行变更。
第三步:查看 Nginx Ingress 网关监控大盘


采集配置名称:作为当前采集配置的唯一 ID 进行设置,如:otel-demo-nginx-ingress Ingress Controller 标签选择器 Key:采集器通过标签选择器查找指定的 Ingress Controller Pod,这里提供选择器的键名,如:app Ingress Controller 标签选择器 Value:采集器通过标签选择器查找指定的 Ingress Controller Pod,这里提供选择器的值,如:otel-demo-nginx,这样与上面的键名组合成查询表达式:app=otel-demo-nginx Ingress Controller 命名空间:Ingress Controller 所在的命名空间,如:otel-demo Ingress Class 标识名:该 Ingress Controller 监听的目标 Ingress Class标识,如:otel-demo-nginx-class
注:监控多套 Nginx Ingress 网关会复用相同的采集器工作负载,它默认的资源限制为 0.5 核/512MB ,请关注网关实际流量规模,进行相应的资源限制调整,请通过 kubectl edit daemonset -narms-prom arms-vector 命令进行变更。
Nginx Ingress 网关监控可视化大盘
Cloud Native
整个 Nginx Ingress 网关监控可视化大盘分为六个区域:
概览:体现首屏亟需关注的指标信息 服务统计 - TopN:以 TopN 视角展示 Host / 域名、服务、URI 的访问 PV、耗时、成功率等信息 服务统计 - 趋势分布:展示 PV、出入流量、请求成功率、延迟等趋势,以及状态码、请求方法、Ingress Pod 请求数等分布 服务统计 - 请求分析:以表格形式呈现贯穿 Host / 域名、Service、Uri 请求路径上的 PV、成功率、4XX 比例、5XX 比例、延迟情况 地理统计:以占比视角和表格明细分别呈现基于地理信息的请求情况 设备统计:以占比视角和表格明细分别呈现基于设备信息的请求情况
① 体现流量的仪表盘
分钟级访问 PV 小时级访问 PV
与一天前的同比 与一小时前的环比
一天级访问 PV
与一周前的同比 与一天前的环比
一周级访问 PV
与四周前(月)的同比 与一周前的环比
同时,通过 Grafana 强大的可视化能力,我们用不同的颜色区分指标是否需要关注的事实,下文可以看到不止一处应用了这一实践:
当同比、环比上涨时使用红色显示指标值 当同比、环比下跌是使用绿色显示指标值
② 体现服务质量/体验的仪表盘
404:当该数值异常升高时需要排查是否应用配置错误导致被搜索引擎抓取的页面无法正确加载 429:当该数值异常升高时需要关注是否有客户端以超过正常的频率访问后端服务导致限流 499:当该数值异常升高时需要关注是否因为后端服务响应耗时过久导致客户端提前关闭连接 500:当该数值异常升高时需要关注是否有后端服务因业务逻辑未正确实现导致内部错误 503:当该数值异常升高时需要关注是否有后端服务因为升级等原因导致不可用 504:当该数值异常升高时需要关注是否有后端服务响应超过了 Nginx Ingress 承受范围导致超时
同时,这里也充分应用了“可观测即颜色”的实践,策略是:
请求成功率
当大于 90% 时表现为绿色 当大于 50% 但小于 90% 时表现为黄色 当小于 50% 时表现为红色
5XX 比例
当大于 50% 时表现为红色 当小于 50% 但大于 10% 时表现为黄色 当小于 10% 时表现为绿色
各类错误请求数:在当前周期内大于 0 即表现为黄色 各类延迟指标:
当小于 200ms 时表现为绿色 当小于 500ms 但大于 200ms 时表现为黄色 当大于 500ms 时表现为红色
此外,需要注意到,正确的请求和错误请求,它们的延迟指标差异较大,因此建议通过顶部下拉筛选,指定正常响应码或错误响应码来区别分析。
① 访问 PV
② 请求耗时
当小于 200ms 时表现为绿色 当小于 500ms 但大于 200ms 时表现为黄色 当大于 500ms 时表现为红色
此外,正确的请求和错误请求,它们的延迟指标差异较大,因此建议通过顶部下拉筛选,指定正常响应码或错误响应码来区别分析。
③ 5XX 比例
当大于 50% 时表现为红色 当小于 50% 但大于 10% 时表现为黄色 当小于 10% 时表现为绿色
① Host / 域名维度的 RED 指标
各 Host / 域名分钟级的 PV 变化 各 Host / 域名分钟级的请求成功率变化 各 Host / 域名分钟级的出入流量变化 各 Host / 域名分钟级的延迟变化
其中,PV 趋势和延迟趋势,受顶部下拉筛选的响应状态码变化控制,可以区分正常请求和错误请求的 PV 和延迟。
② Service 维度的 RED 指标
各 Service 分钟级的 PV 变化 各 Service 分钟级的请求成功率变化 各 Service 分钟级的出入流量变化 各 Service 分钟级的延迟变化
其中,PV 趋势和延迟趋势,受顶部下拉筛选的响应状态码变化控制,可以区分正常请求和错误请求的 PV 和延迟。
③ 请求分布
请求流量分布在各响应状态码的占比与具体数值 请求流量分布在各请求方法的占比与具体数值 请求流量分布在各 Ingress Controller Pod 的占比与具体数值
它们的统计范围是当前顶部选择的时间段。


访问省份
各访问省份 / 地区的占比情况,统计范围是当前顶部选择的时间段 访问省份 / 地区的表格详情,统计范围是当前顶部选择的时间段
访问城市
各访问城市的占比情况,统计范围是当前顶部选择的时间段 访问城市的表格详情,统计范围是当前顶部选择的时间段
访问时区
各访问时区的占比情况,统计范围是当前顶部选择的时间段 访问时区的表格详情,统计范围是当前顶部选择的时间段

设备类型维度
各设备类型的占比、具体数值,统计范围是当前顶部选择的时间段 设备类型的表格详情,统计范围是当前顶部选择的时间段
操作系统维度
各操作系统的占比、具体数值,统计范围是当前顶部选择的时间段 操作系统的表格详情,统计范围是当前顶部选择的时间段
浏览器维度
各浏览器的占比、具体数值,统计范围是当前顶部选择的时间段 浏览器的表格详情,统计范围是当前顶部选择的时间段

Nginx Ingress 网关监控进阶指南
Cloud Native
▷▶︎ 编辑 CR 扩展 URI 收敛规则
匹配表达式:一个正则表达式,如果当前 URI 匹配命中,则进行收敛,如:$/api/product/(.+)$ 收敛后文本:将 URI 收敛为另一个具备可读性的字符串,如:ProductItem
采集器会在第一次启用时扫描当前 K8s 集群的 Ingress 资源,并根据已有的路由规则提供的 Path 信息组装收敛规则。如果这部分配置无法满足您的分析、统计需要,请参照下列步骤进行扩展。
reduceUri:allowList:- pattern: ^/(.+)$reduced: /(.+)- pattern: ^/$reduced: /
allowList 字段为一个数组对象,它的每一个元素即表示一个收敛规则,每个收敛规则下的 pattern 字段表示“匹配表达式”,reduced 字段表示“收敛后文本”。
reduceUri:allowList:- pattern: ^/api/cart$reduced: /api/cart- pattern: ^/api/checkout$reduced: /api/checkout- pattern: ^/api/data$reduced: /api/data- pattern: ^/api/data/\?contextKeys=(.+)$reduced: /api/data/?contextKeys=(.+)- pattern: ^/api/products/(.+)$reduced: /api/products/(.+)- pattern: ^/api/recommendations/\?productIds=(.+)$reduced: /api/recommendations/?productIds=(.+)- pattern: ^/(.+)$reduced: /(.+)- pattern: ^/$reduced: /
这里请按照顺序,将最短匹配路径的规则放到列表末,如:^/$。保存该配置后等待 2-3 分钟,即可在大盘看到根据 URI 收敛规则扩展后的进一步细化的指标数据。
注 1:请您及时在本地备份 URI 收敛规则,因为在卸载当前 Nginx Ingress 网关监控能力后,对应的 IngressLog 自定义资源默认会被删除。
注 2:请不要改动 IngressLog 自定义资源中的其他配置,否则将导致 Nginx Ingress 网关监控无法正常工作!
相关链接:
[2] 《部署多个 Ingress Controller》
https://help.aliyun.com/document_detail/151524.htm
参考资料:
Kubernetes 官方文档
Ingress 介绍: https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/ Ingress Controller 介绍: https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress-controllers/
阿里云 ACK 官方文档
Ingress 概述: https://help.aliyun.com/document_detail/198892.html Nginx Ingress 最佳实践: https://help.aliyun.com/document_detail/398740.html














