云原生可观测性体系构建:Prometheus + Grafana 全栈监控方案设计与落地

云原生可观测性体系构建:Prometheus + Grafana 全栈监控方案设计与落地

cover

一、监控盲区导致的生产故障:从"不知道出问题了"到"提前发现问题"

一次线上事故的复盘会上,团队发现一个尴尬的事实:数据库连接池在故障前 30 分钟就已经开始缓慢耗尽,但监控面板上没有任何告警触发。原因很简单——只监控了 CPU 和内存,没有覆盖连接池、线程池等应用层指标。监控体系存在盲区,等于在黑夜里开车没有仪表盘。

云原生环境下的监控挑战更大:服务数量多、调用链路长、容器生命周期短。传统的 Zabbix Agent 模式已经无法适应动态调度的容器环境。本文将给出一套基于 Prometheus + Grafana 的全栈监控方案,覆盖基础设施、中间件、应用层三个维度。

二、Prometheus 监控数据流与多维度采集架构

Prometheus 采用拉取(Pull)模式采集指标,通过 Service Discovery 自动发现监控目标。在 K8s 环境中,这一机制天然适配动态扩缩容场景。

flowchart TD
    subgraph 采集层
        A1[Node Exporter<br/>节点指标]
        A2[cAdvisor<br/>容器指标]
        A3[kube-state-metrics<br/>K8s 资源指标]
        A4[应用 /metrics<br/>业务指标]
        A5[Blackbox Exporter<br/>探测指标]
        A6[中间件 Exporter<br/>MySQL/Redis/Kafka]
    end

    subgraph 存储层
        B1[Prometheus Server<br/>短期存储]
        B2[Thanos/VM<br/>长期存储]
    end

    subgraph 展示与告警层
        C1[Grafana Dashboard]
        C2[Alertmanager<br/>告警路由]
        C3[钉钉/企微/邮件]
    end

    A1 & A2 & A3 & A4 & A5 & A6 -->|HTTP Pull| B1
    B1 -->|远程写入| B2
    B1 --> C1
    B1 -->|告警规则| C2
    B2 --> C1
    C2 --> C3

关键设计决策:

  • 采集频率:默认 15s,核心服务可缩短到 10s。频率越高存储压力越大,需要权衡。
  • 标签设计:标签是 Prometheus 数据模型的核心。必须统一标签命名规范,如 envserviceinstancenamespace。避免高基数标签(如 user_id),否则会导致时间线爆炸。
  • 联邦架构:大规模集群采用联邦模式,分片 Prometheus 各自采集,全局 Prometheus 汇聚关键指标。

三、全栈监控配置与最佳实践

3.1 Prometheus 核心配置

# prometheus.yml - 生产级配置
global:
  scrape_interval: 15s           # 默认采集间隔
  evaluation_interval: 15s       # 规则评估间隔
  scrape_timeout: 10s            # 采集超时
  external_labels:
    cluster: "prod-cluster-01"   # 集群标识,用于联邦汇聚
    env: "production"

# K8s 服务自动发现
scrape_configs:
  # 采集 K8s 节点指标
  - job_name: "kubernetes-nodes"
    kubernetes_sd_configs:
      - role: node
    relabel_configs:
      - source_labels: [__meta_kubernetes_node_name]
        target_label: node
    metric_relabel_configs:
      # 过滤无用指标,降低存储开销
      - source_labels: [__name__]
        regex: "node_cpu_.*|node_memory_.*|node_disk_.*|node_network_.*"
        action: keep

  # 采集带注解的应用 Pod
  - job_name: "kubernetes-pods"
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      # 只采集带有 prometheus.io/scrape 注解的 Pod
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep
        regex: true
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
      - source_labels: [__meta_kubernetes_namespace]
        target_label: namespace
      - source_labels: [__meta_kubernetes_pod_name]
        target_label: pod

# 远程写入长期存储
remote_write:
  - url: "http://thanos-receive:19291/api/v1/receive"
    queue_config:
      max_samples_per_send: 10000
      max_shards: 10
      batch_send_deadline: 5s

# 告警规则文件
rule_files:
  - "/etc/prometheus/rules/*.yml"

3.2 多维度告警规则

