Categraf 使用 systemd 和容器部署的常见坑

本文介绍 Categraf 在 systemd 和容器部署中的常见问题,覆盖 --install、ExecStart、WorkingDirectory、EnvironmentFile、配置挂载、容器内 127.0.0.1、权限、重启策略、日志持久化和部署验收。

作者 快猫星云

Categraf 本身是一个单二进制采集器,看起来部署很简单:把二进制和 conf 放到机器上,启动即可。但线上问题往往不是“命令跑不起来”,而是“手工前台正常,systemd 没数据”“宿主机能 curl,容器里连不上”“改了配置,进程还在用旧路径”“日志写到容器里,重建后找不到”。

这些问题本质上都和运行环境有关。Categraf 采集的对象可能在本机、远端、容器、Kubernetes、数据库或网络设备里;运行方式一变,配置路径、网络命名空间、文件权限、环境变量和日志位置都会变。

本文把 systemd 和容器部署中最常见的坑集中梳理出来,目标不是替代安装文档,而是给生产排障和标准化部署提供一份检查清单。

核心要点

  • 推荐把二进制和配置放在 /opt/categraf,再用 sudo ./categraf --install 生成 systemd 服务;安装前必须先把文件放到最终目录。
  • --install 会生成 unit、启用服务并执行 daemon-reload,但不会自动启动;还需要 sudo ./categraf --start
  • systemd 不会自动继承登录 shell 的 PATH、代理、Token、数据库密码等环境变量。需要使用受控的 EnvironmentFile 或密钥管理方式注入。
  • Categraf 默认读取二进制旁边的 conf;二进制移动后,旧 unit 不会自动更新 ExecStart
  • 容器内的 127.0.0.1 指向容器自身,不是宿主机,也不是其他容器。remote write、数据库地址和探测目标都要按实际网络命名空间配置。
  • 容器部署必须显式挂载配置、证书、运行状态目录和必要的宿主机路径;否则重建容器后配置、日志或 WAL 状态可能丢失。
  • 不管 systemd 还是容器,部署后都要用“服务状态、日志、--test、后端裸指标、Dashboard 变量”做闭环验收。

1. 先选清楚部署模型

常见部署方式可以分成三类:

模型 适用场景 注意事项
systemd 裸机部署 采 Linux 主机、数据库、本机进程、系统资源 权限、配置路径、EnvironmentFile
Docker/Compose 部署 快速试用、独立采远端目标、伴随夜莺环境 网络命名空间、volume、日志
Kubernetes DaemonSet/Sidecar 采节点、Pod、Service、集群组件 ServiceAccount、hostPath、容器权限

如果需要采集宿主机 CPU、磁盘、进程、systemd、Docker socket 等本机资源,systemd 或特权受控的 DaemonSet 更直观。普通容器如果没有挂载宿主机路径,看到的是容器自己的文件系统和命名空间。

如果只采远端数据库、HTTP 探测、TCP 探测,容器部署也可以很好用,但要明确所有地址都是“从容器里访问”的视角。

2. systemd 推荐目录结构

推荐布局:

/opt/categraf/
├── categraf
├── conf/
│   ├── config.toml
│   ├── logs.toml
│   ├── input.cpu/
│   ├── input.mem/
│   ├── input.redis/
│   └── input.postgresql/
├── run/
├── data-agent/
└── meta/

安装:

cd /opt/categraf
sudo ./categraf --install
sudo ./categraf --start
sudo ./categraf --status

默认生成的 systemd 配置会以当前二进制路径为准,关键项类似:

[Service]
ExecStart=/opt/categraf/categraf -configs /opt/categraf/conf
WorkingDirectory=/opt/categraf
Restart=on-failure
RestartSec=120
EnvironmentFile=-/etc/sysconfig/categraf
ExecReload=/bin/kill -HUP "$MAINPID"

因此有两个常见坑:

  • 在临时目录执行 --install,再把文件移动到 /opt/categraf,unit 仍然指向临时目录;
  • 覆盖二进制后没有确认 ExecStart,导致启动的仍是旧路径。

检查:

systemctl cat categraf
systemctl show categraf \
  -p FragmentPath \
  -p ExecStart \
  -p WorkingDirectory \
  -p User \
  -p EnvironmentFiles

