Ubuntu 24.04 Minimal Server 在 KVM/Libvirt Default NAT 下的網路排障與 Docker 佈署全紀錄

這篇是我把 Ubuntu 24.04 Minimal Server 放進 KVM/libvirt default NAT 網路時,從「apt update 完全失敗」一路排到「Docker Engine 正常運作」的完整紀錄。

重點不是只給一組指令,而是把每個檢查點都寫清楚,避免之後重建環境又卡在同一個地方。

Host 端虛擬化環境準備(CachyOS)

先在 Host 安裝虛擬化與網路相關套件。

Host:

1
paru -S virt-manager qemu-desktop libvirt edk2-ovmf dnsmasq

用途:

  1. virt-manager:圖形化管理 VM。
  2. qemu-desktop:KVM/QEMU hypervisor。
  3. libvirt:VM 與虛擬網路管理核心。
  4. edk2-ovmf:UEFI 韌體支援。
  5. dnsmasqdefault NAT 會用來做 DHCP/DNS。

啟動服務:

Host:

1
2
sudo systemctl enable --now libvirtd
systemctl status libvirtd

把目前使用者加入 libvirt 群組:

Host:

1
sudo usermod -aG libvirt $(whoami)

重新登入後生效。

Ubuntu 24.04 Minimal 安裝時要先勾的項目

在安裝流程中,至少確認:

  1. IPv4 有啟用。
  2. IPv6 有啟用。
  3. 勾選安裝 OpenSSH server。
  4. 網路模式選 libvirt default NAT

如果一開始沒裝 OpenSSH server,後面只能先在 VM Console 打指令,操作效率會很差。

Minimal 版本的現實:工具很少是正常現象

安裝完看到下面狀態不用緊張,這就是 Minimal 的設計:

  1. 沒有 ping
  2. 沒有 vim
  3. 沒有 nano
  4. 沒有 net-tools
  5. 通常只有 ip 可用。

所以最初排障核心會是 ip addrip route/proc/net/route/etc/resolv.conf

問題起點:apt update 失敗

VM:

1
sudo apt update

典型錯誤:

1
Temporary failure resolving 'archive.ubuntu.com'

這個錯誤表面看起來像 DNS,但實務上常常是「路由 + DNS 同時壞掉」。

關鍵普查:先確認 Host/VM 連接現況再修

先確認 VM 網卡實際名稱

VM:

1
ip addr

要抓到:

  1. 介面真名(例如 enp0s1ens1enp1s0)。
  2. 不要假設一定叫 eth0

Ubuntu 24.04 在不同虛擬化平台,命名可能不一樣,指令裡寫錯介面名會讓後續設定全部失效。

IPv6 視覺誤區:看到 inet6 不代表可上網

ip addr 中常見情況是:

  1. 介面有 inet6
  2. 卻沒有可用的 inet (IPv4)。

這通常代表 IPv4 DHCP 沒拿到地址,只剩 IPv6 link-local。它是「網路未完整對接」的警訊,不是正常可上網狀態。

檢查 VM 路由是否有 default gateway

VM:

1
2
ip route
cat /proc/net/route

如果 /proc/net/route 幾乎只剩表頭,或 ip route 沒有 default via ...,就代表 kernel 根本不知道封包要往哪裡送。

檢查 VM DNS

VM:

1
cat /etc/resolv.conf

如果 nameserver 是空的、無效的,或指向不可達目標,apt 會直接卡在網域解析。

普查 Host 虛擬網橋與 gateway

Host:

1
ip addr

virbr* 介面,通常是 virbr0,但名稱不保證固定。

再看它的 IPv4,例如:

1
inet 192.168.122.1/24

這個位址就是 VM 的 gateway 候選值。

檢查 Host 端 forwarding 與 NAT

檢查 bridge 狀態:

Host:

1
ip addr show virbr0

檢查 IP forwarding:

Host:

1
sysctl net.ipv4.ip_forward

如果是:

1
net.ipv4.ip_forward = 0

VM 幾乎不可能透過 Host 出網。

檢查 FORWARD chain:

Host:

