Skip to content
twinkling.top服务PrometheusEN
板型Pi 4B 8GB. With fifteen-day retention and forty series per container this is comfortable; a hundred targets is not
内核6.6.51+rpt-rpi-v8
空闲温度48 °C
内核架构arm64
参考机:Pi 4B 8GB / Bookworm 64-bit

部署配方 · 监控

Prometheus:把数字留到足够有用为止

Uptime Kuma 告诉你某个服务挂了。Prometheus 告诉你这个服务从三月起就在漏内存——后者是更有用的一句话。它是这台机架上最重的单个服务,760MB,也是保留策略决定它到底是留在一 GB 以内、还是把固态盘吃掉的那一个。

prom/prometheus:v3.1.0 · 2026-09-29 ·

Prometheus rack plate: board stack and host ports
服务参数
容器镜像prom/prometheus:v3.1.0
宿主端口:9090/tcp
数据目录/srv/homelab/prometheus/data
内存预留760 MB
CPU 上限0.50 vCPU (cpus: "0.50")
更新节奏twice a year on the LTS releases. The storage format is not backward compatible across major versions, so a downgrade means losing the history
ARM 兼容arm64 native; the ingestion path is single-threaded per target and the Pi handles a few hundred series without trouble
端口映射与暴露面
宿主容器proto暴露用途
:90909090tcp仅局域网query UI and the target health page, mostly used to check what stopped being scraped