如果路径不对,先确认没有自定义 unit 依赖,再按标准方式重建:

cd /opt/categraf
sudo ./categraf --stop
sudo ./categraf --remove
sudo ./categraf --install
sudo ./categraf --start
sudo ./categraf --status

3. systemd 不继承登录 shell 环境

手工终端里能成功:

export PG_PASSWORD='example'
export HTTPS_PROXY='http://proxy.example.com:8080'
./categraf --debug --inputs postgresql

不代表 systemd 服务也能成功。systemd 默认不会读取用户的 .bashrc.zshrc.profile。如果配置中用了环境变量:

address = "host=10.23.25.10 user=categraf password=${PG_PASSWORD} sslmode=disable"

应把变量放进受控环境文件。默认 unit 会读取:

/etc/sysconfig/categraf

示例:

sudo install -d -m 755 /etc/sysconfig
sudo tee /etc/sysconfig/categraf >/dev/null <<'EOF'
PG_PASSWORD=replace_with_real_secret
NO_PROXY=127.0.0.1,localhost,10.0.0.0/8
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
EOF

sudo chmod 600 /etc/sysconfig/categraf
sudo ./categraf --stop
sudo ./categraf --start
sudo ./categraf --status

分享配置或日志时,不要暴露真实密码、Token、代理账号和 Header。

验证 systemd 实际环境:

systemctl show categraf -p Environment -p EnvironmentFiles
pid=$(systemctl show categraf -p MainPID --value)
sudo tr '\0' '\n' < /proc/$pid/environ | sort

最后一条可能包含敏感信息,只在受控终端排查,不要直接贴到公开工单。

4. 前台测试和正式服务要使用同一份配置

排障时常见误判:

./categraf --test --inputs redis

这个命令可能读取当前二进制旁边的 conf,而正式服务读取的是 unit 中 --configs 指定的目录。先确认:

systemctl show categraf -p ExecStart -p WorkingDirectory

再用同一份配置测试:

/opt/categraf/categraf \
  --configs /opt/categraf/conf \
  --test \
  --inputs redis

如果正式服务限制了 --inputs,前台命令也要加同样过滤,否则会出现“手工能采,服务没采”的错觉。

修改配置后,建议先做目标插件测试,再重启服务:

cd /opt/categraf
./categraf --test --inputs redis

sudo ./categraf --stop
sudo ./categraf --start
sudo ./categraf --status
journalctl -u categraf -n 100 --no-pager

HUP 可以触发 Agent reload,但只要改了主配置、writer、heartbeat、Prometheus Agent、Logs Agent、运行用户或二进制,生产上更推荐受控重启。

5. 日志写到哪里

默认 conf/config.toml 中:

[log]
file_name = "stdout"

systemd unit 把标准输出和错误输出写入 journal,因此查看日志:

journalctl -u categraf -b -n 200 --no-pager
journalctl -u categraf -f

如果改成文件:

[log]
file_name = "/var/log/categraf/categraf.log"
max_size = 100
max_age = 7
max_backups = 3
compress = true

要提前创建目录并设置权限:

sudo install -d -m 750 -o root -g root /var/log/categraf

如果 systemd 使用非 root 用户,目录属主也要对应调整。否则 Categraf 可能在日志初始化或运行中因为权限问题失败。

6. 容器内 127.0.0.1 是第一大坑

在 Docker 容器中:

127.0.0.1 = 当前 Categraf 容器

它不是宿主机,不是 Nightingale 容器,也不是 VictoriaMetrics 容器。

错误示例:

[[writers]]
url = "http://127.0.0.1:17000/prometheus/v1/write"

如果 Categraf 在容器里,而夜莺在另一个 Compose service,应该使用 service 名:

[[writers]]
url = "http://nightingale:17000/prometheus/v1/write"

如果后端在宿主机,Linux Docker 默认不一定支持 host.docker.internal。可以在启动时显式增加:

docker run --add-host=host.docker.internal:host-gateway ...

然后配置:

[[writers]]
url = "http://host.docker.internal:17000/prometheus/v1/write"

或者使用 host 网络模式:

docker run --network host ...

host 网络模式下容器共享宿主机网络命名空间,127.0.0.1 才会指向宿主机。但这也扩大了网络权限,应按实际安全要求选择。

