小鸡开出来只是开始。日常运维三件事最磨人:加业务端口、重装系统、批量装监控。裸敲 incus 命令不是不行,但手滑一次就可能删错容器——所以我写了三个交互式脚本:incus_port_manager.sh、incus_reinstall_menu.sh、incus_komari_manager.sh。这篇讲它们的设计思路。
为什么这么做:把"不敢手滑"变成"手滑不了"
三个脚本都认一个理:危险操作必须有多重确认,查询操作必须一目了然。端口加错了可以删,容器删错了数据就没了——所以重装的确认比加端口严格得多。
为什么用交互菜单,而不是纯命令行参数
三个脚本全是交互式的(数字菜单 + /dev/tty 读输入),这是刻意选择。端口管理和重装都是低频、高风险操作:你不会每天加端口,但加错一次就可能把业务搞挂。菜单把"当前有哪些容器、什么状态、已有多少代理设备"先打印出来,你看一眼再动手,比背一串 incus config device 参数安全得多。代价是不能写进 crontab 无人值守——但这类操作本来就不该无人值守。
端口管理器:命名规范 + 三重冲突检测
为什么用 Incus proxy 设备,而不是宿主机 iptables DNAT? proxy 设备是 Incus 原生对象,跟着容器走:incus config device show vps3 一眼看全,ss -lnt 能看到监听,容器重建配置还在。iptables DNAT 规则藏在系统里,和容器生命周期脱节,早晚成糊涂账。
命名规范:管理器创建的设备统一叫 pm_tcp_<端口> / pm_udp_<端口>(pm = port manager)。列表里 [可管理] 和 [保留] 标记一目了然——ssh2201 这类部署脚本建的设备是 [保留],管理器永远不会碰它们。删除时也只认 pm_ 前缀,误伤不了 SSH 映射。
三重冲突检测(添加前全跑一遍,有一条命中就拒绝执行):
- 同名设备已存在(管理器内重名);
- 该协议+端口已被其他容器的 proxy 设备占用(跨容器扫描
expanded_devices); - 宿主机上已有进程在监听该端口(
ss -lntu实查)。
任何一项冲突就直接退出、不做任何修改——宁可让你手动处理,也不做"半吊子"配置。添加中途失败还会回滚已添加的设备。
两个细节:单次最多操作 50 个端口(防手抖输错范围);删除必须手动输入 yes(不能回车默认),因为删端口是破坏性操作。端口规划给提示不给强制:vps3 默认提示 22030 或 22030-22039(规律:22000+N×10 起,每台 10 个),宿主机端口与容器内端口相同,好记。
演进坑:第一版用 Python 写菜单,从 stdin 读输入——在某些终端/重定向场景下菜单显示完直接"退出"。根因是 Python 的 input() 读的是被脚本占用的 stdin。修复版改从 /dev/tty 直接读终端,指南里专门写了"旧版自动退出怎么办"一节。教训:交互脚本永远从 /dev/tty 读,别信 stdin。
一键重装:rebuild 保留配置,双重确认保命
rebuild vs delete+launch,一张表说清:
incus rebuild |
incus delete + incus launch |
|
|---|---|---|
| 根文件系统 | 清空重建 | 全新 |
| proxy 端口映射 | 保留 | 丢失,需重配 |
| 网络/limits 配置 | 保留 | 丢失,需重配 |
| SSH 主机密钥 | 变化 | 变化 |
| 容器内应用数据 | 清空 | 清空 |
结论:重装的目的是"系统干净了",不是"配置推倒重来",所以选 rebuild。双重确认:先输数字编号(3 → vps3),再完整输入容器名(vps3)才执行。输错一个字就取消。重装前还要做指纹预检:检查该容器的 ssh$PORT proxy 设备存在,且 listen 是 tcp:0.0.0.0:$PORT、connect 是 tcp:127.0.0.1:22——对不上说明这台容器的网络配置不是标准部署,不敢动手,直接退出。
重装后自动做设备 diff 验收:对比重装前后的非根盘设备列表,一致则 [PASS],有变化就 [WARN] 让你人工检查。以及必须说清楚的一点:保留的是转发规则,不是业务——重装后原来跑的应用、Komari agent 全没了,端口通了但里面没服务,需要重装应用。这点指南里用黑体标出来了,文章里再强调一次。
另外有个 6.0.6 兼容版(reinstall_incus_vps_6_0_6_fixed.sh):单台、命令行传参、7 步流水线。关键修复是 incus config 在 6.0.6 不支持 --format json,改用 incus query /1.0/... 走 REST API 解析。以及 apt 步骤带了 -o Acquire::ForceIPv4=true——上一篇排障的经验直接进流程。
Komari 批量管理:小鸡多了靠人看不过来
6 台小鸡,每台都 incus exec 进去看负载不现实。Komari agent 装进每台小鸡,面板统一看。管理器做两件事:
- 装:从 GitHub 拉官方
install.sh,incus file push传进容器再执行。参数值得解释一下:--disable-web-ssh关掉面板的 Web SSH 入口( attack surface 能小就小);--interval 10.0是 agent 上报间隔 10 秒;--max-retries 5/--reconnect-interval 10是断线重连策略。已安装的跳过,不重复装。 - 卸:停服务、删 unit 文件、删
/opt/komari/agent和/var/log/komari。只清容器内的,面板上的节点记录要手动去面板删——脚本里明确告知,不替你做越权的事。
两个诚实说明:① agent 显示 active 只证明进程在跑,是否上线以 Komari 面板为准——这就是为什么管理器的列表里要同时显示容器状态和 Komari:active,装之前先看一眼,避免重复安装;② 脚本里的自动发现密钥是测试密钥,你用的时候必须换成自己的:
AUTO_DISCOVERY_KEY='YOUR_KEY_HERE' # 换成你自己面板的 key
为什么卸载时不动面板节点:容器里能删的只有 agent 本体,面板上的节点记录是服务端数据。脚本选择"明确告知、手动去面板删",而不是尝试调面板 API——因为面板 API 需要另外的认证,硬做反而容易把不该删的节点删掉。边界清晰的脚本,比"大包大揽"的脚本更让人放心。
事实边界
三个脚本都是防御性编写、自带验收和回滚,但请以你实际运行结果为准。脚本里的验收是帮你发现问题,不是替你保证"零失败"——任何声称"完美运行"的话,在你亲自跑过之前都不要信,包括我这篇文章。
下一篇收官:6 台小鸡的现状、成本账、安全加固 TODO 和下一步。
