Kubernetes可观测性实战:Metrics、Logging与Tracing全栈方案

系统讲解 Kubernetes 可观测性三大支柱:Prometheus + Grafana 指标监控、EFK/Loki 日志采集、Jaeger/Tempo 分布式追踪,以及 Pod 拓扑分布告警、SLO 定义和值班运维实践。

可观测性(Observability )不是监控的替代词,而是通过**指标(Metrics)、日志(Logs)、追踪(Traces)**三大支柱,回答系统为什么处于当前状态的能力。在 Kubernetes 这样的动态分布式环境中,可观测性建设的复杂度远超传统虚拟机架构。


目录


1. 可观测性三大支柱

支柱回答的问题典型工具数据特点
Metrics系统的宏观状态如何?Prometheus、VictoriaMetrics、Thanos时序数据,低基数,高压缩
Logs发生了什么具体事件?EFK(Elasticsearch /Fluentd/Kibana)、Loki、PLG非结构化/半结构化,高基数
Traces请求在系统中如何流动?Jaeger、Tempo、Zipkin、SkyWalking请求上下文关联,跨度数据

三者关系:告警来自 Metrics,排查先查 Traces 看调用链,再查 Logs 看详细报错。


2. Prometheus + Grafana 指标监控

Prometheus 架构

┌─────────────────────────────────────────────┐
│              Prometheus Stack                │
│                                              │
│  ┌──────────────┐     ┌─────────────────┐   │
│  │  Prometheus  │←────│  ServiceMonitor  │   │
│  │  Server      │     │  /PodMonitor     │   │
│  │              │     │  (自动发现目标)   │   │
│  │  - TSDB      │     └─────────────────┘   │
│  │  - Retention │                           │
│  │  - Alerting  │     ┌─────────────────┐   │
│  └──────┬───────┘     │  Alertmanager    │   │
│         │             │  (告警路由/去重)  │   │
│         ↓             └────────┬────────┘   │
│  ┌──────────────┐              │            │
│  │   Grafana    │←─────────────┘            │
│  │  (可视化)    │                           │
│  └──────────────┘                           │
└─────────────────────────────────────────────┘

ServiceMonitor 自动发现

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: api-server-metrics
  namespace: monitoring
spec:
  namespaceSelector:
    matchNames:
      - production
  selector:
    matchLabels:
      monitoring: enabled
  endpoints:
    - port: metrics          # Service 中的端口名
      path: /metrics
      interval: 15s
      scrapeTimeout: 10s
      honorLabels: true

关键点:

  • ServiceMonitor 通过标签选择器自动发现目标 Service
  • 应用需要在 Service 中暴露 /metrics 端点
  • 不需要在 Prometheus 中手动维护 target 列表

常用 Kubelet 指标

# 节点 CPU 使用率
100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# 节点内存使用率
100 * (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)

# Pod CPU 使用率(相对 limit)
rate(container_cpu_usage_seconds_total[5m]) / container_spec_cpu_quota * 100

# 容器内存使用率(相对 limit)
container_memory_working_set_bytes / container_spec_memory_limit_bytes