7. 容器部署必须挂载配置和运行目录

最小 Docker 运行示例:

docker run -d \
  --name categraf \
  --restart unless-stopped \
  -v /opt/categraf/conf:/etc/categraf/conf:ro \
  -v /opt/categraf/run:/opt/categraf/run \
  -v /opt/categraf/data-agent:/opt/categraf/data-agent \
  -v /opt/categraf/meta:/opt/categraf/meta \
  flashcatcloud/categraf:latest \
  /usr/bin/categraf -configs=/etc/categraf/conf

如果只使用普通 Metrics Agent,rundata-agentmeta 不一定都需要;但一旦启用 Logs Agent、Prometheus Agent 或 Ibex Agent,就应该显式挂载对应状态目录:

目录 常见用途
conf 主配置和 input 配置
run Logs Agent 读取状态
data-agent Prometheus Agent WAL
meta Ibex Agent 任务目录
证书目录 writer、数据库或 HTTP TLS 文件

不要把配置只 baked 到镜像里后在线修改容器内部文件。容器重建后这些改动会丢失,也不利于审计。

8. 采宿主机资源时不能只跑普通容器

如果容器里的 Categraf 要采宿主机文件系统、进程、Docker 或 systemd,需要额外挂载和权限。否则它看到的是容器内部视角。

常见挂载示例:

docker run -d \
  --name categraf \
  --restart unless-stopped \
  --pid host \
  -v /:/hostfs:ro \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  -v /opt/categraf/conf:/etc/categraf/conf:ro \
  flashcatcloud/categraf:latest \
  /usr/bin/categraf -configs=/etc/categraf/conf

是否需要这些挂载取决于启用的插件。比如:

  • 只采远端 Redis,不需要 Docker socket;
  • 采 Docker 插件,需要访问 Docker socket;
  • 采宿主机进程、磁盘或网络时,需要确认插件读取的是宿主机路径还是容器路径;
  • 采 systemd 相关指标时,需要考虑 DBus 权限和宿主机环境。

这些权限会扩大容器对宿主机的访问范围。生产环境应按最小权限原则配置,而不是为了省事直接 --privileged

9. Compose 中的网络和依赖

Compose 示例:

services:
  categraf:
    image: flashcatcloud/categraf:latest
    container_name: categraf
    restart: unless-stopped
    volumes:
      - /opt/categraf/conf:/etc/categraf/conf:ro
      - /opt/categraf/run:/opt/categraf/run
      - /opt/categraf/data-agent:/opt/categraf/data-agent
      - /opt/categraf/meta:/opt/categraf/meta
    command:
      - /usr/bin/categraf
      - -configs=/etc/categraf/conf
    depends_on:
      - nightingale

  nightingale:
    image: flashcatcloud/nightingale:latest

这里 depends_on 只保证启动顺序,不保证夜莺或后端已经可写。Categraf 的 writer 会在运行中发送,后端稍晚起来通常可以恢复,但首次验收要看日志和后端裸指标,不要只看容器状态 Up

Compose service 之间应使用服务名访问:

[[writers]]
url = "http://nightingale:17000/prometheus/v1/write"

如果要访问宿主机上的数据库,也必须使用容器可达的宿主机地址,而不是 127.0.0.1

10. 重启策略和退出频率限制

systemd 默认:

Restart=on-failure
RestartSec=120
StartLimitInterval=3600
StartLimitBurst=10

这能避免配置错误时无限快速重启。修好配置后,如果 systemd 已经进入失败限制,可以执行:

sudo systemctl reset-failed categraf
sudo ./categraf --start

Docker 常用:

--restart unless-stopped

注意:自动重启不能替代配置验证。TOML 错误、证书权限、writer URL 错误会导致容器或服务反复重启,但根因仍然在日志最早的错误里。

11. 权限和文件属主

systemd 使用默认 root 运行时,读取配置和证书通常没问题,但安全边界较宽。自定义运行用户时,要提前检查:

systemctl show categraf -p User -p Group
namei -l /opt/categraf/conf/config.toml
ls -ld /opt/categraf /opt/categraf/conf /opt/categraf/run /opt/categraf/data-agent /opt/categraf/meta

