﻿# 如何替 Multipass 建立的 VM 設定一組固定 IP 地址

雖然透過 [Multipass](https://multipass.run/) 建立 Ubuntu VM 相當便利，但是若要設定一組固定 IP 地址卻相對困難，我最近因為想要在家裡架一台 VM 起來，讓我的在同一個區域網路上的筆電也可以順利連上我的 VM，這篇文章我將來說明我的設定方法。

1.  建立一個 Hyper-V 的**外部網路交換器** (External Virtual Switch)
    
    以下命令請**以系統管理員身份**開啟 PowerShell 執行：
    
    ```powershell
    Import-Module Hyper-V
    
    # 取得擁有連線的實體網路介面
    $adapter = Get-NetAdapter -Physical | where { $_.Status -eq 'Up' }
    
    # 如果超過一張連線的實體網路介面就取用第一張網路介面
    if ($adapter.Count -gt 1) {
        $adapter = $adapter[0]
    }
    
    # 取得目前設定 External 的虛擬交換器 (Virtual Switch)
    $externalSwitch = Get-VMSwitch -SwitchType External
    
    # 如果沒有 External 的虛擬交換器就建立一個新的 (LANBridge)
    if ($externalSwitch -eq $null) {
        $externalSwitch = New-VMSwitch -Name 'LANBridge' -NetAdapterName $adapter.Name -AllowManagementOS $true
    }
    
    $networkName = $externalSwitch.Name
    ```
    
2.  檢查 Multipass 可用的網路清單
    
    接著上一個步驟，你應該會看到名為 `LANBridge` 的網路
    
    ```powershell
    multipass networks --format yaml
    ```
    
3.  設定預設的 Bridge 網路名稱 (`LANBridge`)
    
    ```powershell
    multipass set local.bridged-network=$networkName
    ```
    
4.  透過 multipass **建立虛擬機器** (`vm1`) 並**指定網路**與設定一張**手動的網路介面**
    
    ```powershell
    multipass launch --name 'vm1' --bridged --network "name=${networkName},mode=manual"
    ```
    
5.  查詢網路介面資訊 (包含 IP 資訊)
    
    ```powershell
    multipass exec 'vm1' -- ip -br address show scope global
    ```
    
    此時你應該會看到三張網路介面：
    
    ```
    eth0             UP             172.29.217.133/20
    eth1             UP             192.168.1.12/24
    eth2             DOWN
    ```
    
    這裡的 `eth0` 為 [Multipass](https://multipass.run/) 內部使用的網路介面，這個 IP 地址每次 VM 重開機都會變更。
    
    而這個 `eth1` 的 IP 為 Bridge 網路透過**區域網路**的 DHCP Server 自動取得的 IP 地址。
    
    最後的 `eth2` 則是啟動過程透過 `--network` 指定的**手動網路介面**，你必須自行設定網路介面。
    
6.  手動調整 VM 的固定 IP 地址
    
    編輯 `/etc/netplan/50-cloud-init.yaml` 網路設定：
    
    ```powershell
    multipass exec 'vm1' -- sudo vi /etc/netplan/50-cloud-init.yaml
    ```
    
    原本的設定長這樣：
    
    ```yaml
    network:
        ethernets:
            default:
                dhcp4: true
                match:
                    macaddress: 52:54:00:5d:5b:6e
            extra0:
                dhcp4: true
                dhcp4-overrides:
                    route-metric: 200
                match:
                    macaddress: 52:54:00:5d:49:8e
                optional: true
        version: 2
    ```
    
    加入 `eth2` 網路介面設定後的檔案內容長這樣：
    
    ```yaml
    network:
        ethernets:
            default:
                dhcp4: true
                match:
                    macaddress: 52:54:00:5d:5b:6e
            extra0:
                dhcp4: true
                dhcp4-overrides:
                    route-metric: 200
                match:
                    macaddress: 52:54:00:5d:49:8e
                optional: true
            eth2:
                addresses: [192.168.1.101/24]
                gateway4: 192.168.1.1
                nameservers:
                   addresses: [168.95.1.1, 8.8.8.8]
        version: 2
    ```
    
7.  透過「重新開機」套用網路更新
    
    ```powershell
    multipass exec 'vm1' -- sudo reboot
    ```
    
    > 我有試過用 `sudo netplan apply` 套用網路變更，但是每次都會等到 Timeout 才回應，所以才用重開機套用快多了！
    
8.  查詢網路介面資訊 (包含 IP 資訊)
    
    ```powershell
    multipass exec 'vm1' -- ip -br address show scope global
    ```
    
    此時你應該會看到三張網路介面：
    
    ```
    eth0             UP             172.29.217.133/20
    eth1             UP             192.168.1.12/24
    eth2             UP             192.168.1.101/24
    ```
    
    其中 `eth2` 的 `192.168.1.101` 就會是一個固定的 IP 地址！👍
    

### 相關連結

-   [Use PowerShell to Create Virtual Switches](https://devblogs.microsoft.com/scripting/use-powershell-to-create-virtual-switches/?WT.mc_id=DT-MVP-4015686)
-   [Create a virtual switch for Hyper-V virtual machines](https://learn.microsoft.com/en-us/windows-server/virtualization/hyper-v/get-started/create-a-virtual-switch-for-hyper-v-virtual-machines?WT.mc_id=DT-MVP-4015686)
