Oracle Cloud K3s 迁移到 Cilium:一次把网络、密钥和状态数据都翻出来的升级
目录
背景#
我的 homelab 现在是双集群结构:
homelab跑在 Proxmox 上,负责 Vault、ZITADEL、ArgoCD、Grafana、Kopia 这类核心服务。oracle-k3s跑在 Oracle Cloud A1 免费机上,负责 Homepage、Miniflux、KaraKeep、Uptime Kuma、Timeslot 等轻量工作负载。
前一阵我先把 homelab 主集群从 Flannel 切到了 Cilium。迁移完成后,整个架构留下了一个非常明显的不对称:一边是 Cilium,一边还是 K3s 默认 Flannel。
这件事短期看没有坏处,但中长期会越来越烦:
- 网络问题的排障路径不一致。
- 两套集群文档会慢慢分叉。
- 以后不管是做 ClusterMesh PoC,还是只是想统一认知模型,都会被这块技术债反咬。
所以这次我决定把 oracle-k3s 也迁到 Cilium。
这次迁移真正的目标#
表面目标是把 CNI 从 Flannel 换成 Cilium,但真正目标其实有三个:
- 统一双集群数据面:以后提到 Pod 网络、Hubble、NetworkPolicy,两个集群说的是同一套东西。
- 验证恢复能力:既然是重装 K3s,就顺手检验一下 GitOps、Vault、备份、PVC 恢复到底是不是纸上谈兵。
- 识别复杂度来源:哪些问题是 Cilium 带来的,哪些其实是之前就存在,只是这次被重建过程暴露出来了。
迁移步骤概览#
最终流程大致是这样:
备份本地 PVC 数据
-> 卸载 K3s
-> 关闭 Flannel,重装 K3s
-> 安装 Cilium Helm chart
-> 重装 ESO / Traefik 配置 / 各类 manifests
-> 修 Vault Secret / Cloudflare Tunnel / 探针 / 数据库连接
-> 恢复 PVC 数据
-> 验证所有对外服务
其中真正耗时间的不是安装 Cilium,而是安装完以后把整条依赖链重新扶起来。
Cilium 配置选择#
这次我没有追求特别激进的配置,基本原则是:先求一致,再求花哨。
关键配置如下:
kubeProxyReplacement: false
routingMode: tunnel
tunnelProtocol: vxlan
ipam:
operator:
clusterPoolIPv4PodCIDRList:
- 10.52.0.0/16
hubble:
enabled: true
relay:
enabled: true
ui:
enabled: true
gatewayAPI:
enabled: false
有几个选择是有意为之:
- 继续保留
kube-proxy,不在这次迁移里同时引入 kube-proxy replacement 变量。 - 继续使用
routingMode: tunnel,避免把 Oracle Cloud 的底层网络特性也卷进来。 - 不启用 Cilium Gateway API,继续让 Traefik 管现有流量入口。
原因很简单:这次目标是把 Oracle 集群稳定迁到 Cilium,不是顺手再做一轮网关重构。
第一个坑:Cloudflare Tunnel 连不上#
Cilium 装好后,最先暴露的问题不是业务应用,而是 cloudflared。
Pod 日志里一直是这个错误:
failed to dial to edge with quic: timeout: handshake did not complete in time
看起来像网络问题,但细看会发现它很有指向性:Cloudflared 默认优先走 QUIC,也就是 UDP。
而 Oracle Cloud 这台机器的现实情况是:UDP/QUIC 这条路径并不稳定。在新的网络栈下,这个问题被立刻放大了。
最终修复并不复杂,直接强制 cloudflared 使用 HTTP/2:
args:
- tunnel
- --no-autoupdate
- --protocol
- http2
- --metrics
- 0.0.0.0:2000
- run
改完后两个 cloudflared Pod 很快都恢复到 1/1 Running。
这次让我重新确认了一件事:
在 homelab 场景里,稳定往往比“默认最优协议”更重要。QUIC 很好,但如果底层网络环境不友好,强上只会让问题更隐蔽。
第二个坑:不是 Secret 丢了,是整条 Secret 供应链断了#
集群起来后,应用却没有跟着起来。ExternalSecret 几乎全红。
先查 ESO,再查 ClusterSecretStore,最后定位到一个非常基础但致命的问题:
- oracle 集群访问 Vault 还是走旧的 NodePort
31144 - 实际 homelab 上 Vault 已经换成
31333
也就是说,不是密钥值错了,而是 oracle 集群从一开始就连错了入口。
这个修好后,问题还没结束。
继续往下查,发现这次真正暴露的是另一个现实:我以前以为“已经放进 Vault”的东西,其实并没有全部标准化入库。
最后我补齐和恢复了这几类 Secret:
oracle-k3s/cloudflareoracle-k3s/uptime-kumaoracle-k3s/stirling-pdforacle-k3s/oauth2-proxyhomelab/minifluxhomelab/karakeephomelab/redpanda-connectoracle-k3s/timeslot
这部分工作非常不优雅,但很真实:
- 有的是从现有配置反推。
- 有的是从 Cloudflare API 重新取 tunnel token。
- 有的是从 shell history 和旧部署痕迹里挖回来。
如果没有这次“重建式迁移”,这些隐性缺口以后只会在更糟糕的时间点爆出来。
第三个坑:应用没坏,是健康检查和连接串坏了#
Secret 都恢复后,Pod 还是没有全绿。
Miniflux#
miniflux 一直 CrashLoop,日志里很明显:
dial tcp [::1]:5432: connect: connection refused
原因是 DATABASE_URL 里仍然写着 localhost:5432,但 PostgreSQL 实际是单独的 Deployment,不在同一个 Pod 里。
修复方式就是把连接串改成 Service 名:
postgresql://miniflux:<password>@rss-postgres.rss-system.svc.cluster.local:5432/miniflux?sslmode=disable
RSSHub#
rsshub 的问题更像“漂移”:应用其实启动了,但健康检查一直失败。
我进去手测才发现,当前镜像的健康接口已经不是 /healthcheck,而是 /healthz。
所以这次修的不是业务逻辑,而是文档和 manifest 对镜像行为的过期认知。
第四个坑:真正的恢复演练发生在 PVC#
这次我提前备份了 oracle 节点上的本地 PVC 目录,后面果然派上用场。
恢复的对象包括:
miniflux-db-pvckarakeep-datameilisearch-datauptime-kuma-datastirling-pdf-configstimeslot-pvc
恢复过程并不高级,就是非常朴素的:
- 先 scale down 对应 Deployment
- 把旧 PVC 目录内容拷回新的 PV 路径
- 先起 PostgreSQL,再起依赖它的应用
- 最后逐个验证服务和数据是否回来
这一步的意义很大,因为它证明了一件比“Cilium 安装成功”更重要的事:
我的 oracle 集群即使完全重装,状态数据也不是不可恢复的。
对 homelab 来说,这比任何一个 fancy 网络特性都更值钱。
Timeslot 也顺手补进去了#
这次还顺手把 Timeslot 重新部署并恢复了数据。
这个服务比较特别:它不是主 kustomize 流里直接管的,而是通过 Helm chart 单独装,再打一个 patch 修 chart bug。
这件事本身也说明了当前架构里一个很值得继续收敛的问题:
- 大多数工作负载已经 declarative 了。
- 但仍有少数应用需要额外的 imperative 补丁步骤。
这类“例外路径”越多,系统越难维护。
迁移后的结果#
迁移完成后,我做了三类验证:
集群健康#
所有 oracle-k3s Pod 最终都恢复到 Running / Ready。
对外可用性#
这些入口都恢复正常:
home.meirong.devtool.meirong.devpdf.meirong.devrss.meirong.devstatus.meirong.devslot.meirong.devsquoosh.meirong.devkeep.meirong.dev
其中 302 的入口是预期行为,因为它们会跳去登录页或 SSO。
运维配套#
- Uptime Kuma monitor 已重新 provision
- 文档里的当前状态已经同步成双 Cilium
cloud/oracle/justfile里之前会被 heredoc 卡死的 recipe 也一起修掉了
这次迁移让我重新排序了后续优先级#
迁移前我原本有点想尽快研究 ClusterMesh,但做完之后反而更确定:现在不该急着上。
原因不是 ClusterMesh 不好,而是当前更值钱的事情另有其人:
- 把剩余的手工 bootstrap 继续 declarative 化
- 给文档和自动化脚本加一层 drift 检查
- 做一次真正的恢复演练,把“能恢复”从推测变成证据
换句话说,下一步最需要的不是更多特性,而是更少例外。
我现在对这套架构的判断#
如果你也在做双集群 homelab,我现在的建议会是:
- 先统一基础能力,再追求高级功能。双集群 CNI 一致,排障成本会显著下降。
- 不要把所有问题都归因于 CNI。这次很多暴露出来的问题,本质上是 Secret 管理、探针漂移、文档过期。
- 重建过程才是最好的验收测试。能不能从零把一套集群扶回来,比平时绿不绿更有价值。
- 对 ClusterMesh 保持克制。在真正需要跨集群 Service 发现前,Tailscale underlay + NodePort / public URL 已经够用了。
结语#
这次 Oracle K3s 迁到 Cilium,表面上是一次网络升级,实际上更像一次架构体检。
Cilium 本身并没有制造太多麻烦。真正值得重视的,是迁移把之前那些“平时还能凑合”的隐性问题都拎到了台面上:
- 文档是不是反映真实状态
- Secret 是否真的集中管理
- 数据恢复是不是可执行
- 自动化脚本是不是能从头跑通
从这个角度看,这次迁移很值。
它不只是让我把两个集群都切到了 Cilium,也让我对这套 homelab 终于有了更强的把握感。
如果你感兴趣,完整的实施记录和当前架构文档都在这里:
docs/plans/2026-03-07-homelab-oracle-architecture-optimization.mddocs/architecture/simplification-recommendations-2026-03.mdcloud/oracle/README.md