
👋 大家好,欢迎来到我的技术博客! 📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。 🎯 本文将围绕Kubernetes这个话题展开,希望能为你带来一些启发或实用的参考。 🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!
文章目录
- Kubernetes – 基于 Prometheus+Grafana 搭建 K8s 监控体系 🚀
-
- 一、Kubernetes 监控体系的分层模型 🏗️
-
- 1. 节点层(Node Layer)
- 2. 容器层(Container Layer)
- 3. Kubernetes 组件层(Control Plane Layer)
- 4. 应用层(Application Layer)
- 二、部署 Prometheus 与 Grafana 🛠️
-
- 1. 安装 Helm
- 2. 添加 Prometheus 社区 Helm 仓库
- 3. 部署 Prometheus
- 4. 部署 Grafana
- 5. 访问 Grafana
- 6. 验证 Prometheus 数据源
- 三、Java 微服务暴露 Prometheus 指标 🐘
-
- 1. Maven 依赖
- 2. 配置 application.yml
- 3. 启动应用并验证端点
- 4. 自定义业务指标:订单创建计数器
- 5. 测试指标是否被 Prometheus 抓取
- 四、创建 ServiceMonitor:让 Prometheus 发现 Java 应用 🕵️
-
- 1. 创建 Service
- 2. 创建 ServiceMonitor
- 3. 验证 ServiceMonitor 是否生效
- 五、构建高价值 Grafana 面板 📊
-
- 1. 导入官方 Kubernetes 面板
- 2. 创建自定义 Java 应用监控面板
-
- ✅ 面板标题:`Order Service – Real-time Metrics`
- 🔢 面板包含以下 5 个图表:
- 图表 1:订单创建速率(每秒)
- 图表 2:HTTP 请求延迟(99分位)
- 图表 3:JVM 堆内存使用率
- 图表 4:HTTP 错误率(5xx)
- 图表 5:JVM 线程数与 GC 次数
- 3. 添加变量:按服务/命名空间筛选
- 六、告警规则:从“事后发现”到“事前预警” 🔔
-
- 1. 创建告警规则文件
- 2. 验证告警规则
- 3. 配置 Alertmanager 发送通知
- 七、实战演练:模拟高负载与告警触发 🧪
-
- 1. 部署压测工具
- 八、进阶技巧:日志与链路追踪的协同 🧩
-
- 1. 日志:Fluent Bit + Loki
- 2. 链路追踪:Jaeger + OpenTelemetry
- 九、性能优化与生产建议 🛡️
-
- ✅ 最佳实践清单
- ❌ 避免的陷阱
- 十、总结:从监控到可观测性 🌟
- 附录:常用 PromQL 查询速查表 📋
- 结语:你,就是云原生的守护者 🛡️
Kubernetes – 基于 Prometheus+Grafana 搭建 K8s 监控体系 🚀
在现代云原生架构中,Kubernetes 已成为容器编排的事实标准。它赋予我们弹性伸缩、自动恢复、服务发现与负载均衡的强大能力。然而,随着集群规模的扩大和微服务数量的激增,“看不见的系统” 正在成为运维的最大挑战。一个无法观测的集群,就像一台没有仪表盘的跑车——你不知道它跑得多快、油量还剩多少、引擎是否过热。
🌐 “如果你无法测量它,你就无法改进它。” —— Lord Kelvin
因此,构建一套完整、可靠、可视化的监控体系,是每一个 Kubernetes 生产环境的必选项,而非可选项。
本篇博客将带你从零开始,搭建一套基于 Prometheus + Grafana 的 Kubernetes 监控体系。我们将深入理解每一个组件的职责,亲手编写 Java 应用暴露自定义指标,配置 Prometheus 抓取规则,设计高价值的 Grafana 面板,并最终实现对整个集群的全栈监控。
我们将涵盖:
- Kubernetes 监控架构的分层模型
- Prometheus 的核心概念与部署方式
- Grafana 的可视化设计哲学
- 如何为 Java 微服务暴露 Prometheus 指标
- 自定义监控指标的采集与告警
- 实时仪表盘的构建与分享
准备好,让我们开启这场从“黑盒”到“玻璃盒”的监控革命 🧩➡️🪟
一、Kubernetes 监控体系的分层模型 🏗️
在 Kubernetes 中,监控不是单一工具能解决的问题,而是一个分层的、多维度的系统工程。我们可以将监控体系划分为四个核心层级:
1. 节点层(Node Layer)
这是最底层的基础设施监控。包括:
- CPU 使用率、内存占用
- 磁盘 I/O 与使用率
- 网络吞吐量、丢包率
- 节点是否 Ready、是否出现内存压力(MemoryPressure)
这些指标由 Node Exporter 暴露,Prometheus 通过 ServiceMonitor 抓取。
2. 容器层(Container Layer)
Kubernetes 中的最小调度单元是 Pod,而 Pod 内部运行的是容器。我们需要监控:
- 每个容器的 CPU/内存请求与限制
- 容器重启次数
- 文件系统读写延迟
这些数据由 cAdvisor(容器监控代理)收集,它内置于 kubelet 中,无需额外部署。
3. Kubernetes 组件层(Control Plane Layer)
这是集群的“大脑”,包括:
- API Server
- Scheduler
- Controller Manager
- ETCD
它们的健康状态直接决定集群的稳定性。Prometheus 通过 kube-state-metrics 暴露这些组件的内部状态,如:
- kube_pod_status_phase
- kube_deployment_spec_replicas
- etcd_server_has_leader
4. 应用层(Application Layer)
这是最贴近业务的层级。我们关心:
- HTTP 请求量、响应时间、错误率(如 5xx)
- 数据库连接池使用率
- JVM 内存、GC 频率、线程数
- 自定义业务指标(如订单创建数、支付成功率)
这一层的指标,需要应用主动暴露。对于 Java 应用,我们使用 Micrometer + Prometheus Registry。
📌 关键洞察:只有当这四层指标被完整采集、关联、可视化时,我们才能真正实现“端到端可观测性”。
下面的 Mermaid 图表清晰地展示了这一分层架构:
#mermaid-svg-Vjfnt7gp26rsFVnF{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Vjfnt7gp26rsFVnF .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Vjfnt7gp26rsFVnF .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Vjfnt7gp26rsFVnF .error-icon{fill:#552222;}#mermaid-svg-Vjfnt7gp26rsFVnF .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Vjfnt7gp26rsFVnF .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Vjfnt7gp26rsFVnF .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Vjfnt7gp26rsFVnF .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Vjfnt7gp26rsFVnF .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Vjfnt7gp26rsFVnF .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Vjfnt7gp26rsFVnF .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Vjfnt7gp26rsFVnF .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Vjfnt7gp26rsFVnF .marker.cross{stroke:#333333;}#mermaid-svg-Vjfnt7gp26rsFVnF svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Vjfnt7gp26rsFVnF p{margin:0;}#mermaid-svg-Vjfnt7gp26rsFVnF .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Vjfnt7gp26rsFVnF .cluster-label text{fill:#333;}#mermaid-svg-Vjfnt7gp26rsFVnF .cluster-label span{color:#333;}#mermaid-svg-Vjfnt7gp26rsFVnF .cluster-label span p{background-color:transparent;}#mermaid-svg-Vjfnt7gp26rsFVnF .label text,#mermaid-svg-Vjfnt7gp26rsFVnF span{fill:#333;color:#333;}#mermaid-svg-Vjfnt7gp26rsFVnF .node rect,#mermaid-svg-Vjfnt7gp26rsFVnF .node circle,#mermaid-svg-Vjfnt7gp26rsFVnF .node ellipse,#mermaid-svg-Vjfnt7gp26rsFVnF .node polygon,#mermaid-svg-Vjfnt7gp26rsFVnF .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Vjfnt7gp26rsFVnF .rough-node .label text,#mermaid-svg-Vjfnt7gp26rsFVnF .node .label text,#mermaid-svg-Vjfnt7gp26rsFVnF .image-shape .label,#mermaid-svg-Vjfnt7gp26rsFVnF .icon-shape .label{text-anchor:middle;}#mermaid-svg-Vjfnt7gp26rsFVnF .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Vjfnt7gp26rsFVnF .rough-node .label,#mermaid-svg-Vjfnt7gp26rsFVnF .node .label,#mermaid-svg-Vjfnt7gp26rsFVnF .image-shape .label,#mermaid-svg-Vjfnt7gp26rsFVnF .icon-shape .label{text-align:center;}#mermaid-svg-Vjfnt7gp26rsFVnF .node.clickable{cursor:pointer;}#mermaid-svg-Vjfnt7gp26rsFVnF .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Vjfnt7gp26rsFVnF .arrowheadPath{fill:#333333;}#mermaid-svg-Vjfnt7gp26rsFVnF .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Vjfnt7gp26rsFVnF .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Vjfnt7gp26rsFVnF .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Vjfnt7gp26rsFVnF .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Vjfnt7gp26rsFVnF .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Vjfnt7gp26rsFVnF .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Vjfnt7gp26rsFVnF .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Vjfnt7gp26rsFVnF .cluster text{fill:#333;}#mermaid-svg-Vjfnt7gp26rsFVnF .cluster span{color:#333;}#mermaid-svg-Vjfnt7gp26rsFVnF div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Vjfnt7gp26rsFVnF .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Vjfnt7gp26rsFVnF rect.text{fill:none;stroke-width:0;}#mermaid-svg-Vjfnt7gp26rsFVnF .icon-shape,#mermaid-svg-Vjfnt7gp26rsFVnF .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Vjfnt7gp26rsFVnF .icon-shape p,#mermaid-svg-Vjfnt7gp26rsFVnF .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Vjfnt7gp26rsFVnF .icon-shape .label rect,#mermaid-svg-Vjfnt7gp26rsFVnF .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Vjfnt7gp26rsFVnF .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Vjfnt7gp26rsFVnF .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Vjfnt7gp26rsFVnF :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
抓取
抓取
抓取
抓取
可视化
告警通知
监控体系分层模型
节点层 Node Layer
容器层 Container Layer
Kubernetes 组件层
应用层 Application Layer
Node Exporter
CPU, Memory, Disk, Network
cAdvisor
Container CPU/Mem, Restart Count
kube-state-metrics
Pod/Deployment/Service Status
Micrometer + Prometheus
HTTP Requests, JVM Stats, Custom Metrics
Prometheus
Grafana
Alertmanager
Slack/Email/WeChat
💡 为什么是 Prometheus? 它采用拉取模型(Pull),避免了推模型(Push)的复杂性与单点故障。其强大的 PromQL 查询语言,支持多维度聚合、时间序列关联、函数计算,是云原生监控的事实标准。
💡 为什么是 Grafana? 它不采集数据,只做可视化。但它的面板模板、变量系统、告警规则、数据源插件生态,让它成为唯一能让你把数据讲成故事的工具。
二、部署 Prometheus 与 Grafana 🛠️
我们采用 Helm 部署方式,这是 Kubernetes 社区推荐的包管理工具,简单、可复用、版本可控。
1. 安装 Helm
如果你尚未安装 Helm,请执行:
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
验证安装:
helm version
2. 添加 Prometheus 社区 Helm 仓库
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
3. 部署 Prometheus
我们使用 prometheus-community/kube-prometheus-stack,它打包了:
- Prometheus
- Alertmanager
- Node Exporter
- kube-state-metrics
- cAdvisor(自动集成)
- Grafana(可选)
helm install prometheus prometheus-community/kube-prometheus-stack \\
–namespace monitoring \\
–create-namespace \\
–set grafana.enabled=true \\
–set grafana.adminPassword="admin123" \\
–set prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues=false \\
–set prometheus.prometheusSpec.podMonitorSelectorNilUsesHelmValues=false
⚠️ 注意:serviceMonitorSelectorNilUsesHelmValues=false 是关键配置,它允许我们自定义 ServiceMonitor 资源来抓取应用指标,否则默认只抓取 helm 标签的资源。
4. 部署 Grafana
上面的 Helm Chart 已包含 Grafana,但我们也可以单独部署:
helm install grafana grafana/grafana \\
–namespace monitoring \\
–set service.type=LoadBalancer \\
–set adminPassword="admin123" \\
–set persistence.enabled=true
5. 访问 Grafana
获取 Grafana 服务地址:
kubectl get svc -n monitoring grafana
输出类似:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
grafana LoadBalancer 10.96.123.45 203.0.113.10 80:31234/TCP 2m
访问 http://203.0.113.10,使用用户名 admin,密码 admin123 登录。
🔗 推荐阅读:Grafana 官方文档 – Getting Started
6. 验证 Prometheus 数据源
登录 Grafana → Configuration → Data Sources → Add data source → Prometheus
填写:
- URL: http://prometheus-kube-prometheus-prometheus.monitoring.svc:9090
- 点击 “Save & Test”
✅ 出现 “Data source is working” 即成功。
三、Java 微服务暴露 Prometheus 指标 🐘
现在,我们进入最激动人心的部分:让我们的 Java 应用说话。
假设你有一个 Spring Boot 微服务,处理用户订单。我们希望监控:
- 每秒请求数(HTTP Requests)
- 平均响应时间(Latency)
- JVM 堆内存使用量
- 自定义指标:orders_created_total(订单创建总数)
1. Maven 依赖
在 pom.xml 中添加 Micrometer 与 Prometheus 依赖:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.12.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
📚 Micrometer 是 Spring Boot 官方推荐的监控门面库,支持 Prometheus、Datadog、StatsD 等多种后端。
2. 配置 application.yml
management:
endpoints:
web:
exposure:
include: prometheus,health,info
metrics:
enabled:
true
distribution:
percentiles:
http:
server:
request:
– 0.5
– 0.9
– 0.95
– 0.99
tags:
application: my–order–service
✅ 启用 /actuator/prometheus 端点,这是 Prometheus 抓取的默认路径。
3. 启动应用并验证端点
启动应用后,访问:
http://your-app:8080/actuator/prometheus
你会看到类似输出:
# HELP http_server_requests_seconds Duration of HTTP server requests
# TYPE http_server_requests_seconds histogram
http_server_requests_seconds_count{application="my-order-service",exception="None",method="GET",outcome="SUCCESS",status="200",uri="/orders",} 152.0
http_server_requests_seconds_sum{application="my-order-service",exception="None",method="GET",outcome="SUCCESS",status="200",uri="/orders",} 2.87412345
http_server_requests_seconds_bucket{application="my-order-service",exception="None",method="GET",outcome="SUCCESS",status="200",uri="/orders",le="0.1",} 102.0
http_server_requests_seconds_bucket{application="my-order-service",exception="None",method="GET",outcome="SUCCESS",status="200",uri="/orders",le="0.5",} 145.0
http_server_requests_seconds_bucket{application="my-order-service",exception="None",method="GET",outcome="SUCCESS",status="200",uri="/orders",le="1.0",} 150.0
http_server_requests_seconds_bucket{application="my-order-service",exception="None",method="GET",outcome="SUCCESS",status="200",uri="/orders",le="+Inf",} 152.0
# HELP jvm_memory_used_bytes The amount of used memory
# TYPE jvm_memory_used_bytes gauge
jvm_memory_used_bytes{area="heap",id="PS Old Gen",} 1.123456E8
# HELP orders_created_total Total number of orders created
# TYPE orders_created_total counter
orders_created_total 4567
太棒了!你的 Java 应用已经“开口说话”了 🗣️
4. 自定义业务指标:订单创建计数器
创建一个 MetricsService:
package com.example.orderservice.metrics;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Service;
@Service
public class MetricsService {
private final Counter ordersCreatedCounter;
public MetricsService(MeterRegistry meterRegistry) {
this.ordersCreatedCounter = Counter.builder("orders_created_total")
.description("Total number of orders created")
.register(meterRegistry);
}
public void recordOrderCreated() {
ordersCreatedCounter.increment();
}
}
在你的订单创建服务中调用它:
package com.example.orderservice.controller;
import com.example.orderservice.metrics.MetricsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
@Autowired
private MetricsService metricsService;
@PostMapping("/orders")
public String createOrder(@RequestBody OrderRequest request) {
// 模拟创建订单逻辑
System.out.println("Creating order for: " + request.getCustomer());
// 👇 关键:记录自定义指标
metricsService.recordOrderCreated();
return "Order created successfully";
}
}
现在,每创建一个订单,orders_created_total 就会 +1。
💡 提示:不要使用 Gauge 来记录计数!Counter 是单调递增的,适合计数;Gauge 是瞬时值,适合内存、线程数等。
5. 测试指标是否被 Prometheus 抓取
在 Prometheus UI(http://prometheus-kube-prometheus-prometheus.monitoring.svc:9090)中,输入查询:
orders_created_total
你将看到类似结果:
orders_created_total{instance="10.244.1.12:8080",job="my-order-service",} 4571
说明 Prometheus 已成功抓取!
四、创建 ServiceMonitor:让 Prometheus 发现 Java 应用 🕵️
Prometheus 默认只抓取 kubernetes-service-endpoints 和 kubernetes-pods 这两种目标。我们的 Java 应用部署在 default 命名空间,它没有被自动发现。
我们需要创建一个 ServiceMonitor 资源,告诉 Prometheus:“去抓取这个服务的 /actuator/prometheus”。
1. 创建 Service
首先,确保你的 Java 应用暴露了一个 Service:
apiVersion: v1
kind: Service
metadata:
name: my–order–service
namespace: default
labels:
app: my–order–service
spec:
selector:
app: my–order–service
ports:
– name: http
port: 80
targetPort: 8080
type: ClusterIP
2. 创建 ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: my–order–service–monitor
namespace: default
labels:
app: my–order–service
release: prometheus # 必须与 Prometheus 的 label selector 匹配
spec:
selector:
matchLabels:
app: my–order–service
namespaceSelector:
matchNames:
– default
endpoints:
– port: http
path: /actuator/prometheus
interval: 15s
scheme: http
scrapeTimeout: 10s
📌 关键点:
- release: prometheus 必须与 Helm 安装时的 prometheusOperator.prometheus.spec.serviceMonitorSelector 一致(默认为 release=prometheus)
- port: http 对应 Service 中定义的 name: http
- path: /actuator/prometheus 是 Spring Boot Actuator 的默认路径
应用配置:
kubectl apply -f servicemonitor.yaml
3. 验证 ServiceMonitor 是否生效
进入 Prometheus UI → Status → Targets
你应该看到一个新的 Target:
default/my-order-service/0 (http://10.244.1.12:8080/actuator/prometheus)
状态为 UP,且抓取时间正常。
✅ 成功!Prometheus 已经开始抓取你的 Java 应用指标。
五、构建高价值 Grafana 面板 📊
现在,我们有了丰富的指标数据,下一步是把数据变成洞察。
Grafana 的强大之处在于:你可以用变量、模板、面板组合,构建出“能对话”的仪表盘。
1. 导入官方 Kubernetes 面板
Grafana 社区提供了大量经过验证的面板模板。
进入 Grafana → Create → Import
输入 ID:1860(Kubernetes / API Server)
点击 Load → 选择 Prometheus 数据源 → Import
你会看到一个完整的 Kubernetes 控制平面监控面板:
- API Server 请求速率
- ETCD 延迟
- Scheduler 调度成功率
🔗 推荐面板 ID:
- 1860: Kubernetes / API Server
- 1860: Kubernetes / Nodes
- 11074: Kubernetes / Pods
- 11930: Java Micrometer – JVM Metrics
2. 创建自定义 Java 应用监控面板
我们创建一个专属面板,监控订单服务。
✅ 面板标题:Order Service – Real-time Metrics
🔢 面板包含以下 5 个图表:
图表 1:订单创建速率(每秒)
查询语句:
rate(orders_created_total[1m])
面板类型: Graph 单位: ops/s 描述: 每秒创建的订单数量,用于评估业务负载。
📈 你可能看到曲线在白天高峰时飙升,午夜归于平静——这就是业务的脉搏。
图表 2:HTTP 请求延迟(99分位)
查询语句:
histogram_quantile(0.99, sum(rate(http_server_requests_seconds_bucket[5m])) by (le))
单位: s 描述: 99% 的请求响应时间不超过多少秒。若 >2s,需优化!
💡 为什么用 histogram_quantile? 因为 Prometheus 的 http_server_requests_seconds 是直方图(Histogram),不是平均值。平均值会掩盖长尾延迟。
图表 3:JVM 堆内存使用率
查询语句:
sum(jvm_memory_used_bytes{area="heap"}) / sum(jvm_memory_max_bytes{area="heap"}) * 100
单位: percent 阈值: >85% 触发告警
🚨 如果堆内存持续增长,可能是内存泄漏!结合 GC 指标一起分析。
图表 4:HTTP 错误率(5xx)
查询语句:
sum(rate(http_server_requests_seconds_count{status=~"5.."}[5m]))
/
sum(rate(http_server_requests_seconds_count[5m]))
单位: percent 描述: 服务端错误占比。>1% 就值得调查!
图表 5:JVM 线程数与 GC 次数
查询语句:
jvm_threads_live
rate(jvm_gc_live_data_size_bytes[5m])
组合: 双 Y 轴图
💡 线程数暴涨 + GC 频繁 = 线程死锁或内存溢出!
3. 添加变量:按服务/命名空间筛选
在面板设置 → Variables → New
- Name: namespace
- Type: Query
- Query: label_values(kube_pod_info, namespace)
- Refresh: On Time Range Change
然后在所有查询中加入变量:
rate(orders_created_total{namespace="$namespace"}[1m])
现在,你可以从下拉菜单中选择 default、staging、prod,动态切换监控视图!
✅ 这就是“可复用监控”的真谛:一个面板,适配所有环境。
六、告警规则:从“事后发现”到“事前预警” 🔔
监控的终极目标不是“看图”,而是自动响应。
Prometheus 的告警规则(Alerting Rules)允许你定义“当某个指标超过阈值时,触发告警”。
1. 创建告警规则文件
在 prometheus-kube-prometheus-stack 的 Helm Chart 中,告警规则通过 PrometheusRule CRD 定义。
创建文件 alert-rules.yaml:
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: java–app–alerts
namespace: default
labels:
app: my–order–service
release: prometheus
spec:
groups:
– name: java–app–alerts
rules:
– alert: JavaAppHighErrorRate
expr: |
sum(rate(http_server_requests_seconds_count{status=~"5.."}[5m]))
/
sum(rate(http_server_requests_seconds_count[5m])) > 0.01
for: 2m
labels:
severity: critical
annotations:
summary: "High error rate in Java app ({{ $value }}%)"
description: "HTTP 5xx error rate exceeds 1% for 2 minutes in {{ $labels.namespace }}/{{ $labels.pod }}"
– alert: JavaAppHighMemoryUsage
expr: |
sum(jvm_memory_used_bytes{area="heap"}) / sum(jvm_memory_max_bytes{area="heap"}) * 100 > 85
for: 5m
labels:
severity: warning
annotations:
summary: "High JVM heap usage ({{ $value }}%)"
description: "JVM heap usage has been above 85% for 5 minutes in {{ $labels.namespace }}/{{ $labels.pod }}"
– alert: OrderCreationRateDrop
expr: |
rate(orders_created_total[5m]) < 1
for: 10m
labels:
severity: critical
annotations:
summary: "Order creation rate dropped below 1 per second"
description: "Business-critical order creation has slowed down to {{ $value }} per second for 10 minutes."
应用规则:
kubectl apply -f alert-rules.yaml
2. 验证告警规则
进入 Prometheus UI → Alerting
你会看到三条规则,状态为 pending 或 firing。
⚠️ 告警规则不会自动发送通知!你需要配置 Alertmanager。
3. 配置 Alertmanager 发送通知
Alertmanager 默认已安装。我们配置它向企业微信发送告警。
编辑 Alertmanager ConfigMap:
kubectl edit configmap -n monitoring prometheus-kube-prometheus-alertmanager
在 alertmanager.yaml 中添加:
receivers:
– name: 'wechat-webhook'
webhook_configs:
– url: 'http://your-wechat-webhook-proxy:8080/send'
send_resolved: true
route:
receiver: 'wechat-webhook'
group_by: ['alertname', 'cluster', 'service']
group_wait: 30s
group_interval: 5m
repeat_interval: 3h
📌 你可能需要部署一个简单的 Webhook 转发器,将 Prometheus 的 JSON 告警转为微信消息。可以使用开源项目如 prometheus-wechat-webhook(自行部署)。
🔗 推荐阅读:Alertmanager 官方配置指南
七、实战演练:模拟高负载与告警触发 🧪
现在,我们来“制造”一次故障,验证整个监控体系是否有效。
1. 部署压测工具
创建一个简单的压测 Pod:
apiVersion: v1
kind: Pod
metadata:
name: load–generator
namespace: default
spec:
containers:
– name: curl
image: curlimages/curl
command: ["sh", "-c", "while true; do curl -s -o /dev/null http://my-order-service/orders; sleep 0.1; done"]
应用:
kubectl apply -f load-generator.yaml
观察 Grafana 面板:
- orders_created_total 上升 → ✅
- HTTP 5xx 开始出现 → ✅
- JVM Heap 超过 85% → ✅
- 2 分钟后,Prometheus Alerting → firing
- 5 分钟后,Alertmanager 发送微信通知 → ✅
你收到一条微信消息:
🔥 [CRITICAL] High error rate in Java app (1.7%) HTTP 5xx error rate exceeds 1% for 2 minutes in default/my-order-service-7b8d9c4f56-2x9kq
你立刻登录 Grafana,发现是数据库连接池耗尽了!
🚨 监控的价值:不是你看到了问题,而是你比用户早 5 分钟知道问题。
八、进阶技巧:日志与链路追踪的协同 🧩
监控三支柱:Metrics(指标)、Logging(日志)、Tracing(链路)。
目前我们只完成了 Metrics。但一个完整的可观测性体系,必须三者协同。
1. 日志:Fluent Bit + Loki
部署 Loki + Grafana Loki 插件,收集容器日志:
helm repo add grafana https://grafana.github.io/helm-charts
helm install loki grafana/loki-stack –namespace monitoring
在 Grafana 中添加 Loki 数据源,即可查询:
{container="my-order-service"} |= "ERROR"
2. 链路追踪:Jaeger + OpenTelemetry
在 Java 应用中引入 OpenTelemetry:
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
<version>1.36.0</version>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-jaeger</artifactId>
<version>1.36.0</version>
</dependency>
配置:
OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
.setTracerProvider(
SdkTracerProvider.builder()
.addSpanProcessor(
BatchSpanProcessor.builder(
JaegerGrpcSpanExporter.builder()
.setEndpoint("http://jaeger-collector.monitoring.svc:14250")
.build()
).build()
)
.build()
)
.buildAndRegisterGlobal();
在控制器中手动创建 Span:
Tracer tracer = GlobalOpenTelemetry.getTracer("order-service");
Span span = tracer.spanBuilder("createOrder").startSpan();
try (Scope scope = span.makeCurrent()) {
// 业务逻辑
span.setAttribute("customer.id", request.getCustomerId());
span.setAttribute("amount", request.getAmount());
} finally {
span.end();
}
在 Jaeger UI 中,你可以看到:
- 每个订单请求的完整调用链
- 哪个服务慢?哪个数据库查询超时?
- 依赖关系图谱
🔗 推荐:Jaeger 官方文档
💡 终极目标:当你收到告警时,不仅知道“哪里出错”,还能看到“为什么出错”——这就是可观测性的力量。
九、性能优化与生产建议 🛡️
✅ 最佳实践清单
| 📦 部署 | 使用 Helm 部署,避免手动 YAML,便于版本回滚 |
| 📈 指标 | 指标命名使用 snake_case,避免大写和特殊字符 |
| ⏱️ 抓取间隔 | 业务指标 15s,系统指标 30s,避免 Prometheus 压力过大 |
| 📊 面板 | 每个面板不超过 8 个图,聚焦核心指标 |
| 🔔 告警 | 告警必须有明确的“Actionable”(可操作)描述,避免“CPU 高”这种模糊告警 |
| 🧩 标签 | 所有指标都打上 namespace, pod, app, version 标签 |
| 🔐 安全 | Prometheus 与 Grafana 使用 Ingress + OAuth2 认证,禁止公网暴露 |
| 📦 持久化 | Prometheus 使用 PVC 存储数据,避免重启丢失历史 |
❌ 避免的陷阱
| 指标命名混乱 | 查询困难,无法复用 |
| 告警无降噪 | 告警疲劳,忽略真实故障 |
| 未设置 retention | Prometheus 占满磁盘,崩溃 |
| 未配置备份 | 数据丢失,无法回溯 |
| 依赖单点 | Prometheus 单实例,无高可用 |
📌 生产建议:使用 Thanos 或 Cortex 实现 Prometheus 高可用与长期存储。
🔗 推荐阅读:Prometheus Production Best Practices
十、总结:从监控到可观测性 🌟
我们走过了完整的旅程:
🎯 真正的监控,不是一张漂亮的图,而是一套能让你在凌晨三点安心睡觉的系统。
你不再需要“猜”为什么服务变慢,因为你看到:
- 订单创建率下降了 80%
- 数据库连接池耗尽
- 有 12 个请求在等待锁
- 2 分钟前,某个微服务开始返回 503
你点开 Jaeger,发现是缓存服务超时,立即回滚版本,5 分钟内恢复。
这不是神话,这是你亲手构建的监控体系。
附录:常用 PromQL 查询速查表 📋
| 某服务的 HTTP 请求数(5分钟) | sum(rate(http_server_requests_seconds_count[5m])) |
| 95% 延迟 | histogram_quantile(0.95, sum(rate(http_server_requests_seconds_bucket[5m])) by (le)) |
| JVM 堆内存使用率 | sum(jvm_memory_used_bytes{area="heap"}) / sum(jvm_memory_max_bytes{area="heap"}) * 100 |
| Pod 重启次数 | sum(rate(kube_pod_container_status_restarts_total[5m])) |
| 集群 CPU 使用率 | sum(rate(container_cpu_usage_seconds_total[5m])) / sum(machine_cpu_cores) * 100 |
| 磁盘使用率 | 100 – (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"} * 100) |
| 某命名空间的 Pod 数 | count(kube_pod_status_phase{phase="Running", namespace="default"}) |
🔗 推荐学习:Prometheus Query Language (PromQL) 教程
结语:你,就是云原生的守护者 🛡️
在这个万物皆可自动化的时代,监控不再是运维的“附加任务”,而是开发者的责任。
🌱 “如果你写代码,你就该负责它的健康。”
你写的每一个微服务,都应该能被观测、被理解、被信任。
今天,你用 Prometheus + Grafana + Micrometer,为你的 Java 应用装上了“心电图仪”。
明天,你将为整个集群装上“AI 预测引擎”。
而这一切,都始于你今天按下 kubectl apply -f servicemonitor.yaml 的那一刻。
🙏 感谢你读完这篇深度指南。 愿你的服务永不宕机, 愿你的告警永不误报, 愿你的夜晚,永远宁静。
📚 延伸阅读:
- Grafana Labs – Observability for Kubernetes
- Micrometer Docs – Spring Boot Integration
- Prometheus Best Practices
- The Three Pillars of Observability
🌐 你的监控体系,现在开始,才真正启动。 加油,云原生工程师!🚀
🙌 感谢你读到这里! 🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。 💡 如果本文对你有帮助,不妨 👍 点赞、📌 收藏、📤 分享 给更多需要的朋友! 💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿 🔔 关注我,不错过下一篇干货!我们下期再见!✨