1
sudo iptables -L FORWARD -n -v

要注意 policy 是否是 DROP,以及是否允許 virbr 封包轉送。

檢查 NAT POSTROUTING:

Host:

1
sudo iptables -t nat -L POSTROUTING -n -v

要看到類似:

1
MASQUERADE  all  --  192.168.122.0/24  anywhere

沒有 MASQUERADE 的話,VM 即使有 gateway 也常常出不去外網。

Host 端修復(若上述普查不通)

啟用 IP forwarding:

Host:

1
sudo sysctl -w net.ipv4.ip_forward=1

把 FORWARD policy 調成 ACCEPT:

Host:

1
sudo iptables -P FORWARD ACCEPT

新增 NAT 規則:

Host:

1
sudo iptables -t nat -A POSTROUTING -s 192.168.122.0/24 -j MASQUERADE

重新驗證:

Host:

1
2
sudo iptables -L FORWARD -n -v
sudo iptables -t nat -L POSTROUTING -n -v

VM 端強制手動接通流程

先確認兩件事:

  1. VM 網卡名,例如 enp1s0
  2. Host virbr IP,例如 192.168.122.1

手動綁 IP:

VM:

1
sudo ip addr add 192.168.122.100/24 dev enp1s0

建立同網段路由:

VM:

1
sudo ip route add 192.168.122.0/24 dev enp1s0

加預設閘道:

VM:

1
sudo ip route add default via 192.168.122.1 dev enp1s0

檢查路由:

VM:

1
ip route

要看到 default via 192.168.122.1 dev enp1s0

強制注入 DNS:

VM:

1
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf

連通測試:

VM:

1
2
3
ping 8.8.8.8
ping archive.ubuntu.com
sudo apt update

只要這一步通了,後續工具與服務安裝就能接上。

SSH 遠端管理:解決 VM Console 不好用

常見痛點是 VM console 無法順暢複製貼上,長指令容易打錯。

先裝核心工具:

VM:

1
sudo apt update && sudo apt install openssh-server vim

啟動 SSH:

VM:

1
sudo systemctl enable --now ssh

從 Host 連入:

Host:

1
ssh user@192.168.122.100

之後改用本機終端維運 VM,效率會高很多。

Docker 引擎佈署:選 Docker 官方來源而不是 docker.io

Ubuntu 內建倉庫的 docker.io 可用,但我這次改用 Docker 官方來源,原因是:

  1. 版本更新通常比較快。
  2. buildxcompose v2 插件整合更完整。
  3. 安全更新節奏跟官方同步。

Docker 官方安裝流程(Ubuntu 24.04)

建立 keyring 目錄:

VM:

1
sudo install -m 0755 -d /etc/apt/keyrings

導入 Docker GPG:

VM:

1
2
3
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

加入 Docker repository:

VM:

1
2
3
4
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

安裝 Docker Engine 與插件:

VM:

1
sudo apt update && sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

設定免 sudo(目前使用者):

VM:

1
2
sudo usermod -aG docker $USER
newgrp docker

驗證:

VM:

1
docker ps

最終驗收清單

Host 端:

  1. libvirtd 正常 running。
  2. virbr* bridge 存在且有 IPv4。
  3. net.ipv4.ip_forward = 1
  4. FORWARD 鏈可放行 VM 封包。
  5. NAT 有對 VM 網段做 MASQUERADE。

VM 端:

  1. 介面有有效 IPv4。
  2. 路由表有 default via <virbr IP>
  3. /etc/resolv.conf 有可用 nameserver。
  4. apt update 可成功。
  5. SSH 可登入。
  6. Docker hello-world 可成功執行。

到這裡就完成「Minimal 初始不可用」到「可維運、可部署容器」的整條路徑。

參考資料

  1. libvirt: NAT forwarding (virtual networks)
  2. libvirt: Network XML format(含 default NAT 範例)
  3. Ubuntu Server docs: Networking(How-to)
  4. Ubuntu Server docs: About Netplan
  5. Docker Docs: Install Docker Engine on Ubuntu
  6. Docker Docs: Linux post-installation steps
0%