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
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 页输入:
这条查询返回每个节点的 CPU 使用率百分比。看到有数就成功。
常见内存 / 磁盘事故
Prometheus 装完之后最头疼的两件事:内存爆和磁盘满。这两个问题的根因和修复路径固定,记住就能省时间。
事故一:内存爆掉
症状:node_memory_MemAvailable_bytes 持续下降,Prometheus 容器 OOM 被 Docker 杀掉。
根因:
1. 抓了太多 target(每加一台机器 + 100 个指标)
2. 抓了高基数标签(比如按 user_id、request_id 分组,每请求一个时间序列)
3. --storage.tsdb.retention.time 太长,WAL 目录膨胀
排查:
这条 PromQL 返回 Prometheus 里活跃的时间序列总数。超过 100 万就要注意,超过 500 万必须扩容。
看哪个指标名产生的序列最多,通常是 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 上限
修复:
--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 只是起点。下一步的自然延伸:
- 接入 Alertmanager 做告警:Prometheus 只负责指标存储,告警分发要交给 Alertmanager。详见本站 Prometheus 告警与 Alertmanager 通知链。
- 接 Grafana 做面板:Prometheus UI 是查询工具,不是可视化平台。Grafana 让数据变得可用。详见本站 Grafana 面板搭建。
- 写 PromQL 常用查询:10 个常用查询模板可以直接抄。详见本站 PromQL 常用查询模板。
- 进阶 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。
生产建议: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。