可观测性学习路径:从指标、日志、链路到 SLO 与值班

使用方式

这条路径解决“出事时只能靠猜”的问题:把指标、日志、链路和剖析四种信号接到同一条排障流程里,最后用 SLO 和值班制度把告警变成可执行的动作。适合已经会 Linux 基础、能读 YAML、手上有 Docker 或 kind 集群的后端与运维工程师。

前置知识:看得懂 HTTP 状态码,用过 systemctl 和 docker,知道 CPU、内存、磁盘的基本含义。四个阶段按依赖排序,每阶段建议 3–4 小时;没有监控环境的,先用 Docker 或 kind 起一套单机栈。

所有实验只在本地或测试环境做。给生产加采集器、改告警规则、调采样率都属于变更,需要评审、灰度和回滚方案。

阶段一:指标、Prometheus 与 exporters

目标:能从一条 PromQL 查询追到采集目标,判断问题在应用、exporter 还是采集链路。

阅读顺序:

  1. prometheus — 数据模型、抓取、TSDB 和 PromQL 的执行入口。
  2. node-exporter — 主机指标的标准来源,先分清 CPU、内存、磁盘和文件系统。
  3. kube-state-metrics — 集群对象状态,和主机指标不是同一类数据。
  4. metrics-server — 只服务 HPA 和 kubectl top,不能替代 Prometheus。
  5. promql-cheatsheet — rate、histogram_quantile 和聚合的常用写法。
  6. promtool — 本地校验规则、查询和 TSDB 块,避免把错误规则推上线。
  7. grafana — 把查询变成可复用看板,理解变量、面板和时间范围。
  8. victoriametrics — 单机高压缩长期存储,理解远程写和 PromQL 兼容。
  9. prometheus-vs-victoriametrics — 选型时比较抓取模型、存储和运维成本。
  10. thanos — 多集群全局查询和长期保留,SLO 历史数据的基础。

动手任务:在本地 Docker 起 Prometheus、node-exporter 和一条告警规则,确认 up 指标与规则校验通过。环境是本机 Docker,端口只绑定回环地址;Linux 上把 host.docker.internal 换成宿主机地址或改用 --network host。风险是端口暴露和容器残留,实验后删除容器。

mkdir -p /tmp/obs-lab
cat > /tmp/obs-lab/prometheus.yml <<'EOF'
scrape_configs: [{job_name: node, static_configs: [{targets: ['host.docker.internal:9100']}]}]
EOF
cat > /tmp/obs-lab/alerts.yml <<'EOF'
groups: [{name: lab, rules: [{alert: InstanceDown, expr: 'up == 0', for: 5m}]}]
EOF
docker run -d --name node-exporter -p 127.0.0.1:9100:9100 prom/node-exporter:v1.8.2
docker run -d --name prometheus -p 127.0.0.1:9090:9090 -v /tmp/obs-lab/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus:v2.54.1
docker run --rm -v /tmp/obs-lab:/lab --entrypoint promtool prom/prometheus:v2.54.1 check rules /lab/alerts.yml
curl -s 'http://127.0.0.1:9090/api/v1/query?query=up' | head -c 300

过关标准:

阶段二:日志与 Loki

目标:让一条错误日志能从容器、节点到 Loki 全链路查到,并能按标签和 trace_id 收敛范围。

阅读顺序:

  1. loki — 只索引标签、不索引全文的日志存储模型。
  2. promtail — 采集容器日志、positions 文件和标签重写。
  3. logql-cheatsheet — 流选择器、过滤器和 metric query 的语法。
  4. logcli — 不经过 Grafana 直接查 Loki,适合脚本和排障。
  5. fluent-bit — 轻量采集器,理解 parser、filter 和 output。
  6. vector — 采集与转换一体,适合多源日志和脱敏。
  7. filebeat — ELK 生态采集器,对照 Loki 方案的差异。
  8. loki-vs-elk — 成本、索引模型和查询能力的取舍。
  9. grafana-vs-kibana — 看板与日志检索的使用边界。

动手任务:在本机 Docker 起 Loki 和 promtail,采集 /var/log 下的系统日志,用 logcli 查询标签并过滤关键字。环境是本机 Docker;只读挂载 /var/log,不要把采集范围扩到用户目录。风险是日志可能含敏感信息、磁盘被占满,实验后删除容器并限制保留时间。

