kula 部署笔记:单二进制监控、27960 面板与 Docker 里的 /proc 挂载
项目地址:github.com/c0m4r/kula | 官网:kula.ovh | Demo:demo.kula.ovh | 镜像:hub.docker.com/r/c0m4r/kula
kula 是一个自包含的 Linux 服务器监控工具:单二进制、无外部依赖、不依赖数据库。它每秒从 /proc 和 /sys 读一次指标,写入内置的分层环形缓冲存储,再通过 Web 面板、终端 UI 和 Prometheus 端点对外提供。
它到底采什么
采集器每秒直接读内核暴露的文件,不经过 agent 中间层:
- CPU:总使用率(user、system、iowait、irq、softirq、steal)、核心数;可选 GPU 的负载、功耗、VRAM,NVIDIA GPU 需要额外配置
- Load:1/5/15 分钟负载、running 与 total 任务数
- 内存与 Swap:total/free/available/used/buffers/cached/shmem
- 网络:按接口的吞吐 Mbps、packets/s、errors、drops;TCP 层的 errors/s、resets/s、retrans、established、sockets
- 磁盘:按设备的 IO(读写字节/s、读写次数/s 即 IOPS)、文件系统占用
- 系统:uptime、entropy、时钟同步、hostname、登录用户数
- 进程:running/sleeping/blocked/zombie 计数
- 自身:kula 进程的 CPU%、RSS、打开的 fd 数
- 温度与电池:CPU/GPU/磁盘温度,
/sys/class/power_supply - 容器与应用:Docker、podman、raw cgroups;PostgreSQL、MySQL/MariaDB、nginx、apache2;另支持自定义指标
架构很直白:内核的 /proc/stat、/proc/meminfo、/sys 由 collectors 每秒读取,写入 storage engine,同时供 web server 与 TUI 使用。
三层环形缓冲
存储是固定大小的二进制文件,按采样精度分三层:
| Tier | 精度 | 默认大小 |
|---|---|---|
| Tier 0 | 1 秒原始样本 | 250 MB |
| Tier 1 | 1 分钟 rollup | 150 MB |
| Tier 2 | 5 分钟 rollup | 50 MB |
文件写满后循环覆盖,所以磁盘占用是封顶的,历史深度由分配大小和样本密度决定,不会随时间无限增长。指标先写原始 1 秒层,再向上聚合成 1 分钟、5 分钟两层,面板上 pan/zoom 查看历史时按缩放级别取对应层。整个过程没有外部数据库。
装起来
引导脚本:
bash -c "$(curl -fsSL https://raw.githubusercontent.com/c0m4r/kula/refs/heads/main/addons/install_v2.sh)"
单文件包(以 0.21.0 为例):
wget https://github.com/c0m4r/kula/releases/download/0.21.0/kula-0.21.0-amd64.tar.gz
echo "270f... kula-0.21.0-amd64.tar.gz" | sha256sum -c || rm -f ...
tar -xvf kula-0.21.0-amd64.tar.gz && cd kula && ./kula
校验那行的哈希要替换成 release 页面给出的完整值,不要照抄省略号。deb、rpm、AUR、snap 都有对应包,release 覆盖 amd64、arm64、riscv64。
Docker 运行:两个参数不能省
docker run --rm -it --name kula --pid host --network host -v /proc:/proc:ro c0m4r/kula:latest
需要持久化时加 -v kula_data:/app/data。
--pid host 与 -v /proc:/proc:ro 都是为了解决同一个问题:容器默认有独立的 PID 命名空间,容器内的 /proc 只反映容器自己那一两个进程;而 kula 的采集器读的是宿主机的 /proc/stat、/proc/meminfo、/proc/net/dev 这类文件。不共享 PID 命名空间,面板上就只剩容器自身的指标,宿主机的进程数、网络接口、磁盘 IO 全是空的或者错的。
--pid host 让容器加入宿主的 PID 命名空间,-v /proc:/proc:ro 则把宿主 /proc 只读挂到容器里,确保读到的是宿主完整视图,同时杜绝监控程序往 procfs 里写东西。--network host 同理,避免网络接口统计被容器网络栈隔开。三项配置缺一项,采集结果都会不完整。
面板、TUI 与 Prometheus
直接执行 ./kula,dashboard 在 http://localhost:27960。默认子命令就是 serve;配置文件为 config.yaml,可用环境变量 KULA_LISTEN、KULA_PORT 覆盖监听地址与端口;全局 flag 有 -config 和 -version。
面板提供实时图表、历史 pan/zoom、Min–Max 区间带、Focus/TV 模式、System Info 页,界面有 26 种语言。
SSH 环境下用 TUI,带历史图表:
./kula tui
Prometheus 抓取走内置 exporter 端点,配到 scrape config 里即可,不需要额外组件。
认证用 ./kula hash-password 生成 Argon2id 哈希,写进 config.yaml 的 web.auth。服务本身带严格的安全响应头、CSRF 防护和限流,并用 Landlock sandbox 限制进程的文件与网络访问范围。整个程序无云连接、无第三方 API,可以在空气隔离的网络里跑。
AGPLv3 与单机定位的取舍
kula 用 AGPL-3.0 授权。对通过网络对外提供服务的场景,AGPL 有源码义务;如果是商业分发或嵌入到自己的产品里,需要先评估这条。
定位上它就是个单机工具:没有集群、没有多机聚合、没有告警规则引擎、没有长期归档。三层 ring-buffer 是循环覆盖的,指望它当容量规划的数据源并不合适。它的价值在于一台机器上扔一个二进制或一个容器就能看全套指标,不引入 Prometheus + exporter + TSDB 那一整套,顺带还留一个 Prometheus 端点给已有体系用。
开发
本地检查:./addons/check.sh,包含 govulncheck、gofmt、vet、race tests、golangci-lint。交叉编译:./addons/build.sh cross,产出 amd64/arm64/riscv64。