在这里插入图片描述

👋 大家好,欢迎来到我的技术博客!
📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。
🎯 本文将围绕Prometheus这个话题展开,希望能为你带来一些启发或实用的参考。
🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!


文章目录

Prometheus - 监控 K8s 集群:kube-state-metrics 集成与全维度监控

在现代云原生架构中,Kubernetes(简称 K8s)已成为容器编排的事实标准。然而,随着集群规模的扩大和微服务数量的激增,如何有效监控整个系统运行状态成为运维团队的核心挑战。Prometheus 作为 CNCF 毕业项目,凭借其强大的多维数据模型、灵活的查询语言 PromQL 以及活跃的生态系统,已成为 Kubernetes 监控领域的首选方案。而 kube-state-metrics 作为连接 Kubernetes API 与 Prometheus 的关键桥梁,提供了对集群资源状态的深度洞察。

本文将深入探讨如何通过集成 kube-state-metrics 构建一个覆盖基础设施、工作负载、应用性能和业务指标的全维度 Kubernetes 监控体系,并结合 Java 应用示例展示端到端的可观测性实践。

为什么需要 kube-state-metrics?

在理解 kube-state-metrics 的作用之前,我们先明确 Kubernetes 监控的两个核心维度:

  1. 基础设施监控(Infrastructure Metrics)
    关注节点(Node)、Pod、容器的资源使用情况,如 CPU、内存、磁盘 I/O、网络流量等。这类指标通常由 cAdvisor(集成在 kubelet 中)或 node-exporter 提供。

  2. 资源状态监控(Resource State Metrics)
    关注 Kubernetes 资源对象的元数据状态,例如:

    • Deployment 是否处于期望的副本数?
    • Pod 是否处于 Pending、CrashLoopBackOff 等异常状态?
    • Service 是否有可用的 Endpoints?
    • Job 是否成功完成?

这些状态信息无法通过传统的资源使用率指标反映,但对判断系统健康度至关重要。而这正是 kube-state-metrics 的核心价值所在。

📌 kube-state-metrics 是什么?
它是一个简单的服务,监听 Kubernetes API Server,将集群中各种资源对象(如 Pods、Deployments、Services 等)的状态转换为 Prometheus 可抓取的指标格式。它不存储任何数据,仅提供实时快照。

与 cAdvisor / node-exporter 的区别

组件 数据来源 指标类型 示例
cAdvisor 容器运行时(如 containerd) 资源使用率 container_cpu_usage_seconds_total
node-exporter 主机操作系统 主机级资源 node_memory_MemAvailable_bytes
kube-state-metrics Kubernetes API Server 资源对象状态 kube_pod_status_phase{phase="Running"}

三者互补,共同构成完整的监控视图。

部署 kube-state-metrics 到 Kubernetes 集群

kube-state-metrics 通常以 Deployment 形式部署在集群中,并通过 Service 暴露指标端点。以下是推荐的部署方式(基于 Helm):

# 添加 prometheus-community Helm 仓库
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

# 安装 kube-state-metrics
helm install kube-state-metrics prometheus-community/kube-state-metrics \
  --namespace monitoring \
  --create-namespace

🔗 官方 Helm Chart 文档:https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-state-metrics

安装完成后,验证服务是否正常运行:

kubectl get pods -n monitoring -l app.kubernetes.io/name=kube-state-metrics
# 应看到类似输出:
# NAME                                  READY   STATUS    RESTARTS   AGE
# kube-state-metrics-7d5f9c8b4d-2xk9l   1/1     Running   0          2m

访问指标端点(需端口转发):

kubectl port-forward svc/kube-state-metrics -n monitoring 8080:8080
curl http://localhost:8080/metrics

你将看到大量以 kube_ 开头的指标,例如:

kube_pod_status_phase{namespace="default",pod="my-app-7d5f9c8b4d-abc12",phase="Running"} 1
kube_deployment_status_replicas_available{namespace="monitoring",deployment="kube-state-metrics"} 1

配置 Prometheus 抓取 kube-state-metrics 指标

