Podman 6.0 在 2026 年 6 月底釋出,release note 讀起來像一份除役清單:CNI 網路棧、iptables firewall backend、slirp4netns rootless 網路層、cgroups v1、BoltDB 狀態資料庫,五個從 Podman 誕生就一路帶著的舊架構同時被砍。對 VPS operator 來說這不是換版本號那麼簡單——升級路徑本身有兩段,跳過中間那段會直接讀不到既有容器狀態。這篇拆解每個移除背後的技術動機,以及怎麼安全地把 5.x 環境過渡到 6.0。
Podman 過去幾年一直用「相容並存」的策略維持轉型:CNI 跟 Netavark 並存兩年、iptables 跟 nftables 並存一年、slirp4netns 跟 pasta 並存整條 5.x 生命週期。並存的代價是配置矩陣爆炸,同一份 Quadlet 檔在不同主機上跑出來的行為可能不一樣。6.0 把並存收乾淨,換得的是可預期的 runtime,代價是升級不能一鍵搞定。
BoltDB 到 SQLite 中間必須經過 5.8
Podman 5.x 之前的 container metadata、network、volume 狀態全部存在 BoltDB 裡。BoltDB 是 Go 原生實作的 B+tree KV store,好處是零依賴、單檔案;壞處是 schema 難改、多 process 寫入要靠外部 lock。5.0 引入 SQLite backend 作為新環境的預設,5.8 把 BoltDB 環境的自動 migration 補齊——啟動時偵測到 BoltDB 就把資料倒進 SQLite、下次啟動兩邊並存驗證、確認一致後才拆掉舊檔。
6.0 把 BoltDB 讀取程式碼完全移除。從 5.7 或更早版本直接升到 6.0,Podman 啟動時看到 BoltDB 檔案會回報找不到相容的 state backend,容器清單全空。這不是資料被刪,而是 6.0 沒有能力讀。修復方式只有兩條:降版到 5.8 讓 migration 跑完、或者手動用 5.8 的 CLI 匯出重建。
升級前先確認資料庫後端:
1 | podman info --format '{{.Host.DatabaseBackend}}' |
回傳 sqlite 就可以直接跳 6.0,回傳 boltdb 就得先過 5.8。RHEL 系的套件庫在 2026 年上半年才把 5.8 放進 EPEL,Debian 13 官方倉庫停在 5.4,得從 Kubic 或者 Podman 官方的 apt repo 拉。這段落差是 Debian 主機最容易踩的坑——apt upgrade 從 5.4 直接跳到 6.0,中間跳過 5.8 這班車。
CNI 移除得手動跑兩條 migrate 指令
CNI(Container Network Interface)是 Kubernetes 用了很多年的介面標準,Podman 4.0 之前也用它管容器網路。4.0 引入 Netavark 作為新的網路後端,設計更貼近單機容器場景、不用背 Kubernetes 那套 pod-level 抽象。Netavark 直接呼叫 nftables、跳過 CNI plugin discovery 那段延遲,冷啟動容器的網路建立時間從 200ms 降到 30ms 左右。
6.0 把 CNI 相關程式碼全部移除。危險的地方是 6.0 遇到舊的 CNI config 檔不會噴錯,只會靜默忽略——容器起得來、看起來一切正常,但外部進不去、容器之間也連不上。這種 silent failure 比噴錯難 debug 得多,因為 Podman 沒吐出任何線索。
升級後必跑兩條指令把 network config 遷過去:
1 | podman system migrate |
第一條處理 container state 對新網路的重新註冊,第二條把 /etc/cni/net.d/ 底下的舊設定轉成 Netavark 的 /etc/containers/networks/ 格式。跑完之後最好用 podman network ls 對一次數量,確認舊網路都轉過來。自訂 CNI plugin(例如接 Cilium 或 Calico 的環境)就沒這麼幸運,Netavark 沒有 plugin 機制,得改成 Netavark 的 external tool 介面重寫。
slirp4netns 到 pasta 的效能差不是重點,client IP 才是
slirp4netns 是 rootless Podman 一路用來繞開 root 權限限制的網路 emulator。它跑在 user namespace 裡、用 tap device 把封包在 host 跟 container 之間搬。5.0 引入 pasta 當替代方案,效能是主要賣點——pasta 在 loopback 場景下能跑到 slirp4netns 的 5 倍以上吞吐。
真正影響設計決策的是 client source IP。slirp4netns 做 port forwarding 時會把來源 IP 全部改寫成 host 本地 IP,rootless 容器裡跑的服務永遠看到 127.0.0.1。這對紀錄稽核、防濫用、rate limit 全部有影響,很多服務被迫走 root 模式或者接 reverse proxy 補 X-Forwarded-For。pasta 的做法是保留原始 client IP,rootless 容器裡 nginx 直接就能拿到來源位址。
Podman 5.x 允許 quadlet 檔案裡明確指定 Network=slirp4netns,6.0 之後這行會直接讓 systemd unit 啟動失敗,錯誤訊息是 unknown network mode。升級前用 grep 掃一次:
1 | grep -rE 'slirp4netns|--network=slirp4netns' \ |
搜到的每一處都刪掉 Network=slirp4netns 這一行,讓它 fallback 到預設的 pasta 就好。手寫的 shell script 裡 podman run --network=slirp4netns 也是同樣處理。
pause process 用 nsfs handle 收掉,Kernel 6.18 才生效
Rootless Podman 為了在容器全部退出後仍然保住 user namespace 不被回收,會另外開一支 catatonit 當 pause process 掛著。這支 process 本身不做事,就是拿來 hold 住 namespace fd。缺點是每個 podman user 都會多一支常駐 process,資源監控會多一條雜訊。
6.0 加了實驗性支援:Kernel 6.18 以上可以用 nsfs(namespace filesystem)的檔案 handle 直接固定 namespace,不需要 hold-open 那支 process。啟用方式是設環境變數 PODMAN_DROP_PAUSE_PROCESS=1,這個選項刻意 gate 住不預設開,因為需要對應 kernel 版本,且行為在 stable 之前可能還會調整。Debian 13 帶的是 6.12、Ubuntu 26.04 是 6.18,臺灣 VPS 上比較多的 Rocky 10 走 kernel 6.6 就沒得用。
cgroups v1 直接拒絕啟動、iptables backend 拉掉要重看防火牆規則
Podman 6.0 開機時偵測到 host 只有 cgroups v1 會直接拒絕啟動、不是 fallback 或者警告。判斷指令是:
1 | cat /sys/fs/cgroup/cgroup.controllers |
檔案存在且有內容就是 v2 unified、檔案不存在就是還在 v1。Debian 11 以下、CentOS 7、Ubuntu 20.04 預設仍在 v1,這些主機得先切到 unified 才能上 Podman 6。切換方式是在 kernel cmdline 加 systemd.unified_cgroup_hierarchy=1,寫進 /etc/default/grub 之後重跑 update-grub 再重開。
iptables backend 拉掉是另一件 operator 得回頭審的事。Netavark 從 6.0 開始只走 nftables,之前用 iptables -L 或 iptables-save 監控 container 流量的 script 全部要改寫。fail2ban 這類接 iptables chain 的工具在 Podman 6 環境下沒法直接看到容器規則,得改用 nftables 對應 API 或者 fail2ban 的 nftables backend。監控端最容易漏的一件事是 DOCKER-USER 這條 iptables chain 早就不存在,Netavark 對應的 chain 名字是 NETAVARK-HOSTPORT-DNAT 跟 NETAVARK-FORWARD。
AMD GPU 直接進 –gpus 旗標
--gpus 旗標從 6.0 開始正式支援 AMD ROCm GPU,語法跟 NVIDIA 一致:
1 | podman run --gpus all --rm rocm/pytorch:latest |
實務上這對自架 LLM inference 開了一條新路徑。過去 Podman 上跑 ROCm 得手動 mount /dev/kfd、/dev/dri、加 --security-opt seccomp=unconfined、還要把 render group 對進去;6.0 把這些包進 --gpus 的行為裡,跟 nvidia-container-toolkit 的 UX 對齊。臺灣機房裡 AMD MI300 跟 MI325 的部署開始出現,這個對齊拿掉了一個常被抱怨的搬遷成本。
VPS 升級的實際順序
把上面那些拆解合起來,一份可以照做的升級順序是:
podman info --format '{{.Host.DatabaseBackend}}'確認資料庫後端,回boltdb就先把版本鎖在 5.8 跑完 migrationcat /sys/fs/cgroup/cgroup.controllers確認 cgroups v2,v1 環境先切grep -rE 'slirp4netns' /etc/containers/ ~/.config/containers/掃 Quadlet 跟 shell script,把顯式指定拿掉- 稽核 iptables 相關的監控與 fail2ban 規則,準備好對應的 nftables 版本
- 升級到 6.0,跑
podman system migrate跟podman network migrate podman network ls對數量、隨機起一個既有容器測 pull 跟 exec 都能過- Buildah、Skopeo、Netavark、Aardvark DNS 一併升到 6.0 相容版本(Buildah 1.44、Skopeo 1.23、Netavark/Aardvark 2.0)
依賴版本鎖是這次升級容易被忽略的一步。Podman 6.0 呼叫 Netavark 2.0 的新 API,舊版 Netavark 會回 unsupported call。發行版套件庫如果版本不齊,得從 upstream repo 拉,或者暫緩升級到套件庫追上為止。
結論
Podman 6.0 這次的改動看起來像是激進地拆東西,實際上是把 4.x、5.x 兩代累積下來的相容包袱一次清完。CNI、slirp4netns、iptables、cgroups v1、BoltDB 這五層每一層都有它的替代方案,維護成本降下來、行為變得更可預期。臺灣 VPS 環境要跟上這波節奏,關鍵是別讓 apt 或 dnf 幫忙做「一鍵升級」的決策,中間那段 5.8 的過渡不能跳。
NCSE Network 提供的臺灣 VPS 主機採用 Intel Gold CPU 搭配 NVMe SSD,作業系統選擇涵蓋 Debian 13、Ubuntu 26.04、Rocky 10 等現代版本,cgroups v2 與新版 kernel 都是預設狀態,適合作為 Podman 6.0、Quadlet 與 systemd 容器化架構的部署基地。若正在規劃把 Docker 環境搬到 Podman 或者從 5.x 升到 6.0,可以到 ncse.tw 了解主機規格與網路架構。