拿到 Oracle ARM 机器时,我一开始的第一反应其实也很常规:既然资源还不错,那就照着以前那套思路,装 PVE、跑 KVM,把一台大机切成几台小机。
但这次折腾下来,我反而更确定了一件事:在 Oracle ARM 这类环境里,别急着把方案押在 KVM 上。
原因很简单。你以为自己在做“标准虚拟化方案”,但只要底层的 nested KVM 不可用,后面很多努力都会慢慢变成无效消耗。不是你不够能折腾,而是这条路本身就不顺。
最后我落地的方案很朴素:Debian 宿主 + Incus routed 容器。一台宿主,切两只 routed 容器,结果反而比我最开始想象得更稳,也更适合长期运维。
整个结构非常简单:
- 1 台宿主(Host):Debian ARM64
- 2 台 routed 容器(Chick1 / Chick2)
也就是典型的:1 个 host + 2 只小鸡。
这篇文章就按照完整复盘的方式,把我为什么最后收敛到这条路、实际踩过哪些坑,以及怎么把网络和安全真正收口,讲清楚。
先确认能力边界:别让沉没成本把你拖进 KVM 的坑里
很多时候,系统里“能装上某些组件”,会让人误以为“那应该也能跑起来”。但在 Oracle ARM 这种场景里,真正决定成败的,往往不是软件层能不能装,而是底层有没有把能力给你。
所以我现在更倾向于把第一步做得直接一点:
- 先看 KVM 相关设备节点在不在
- 再看内核模块和虚拟化能力是不是真的可用
- 如果关键能力不存在,就及时止损,不再往下追加复杂度
这一步听起来很基础,但实际上特别值钱。
因为一旦你已经确认 nested KVM 这条路走不通,后面继续死磕 PVE/KVM,基本就会进入一种很典型的状态:装的东西越来越多,系统越来越重,排障越来越碎,但离“稳定可用”并没有真正更近。
很多时候,我们以为自己在追求的是“必须做成虚拟机”。但回头看,你真正想要的,其实通常只有两件事:
- 要有隔离
- 要有接近独立节点的运维体验
只要这两个目标能达成,容器未必就是退而求其次。
为什么最后选 routed:我要的不是容器能跑,而是它像一台独立的小机器
如果只是为了把服务跑起来,NAT 容器当然已经够用了。
但“切小鸡”这件事,本质上并不只是为了省资源,而是为了得到几台边界清晰、职责独立、后续好管理的小节点。也就是说,你真正想要的是一种更接近轻量 VPS 的感觉。
至少对我来说,我会在意这几件事:
- 每只小鸡能各自承载不同业务,互不干扰
- 登录、更新、限权这些事情可以独立处理
- 对外访问不要太绕,不想所有流量都回到宿主再做一堆端口映射
而 routed 模型刚好很适合这个目标:
- 宿主保留自己的公网地址
- 每只 routed 容器都能有独立公网地址
- 管理和使用体验上,更像真正独立的节点
这也是我最后选 Incus routed 的核心原因。它不是“凑合能用”的替代品,反而更像是在现有约束下,一条更顺手、也更长期主义的路线。
最终拓扑很简单:一台 Host + 两只 Chick,角色越清楚,后面越省心
整个结构抽象出来,其实非常清楚:
Internet
|
(宿主公网地址)
[Host]
Debian + Incus
|
routed 转发/路由
/ \
(Chick1 公网地址) (Chick2 公网地址)
[Chick1] [Chick2]
业务/服务 A 业务/服务 B
我后来越来越觉得,这种场景里最重要的不是“把节点切出来”,而是从一开始就把角色分清:
- Host(宿主):负责 Incus 管理、routed 支撑、必要的转发控制,以及后续备份、监控、统一运维入口
- Chick1 / Chick2(小鸡):各自承载独立业务,把应用层的复杂度尽量留在容器内部
宿主最好始终把自己当成控制面,而不是一个什么都往上堆的杂物间。
只要这个定位立住,后面很多决策会自然清晰很多。
容器能启动,只是开始:真正的验收标准是它能不能长期维护
一开始最容易让人产生错觉的,就是容器创建成功之后那种“好像已经差不多了”的感觉。
比如:
- 能启动
- 能看到地址
- 能 ping
- 看起来网络也通了
但这些都只能说明它“活着”,还不能说明它已经是一只可以长期运维的小鸡。
对 routed 容器来说,真正值得验收的,其实是这些更务实的问题:
- 出网是不是稳定,不只是偶尔能通
- 包管理能不能正常更新、安装依赖
- 能不能独立 SSH 管理
- 安全策略能不能统一收口
这次实践里,真正麻烦的问题,基本都集中在这些“不是不能用,但离好用还差一步”的地方。
坑位 1:很多时候看起来像 DNS,实际上更常见的是宿主转发或防火墙在拦
我碰到过一个非常典型的状态:
- 容器能 ping 外网
- 但 HTTPS 或其他 TCP 流量不稳定
apt update这种事情看起来像网络通了,实际却各种报错或卡住
这种时候,很多人的第一反应会放在容器内部:
- DNS 对不对
- 源是不是有问题
resolv.conf有没有被覆盖
这些当然都值得查,但 routed 场景下有一个特别容易被忽略的事实:宿主本身就是网络路径的一部分。
只要宿主的转发策略或者防火墙规则没有处理好,就会出现一种特别迷惑的“半通不通”:
- ICMP 没问题
- 真正要用的 TCP 流量却在宿主这一层被挡住了
所以我现在排查这类问题,会更习惯按层看:
- 容器内部先看路由、DNS、基础出站行为
- 宿主层再看 forwarding 和防火墙策略,尤其是 routed 流量是不是被明确允许
- 最后再从外部视角验证公网地址上的访问行为
只要把宿主层纳入排障范围,这类问题通常就会一下子清晰很多。
坑位 2:网络修好了,HTTPS 还是不对?那就别再只盯着路由了
还有一种情况也很容易误判。
就是你把网络问题基本处理完以后,发现 HTTPS 依旧报错,证书链不受信任,或者包管理走 HTTPS 源还是失败。
这时候很多人会直觉觉得:是不是网络还有一层没打通?
但实际并不一定。
有些新起的容器,问题并不在网络,而在它的基础维护环境还没有补齐,尤其是证书链相关组件不完整的时候,表面现象就会非常像“网络依旧不通”。
更稳妥的处理方式通常是:
- 先临时使用可靠的 HTTP 源,完成基础更新
- 补齐证书链和加密相关组件,比如
ca-certificates、openssl - 再把源切回 HTTPS
做完这一步以后,系统才真正进入“可以正常维护”的状态。否则你后面无论装依赖、打补丁,还是做自动化,都会一直被这些基础问题绊住。
坑位 3:Zero-Trust 收口不是锦上添花,而是完工条件
把两只小鸡切出来之后,表面上你只是多了两个节点,实际上你也多了新的暴露面:
- 节点变多了
- 对外可达入口变多了
- 宿主还多承担了一层转发责任
如果你把安全收口放到最后再说,后面每加一个服务、每改一次配置,都会多一笔认知负担:
- 哪些端口是必须开的
- 哪些规则是历史遗留
- 哪些策略会影响 routed
比起最后回头补,我更推荐在完工定义里直接把收口算进去,而且宿主和小鸡尽量统一口径:
- SSH 只保留一个高位端口
- 默认端口关闭
- 仅允许公钥登录(key-only)
- 防火墙默认拒绝入站,只放行必要端口
- 基础爆破防护开启,比如 fail2ban
宿主侧的 forwarding 也一样,不是简单粗暴地“一键全关”,而是只保留业务真正需要的那部分,把历史遗留和多余转发尽量清干净。
这一步做得越克制,后面通常越稳。
最后的结论:在 Oracle ARM 这种约束里,Incus routed 往往比硬冲 KVM 更像正解
回头看这次实践,我觉得最有价值的,并不是“我成功把容器跑起来了”,而是下面这些判断最后都做对了:
- 先确认能力边界,不让沉没成本带着自己乱跑
- 选择 routed,让容器真正具备接近独立节点的体验
- 把宿主转发和防火墙纳入网络路径来排查
- 补齐证书链,让系统进入可维护状态
- 把 Zero-Trust 收口当成完工条件,而不是附录
如果你也在 Oracle ARM 这类环境里,想把一台机器拆成两只能长期运维的小鸡,我现在的建议会很明确:
别再把精力耗在一个并不成立的 KVM 预设上。
把目标换成“做出两台好维护、边界清晰、足够独立的小节点”,很多事情反而会顺起来。而在这个前提下,Incus routed 往往就是那条更轻、更稳,也更省心的路。
#OracleCloud #ARM #Incus #Debian #Zero-Trust #运维