Wiki LogoWiki - The Power of Many

Week 07: 深度可观测性 - 监控、日志与链路追踪

构建现代云原生可观测性架构, 实现全栈性能洞察与流量治理.

1. 本周核心目标

Week 06 完成了安全加固与策略治理的深度学习. 本周聚焦于 可观测性 (Observability) 三大支柱: 指标 (Metrics), 日志 (Logs), 链路追踪 (Traces), 构建完整的故障诊断与性能优化能力.

1.1 本周任务清单

  1. 指标体系: 理解 Prometheus 数据模型, TSDB 存储原理与 PromQL 查询.
  2. 日志系统: 掌握 Loki 架构与日志收集模式 (Sidecar vs DaemonSet).
  3. 链路追踪: 理解分布式追踪原理与 OpenTelemetry 标准.
  4. 告警治理: 配置告警规则, 路由与静默抑制.
  5. 黄金信号: 实践 SRE 四大黄金信号监控模型.

2. Prometheus Service Discovery 机制

2.1 Kubernetes SD 角色

Prometheus 通过 Kubernetes API 自动发现监控目标:

Role发现目标典型用途
node集群节点node_exporter
pod所有 Pod应用指标
serviceService 对象通过 Service 访问
endpointsEndpoints 对象直接访问 Pod IP
ingressIngress 对象黑盒探测

2.2 Relabeling 管道

scrape_configs:
- 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_port]
    action: replace
    target_label: __address__
    regex: (.+)
    replacement: ${1}
  # 添加 namespace 标签
  - source_labels: [__meta_kubernetes_namespace]
    target_label: namespace
  # 添加 pod 标签
  - source_labels: [__meta_kubernetes_pod_name]
    target_label: pod

2.3 metric_relabel_configs

在抓取后但存储前修改指标:

metric_relabel_configs:
# 删除高 Cardinality 标签
- source_labels: [url]
  action: labeldrop
# 重命名指标
- source_labels: [__name__]
  regex: 'http_requests_total'
  replacement: 'http_requests'
  target_label: __name__
# 删除不需要的指标
- source_labels: [__name__]
  regex: 'go_.*'
  action: drop

3. SLO-based Alerting

3.1 Error Budget 告警

基于 SLO 的告警比阈值告警更有效:

# 30 天 99.9% 可用性 SLO
# Error Budget = 30 * 24 * 60 * 0.001 = 43.2 分钟

groups:
- name: slo-alerts
  rules:
  # 快速燃烧 (5% budget in 1h)
  - alert: HighErrorBudgetBurn
    expr: |
      (
        sum(rate(http_requests_total{status=~"5.."}[1h]))
        /
        sum(rate(http_requests_total[1h]))
      ) > 14.4 * 0.001
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: "Error budget burning too fast"

  # 慢速燃烧 (10% budget in 6h)
  - alert: ErrorBudgetBurn
    expr: |
      (
        sum(rate(http_requests_total{status=~"5.."}[6h]))
        /
        sum(rate(http_requests_total[6h]))
      ) > 2.4 * 0.001
    for: 30m
    labels:
      severity: warning

3.2 Multi-window, Multi-burn-rate

结合多个时间窗口减少误报:

# 短窗口 (快速检测) + 长窗口 (确认趋势)
- alert: HighErrorRate
  expr: |
    (
      sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) > 0.01
    ) and (
      sum(rate(http_requests_total{status=~"5.."}[1h])) / sum(rate(http_requests_total[1h])) > 0.01
    )

4. Kubernetes 组件关键指标

4.1 API Server

指标描述告警阈值
apiserver_request_total请求总数 (按 verb, resource, code)5xx 比例 > 1%
apiserver_request_duration_seconds请求延迟p99 > 1s
apiserver_current_inflight_requests并发请求数接近限制
etcd_request_duration_secondsEtcd 请求延迟p99 > 100ms

4.2 Scheduler

指标描述
scheduler_schedule_attempts_total调度尝试次数 (按结果)
scheduler_pod_scheduling_duration_seconds调度延迟
scheduler_pending_pods等待调度的 Pod 数
scheduler_preemption_attempts_total抢占尝试次数

4.3 Kubelet

指标描述
kubelet_running_pods运行中的 Pod 数
kubelet_pleg_relist_duration_secondsPLEG relist 耗时
kubelet_pod_start_duration_secondsPod 启动延迟
kubelet_volume_stats_*卷使用统计

4.4 Etcd

