跳转至

Prometheus 部署实战:Docker / systemd / K8s 三种方案 60 秒选型

Prometheus 是监控栈的默认起点,但装 Prometheus 之前,先花 60 秒想清楚三件事:装在哪、要不要装 exporter、保留多久。这三件事想清楚,后面不会走弯路。

60 秒选型:三种装法谁该选谁

装法 适合场景 优点 坑
Docker 个人学习、小团队、非 K8s 环境 版本切换简单、迁移方便 需要装 Docker、卷挂载要注意权限
systemd 原生 Linux、追求极简、生产单节点 无依赖、资源占用低 升级麻烦、需要 root
K8s 已有 K8s 集群 与其他服务对齐、Helm 管理 学习曲线陡、Helm Chart 版本更新慢

决策原则: - 已有 K8s 集群 → K8s,不折腾 Docker - 原生 Linux、要长期跑 → systemd - 学习、多机迁移、快速试错 → Docker

下文以 Docker 为主讲(覆盖 80% 场景),systemd 和 K8s 各给最小可用配置。

步骤 1:拉镜像或下载二进制

Docker 装法

# 拉官方镜像
docker pull prom/prometheus:v2.53.0

# 看版本
docker run --rm prom/prometheus:v2.53.0 prometheus --version

你应该看到什么:Prometheus 版本号,如 prometheus, version 2.53.0。

systemd 装法

# 官方 tar.gz
wget https://github.com/prometheus/prometheus/releases/download/v2.53.0/prometheus-2.53.0.linux-amd64.tar.gz
tar xzf prometheus-2.53.0.linux-amd64.tar.gz
sudo mv prometheus-2.53.0.linux-amd64 /opt/prometheus
sudo useradd -r -s /bin/false prometheus
sudo chown -R prometheus:prometheus /opt/prometheus

systemd unit 文件(/etc/systemd/system/prometheus.service):

[Unit]
Description=Prometheus
After=network-online.target