# 节点磁盘使用率
100 - (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"} * 100)

Grafana 看板设计

推荐内置或导入的看板:

看板ID / 来源用途
Node Exporter Full1860节点资源全貌
Kubernetes Cluster7249集群整体状态
Kubernetes Pod747Pod 级别资源
Kubernetes Network12658网络流量
Kubernetes Storage11454PVC/磁盘使用

3. 日志采集方案

方案对比:EFK vs PLG

方案存储查询语言资源占用扩展性云原生
EFK (Elasticsearch)索引倒排KQL/Lucene高(内存)好中
PLG (Loki)标签索引 + 对象存储LogQL低(无索引)很好原生
Vector+ClickHouse列式SQL中很好新兴

PLG 栈部署

# Promtail(日志采集)
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: promtail
spec:
  template:
    spec:
      containers:
        - name: promtail
          image: grafana/promtail:latest
          args:
            - -config.file=/etc/promtail/promtail.yaml
          volumeMounts:
            - name: logs
              mountPath: /var/log
            - name: containers
              mountPath: /var/log/containers
            - name: pods
              mountPath: /var/log/pods
      volumes:
        - name: logs
          hostPath:
            path: /var/log
        - name: containers
          hostPath:
            path: /var/log/containers

LogQL 查询示例

# 1. 查询应用日志
{app="api-server", namespace="production"}

# 2. 包含错误的日志
{app="api-server"} |= "ERROR"

# 3. 按错误类型聚合统计
sum by (level) (rate({app="api-server"} |= "ERROR" [1m]))

# 4. 追踪特定请求 ID
{app="api-server"} |= "trace_id=abc123"

# 5. 解析 JSON 日志字段
{app="api-server"}
  | json
  | status_code = "500"
  | line_format "{{.timestamp}} {{.message}}"

Loki 设计优点:

  • 只索引标签(类似 Prometheus),不索引日志内容,存储成本极低
  • 日志存储在对象存储(S3/GCS/MinIO),无状态易于扩展
  • 查询语法 LogQL 与 PromQL 一致,降低学习成本

4. 分布式追踪

OpenTelemetry 架构

OpenTelemetry 已成为云原生可观测性的统一标准,集成了 Metrics、Logs、Traces:

App (OpenTelemetry SDK)
  ↓
  Traces → OTLP → Collector → Jaeger/Tempo
  Metrics → OTLP → Collector → Prometheus/Thanos
  Logs → OTLP → Collector → Loki/Elasticsearch

自动埋点(零侵入)

# OpenTelemetry Operator 注入 sidecar
apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
  name: production
spec:
  mode: deployment
  config: |
    receivers:
      otlp:
        protocols:
          grpc:
            endpoint: 0.0.0.0:4317
          http:
            endpoint: 0.0.0.0:4318
    exporters:
      otlp/jaeger:
        endpoint: jaeger-collector:4317
        tls:
          insecure: true
    service:
      pipelines:
        traces:
          receivers: [otlp]
          exporters: [otlp/jaeger]

在 Pod 上加注解自动注入:

metadata:
  annotations:
    instrumentation.opentelemetry.io/inject-sdk: "true"

Jaeger 查询

# 找到慢请求
jaeger-query:16686 → Service: api-server → Operation: POST /api/orders

# 查看某 trace 的完整调用链
trace_id: 4f7d3c8a9b2e1f (横跨 api-server → order-service → payment-service → postgres)

5. Kubernetes 核心指标

必须监控的指标

维度指标告警阈值严重度
节点CPU 使用率> 80% 持续 5mWarning
节点内存使用率> 85% 持续 5mWarning
节点磁盘使用率> 85%Warning
节点磁盘只读inode 耗尽Critical
Pod重启次数> 3 次 / 10mWarning
PodOOM KillOOMKilled 状态Critical
Pod就绪状态Not Ready > 5mCritical
集群Pod 调度失败Pending > 30mWarning
集群API Server 延迟P99 > 1sCritical

Prometheus 告警规则示例

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: kubernetes-alerts
  namespace: monitoring
spec:
  groups:
    - name: kubernetes-resources
      rules:
        - alert: KubernetesNodeNotReady
          expr: kube_node_status_condition{condition="Ready",status="true"} == 0
          for: 10m
          labels:
            severity: critical
          annotations:
            summary: "节点 {{ $labels.node }} 不可用"
            description: "节点已持续 10 分钟报告 NotReady 状态"

        - alert: KubernetesPodCrashLooping
          expr: rate(kube_pod_container_status_restarts_total[15m]) > 0
          for: 5m
          labels:
            severity: warning
          annotations:
            summary: "Pod {{ $labels.pod }} 频繁重启"

        - alert: KubernetesHighMemoryUsage
          expr: |
            container_memory_working_set_bytes{container!=""} /
            container_spec_memory_limit_bytes > 0.9
          for: 5m
          labels:
            severity: warning
          annotations:
            summary: "Pod {{ $labels.pod }} 内存使用率超过 90%"

        - alert: KubernetesPersistentVolumeFillingUp
          expr: |
            kubelet_volume_stats_used_bytes /
            kubelet_volume_stats_capacity_bytes > 0.85
          for: 5m
          labels:
            severity: warning
          annotations:
            summary: "PVC {{ $labels.persistentvolumeclaim }} 使用率超过 85%"

Alertmanager 告警路由

apiVersion: monitoring.coreos.com/v1
kind: AlertmanagerConfig
metadata:
  name: main-routes
  namespace: monitoring
spec:
  route:
    groupBy: ['alertname', 'namespace']
    groupWait: 30s
    groupInterval: 5m
    repeatInterval: 12h
    receiver: default
    routes:
      - match:
          severity: critical
        receiver: pagerduty
        continue: true
      - match:
          severity: warning
        receiver: slack
  receivers:
    - name: default
      slackConfigs:
        - apiURL:
            key: url
            name: slack-webhook
          channel: '#alerts'
    - name: pagerduty
      pagerdutyConfigs:
        - serviceKey:
            key: key
            name: pagerduty-key

6. 告警规则与值班

告警分级

级别响应时间通知方式示例
P0 (Critical)5 分钟内电话 + PagerDuty核心服务宕机、数据丢失
P1 (High)15 分钟内Slack @channel节点故障、大量 5xx
P2 (Medium)1 小时内Slack 消息资源使用率告警
P3 (Low)下个工作日邮件/周报容量规划预警

告警疲劳防治

  1. 去重:同问题在恢复前只发送一次
  2. 分组:相关告警合并通知
  3. 静默(Silence):维护窗口自动静默已知告警
  4. 抑制:高级别告警自动抑制相关低级别告警

7. SLO/SLI 实践

定义 SLI/SLO

服务SLISLO测量窗口
API Gateway可用性99.95%30天
API Gateway延迟 (p99)< 200ms30天
Order Service错误率< 0.1%30天
Database查询延迟 (p99)< 50ms7天

错误预算

月度错误预算 = (1 - SLO) × 月度时间

SLO = 99.95%
月度错误预算 = 0.05% × 30天 = 21.6 分钟

错误预算耗尽前:优先稳定性和修复
错误预算充足时:可以承担更多变更风险

SLO 监控 PromQL

# 可用性(成功案例 / 总请求)
sum(rate(http_requests_total{status=~"2.."}[1h]))
/
sum(rate(http_requests_total[1h]))

# 延迟百分位
histogram_quantile(0.99,
  sum(rate(http_request_duration_seconds_bucket[1h])) by (le)
)

8. 可观测性架构设计

中等规模集群(<500 节点)

┌───────────────────────────────────────┐
│           业务集群(500节点)            │
│                                        │
│  Promtail(DS) → Loki → Object Storage  │
│  Prometheus → Remote Write → Thanos    │
│  OTEL SDK → OTEL Collector → Jaeger    │
│                                        │
└───────────────────────────────────────┘
            ↓
┌───────────────────────────────────────┐
│           观测集群(独立)               │
│                                        │
│  Thanos Query → Grafana                │
│  Loki Query Frontend                   │
│  Jaeger Query                          │
│  Alertmanager                          │
│                                        │
└───────────────────────────────────────┘

大规模集群(>500 节点)

  • 指标:VictoriaMetrics 或 Thanos(对象存储后端)
  • 日志:Loki(多租户 + S3)
  • 追踪:Tempo(比 Jaeger 更轻量,对象存储后端)

总结

支柱工具核心设计要点
MetricsPrometheus + GrafanaServiceMonitor 自动发现,Recording Rule 预聚合
LogsLoki + Promtail标签索引降成本,LogQL 统一查询
TracesJaeger/Tempo + OTELSidecar 自动注入,TraceID 贯穿调用链
告警Alertmanager分级路由、去重、抑制、静默
SLOPromQL + Grafana错误预算量化可用性,指导发布节奏

可观测性不是事后补充,而是系统设计的一部分。完善的可观测体系能够显著缩短 MTTR(平均恢复时间),是让运维团队从"救火"转向"预防"的关键基础设施。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「云原生」更多文章

  1. 证书管理与自动轮换:cert-manager 与 kubelet 证书轮换
  2. Sidecar 模式与原生边车容器:init 容器、生命周期与重启策略
  3. CoreDNS 与服务发现:插件链、NDOTS 与 Headless Service