为了让 Prometheus 发现并抓取 kube-state-metrics 的指标,我们需要配置 ServiceMonitor(如果使用 Prometheus Operator)或直接在 prometheus.yml 中添加 job。

方式一:使用 Prometheus Operator(推荐)

如果你使用 kube-prometheus-stack(包含 Prometheus Operator),只需创建一个 ServiceMonitor

# kube-state-metrics-servicemonitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: kube-state-metrics
  namespace: monitoring
  labels:
    release: prometheus-operator  # 与 Prometheus 实例的 serviceMonitorSelector 匹配
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: kube-state-metrics
  namespaceSelector:
    matchNames:
      - monitoring
  endpoints:
    - port: http
      interval: 30s

应用后,Prometheus 会自动发现该目标。

方式二:直接修改 prometheus.yml

如果你手动部署 Prometheus,编辑其配置文件:

scrape_configs:
  - job_name: 'kube-state-metrics'
    static_configs:
      - targets: ['kube-state-metrics.monitoring.svc.cluster.local:8080']

💡 提示:确保 Prometheus 有权限访问 monitoring 命名空间中的服务。

核心 kube-state-metrics 指标详解

kube-state-metrics 暴露了数百个指标,覆盖几乎所有 Kubernetes 资源。以下是几类关键指标及其使用场景:

1. Pod 状态监控

  • kube_pod_status_phase{phase="Pending|Running|Succeeded|Failed|Unknown"}

    • 用途:检测卡在 Pending 状态的 Pod(可能因资源不足或镜像拉取失败)
    • 告警规则示例
      - alert: PodStuckInPending
        expr: kube_pod_status_phase{phase="Pending"} > 0
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Pod stuck in pending state"
      
  • kube_pod_container_status_restarts_total

    • 用途:识别频繁重启的容器(可能因 OOM 或应用崩溃)
    • PromQL 查询
      # 过去 5 分钟内重启次数 > 3 的容器
      rate(kube_pod_container_status_restarts_total[5m]) > 0.01
      

2. Deployment 健康度

  • kube_deployment_status_replicas_available
  • kube_deployment_spec_replicas
    • 用途:判断 Deployment 是否达到期望副本数
    • PromQL 查询
      # 可用副本数 < 期望副本数的 Deployment
      kube_deployment_status_replicas_available < kube_deployment_spec_replicas
      

3. 节点状态

  • kube_node_status_condition{condition="Ready", status="true"}
    • 用途:监控节点是否就绪
    • 告警规则
      - alert: NodeNotReady
        expr: kube_node_status_condition{condition="Ready", status="true"} == 0
        for: 2m
        labels:
          severity: critical
      

4. 资源配额与限制

  • kube_pod_container_resource_requests
  • kube_pod_container_resource_limits
    • 用途:分析集群资源分配情况,避免资源碎片

构建全维度监控体系:四层监控模型

一个健壮的 Kubernetes 监控体系应覆盖以下四个层次:

渲染错误: Mermaid 渲染失败: Parse error on line 9: ... C --> Application Instrumentation -----------------------^ Expecting 'SEMI', 'NEWLINE', 'EOF', 'AMP', 'START_LINK', 'LINK', 'LINK_ID', got 'NODE_STRING'

第一层:基础设施监控(Infrastructure)

  • 关注点:Node、Pod、容器的 CPU、内存、磁盘、网络
  • 数据源
    • node_exporter:主机级指标
    • cAdvisor:容器级指标(通过 kubelet /metrics/cadvisor 暴露)
  • 关键指标
    • node_cpu_seconds_total
    • container_memory_usage_bytes
    • rate(container_network_receive_bytes_total[5m])

第二层:工作负载监控(Workload)

  • 关注点:Kubernetes 资源对象的状态与配置
  • 数据源kube-state-metrics
  • 关键指标
    • kube_pod_status_phase
    • kube_deployment_status_replicas_available
    • kube_service_info

第三层:应用性能监控(APM)

  • 关注点:应用内部的性能指标,如 HTTP 延迟、错误率、JVM 状态
  • 数据源:应用自身暴露的指标(通过 Micrometer、Prometheus Client 等)
  • 关键指标
    • http_server_requests_seconds_count
    • jvm_memory_used_bytes
    • logback_events_total