部署步骤

  1. 按正确属主建好配置和数据目录

    Prometheus 在容器里以 uid 1000 运行,数据目录不可写就不会启动。配置目录可以保持 root 所有,只要可读即可。

    run
    sudo mkdir -p /srv/homelab/prometheus/{config/rules,data}
    sudo chown -R 1000:1000 /srv/homelab/prometheus/data
    sudo chmod -R a+rX /srv/homelab/prometheus/config
  2. 写抓取配置,并带上外部标签

    外部标签是以后区分这个 Prometheus 和另一个的方式,也是远程写入目标用来路由数据的依据。即使现在只有一个实例,也先设好。

    run
    cat > /srv/homelab/prometheus/config/prometheus.yml <<'EOF'
    global:
      scrape_interval: 30s
      evaluation_interval: 30s
    external_labels:
      rack: home
    tls_config:
      insecure_skip_verify: false
    scrape_configs:
      - job_name: prometheus
        static_configs: [{targets: ['localhost:9090']}]
      - job_name: node
        static_configs: [{targets: ['node-exporter:9100']}]
      - job_name: cadvisor
        static_configs: [{targets: ['cadvisor:8080']}]
    rule_files:
      - /etc/prometheus/rules/*.yml
    EOF
  3. 启动并确认每个目标都是 UP

    报 DOWN 且是 context deadline 的,是网络问题;报 DOWN 且是 404 的,是路径问题。改配置之前先看清是哪一种。

    run
    cd /srv/homelab/prometheus && docker compose up -d
    docker logs --tail 30 prometheus
    # 打开 http://192.168.10.20:9090/targets 确认三个都是 UP
  4. 加上记录规则,并且查一次验证

    从没被查过的记录规则,就是一条你不知道能不能用的规则。等一分钟后在查询框里输入记录出来的序列名。

    run
    docker compose restart prometheus
    # 查询:instance:node_cpu:rate5m
    # 一个评估周期内图上就应该有线
  5. 让 Grafana 指向它,并设好保留上限

    数据源已经在 Grafana 的配置里备好了;确认连接测试通过,然后观察一周磁盘占用,再决定十五天是否负担得起。

    run
    docker exec grafana wget -qO- http://prometheus:9090/-/ready
    docker exec prometheus du -sh /prometheus

保留策略才是关键设置

Prometheus 压缩率不错——大约每个样本 1.7 字节——但四十个容器、每个容器一百五十条序列,每天会产生约两百万个样本。十五天大约占 250MB 磁盘,所以这里把保留期显式设成十五天,而不是留给「永久」这个默认值。

除了时间上限还设了大小上限。时间上限是你画图想要的;大小上限则是给「某天某个容器突然导出十倍序列」这种情况准备的安全带。

shell
# 看实际占用,而不是靠猜
docker exec prometheus du -sh /prometheus
curl -s localhost:9090/api/v1/status/tsdb | python3 -c 'import json,sys; d=json.load(sys.stdin)["data"]; print(d["headStats"])'

记录规则把慢查询变成快查询

每一个对十五天窗口跑 rate() 的面板,都会在每次打开页面时重新计算。记录规则把这些预先算成新序列,这正是树莓派能把一块仪表盘在一秒内画出来的原因。

四条记录规则覆盖了这里全部三块仪表盘:每实例五分钟 CPU 速率、内存占用比例、五分钟容器内存、以及磁盘使用比例。其它一切按需查询。

shell
# /srv/homelab/prometheus/config/rules/recording.yml
groups:
  - name: rack-recording
    interval: 30s
    rules:
      - record: instance:node_cpu:rate5m
        expr: 1 - avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m]))
      - record: instance:node_memory:used_fraction
        expr: 1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes
      - record: container:memory:rate5m
        expr: sum by (name) (rate(container_memory_working_set_bytes[5m]))

该对什么告警,该放过什么

三条告警规则,而且全部是慢性的,而不是瞬时阈值。磁盘超过百分之八十持续两小时。根据六小时线性趋势预测七天内写满。以及一小时内重启超过五次的容器。

刻意不告警的:CPU 尖峰、温度超过七十、服务短暂不可达。这些会产生那种让人学会忽略通知的通知。温度是仪表盘上的一块面板加一个人,而不是一条规则加一部手机。

shell
# /srv/homelab/prometheus/config/rules/alerts.yml
groups:
  - name: rack-alerts
    rules:
      - alert: DiskFillingUp
        expr: predict_linear(node_filesystem_avail_bytes{mountpoint="/"}[6h], 7*86400) < 0
        for: 2h
      - alert: ContainerRestartLoop
        expr: increase(container_start_time_seconds[1h]) > 5
        for: 10m

导出器,以及该小心哪一个

node exporter 以 pid: host 运行、并把根文件系统只读挂在 /host,这正是让宿主机指标(含温度区)可用的原因。这是标准做法,同时也意味着对宿主机文件系统的一次宽泛读取——这是在容器平台上获取宿主机指标所要付出的代价。

需要留意的是 cAdvisor:它以特权运行,并读取 Docker 套接字目录来枚举容器,这实际上等于对守护进程所知的一切拥有读权限。它绑定在局域网接口上,绝不发布到别处。

compose 文件

整份文件放在 /srv/homelab/prometheus/compose.yaml。标签固定版本号,不用 latest——树莓派上回滚比升级麻烦得多。

compose.yaml
services:
  prometheus:
    image: prom/prometheus:v3.1.0
    container_name: prometheus
    restart: unless-stopped
    ports:
      - "9090:9090/tcp"
    command:
      - --config.file=/etc/prometheus/prometheus.yml
      - --storage.tsdb.path=/prometheus
      - --storage.tsdb.retention.time=15d
      - --storage.tsdb.retention.size=4GB
      - --web.enable-lifecycle=false
      - --web.enable-admin-api=false
      - --web.listen-address=0.0.0.0:9090
    volumes:
      - /srv/homelab/prometheus/config:/etc/prometheus
      - /srv/homelab/prometheus/data:/prometheus
    user: "1000:1000"
    networks: [rack]

  node-exporter:
    image: prom/node-exporter:v1.8.2
    container_name: node-exporter
    restart: unless-stopped
    pid: host
    volumes:
      - /:/host:ro,rslave
    command:
      - --path.rootfs=/host
      - --collector.thermal_zone
      - --collector.hwmon
    networks: [rack]

  cadvisor:
    image: gcr.io/cadvisor/cadvisor:v0.50.0
    container_name: cadvisor
    restart: unless-stopped
    privileged: true
    devices:
      - /dev/kmsg
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
    networks: [rack]

networks:
  rack:
    external: true

加固清单

  • 查询界面只在局域网内;它能在机架上对任何指标执行任意查询,绝不该出现在公网上
  • 关闭管理 API 和生命周期端点,外部没有任何 HTTP 调用能删除时序或触发重载
  • 在导出器支持的情况下,抓取目标使用只读凭据;导出器绑定在局域网接口而不是 0.0.0.0
  • 容器指标来自绑定在局域网上的 cAdvisor,它是机架上攻击面最大的导出器

备份方案

时序数据库被当作可丢弃的东西:丢了它丢的是图表,不是采集能力。真正持久的是配置、告警规则和记录规则,它们在 git 里。唯一值得复制的是告警状态文件,而那也只是图个方便,不算数据。

上线后验证

  • 目标页面里每个 job 都是 UP,抓取耗时远小于三十秒的间隔
  • 按名字查询某条记录规则序列能返回数据
  • 跑一周后磁盘占用低于 300MB,说明保留设置起作用了
  • 停掉某个容器后,两个抓取周期内容器内存面板上出现可见的空隙

踩过的坑

  • 存储格式在大版本之间不向后兼容。一旦跑了一个月,降级就意味着删掉数据目录。锁死版本,大版本升级前先读发布说明。
  • 抓取间隔设成 15 秒,序列数和磁盘占用相比 30 秒翻倍,而对家庭机架来说多出来的分辨率什么都换不来。保持 30 秒。
  • 能读 Docker 套接字的 cAdvisor,能看到每个容器的环境变量,包括 compose 文件里的密码。它待在局域网里,且不挂任何代理规则。
  • 从没被查询过的记录规则,依然会在每次评估时消耗 CPU。本机架上每一条规则的存在都是因为某块面板要用它,这里没有推测性的规则编写。

硬件与选型问答

用 Prometheus 还是 VictoriaMetrics 还是 InfluxDB?
如果生态里的导出器和 Grafana 仪表盘比长期保留更重要,就用 Prometheus。如果想要在同一套硬件上保留几年,用 VictoriaMetrics——它压缩更好、查询更快,而且能直接吃 Prometheus 的抓取配置。对保留十五天的家庭机架来说,这点差别不值得做一次迁移。
树莓派能扛多少个目标?
Pi 4 能扛几十万条活跃序列;按四十个容器、每个一百五十条算大约是六千条——还有两个数量级的余量。你会先撞上的限制是固态盘的写入寿命,不是 CPU。
已经有 Grafana 和 Uptime Kuma 了,还需要这个吗?
如果只想知道服务在不在,不需要。如果想知道内存占用是不是在往上走,那就需要——而且在机架上没有别的办法回答这个问题:Uptime Kuma 不存指标,而 Grafana 没有数据源就没东西可画。