docker run -d --name loki -p 127.0.0.1:3100:3100 grafana/loki:3.1.1
cat > /tmp/obs-lab/promtail.yml <<'EOF'
server: {http_listen_port: 9080, grpc_listen_port: 0}
positions: {filename: /tmp/positions.yaml}
clients: [{url: http://host.docker.internal:3100/loki/api/v1/push}]
scrape_configs:
  - job_name: varlogs
    static_configs: [{targets: [localhost], labels: {job: varlogs, __path__: /var/log/*.log}}]
EOF
docker run -d --name promtail -v /tmp/obs-lab/promtail.yml:/etc/promtail/config.yml -v /var/log:/var/log:ro grafana/promtail:3.1.1 -config.file=/etc/promtail/config.yml
curl -s http://127.0.0.1:3100/loki/api/v1/labels

过关标准:

阶段三:链路与 OpenTelemetry

目标:用一个 trace_id 串起服务调用,并能从最慢 span 定位到下游依赖或代码热点。

阅读顺序:

  1. opentelemetry — 统一的 API、SDK、Collector 和上下文传播。
  2. tempo — 低成本 trace 存储,理解 trace_id 与日志关联。
  3. jaeger — 另一套 trace 后端和 UI,理解 span 模型与查询方式。
  4. otel-cli — 手动产生 span,验证采集链路是否通。
  5. pyroscope — 持续 profiling,按 CPU 和内存看火焰图。
  6. parca — eBPF 持续剖析,理解无侵入采样的边界。
  7. coroot — 把指标、日志和链路关联到服务拓扑。
  8. ebpf-observability — 内核态观测,理解无埋点数据的来源。
  9. hubble — Cilium 的网络流可观测性,定位服务间连接问题。

动手任务:起本地 Jaeger,用 otel-cli 发送一个 span,再通过 Jaeger API 确认服务已注册。环境是本机 Docker,OTLP 端口只给本地使用。风险是 trace 会携带请求元数据,不要写入密码、令牌或个人数据;实验结束删除容器。

docker run -d --name jaeger -p 127.0.0.1:16686:16686 -p 127.0.0.1:4317:4317 -p 127.0.0.1:4318:4318 jaegertracing/all-in-one:1.60
sleep 5
otel-cli span --endpoint http://127.0.0.1:4317 --service demo --name checkout
curl -s http://127.0.0.1:16686/api/services

过关标准:

阶段四:SLO、告警与值班

目标:把“系统慢”变成有错误预算、有告警路由、有值班动作的闭环。

阅读顺序:

  1. slo — SLI、SLO 和错误预算的定义与计算。
  2. error-budget — 用剩余预算决定发布节奏和止损。
  3. alertmanager — 分组、抑制、静默和路由。
  4. amtool — 从命令行校验配置、添加告警和创建静默。
  5. on-call — 值班轮换、升级路径和交接。
  6. sre-oncall-checklist — 告警确认、沟通和升级的检查表。
  7. incident-response-playbook — 分级、指挥、止损和复盘。
  8. runbook — 每条告警对应可执行步骤。
  9. postmortem — 无责复盘、时间线和行动项。
  10. observability-roadmap — 从零建设的阶段和验收项。

动手任务:在本地起 Alertmanager,用 amtool 校验配置、注入一条告警并创建静默,确认 API 能看到状态变化。环境是本机 Docker,配置和接收端都是假的。风险是静默会掩盖真实告警,生产环境创建静默必须写原因和过期时间。

cat > /tmp/obs-lab/alertmanager.yml <<'EOF'
route: {receiver: default}
receivers: [{name: default}]
EOF
docker run -d --name alertmanager -p 127.0.0.1:9093:9093 -v /tmp/obs-lab/alertmanager.yml:/etc/alertmanager/alertmanager.yml prom/alertmanager:v0.27.0
docker exec alertmanager amtool check-config /etc/alertmanager/alertmanager.yml
docker exec alertmanager amtool alert add alertname=ServiceLatency service=api severity=warning --alertmanager.url=http://127.0.0.1:9093
curl -s http://127.0.0.1:9093/api/v2/alerts

过关标准:

常见误区

读完自测

合上页面,先回答,再展开对照。

  1. 一个服务 up 为 1,但用户请求全部超时,你会先看哪三类信号?
  2. Loki 的标签设计为什么不能用 request_id 做标签?
  3. 错误预算只剩 10%,本周有一个大版本发布,你会怎么决策?
答案
  1. 先看应用的请求量、错误率和延迟分位数确认影响面与起点,再看 trace 找最慢 span 和下游依赖,最后用 Loki 按 trace_id 或错误关键字查日志,同时核对最近变更和依赖状态。
  2. request_id 每个请求都不同,会产生海量独立流,导致索引和 chunk 数量爆炸;它应放在日志内容里用过滤器查询,标签只保留服务、环境、级别等低基数维度。
  3. 先用 burn-rate 确认预算消耗是否异常,冻结非必要变更,只允许修复和小流量灰度;发布前设置更严格的监控与回滚条件,预算耗尽则暂停发布,先恢复稳定性。

相关条目