第四层:业务监控(Business)

  • 关注点:与业务直接相关的指标,如订单量、支付成功率
  • 数据源:应用埋点
  • 关键指标
    • order_created_total
    • payment_success_rate

接下来,我们将通过一个 Java Spring Boot 应用示例,展示如何实现第三层和第四层监控。

Java 应用集成:Spring Boot + Micrometer + Prometheus

Spring Boot 应用可通过 Micrometer 库轻松暴露 Prometheus 指标。Micrometer 是一个应用指标门面(类似 SLF4J),支持多种监控后端,包括 Prometheus。

步骤 1:添加依赖

pom.xml 中添加:

<dependencies>
    <!-- Spring Boot Actuator -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    
    <!-- Micrometer Registry for Prometheus -->
    <dependency>
        <groupId>io.micrometer</groupId>
        <artifactId>micrometer-registry-prometheus</artifactId>
    </dependency>
</dependencies>

步骤 2:启用 Prometheus 端点

application.yml 中配置:

management:
  endpoints:
    web:
      exposure:
        include: health,info,prometheus  # 暴露 prometheus 端点
  metrics:
    tags:
      application: ${spring.application.name}

启动应用后,访问 http://localhost:8080/actuator/prometheus 即可看到指标。

步骤 3:自定义业务指标

假设我们有一个订单服务,希望监控订单创建数量和支付成功率:

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.stereotype.Service;

@Service
public class OrderService {

    private final Counter orderCreatedCounter;
    private final Counter paymentSuccessCounter;
    private final Counter paymentFailureCounter;
    private final Timer orderProcessingTimer;

    public OrderService(MeterRegistry meterRegistry) {
        // 订单创建计数器
        this.orderCreatedCounter = Counter.builder("order_created_total")
                .description("Total number of orders created")
                .register(meterRegistry);
        
        // 支付成功/失败计数器
        this.paymentSuccessCounter = Counter.builder("payment_success_total")
                .description("Total successful payments")
                .register(meterRegistry);
        this.paymentFailureCounter = Counter.builder("payment_failure_total")
                .description("Total failed payments")
                .register(meterRegistry);
        
        // 订单处理耗时
        this.orderProcessingTimer = Timer.builder("order_processing_duration_seconds")
                .description("Time taken to process an order")
                .register(meterRegistry);
    }

    public void createOrder(Order order) {
        Timer.Sample sample = Timer.start();
        try {
            // 业务逻辑
            doCreateOrder(order);
            orderCreatedCounter.increment();
        } finally {
            sample.stop(orderProcessingTimer);
        }
    }

    public boolean processPayment(Payment payment) {
        try {
            boolean success = doProcessPayment(payment);
            if (success) {
                paymentSuccessCounter.increment();
            } else {
                paymentFailureCounter.increment();
            }
            return success;
        } catch (Exception e) {
            paymentFailureCounter.increment();
            throw e;
        }
    }
}

步骤 4:配置 Prometheus 抓取应用指标

在 Prometheus 配置中添加 job:

scrape_configs:
  - job_name: 'spring-boot-app'
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_label_app]
        action: keep
        regex: my-java-app  # 你的应用标签
      - source_labels: [__address__]
        action: replace
        target_label: __address__
        regex: ([^:]+)(?::\d+)?
        replacement: $1:8080  # 应用端口
      - source_labels: [__meta_kubernetes_pod_name]
        target_label: pod

🔗 Micrometer 官方文档:https://micrometer.io/docs

关键告警规则设计

有效的告警应遵循 SMART 原则(具体、可衡量、可实现、相关、有时限)。以下是针对不同层级的典型告警规则:

1. 节点级别告警

- alert: HighNodeCPU
  expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 90
  for: 10m
  labels:
    severity: warning
  annotations:
    summary: "High CPU usage on {{ $labels.instance }}"

- alert: NodeDiskSpaceLow
  expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) < 0.1
  for: 5m
  labels:
    severity: critical

2. Pod 级别告警