指标描述告警阈值
etcd_mvcc_db_total_size_in_bytes数据库大小> 6GB 需压缩
etcd_disk_wal_fsync_duration_secondsWAL fsync 延迟p99 > 10ms
etcd_server_leader_changes_seen_totalLeader 切换次数频繁切换
etcd_network_peer_round_trip_time_seconds节点间 RTT> 50ms

5. 可观测性三大支柱

支柱特点适用场景
Metrics聚合的时序数值, 低存储成本趋势监控, 容量规划, 告警
Logs结构化/非结构化事件记录事故调查, 调试, 审计
Traces请求在服务间的传播路径分布式系统延迟分析

6. 指标体系: Prometheus 深度剖析

6.1 Prometheus 架构

  • 核心组件:
    组件职责
    Prometheus Server采集、存储、查询指标
    TSDB时序数据库, 高效压缩存储
    Alertmanager告警路由、去重、静默
    Pushgateway短生命周期任务的指标推送
    Exporters暴露应用/系统指标 (如 node_exporter)

6.2 数据模型

Prometheus 使用 多维度时序数据模型:

<metric_name>{<label_name>=<label_value>, ...} <value> [<timestamp>]
  • 示例:

    http_requests_total{method="GET", handler="/api", status="200"} 1234
  • 指标类型:

    类型描述示例
    Counter单调递增http_requests_total
    Gauge可增可减temperature, memory_usage
    Histogram分布统计 (桶)request_duration_seconds
    Summary分布统计 (分位数)request_duration_seconds

6.3 TSDB 存储原理

  • 写入路径:

    1. 数据首先写入内存中的 Head Block.
    2. 每 2 小时压缩为磁盘上的 Block.
    3. 旧 Block 定期合并 (Compaction).
  • 压缩算法:

    • 时间戳: Delta-of-Delta 编码, 相邻样本的时间差通常固定.
    • : XOR 编码, 相邻浮点数通常相似.
    • 压缩率: 每个样本平均约 1-2 bytes.
  • 存储目录结构:

    /prometheus/data/
    ├── 01BKGV7JBM69T2G1BGBGNNGxxxx/   # Block
    │   ├── meta.json
    │   ├── chunks/
    │   ├── index
    │   └── tombstones
    ├── wal/                            # Write-Ahead Log
    └── queries.active

6.4 PromQL 核心查询

  • 即时向量 (Instant Vector):

    http_requests_total{job="api-server"}
  • 范围向量 (Range Vector):

    http_requests_total{job="api-server"}[5m]
  • 常用函数:

    函数描述
    rate()Counter 的每秒变化率
    increase()范围内的增量
    histogram_quantile()计算分位数
    sum(), avg(), max()聚合函数
    by(), without()标签分组
  • P99 响应延迟:

    histogram_quantile(0.99, 
      sum(rate(http_request_duration_seconds_bucket[5m])) by (le, handler)
    )

6.5 Cardinality 问题

  • 定义: 唯一时间序列的数量. 由 metric_name × label_combinations 决定.
  • 问题: 高 Cardinality 导致内存爆炸.
  • 常见原因: Label 中包含 PID, URL 参数, Trace ID.
  • 检测:
    topk(10, count by (__name__)({__name__=~".+"}))
  • 缓解: 使用 Recording Rules 预聚合, 减少标签维度.

7. 告警系统

7.1 Recording Rules

预先计算并存储查询结果, 减少实时查询开销:

# /etc/prometheus/rules/recording.yml
groups:
- name: recording_rules
  rules:
  - record: job:http_requests_total:rate5m
    expr: sum(rate(http_requests_total[5m])) by (job)

7.2 Alerting Rules

# /etc/prometheus/rules/alerting.yml
groups:
- name: api_alerts
  rules:
  - alert: HighErrorRate
    expr: |
      sum(rate(http_requests_total{status=~"5.."}[5m])) by (job)
      /
      sum(rate(http_requests_total[5m])) by (job)
      > 0.05
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: "High 5xx error rate on {{ $labels.job }}"
      description: "Error rate is {{ $value | humanizePercentage }}"

7.3 Alertmanager 路由

# /etc/alertmanager/alertmanager.yml
route:
  receiver: default
  group_by: [alertname, job]
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  routes:
  - match:
      severity: critical
    receiver: pagerduty
  - match:
      severity: warning
    receiver: slack

receivers:
- name: default
  email_configs:
  - to: ops@example.com
- name: pagerduty
  pagerduty_configs:
  - service_key: <key>
- name: slack
  slack_configs:
  - channel: '#alerts'
    api_url: https://hooks.slack.com/...

7.4 静默 (Silences)

在计划维护期间静默告警:

amtool silence add alertname="HighErrorRate" --duration=2h --comment="Planned maintenance"

8. 日志系统: Loki

8.1 Loki 架构

  • 核心设计: 只索引 标签 (Labels), 不索引日志内容. 查询时流式扫描.
  • 优势: 存储成本极低, 适合高吞吐场景.
  • 劣势: 全文搜索性能低于 Elasticsearch.

8.2 日志收集模式

模式架构优势劣势
DaemonSet每个节点一个 Agent资源共享, 配置统一无法定制化处理
Sidecar每个 Pod 一个 Agent隔离性强, 可定制资源消耗大

8.3 Promtail 配置

# promtail-config.yaml
server:
  http_listen_port: 9080

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
  - job_name: kubernetes-pods
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_label_app]
        target_label: app
      - source_labels: [__meta_kubernetes_namespace]
        target_label: namespace
    pipeline_stages:
      - json:
          expressions:
            level: level
            msg: msg
      - labels:
          level:

8.4 LogQL 查询

  • 日志流选择:

    {namespace="production", app="api-server"}
  • 过滤:

    {app="api-server"} |= "error" | json | level="error"
  • 聚合:

    sum(rate({app="api-server"} |= "error" [5m])) by (level)

9. 链路追踪: OpenTelemetry

9.1 分布式追踪原理

  • 核心概念:
    概念描述
    Trace一个完整请求的生命周期
    SpanTrace 中的一个操作单元
    Trace ID全局唯一标识, 跨服务传播
    Span ID单个 Span 的标识
    Parent Span ID父 Span 的引用

9.2 OpenTelemetry 架构

9.3 自动注入 (Kubernetes Operator)

helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm install opentelemetry-operator open-telemetry/opentelemetry-operator
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: auto-instrumentation
spec:
  exporter:
    endpoint: http://otel-collector:4317
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: "0.25" # 采样率 25%
  java:
    image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-java:latest
  python:
    image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-python:latest
# Pod 注解自动注入
metadata:
  annotations:
    instrumentation.opentelemetry.io/inject-java: "true"

10. SRE 黄金信号

Google SRE 提出的四大黄金信号是监控的核心:

信号描述示例指标
Latency请求响应时间histogram_quantile(0.99, ...)
Traffic请求吞吐量sum(rate(http_requests_total[5m]))
Errors错误率sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m]))
Saturation资源饱和度1 - avg(rate(node_cpu_seconds_total{mode="idle"}[5m]))

10.1 RED Method (请求驱动服务)

适用于 Request-Driven Services:

  • Rate: 请求速率
  • Errors: 错误率
  • Duration: 响应延迟

10.2 USE Method (资源)

适用于资源监控:

  • Utilization: 使用率
  • Saturation: 饱和度 (队列深度)
  • Errors: 错误数

11. 实战演练

11.1 Lab 1: 配置黄金信号 Dashboard

目标: 在 Grafana 中创建包含四大黄金信号的 Dashboard.

  1. 部署 kube-prometheus-stack.
  2. 导入或创建 Dashboard, 包含:
    • P50/P90/P99 响应延迟
    • 请求速率 (QPS)
    • 错误率
    • CPU/Memory 饱和度

11.2 Lab 2: 日志告警集成

目标: 当错误日志超过阈值时触发告警.

# Loki Ruler 配置
groups:
- name: log_alerts
  rules:
  - alert: HighErrorLogRate
    expr: sum(rate({app="api-server"} |= "ERROR" [5m])) > 10
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "High error log rate"

11.3 Lab 3: 链路追踪分析

目标: 定位分布式请求的延迟瓶颈.

  1. 部署 Jaeger 或 Grafana Tempo.
  2. 为测试应用注入 OpenTelemetry SDK.
  3. 模拟高延迟场景.
  4. 使用 Trace 视图分析调用链.

12. 本周核心要点回顾

领域核心概念关键配置
MetricsPrometheus TSDB, PromQL, CardinalityRecording Rules, Alerting Rules
LogsLoki (只索引 Labels), LogQLPromtail, Pipeline Stages
TracesOpenTelemetry, Trace/Span 模型Auto-instrumentation, Sampling
告警Alertmanager 路由, 静默group_by, inhibit_rules
黄金信号Latency, Traffic, Errors, SaturationRED/USE Method

可观测性的目标不是为了告警, 而是为了在故障发生时快速定位根因, 在故障发生前预测容量瓶颈. 一个好的监控系统应该能讲述出系统整体的健康状况, 而不是淹没在无意义的告警风暴中.

On this page