多 VPS 统一监控(六):Portainer(二)排障实录与收尾

这是《多 VPS 统一监控》系列的第六篇,也是最后一篇。上篇把 Portainer 的管理员建好、四个环境接了进来,这篇讲接管过程中踩的三个实战坑,以及整个系列的收尾。

实战三个坑

坑一:107 那台 Docker 转发坏了

RackNerd 1G 这台,Agent 装好了但 9001 端口从外面连不上。排查过程是这样的:

# 1. 先看 Docker 的转发链还在不在
iptables -L DOCKER -n 2>&1 | head -3
# iptables: No chain/target/match by that name.
# → DOCKER 链丢了,这台上所有容器的端口转发全坏

# 2. 重启 docker daemon 重建链
systemctl restart docker
# 这台上跑的 webssh 容器设了 restart=always,daemon 重启后自己回来了,有惊无险

但修完 9001 还是不通——bridge 网络的 DNAT 就是过不去。最后把这台的 Agent 改成 --network host 模式跑,绕开 Docker 的端口转发:

docker run -d --name portainer_agent --restart=always --network host \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /var/lib/docker/volumes:/var/lib/docker/volumes \
  portainer/agent:2.45.2
# 通了

教训:Agent 连不上时,先看宿主机防火墙,再看 Docker 自身的转发链,host 网络是最后的兜底。

坑二:Agent 镜像 tag 不存在

上篇提过:portainer/agent:2 没有这个标签。Portainer 的 Agent 镜像只有完整版本号 tag,和服务端版本保持一致就行(服务端 2.45.2 → Agent 用 portainer/agent:2.45.2)。

坑三:密码里的特殊字符把脚本炸了

Dedirock 那台的 root 密码是一串包含 }、$、{ 等 shell 特殊字符的强密码(原文已打码处理),我当时用 heredoc 明文传密码,shell 直接把 $ 后面的内容当变量、} 当语法解析,脚本原地爆炸。修法:先把密码 base64 编码再传,绕开 shell 解析:

# 发送端:编码后再传,特殊字符不再被 shell 解析
echo -n '你的密码' | base64
# 接收端:解码使用
echo '编码后的字符串' | base64 -d

教训:自动化脚本里传密码,永远先做编码或转义,别裸传。

最后的效果

点进任意一个环境,先看到的是总览页:这台机器上有几个 Stack、几个容器、几个镜像,一目了然。比如博客主机这个环境,8 个容器全在跑:

Portainer 环境总览:8 个容器全部运行中
Portainer 里点进 local 环境的总览页:8 个容器全部 running、2 个 healthy。红框标出的是容器统计卡片。

再点进 Containers,能看到每个容器的名字、状态、端口映射,点容器名能看实时日志,能重启、能重建,镜像更新也在页面里点几下搞定。四台机器,一个页面,全了。

系列收尾

六篇到此结束,整套监控至此跑通:Beszel 看机器内部、Uptime Kuma 从外部探测、Bark 推手机、Portainer 统一管容器。

如果你也照着搭,记住三个检查点:① 三个面板都能 HTTPS 打开;② Beszel 里四台(或你的 N 台)全绿;③ 故意停一个测试服务,手机能收到 Bark 推送。三点全过,这套监控就算真正验收了。

后记:三个面板各一个网址,来回切换有点烦。后来我又搭了个统一入口 panel.nettodata.com,一个页面三个标签页嵌进去(Beszel / Uptime Kuma / Portainer 原生界面,功能一点不少),各面板登录一次后浏览器会记住。这是个锦上添花的小改造,有机会单独写一篇。

还差一个独立外部哨兵(监控域名本身的存活)没部署——监控和博客跑在同一台 VPS 上,整台挂了的话告警自己也发不出来。这个列在待办里,部署完再写一篇番外。

发表评论