- alert: PodCrashLooping
  expr: rate(kube_pod_container_status_restarts_total[5m]) > 0.1
  for: 10m
  labels:
    severity: warning
  annotations:
    summary: "Pod {{ $labels.pod }} is crash looping"

- alert: PodNotReady
  expr: sum by (pod) (kube_pod_status_ready{condition="true"}) == 0
  for: 5m
  labels:
    severity: critical

3. 应用级别告警(Java)

- alert: HighHttpErrorRate
  expr: sum(rate(http_server_requests_seconds_count{status=~"5.."}[5m])) 
        / sum(rate(http_server_requests_seconds_count[5m])) > 0.05
  for: 5m
  labels:
    severity: warning
  annotations:
    summary: "HTTP error rate is above 5%"

- alert: JVMHeapUsageHigh
  expr: jvm_memory_used_bytes{area="heap"} / jvm_memory_max_bytes{area="heap"} > 0.85
  for: 10m
  labels:
    severity: warning

4. 业务级别告警

- alert: OrderCreationDropped
  expr: rate(order_created_total[10m]) < 1
  for: 15m
  labels:
    severity: critical
  annotations:
    summary: "Order creation rate dropped below 1 per 10 minutes"

可视化:Grafana 仪表盘构建

Grafana 是 Prometheus 最流行的可视化工具。我们可以创建多层仪表盘:

1. 集群概览仪表盘

  • 节点 CPU/内存使用率
  • Pod 状态分布(Running/Pending/Failed)
  • Deployment 健康度(可用副本 vs 期望副本)

2. 应用性能仪表盘

  • HTTP 请求速率、延迟、错误率
  • JVM 内存、GC 次数、线程数
  • 自定义业务指标(如订单量)

3. 业务指标仪表盘

  • 实时订单量趋势
  • 支付成功率
  • 用户地域分布(需额外埋点)

🔗 Grafana 官方仪表盘库:https://grafana.com/grafana/dashboards/
推荐导入 ID:1860(Kubernetes Cluster Monitoring)、12856(Spring Boot Stats)

高级技巧:指标关联与根因分析

真正的全维度监控不仅在于收集指标,更在于关联分析。例如:

场景:应用响应时间突然升高

  1. 基础设施层:检查节点 CPU 是否打满 → node_cpu_seconds_total
  2. 工作负载层:检查 Pod 是否被驱逐或重启 → kube_pod_status_phase, kube_pod_container_status_restarts_total
  3. 应用层:检查 GC 暂停时间是否过长 → jvm_gc_pause_seconds_sum
  4. 业务层:检查是否伴随订单量激增 → order_created_total

通过 PromQL 的 join 操作,我们可以关联不同维度的指标:

# 查看高延迟请求对应的 Pod
http_server_requests_seconds_count{status=~"5.."} 
  + on(pod) group_left() 
  kube_pod_status_phase{phase="Running"}

使用 Recording Rules 优化查询

对于复杂查询,可创建 Recording Rules 预计算结果:

# prometheus-rules.yaml
groups:
- name: app-rules
  rules:
  - record: job:http_inprogress_requests:sum
    expr: sum(http_server_requests_seconds_count) by (job)
  - record: cluster:pod_cpu_usage:ratio
    expr: sum(rate(container_cpu_usage_seconds_total[5m])) 
          / sum(kube_pod_container_resource_requests{resource="cpu"})

故障排查实战:从告警到修复

让我们通过一个真实案例演示全维度监控的价值。

问题现象

收到告警:PodCrashLooping,Pod order-service-7d5f9c8b4d-abc12 每 2 分钟重启一次。

排查步骤

  1. 查看 Pod 日志

    kubectl logs order-service-7d5f9c8b4d-abc12 --previous
    

    输出:java.lang.OutOfMemoryError: Java heap space

  2. 检查 JVM 指标

    • 在 Grafana 中查看 jvm_memory_used_bytes,发现堆内存持续增长至上限
    • jvm_gc_pause_seconds_count 显示 Full GC 频繁但无法释放内存
  3. 关联业务指标

    • order_created_total 在问题发生前有突增
    • 推测:大促活动导致订单量激增,应用未做限流
  4. 检查资源请求

    • kube_pod_container_resource_requests{resource="memory"} 显示内存请求为 512Mi
    • container_memory_usage_bytes 显示实际使用已超 1Gi