# 基础设施告警
groups:
  - name: infrastructure-alerts
    rules:
      # 节点 CPU 使用率持续高
      - alert: NodeCPUHigh
        expr: |
          100 - (avg by (node) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
        for: 10m
        labels:
          severity: warning
          team: infra
        annotations:
          summary: "节点 {{ $labels.node }} CPU 使用率超过 85%"
          runbook: "https://wiki.internal/runbook/node-cpu-high"

      # 节点内存压力
      - alert: NodeMemoryPressure
        expr: |
          (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 > 90
        for: 5m
        labels:
          severity: critical
          team: infra
        annotations:
          summary: "节点 {{ $labels.node }} 内存使用率超过 90%"

  # 应用层告警
  - name: application-alerts
    rules:
      # HTTP 错误率飙升
      - alert: HighErrorRate
        expr: |
          sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)
          / sum(rate(http_requests_total[5m])) by (service) > 0.05
        for: 3m
        labels:
          severity: critical
          team: app
        annotations:
          summary: "服务 {{ $labels.service }} 5xx 错误率超过 5%"

      # P99 延迟异常
      - alert: HighLatencyP99
        expr: |
          histogram_quantile(0.99,
            sum(rate(http_request_duration_seconds_bucket[5m])) by (le, service)
          ) > 2
        for: 5m
        labels:
          severity: warning
          team: app
        annotations:
          summary: "服务 {{ $labels.service }} P99 延迟超过 2s"

  # 中间件告警
  - name: middleware-alerts
    rules:
      # Redis 连接池耗尽
      - alert: RedisConnPoolExhausted
        expr: |
          redis_connected_clients / redis_config_maxclients > 0.8
        for: 3m
        labels:
          severity: critical
          team: middleware
        annotations:
          summary: "Redis {{ $labels.instance }} 连接数超过最大连接数的 80%"

      # Kafka 消费延迟
      - alert: KafkaConsumerLag
        expr: |
          kafka_consumer_group_lag > 100000
        for: 10m
        labels:
          severity: warning
          team: middleware
        annotations:
          summary: "Kafka 消费组 {{ $labels.group }} 延迟超过 10万条"

3.3 Alertmanager 告警路由配置

# alertmanager.yml - 告警路由与降噪
global:
  resolve_timeout: 5m

route:
  group_by: ["alertname", "namespace", "service"]
  group_wait: 30s          # 同组告警等待合并时间
  group_interval: 5m       # 同组新告警发送间隔
  repeat_interval: 4h      # 重复告警发送间隔
  receiver: "default"
  routes:
    # 严重告警立即通知
    - match:
        severity: critical
      receiver: "critical-channel"
      group_wait: 10s
      repeat_interval: 1h
    # 基础设施告警发送到运维组
    - match:
        team: infra
      receiver: "infra-channel"
    # 应用告警发送到开发组
    - match:
        team: app
      receiver: "app-channel"

receivers:
  - name: "default"
    webhook_configs:
      - url: "http://alert-gateway:8080/api/alert"
  - name: "critical-channel"
    webhook_configs:
      - url: "http://alert-gateway:8080/api/alert/critical"
  - name: "infra-channel"
    webhook_configs:
      - url: "http://alert-gateway:8080/api/alert/infra"
  - name: "app-channel"
    webhook_configs:
      - url: "http://alert-gateway:8080/api/alert/app"

# 告警抑制规则:节点宕机时抑制该节点上的所有告警
inhibit_rules:
  - source_match:
      alertname: NodeDown
    target_match:
      severity: warning
    equal: ["node"]

3.4 应用埋点规范(Python 示例)

from prometheus_client import Counter, Histogram, Gauge, generate_latest
from functools import wraps
import time

# 请求计数器
http_requests_total = Counter(
    "http_requests_total",
    "HTTP 请求总数",
    ["method", "endpoint", "status"]
)

# 请求延迟直方图
http_request_duration_seconds = Histogram(
    "http_request_duration_seconds",
    "HTTP 请求延迟",
    ["method", "endpoint"],
    buckets=[0.01, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0]
)

# 业务指标:活跃连接数
active_connections = Gauge(
    "active_connections",
    "当前活跃连接数",
    ["service"]
)

def monitor_request(endpoint: str):
    """请求监控装饰器,自动记录请求计数和延迟"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            start = time.time()
            status = "200"
            try:
                result = func(*args, **kwargs)
                return result
            except Exception as e:
                status = "500"
                raise e
            finally:
                duration = time.time() - start
                http_requests_total.labels(
                    method="GET", endpoint=endpoint, status=status
                ).inc()
                http_request_duration_seconds.labels(
                    method="GET", endpoint=endpoint
                ).observe(duration)
        return wrapper
    return decorator

四、监控方案的架构代价与适用边界

Pull 模式的网络限制:Prometheus 的 Pull 模式要求 Server 能访问所有 Target。在跨网络、跨集群场景下,需要额外部署 Pushgateway 或使用 Thanos 的 Sidecar 模式。Pushgateway 适合短生命周期任务,但不适合长期运行的指标推送。

存储成本与查询性能:Prometheus 本地存储(TSDB)默认保留 15 天数据。长期存储需要接入 Thanos 或 VictoriaMetrics。高基数指标(如每个用户一条时间线)会导致存储膨胀和查询超时,必须严格控制标签基数。

告警规则的维护成本:随着业务增长,告警规则会不断膨胀。缺乏统一管理的规则容易出现冲突和冗余。建议将告警规则代码化,纳入 Git 管理,通过 CI/CD 自动同步到 Prometheus。

Grafana 面板的碎片化:不同团队各自创建面板,缺乏统一规范,导致面板重复且难以维护。建议建立面板模板库,统一命名和布局规范。

联邦架构的查询延迟:全局 Prometheus 通过联邦采集下级数据时,查询延迟会随分片数量增加而上升。对于大规模集群,建议直接查询 Thanos Query,利用 Store Gateway 并行查询。

五、总结

构建云原生可观测性体系,核心是建立"指标采集 → 告警触发 → 面板展示"的完整闭环。技术选型上,Prometheus + Grafana 是当前最成熟的组合,但需要关注存储成本和查询性能的长期演进。

落地路线建议:第一步,部署 Prometheus + Node Exporter + cAdvisor,覆盖基础设施监控;第二步,接入 kube-state-metrics 和中间件 Exporter,补齐平台层监控;第三步,推动应用埋点,覆盖业务指标;第四步,完善告警规则和路由策略,实现分级告警;第五步,接入 Thanos 实现长期存储,建立全局视图。每一步都要以"能发现问题"为验收标准,避免监控数据堆砌而告警能力不足。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值