欢迎光临
我们一直在努力

Kubernetes - 基于 Prometheus+Grafana 搭建 K8s 监控体系

在这里插入图片描述

👋 大家好,欢迎来到我的技术博客! 📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。 🎯 本文将围绕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


十、总结:从监控到可观测性 🌟

我们走过了完整的旅程:

  • 🏗️ 理解了 Kubernetes 监控的四层模型
  • 🛠️ 用 Helm 部署了 Prometheus + Grafana + Alertmanager
  • 🐘 为 Java 应用接入 Micrometer,暴露了 JVM 与业务指标
  • 🕵️ 创建了 ServiceMonitor,让 Prometheus 自动发现应用
  • 📊 设计了高价值的 Grafana 面板,用可视化讲述数据故事
  • 🔔 配置了精准告警规则,实现“事前预警”
  • 🔗 探索了日志与链路追踪的协同,迈向完整可观测性
  • 🎯 真正的监控,不是一张漂亮的图,而是一套能让你在凌晨三点安心睡觉的系统。

    你不再需要“猜”为什么服务变慢,因为你看到:

    • 订单创建率下降了 80%
    • 数据库连接池耗尽
    • 有 12 个请求在等待锁
    • 2 分钟前,某个微服务开始返回 503

    你点开 Jaeger,发现是缓存服务超时,立即回滚版本,5 分钟内恢复。

    这不是神话,这是你亲手构建的监控体系。


    附录:常用 PromQL 查询速查表 📋

    目标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

    🌐 你的监控体系,现在开始,才真正启动。 加油,云原生工程师!🚀


    🙌 感谢你读到这里! 🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。 💡 如果本文对你有帮助,不妨 👍 点赞、📌 收藏、📤 分享 给更多需要的朋友! 💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿 🔔 关注我,不错过下一篇干货!我们下期再见!✨

    赞(0)
    未经允许不得转载:171主机测评 » Kubernetes - 基于 Prometheus+Grafana 搭建 K8s 监控体系
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址