[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/opt/prometheus/prometheus \
  --config.file=/opt/prometheus/prometheus.yml \
  --storage.tsdb.path=/opt/prometheus/data \
  --storage.tsdb.retention.time=15d \
  --web.listen-address=0.0.0.0:9090
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
sudo systemctl enable --now prometheus
sudo systemctl status prometheus

K8s 装法(有 Helm 的场景)

helm repo add prometheus https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/kube-prometheus-stack

注意:kube-prometheus-stack 是社区维护的完整栈(含 Grafana、Alertmanager、node_exporter),不适合学习原理,但适合快速生产。若只是学习,prometheus-community/prometheus 更纯粹。

步骤 2:写最小可用配置

Prometheus 的主配置文件是 prometheus.yml。最小可用配置只需 3 行核心内容:

# prometheus.yml 最小可用版本
global:
  scrape_interval: 15s        # 默认 15 秒抓一次
  evaluation_interval: 15s    # 默认 15 秒评估一次告警规则

scrape_configs:
  - job_name: 'prometheus'    # 抓自己(自监控)
    static_configs:
      - targets: ['localhost:9090']

每个字段为什么这么写:

  • scrape_interval: 15s 是 Prometheus 默认值,也是绝大多数 exporter 推荐的采样频率。15 秒太慢会漏细节,太快会烧指标数。
  • evaluation_interval: 15s 控制告警规则的评估频率,一般与 scrape_interval 一致。
  • job_name: 'prometheus' 抓自己,用于监控 Prometheus 本身的运行状态(内存、抓取耗时、抓取失败率)。这是自监控的起点。

Docker 用 -v 挂载配置文件

mkdir -p ~/prometheus && cd ~/prometheus
cat > prometheus.yml <<'EOF'
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']
EOF

docker run -d \
  --name prometheus \
  --restart=unless-stopped \
  -p 9090:9090 \
  -v ~/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro \
  -v ~/prometheus/data:/prometheus \
  --user $(id -u):$(id -g) \
  prom/prometheus:v2.53.0 \
  --storage.tsdb.retention.time=15d

关键点: - :ro 让配置文件只读,避免容器意外修改 - --user $(id -u):$(id -g) 用当前用户跑,避免生成 root 拥有的文件 - retention.time=15d 是官方默认,够个人 / 小团队使用

步骤 3:启动并验证

# 1. 检查容器
docker ps | grep prometheus

# 2. 看日志
docker logs prometheus --tail 30

# 3. 验证存活
curl -f http://localhost:9090/-/healthy && echo "OK"

# 4. 看 targets
curl -s http://localhost:9090/api/v1/targets | jq '.data.activeTargets[0]'

你应该看到什么: - Step 3 命令返回 OK - Step 4 命令返回 health: "up"

浏览器打开 http://localhost:9090,能看到 Prometheus UI,Targets 页面里 prometheus 这一行显示 UP 状态。

步骤 4:装 node_exporter(Prometheus 的最低门槛)

Prometheus 自己抓自己只是自监控。要真正监控 Linux 主机,必须装 node_exporter。这是 Prometheus 生态最基础、最常用的 exporter。

Docker 装 node_exporter

docker run -d \
  --name node-exporter \
  --restart=unless-stopped \
  -p 9100:9100 \
  -v /proc:/host/proc:ro \
  -v /sys:/host/sys:ro \
  -v /:/host/root:ro \
  quay.io/prometheus/node-exporter:v1.8.2 \
  --path.procfs=/host/proc \
  --path.sysfs=/host/sys \
  --path.rootfs=/host/root \
  --collector.filesystem.mount-points-exclude='^/(dev|proc|sys|var|etc|run)(/|$)'

关键点:node_exporter 必须能读到 /proc、/sys 文件系统,这是它采集 CPU、内存、磁盘指标的数据源。

更新 prometheus.yml 加上 node_exporter

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node'
    static_configs:
      - targets: ['localhost:9100']
# 重启 Prometheus 让新配置生效
docker restart prometheus

# 30 秒后看 targets
curl -s http://localhost:9090/api/v1/targets | jq '.data.activeTargets[] | {job, health}'

你应该看到什么:两个 job 都是 "health": "up"。

Prometheus UI 里现在应该能看到 node_cpu_seconds_total、node_memory_MemAvailable_bytes 等指标。

验证第一个 PromQL 查询

在 Prometheus UI 的 Explore 页输入:

100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

这条查询返回每个节点的 CPU 使用率百分比。看到有数就成功。

常见内存 / 磁盘事故

Prometheus 装完之后最头疼的两件事:内存爆和磁盘满。这两个问题的根因和修复路径固定,记住就能省时间。

事故一:内存爆掉

症状:node_memory_MemAvailable_bytes 持续下降,Prometheus 容器 OOM 被 Docker 杀掉。

根因: 1. 抓了太多 target(每加一台机器 + 100 个指标) 2. 抓了高基数标签(比如按 user_id、request_id 分组,每请求一个时间序列) 3. --storage.tsdb.retention.time 太长,WAL 目录膨胀

排查:

count(count by (__name__) ({__name__=~".+"}))

这条 PromQL 返回 Prometheus 里活跃的时间序列总数。超过 100 万就要注意,超过 500 万必须扩容。

topk(10, count by (__name__) ({__name__=~".+"}))

看哪个指标名产生的序列最多,通常是 http_request_duration_seconds_bucket 之类的 histogram。

修复:删掉高基数标签,或改用 histogram_quantile 聚合而非原始数据。

事故二:磁盘写满

症状:Prometheus 报 cannot allocate memory: resource temporarily unavailable 或 WAL 目录超过磁盘。

根因: 1. retention.time 太长(默认 15d,但抓高频指标场景可能爆) 2. WAL 目录没有和 TSDB 目录分开

修复:

# 分开两个卷,WAL 用临时盘
docker run -d \
  -v ~/prometheus/tsdb:/prometheus/tsdb \
  -v /tmp/prometheus-wal:/prometheus/wal \
  ... \
  --storage.tsdb.path=/prometheus/tsdb \
  --storage.tsdb.retention.time=30d \
  --storage.tsdb.wal-compression

--storage.tsdb.wal-compression 是关键:启用 WAL 压缩能减少 30-50% 磁盘写入。

事故三:查询超时

症状:Prometheus UI 查询 rate(xxx[1h]) 报 context deadline exceeded。

根因: 1. 查询范围太长(比如 [24h] 但数据密集) 2. 查询本身计算量大(比如复杂 nested rate) 3. Prometheus 没配 --query.timeout 上限

修复:

# 容器参数
--query.timeout=10s \
--query.lookback-delta=5m \
--web.enable-lifecycle

--web.enable-lifecycle 开启后可以通过 POST /-/reload 热加载配置,不用重启。

数据保留策略

retention.time 是 Prometheus 磁盘规划的关键参数。经验值:

场景 建议保留 磁盘估算
个人学习 3d 500MB
小团队生产 15d 5GB
中规模生产 30d 20GB
长期分析 90d+ 用 Thanos / VictoriaMetrics,不用 Prometheus 单节点

关键规则:Prometheus 单节点不适合超过 90 天。要长期保留就上 Thanos 或 VictoriaMetrics,通过 remote_write 推送数据。

Roadmap 延伸:装完 Prometheus 之后做什么

装完 Prometheus + node_exporter 只是起点。下一步的自然延伸:

  1. 接入 Alertmanager 做告警:Prometheus 只负责指标存储,告警分发要交给 Alertmanager。详见本站 Prometheus 告警与 Alertmanager 通知链。
  2. 接 Grafana 做面板:Prometheus UI 是查询工具,不是可视化平台。Grafana 让数据变得可用。详见本站 Grafana 面板搭建。
  3. 写 PromQL 常用查询:10 个常用查询模板可以直接抄。详见本站 PromQL 常用查询模板。
  4. 进阶 exporter:黑盒探测(blackbox_exporter)、MySQL(mysqld_exporter)、Redis(redis_exporter)、Nginx(nginx-exporter)。这些是 exporter 生态最活跃的部分。

FAQ

Q:Prometheus 和 Zabbix 怎么选?

短答:不是二选一,取决于你的技术栈。

  • Prometheus 强项:pull 模型(Prometheus 主动去问)、PromQL(查询语言强大)、云原生生态、Grafana 集成、告警规则表达式成熟。
  • Zabbix 强项:push 模型(Agent 主动上报)、传统基础设施(Windows、物理机)、大规模主机(10 万 +)、内置告警 UI、中文社区成熟。

我的建议:纯 Linux + 云原生选 Prometheus;混合环境(Windows + Linux + 网络设备)选 Zabbix 打底,K8s 部分用 Prometheus 补充。两套不冲突。

Q:Prometheus 数据保留策略怎么写?

retention.time 参数是硬编码的,写在启动参数里。要动态调整,得配合 Thanos 或 VictoriaMetrics。

# Docker
--storage.tsdb.retention.time=30d
--storage.tsdb.retention.size=50GB   # 也可以用大小限制

生产建议:retention.time 用时间(30d),retention.size 用大小(防止数据异常膨胀)。

Q:Prometheus 和 Consul / Thanos 什么关系?

三个都是 Prometheus 生态的重要组件,但角色不同:

  • Consul:服务发现工具。Prometheus 用 Consul 做 target 动态发现。scrape_configs 里用 consul_sd_configs 块。
  • Thanos:Prometheus 之上的长期存储和全局查询层。Prometheus 单节点最多 30-90 天,Thanos 通过 remote_write 汇聚多个 Prometheus 的数据到对象存储(S3、GCS),支持数年查询。
  • VictoriaMetrics:Thanos 的替代品,性能更高、部署更简单,社区认可度也在快速提升。

决策原则:小规模(10 台机器以内,保留 30 天内)→ 单 Prometheus 就够;中规模(50-500 台)→ 加 Thanos 或 VictoriaMetrics;大规模(500 台以上)→ 考虑 M3DB、Cortex 等分布式方案。


本文由 ops.jiunotes.top 独立撰写。所有配置、命令、事故复盘均为作者实操经验总结,未搬运任何第三方博客内容。官方 YAML 片段参考 prometheus.io。CC BY-NC-SA 4.0。