可观测性(Observability )不是监控的替代词,而是通过**指标(Metrics)、日志(Logs)、追踪(Traces)**三大支柱,回答系统为什么处于当前状态的能力。在 Kubernetes 这样的动态分布式环境中,可观测性建设的复杂度远超传统虚拟机架构。
目录
- 1. 可观测性三大支柱
- 2. Prometheus + Grafana 指标监控 –grafana-指标监控)
- 3. 日志采集方案
- 4. 分布式追踪
- 5. Kubernetes 核心指标
- 6. 告警规则与值班
- 7. SLO/SLI 实践
- 8. 可观测性架构设计
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 Full | 1860 | 节点资源全貌 |
| Kubernetes Cluster | 7249 | 集群整体状态 |
| Kubernetes Pod | 747 | Pod 级别资源 |
| Kubernetes Network | 12658 | 网络流量 |
| Kubernetes Storage | 11454 | PVC/磁盘使用 |
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% 持续 5m | Warning |
| 节点 | 内存使用率 | > 85% 持续 5m | Warning |
| 节点 | 磁盘使用率 | > 85% | Warning |
| 节点 | 磁盘只读 | inode 耗尽 | Critical |
| Pod | 重启次数 | > 3 次 / 10m | Warning |
| Pod | OOM Kill | OOMKilled 状态 | Critical |
| Pod | 就绪状态 | Not Ready > 5m | Critical |
| 集群 | Pod 调度失败 | Pending > 30m | Warning |
| 集群 | API Server 延迟 | P99 > 1s | Critical |
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) | 下个工作日 | 邮件/周报 | 容量规划预警 |
告警疲劳防治
- 去重:同问题在恢复前只发送一次
- 分组:相关告警合并通知
- 静默(Silence):维护窗口自动静默已知告警
- 抑制:高级别告警自动抑制相关低级别告警
7. SLO/SLI 实践
定义 SLI/SLO
| 服务 | SLI | SLO | 测量窗口 |
|---|---|---|---|
| API Gateway | 可用性 | 99.95% | 30天 |
| API Gateway | 延迟 (p99) | < 200ms | 30天 |
| Order Service | 错误率 | < 0.1% | 30天 |
| Database | 查询延迟 (p99) | < 50ms | 7天 |
错误预算
月度错误预算 = (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 更轻量,对象存储后端)
总结
| 支柱 | 工具 | 核心设计要点 |
|---|---|---|
| Metrics | Prometheus + Grafana | ServiceMonitor 自动发现,Recording Rule 预聚合 |
| Logs | Loki + Promtail | 标签索引降成本,LogQL 统一查询 |
| Traces | Jaeger/Tempo + OTEL | Sidecar 自动注入,TraceID 贯穿调用链 |
| 告警 | Alertmanager | 分级路由、去重、抑制、静默 |
| SLO | PromQL + Grafana | 错误预算量化可用性,指导发布节奏 |
可观测性不是事后补充,而是系统设计的一部分。完善的可观测体系能够显著缩短 MTTR(平均恢复时间),是让运维团队从"救火"转向"预防"的关键基础设施。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。