解决方案

  1. 临时扩容:增加 Pod 内存限制
    resources:
      requests:
        memory: "1Gi"
      limits:
        memory: "2Gi"
    
  2. 长期优化
    • 引入缓存减少数据库压力
    • 添加限流机制(如 Resilience4j)
    • 优化代码内存使用(如分页查询)

验证修复

  • 观察 kube_pod_container_status_restarts_total 是否归零
  • 监控 jvm_memory_used_bytes 是否稳定
  • 确认 order_created_total 恢复正常

性能优化与最佳实践

1. 控制指标基数(Cardinality)

高基数指标会显著增加 Prometheus 存储和查询压力。避免在标签中使用高变异性字段(如用户 ID、请求 ID)。

好做法

// 使用有限枚举值作为标签
Counter.builder("http_requests_total")
       .tag("method", request.getMethod()) // GET/POST 等
       .tag("status", String.valueOf(response.getStatus())) // 200/404/500

坏做法

// 用户 ID 可能有百万级,导致指标爆炸
.tag("user_id", userId)

2. 合理设置抓取间隔

  • 基础设施指标:15-30s
  • 应用指标:30-60s
  • 业务指标:60s+

过短的间隔会增加负载,过长则影响告警时效性。

3. 使用 Relabeling 精简标签

通过 relabel_configs 移除不必要的标签:

relabel_configs:
  - source_labels: [__meta_kubernetes_pod_label_app]
    target_label: app
  - action: labeldrop
    regex: __meta_kubernetes_pod_label_.*

4. 分离长期存储

对于超过 15 天的历史数据,建议使用 Thanos 或 Cortex 实现长期存储和全局查询。

总结:构建可观测性闭环

通过集成 kube-state-metrics,我们成功将 Kubernetes 集群的“状态”纳入监控体系,与基础设施指标、应用性能指标、业务指标共同构成了完整的可观测性金字塔:

渲染错误: Mermaid 渲染失败: Parsing failed: Lexer error on line 3, column 5: unexpected character: ->“<- at offset: 25, skipped 8 characters. Lexer error on line 3, column 14: unexpected character: ->:<- at offset: 34, skipped 1 characters. Lexer error on line 4, column 5: unexpected character: ->“<- at offset: 43, skipped 8 characters. Lexer error on line 4, column 14: unexpected character: ->:<- at offset: 52, skipped 1 characters. Lexer error on line 5, column 5: unexpected character: ->“<- at offset: 61, skipped 8 characters. Lexer error on line 5, column 14: unexpected character: ->:<- at offset: 70, skipped 1 characters. Lexer error on line 6, column 5: unexpected character: ->“<- at offset: 79, skipped 6 characters. Lexer error on line 6, column 12: unexpected character: ->:<- at offset: 86, skipped 1 characters. Parse error on line 3, column 16: Expecting token of type 'EOF' but found `25`. Parse error on line 4, column 16: Expecting token of type 'EOF' but found `25`. Parse error on line 5, column 16: Expecting token of type 'EOF' but found `30`. Parse error on line 6, column 14: Expecting token of type 'EOF' but found `20`.

但这仅仅是开始。真正的价值在于:

  • 预防性:通过容量规划避免故障(如预测内存耗尽)
  • 快速定位:从告警到根因分析的时间从小时级缩短到分钟级
  • 业务驱动:将技术指标与业务结果关联,证明 IT 价值

🌟 记住:监控不是目的,而是手段。最终目标是构建一个自愈、自适应、以业务为中心的云原生系统。

随着 Kubernetes 生态的演进,Service Mesh(如 Istio)、eBPF 等新技术将进一步丰富监控维度。但无论技术如何变化,全维度、关联性、自动化始终是监控体系的核心原则。

现在,是时候检查你的集群是否已具备这四层防护了!🚀


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

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