現代雲端運算中,容器化技術雖然提供了輕量級的隔離環境,但傳統容器共享主機 kernel,安全隔離性有限。本專題旨在整合 Firecracker MicroVM、MicroK8s 和 Kata Containers,實現:
- MicroVM:使用 Firecracker 啟動 MicroVM。
- Kubernetes 支援:透過 MicroK8s 統一管理 MicroVM 化的 Pod。
- 隔離與安全:每個 Pod 運行在獨立的 MicroVM 中,而非共享宿主機 kernel。
- Hypervisor 架構:將 Kata Containers 預設的 QEMU 虛擬化引擎,替換為專為雲原生設計的 Firecracker MicroVM。
- 作業系統:Ubuntu 24.04 LTS(目前只在 24.04 測試過)
- CPU:必須支援 KVM 硬體虛擬化(具備
vmx或svmflag) - 記憶體:至少 8GB(建議 16GB 以上)
- 磁碟空間:至少 50GB 可用空間
| 軟體/模組名稱 | 參考版本 | 系統角色 |
|---|---|---|
| Firecracker | v1.10.0 | VMM(虛擬機監控器) |
| Kata Containers | v3.31.0 | 容器虛擬化安全隔離層:作為 Container 與 MicroVM 的中間橋樑 |
| MicroK8s | v1.28 | 輕量化 Kubernetes 叢集:負責整體 Pod 的生命週期管理、網路調度與服務暴露 |
| containerd | Snap 內建版 | Container Runtime:K8s 控管容器的直接接口,透過修改其 TOML 模板來切換底層儲存後端 |
| KVM | Linux 內建 | 核心虛擬化模組:為 Firecracker 提供底層硬體加速 |
| device-mapper | Linux 核心內建 | 儲存對應子系統:建立 thin-pool,將檔案模擬成 Firecracker 唯一支援的 Block Device |
util-linux (dmsetup/losetup) |
Ubuntu 內建 | 區塊裝置管理工具:掛載虛擬磁碟並配置 thin-pool 結構 |
| Nginx | Docker Hub image | 測試與驗證應用:驗證 MicroVM Pod 內的獨立 Kernel 與外部網路連線 |
開發歷程分為四個階段:
- Firecracker 手動部署:初步下載 Firecracker 二進制檔,透過 REST API 發送 JSON 格式指令,成功配置 Kernel 與 rootfs 並實現啟動,驗證其底層運作原理。
- MicroK8s 與 Docker 基礎建置:建立標準的 Kubernetes 測試環境,透過一般 nginx Pod 確認容器與宿主機共用 Kernel(例如 6.8.0 版本)。
- Kata Containers + QEMU 整合驗證:導入 Kata Containers 框架,使用預設的 QEMU 模式,成功讓 Pod 跑在獨立的 MicroVM 中(核心版本變為 6.18.28),確認架構可行。
- Kata Containers + Firecracker 整合:遭遇 containerd 使用 overlayfs 但 Firecracker 僅支援 Block Device 的衝突,最終引入 devmapper snapshotter 解決,建立 Device Mapper Thin-Pool 並修改
containerd-template.toml完成整合。
# 確認 CPU 支援虛擬化(有輸出代表支援)
grep -E "vmx|svm" /proc/cpuinfo# 下載並解壓縮
mkdir -p ~/firecracker-install && cd ~/firecracker-install
wget https://github.com/firecracker-microvm/firecracker/releases/download/v1.10.0/firecracker-v1.10.0-x86_64.tgz
tar -xvf firecracker-v1.10.0-x86_64.tgz
# 移至專屬資料夾並賦予執行權限
mkdir -p ~/firecracker-bin
mv release-v1.10.0-x86_64/firecracker-v1.10.0-x86_64 ~/firecracker-bin/firecracker
mv release-v1.10.0-x86_64/jailer-v1.10.0-x86_64 ~/firecracker-bin/jailer
chmod +x ~/firecracker-bin/firecracker ~/firecracker-bin/jailer
cd ~ && rm -rf ~/firecracker-install
# 建立軟連結至系統路徑
sudo ln -sf ~/firecracker-bin/firecracker /usr/local/bin/firecracker
sudo ln -sf ~/firecracker-bin/jailer /usr/local/bin/jailer
# 驗證
firecracker --versionsudo snap install microk8s --classic --channel=1.28/stable
sudo usermod -a -G microk8s $USER
sudo chown -f -R $USER ~/.kube
newgrp microk8s
microk8s status --wait-readyUbuntu 24.04 注意:在啟用 community 插件庫之前,需先設定 Git 信任清單,否則 Snap 沙盒機制會讓 MicroK8s 內部的 git clone 被擋下。
git config --global --add safe.directory '*'
sudo git config --global --add safe.directory '*'
microk8s enable communitycd ~
wget https://github.com/kata-containers/kata-containers/releases/download/3.31.0/kata-static-3.31.0-amd64.tar.zst
sudo apt-get update && sudo apt-get install zstd -y
sudo tar -I zstd -xf kata-static-3.31.0-amd64.tar.zst -C /
rm kata-static-3.31.0-amd64.tar.zstFirecracker 只支援 Block Device,無法使用 Kubernetes 預設的 overlayfs,需建立 Device Mapper thin-pool 作為儲存後端。
# 建立目錄與虛擬磁碟檔
sudo mkdir -p /var/lib/containerd-devmapper
sudo mkdir -p /var/snap/microk8s/common/var/lib/containerd-devmapper
sudo truncate -s 20G /var/lib/containerd-devmapper/data
sudo truncate -s 2G /var/lib/containerd-devmapper/metadata
# 掛載為 Loop 設備
sudo losetup -f /var/lib/containerd-devmapper/data
sudo losetup -f /var/lib/containerd-devmapper/metadata重要:每台機器分配到的 loop 編號不同,執行以下指令確認後再繼續:
losetup -a
# 範例輸出:
# /dev/loop3: [xxx] (/var/lib/containerd-devmapper/data)
# /dev/loop4: [xxx] (/var/lib/containerd-devmapper/metadata)將下方指令中的 loop3(data)與 loop4(metadata)替換為你實際看到的編號:
sudo dmsetup create containerd-thinpool \
--table "0 $(sudo blockdev --getsz /dev/loop3) thin-pool /dev/loop4 /dev/loop3 128 32768"
# 驗證
sudo dmsetup ls
# 應看到:containerd-thinpool (253:0)若需要重建 thinpool:thinpool 和 containerd 各自維護一套狀態,重建時必須兩邊同時清空,否則會出現
snapshot does not exist錯誤。單獨重建 thinpool 或單獨清 containerd 都不夠,必須一起來:sudo microk8s stop sudo dmsetup remove --force containerd-thinpool sudo losetup -d /dev/loopX # 替換為實際編號 sudo losetup -d /dev/loopY sudo rm -rf /var/snap/microk8s/common/var/lib/containerd sudo rm -rf /var/snap/microk8s/common/var/lib/containerd-devmapper/*清完後從重新掛載 loop 設備開始跑。
# 將 snapshotter 改為 devmapper
sudo sed -i 's/snapshotter = "${SNAPSHOTTER}"/snapshotter = "devmapper"/' \
/var/snap/microk8s/current/args/containerd-template.toml
# 追加 devmapper 設定區塊
sudo tee -a /var/snap/microk8s/current/args/containerd-template.toml << 'EOF'
[plugins."io.containerd.snapshotter.v1.devmapper"]
pool_name = "containerd-thinpool"
root_path = "/var/snap/microk8s/common/var/lib/containerd-devmapper"
base_image_size = "8192MB"
discard_blocks = true
EOF
# 切換 Kata 設定為 Firecracker 模式
sudo cp /opt/kata/share/defaults/kata-containers/configuration-fc.toml \
/opt/kata/share/defaults/kata-containers/configuration.toml
# 重啟 MicroK8s
sudo microk8s stop && sudo microk8s start
microk8s status --wait-readyMicroK8s 的 containerd 會在系統 $PATH 中尋找 containerd-shim-kata-v2,但 Kata 靜態包安裝在 /opt/kata/bin/,需手動建立軟連結橋接。
若跳過此步驟,Pod 會永遠卡在
ContainerCreating,並出現"containerd-shim-kata-v2": file does not exist錯誤。
sudo ln -sf /opt/kata/bin/containerd-shim-kata-v2 /usr/local/bin/containerd-shim-kata-v2
sudo ln -sf /opt/kata/bin/kata-runtime /usr/local/bin/kata-runtime
sudo ln -sf /opt/kata/bin/kata-monitor /usr/local/bin/kata-monitormicrok8s enable kata --runtime-path=/opt/kata/bin
cat <<EOF | microk8s kubectl apply -f -
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: kata
handler: kata
EOFcat <<EOF | microk8s kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: nginx-kata
labels:
app: nginx
spec:
runtimeClassName: kata
containers:
- name: nginx
image: nginx
EOF
microk8s kubectl get pods -w# 宿主機 Kernel(例如 6.8.x)
uname -r
# Pod 內 Kernel(應與宿主機不同,代表跑在獨立 MicroVM 中)
microk8s kubectl exec -it nginx-kata -- uname -r
# 確認使用 Firecracker
/opt/kata/bin/kata-runtime kata-env 2>/dev/null | grep "firecracker"microk8s kubectl expose pod nginx-kata \
--type=NodePort --port=80 --target-port=80 \
--name=nginx-kata-service
# 查看分配到的 Port
microk8s kubectl get svc nginx-kata-service
# 測試連線(將 <NodePort> 換成上方查到的號碼)
curl http://localhost:<NodePort>| 錯誤訊息 | 原因 | 解法 |
|---|---|---|
404 Not Found on wget |
AWS S3 下載連結已失效 | 使用步驟 2 的 GitHub 連結 |
fatal: detected dubious ownership |
Ubuntu 24.04 Snap + Git 安全機制衝突 | 步驟 3 執行 git config safe.directory '*' |
device-mapper: reload ioctl failed |
loop 設備編號填錯 | losetup -a 確認實際編號後再建立 thinpool |
Pod 卡在 ContainerCreating |
系統找不到 containerd-shim-kata-v2 |
步驟 7 執行軟連結指令 |
error: selector is required |
Pod 缺少 Label | 確認 YAML 中有 labels: app: nginx |
snapshot does not exist: not found |
thinpool 重建後與 containerd metadata 資料庫不同步 | 停掉 MicroK8s,同時清除 thinpool 和 /var/snap/microk8s/common/var/lib/containerd,再從重新掛載 loop 開始 |