常见权限问题:

  • 配置目录只有 root 可读,服务用户不可读;
  • TLS 证书文件权限过严;
  • run_pathwal_storage_pathmeta_dir 不可写;
  • exec 插件调用的脚本没有执行权限;
  • Docker socket 对服务用户不可读;
  • 容器内 UID/GID 与宿主机挂载目录不匹配。

不要为了快速修复直接 chmod -R 777 /opt/categraf。应该明确 Categraf 运行用户,并只授予需要的读写权限。

12. 部署后的最小验收

systemd:

cd /opt/categraf
sudo ./categraf --status
systemctl show categraf -p ExecStart -p WorkingDirectory -p User -p EnvironmentFiles
journalctl -u categraf -n 100 --no-pager

容器:

docker ps --filter name=categraf
docker logs --tail=100 categraf
docker inspect categraf --format '{{json .Mounts}}'
docker exec categraf /usr/bin/categraf --version

采集验证:

/opt/categraf/categraf --configs /opt/categraf/conf --test --inputs redis
docker exec categraf /usr/bin/categraf -configs=/etc/categraf/conf --test --inputs redis

后端验证:

redis_up

如果已经导入 Dashboard,再验证变量:

count by (instance, agent_hostname) (redis_up)

最小闭环:

服务或容器处于运行状态
  + 日志没有持续 fatal/error
  + 前台 test 能采到目标插件
  + 正式模式写入后端
  + 后端裸指标有最新样本
  + Dashboard 变量能列出实例

13. 常见问题

为什么 --install--status 还是 stopped?

--install 只负责安装并启用服务,不会自动启动。继续执行 sudo ./categraf --start

为什么手工 --test 正常,systemd 没有指标?

优先比较 ExecStartWorkingDirectory--configs--inputs、运行用户和 EnvironmentFile。两者很可能不是同一份配置或同一套环境。

容器里 writer 写 127.0.0.1 为什么失败?

容器内 127.0.0.1 是 Categraf 容器自身。使用 Compose service 名、宿主机网关地址,或选择 host 网络模式。

容器重建后配置丢了怎么办?

配置不应只修改容器内部文件。把 conf、证书和状态目录挂载到宿主机,并纳入配置管理。

生产环境应该用 HUP 还是重启?

只改本地 input 配置且已确认版本行为时可以考虑 HUP。改主配置、writer、日志、Prometheus/Logs/Ibex、环境变量、证书、运行用户或二进制时,使用受控重启更清晰。

14. 生产建议

  • systemd 部署前先把文件放到最终目录,再执行 --install
  • 所有服务都记录 ExecStartWorkingDirectory、配置目录和二进制版本;
  • 密码、Token、代理和 PATH 通过受控 EnvironmentFile 或密钥系统注入;
  • 配置和证书权限按运行用户最小授权;
  • 容器部署显式挂载 conf 和所需运行状态目录;
  • 容器内地址按容器网络视角编写,不把宿主机 127.0.0.1 直接照搬;
  • 不依赖容器内部可变文件保存配置;
  • 日志进入 journal、容器日志系统或持久化文件,不能只留在临时容器层;
  • 配置变更先 test,再重启,再查后端裸指标;
  • 自动重启只作为兜底,不能替代日志和指标验收。

15. 小结

systemd 和容器部署的差异,本质上是运行上下文差异:

配置路径
  + 运行用户
  + 环境变量
  + 网络命名空间
  + 文件系统挂载
  + 日志位置

只要这六件事说清楚,Categraf 部署问题通常可以很快定位。反过来,如果只看“进程是 running”或“容器是 Up”,很容易漏掉真正的数据链路问题。

下一篇继续讲维护层问题:Categraf 升级与回滚实践:配置备份、灰度验证和版本兼容


内容更新时间:2026-07-21

证据边界:systemd unit 模板、--install 行为、HUP reload 和默认配置路径来自当前 Categraf 仓库源码与默认配置;容器镜像入口、Kubernetes 部署方式和不同发行版的 systemd 细节可能随环境变化,应以实际部署产物为准。

延伸路径

继续看解决方案和产品对比

如果你正在做监控、可观测性或故障定位相关选型,建议从解决方案和产品对比继续往下看。

快猫星云 联系方式 快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云