---
url: /courses/virtualization-tech/02-ubuntu-server-first-vm/index.md
---
# 第 2 课 用 virt-manager 创建第一台 Ubuntu 服务器

::: tip 项目目标
你将以“星舟实训云”初级运维工程师的身份，用 virt-manager 图形界面创建并安装第一台 Ubuntu Server 来宾 `svr01`。第 1 课已经搭好并检查了 KVM、libvirt 和 virt-manager 环境，本课就在这套环境上把第一台服务器开出来。本课交付一台别人能检查、能连接、出了问题能定位的服务器，并且用可复核证据证明配置与结果一致。
:::

![学生在 virt-manager 中创建第一台 Ubuntu Server 虚拟机，并沿网络路径完成验证](./assets/02/ubuntu-server-illustration.png)

先花两分钟确认你的起点。下面的自测结果会帮课程助教判断该从哪里开始讲。

{{assessment:lesson-02-precheck}}

## 2.1 为什么用图形界面创建虚拟机

第 1 课搭好了 KVM、libvirt 和 virt-manager，也理解了虚拟化概念。现在要真正创建一台服务器，最简单的方式就是用 virt-manager 的**图形向导**：每一步都有界面提示，选什么、填什么一目了然；虚拟机启动后的运行状态也能直接在窗口里看见。

virt-manager 是 libvirt 的图形前端。你在界面上的每个操作都会转成对 libvirt 的请求，由 libvirt 保存虚拟机的定义并交给 QEMU/KVM 执行。创建向导其实只做一件事：**把你要的“电脑配置”记录下来**。向导里问你几个问题，恰好对应上一课的概念：

| 向导问题 | 对应概念 | 本课选择 |
| --- | --- | --- |
| 名称和系统类型 | 虚拟机的身份与默认配置 | `svr01`、Ubuntu (64-bit) |
| 内存与 CPU | 从宿主物理内存和 CPU 划资源给虚拟机 | 2048 MiB、2 vCPU |
| 虚拟磁盘 | 给虚拟机一块“硬盘” | 25 GiB，QCOW2 |
| 网络 | 虚拟机怎么上网 | `default`（NAT） |
| 安装介质 | 给虚拟机插入“安装光盘” | Ubuntu Server ISO |

::: tip 为什么要懂每个字段
跟着向导点“下一步”很容易，但你要清楚每一步在配置什么。后面的验收、排错和改配置，都建立在你理解这些字段含义的基础上。
:::

## 2.2 创建前先做资源预算

::: warning 先看资源，再动手
创建虚拟机之前，先确认宿主机还有多少内存和磁盘可用。虚拟机从宿主物理内存和磁盘里“借”资源，宿主自己也要留足余量。
:::

virt-manager 的连接详情页能看到宿主的 CPU 和内存概况。需要精确数字时，在宿主机终端运行：

```bash
free -h
df -h /
```

把结果和本课规格对比：

| 资源 | 宿主可用 | `svr01` 计划 | 说明 |
| --- | ---: | ---: | --- |
| 内存 |  | 2048 MiB | 宿主桌面和系统服务也要内存 |
| 磁盘 |  | 25 GiB（QCOW2） | 实际占用按写入增长 |
| CPU |  | 2 vCPU | 基础服务器足够 |
| 网络 |  | `default`（NAT） | libvirt 默认网络，虚拟机经宿主上网；网卡模型 VirtIO |

::: tip 本课规格
`svr01` 使用 2 vCPU、2048 MiB 内存、25 GiB QCOW2 虚拟磁盘，网卡接在 libvirt 的 `default` 网络上，模型为 VirtIO。这些数值是课堂预算，足够完成基础服务练习，也不会让宿主机太紧张。
:::

## 2.3 认识 NAT 网络模式

::: tip 本节学什么
创建虚拟机时，virt-manager 会给虚拟机接一张网卡，默认连到 `default` NAT 网络。为什么默认选它？它到底是什么？本节把这个问题讲清楚，后面创建 `svr01` 时你就知道自己在配什么了。
:::

### NAT 是什么

NAT 的全称是 **Network Address Translation，网络地址转换**。它的作用是：**让虚拟机藏在宿主机后面上网**。

想象一栋公寓：宿主机是楼，虚拟机是楼里的房间。NAT 相当于楼的门卫——房间里的电脑想上网，先把请求交给门卫，门卫用自己的身份（宿主的网络地址）替它出去，再把外面的回应带回来交给房间。

```mermaid
flowchart LR
  V["svr01（虚拟机）"] -->|"请求上网"| N["NAT（宿主机上的转换）"]
  N -->|"用自己的地址转发"| H["宿主机网卡"]
  H --> W["校园网 / 互联网"]
  W -->|"回应"| H --> N --> V
```

在 libvirt 里，这套“门卫”就是默认的 `default` 虚拟网络。它相当于一个虚拟交换机，通过网络地址转换给来宾分配 `192.168.122.x` 的私有地址，让来宾经宿主机上网。创建虚拟机前，可以在宿主机终端用只读命令看一眼它：

```bash
virsh net-info default
```

输出会显示 `default` 网络的状态、桥接设备和 IP 范围。确认它处于 `active`（活动）状态，再开始创建。

下面的动画把一次 NAT 出站请求拆成五步，观察数据包从虚拟网卡到外部网络再返回的完整路径：

观察要点：

1. 前两步是"出去"：svr01 把数据包交给虚拟网卡，NAT 把私有地址换成宿主地址。
2. 第三步是"出站"：外部服务器只看到宿主机，看不到虚拟机。
3. 后两步是"回来"：NAT 记住每个连接，响应原路返回 svr01。

### 为什么默认用 NAT

| 好处 | 说明 |
| --- | --- |
| 开箱即用 | 虚拟机启动就能上网，不需要额外配置 |
| 不占用网络地址 | 只有宿主机占一个真实 IP，所有虚拟机共用它出去 |
| 相对安全 | 外部网络看不到虚拟机，虚拟机默认不对外暴露服务 |

::: tip 一句话理解
NAT 模式下，**虚拟机通过宿主机上网，外部世界只看到宿主机，看不到虚拟机**。libvirt 的 `default` 网络就是这种模式，通常使用 `192.168.122.0/24` 这样的私有网段。
:::

### 和其他网络模式的对比

libvirt 用虚拟网络连接虚拟机网卡，网卡连到哪种网络由网络类型决定。除了 NAT 网络，还有两种常见类型：

| 模式 | 通俗理解 | 什么时候用 |
| --- | --- | --- |
| NAT 网络 | 虚拟机藏在宿主机后面上网，外部看不到它 | 默认模式，日常学习最常用（`default` 就是它） |
| 桥接网络 | 虚拟机像一台独立电脑，直接连上物理网络 | 需要对外提供服务，让其他机器能访问它 |
| 隔离网络 | 只有同一虚拟网络里的虚拟机之间能通信 | 多台虚拟机互相联调，不接触外网 |

::: tip 本课为什么用 default NAT
`svr01` 是学习用的服务器，需要能上网更新系统、安装软件，但不需要对外提供服务。libvirt 的 `default` NAT 网络完全满足需求，还最省事。桥接和隔离网络会在后续网络课程里逐个用到。
:::

## 2.4 新建虚拟机向导：整体流程

下面用动画演示 virt-manager 从新建虚拟机到安装前复查的完整流程。先观察每一步在做什么，再对照文字操作。

这个动画展示了六步：**新建虚拟机 → 选择安装方式 → 设置内存与 CPU → 创建虚拟磁盘 → 设置名称与网络 → 安装前复查**。观察要点：

1. virt-manager 通过 **QEMU/KVM 系统连接**管理虚拟机，连接 URI 是 `qemu:///system`。整个向导都在这个连接里完成，创建结果由 libvirt 保存。
2. 向导的每一步都在往 `svr01` 的定义里写入一项：内存、CPU、磁盘、网卡、安装介质。
3. 磁盘选择 QCOW2 按需增长，25 GiB 是上限，不是创建时立刻占满。

用一张图串起整个流程：

```mermaid
flowchart LR
  A[打开 virt-manager] --> B[确认 QEMU/KVM 系统连接]
  B --> C[新建虚拟机向导]
  C --> D[本地安装介质，选择 Ubuntu Server ISO]
  D --> E[2 vCPU 与 2048 MiB 内存]
  E --> F[创建 25 GiB QCOW2 虚拟磁盘]
  F --> G[命名 svr01，网络 default]
  G --> H[安装前自定义配置复查]
  H --> I[开始安装 Ubuntu Server]
```

## 2.5 用向导创建 `svr01`

按顺序在 virt-manager 中完成以下操作。

:::: steps

1. **打开 virt-manager 并确认连接**

   启动 virt-manager。在主窗口里确认连接显示为 **QEMU/KVM 系统连接**（URI 是 `qemu:///system`），而不是用户会话。双击连接进入管理界面，点击左上角的\*\*“创建新虚拟机”\*\*。不同版本的按钮文字和位置可能略有不同，以页面含义为准。

2. **选择安装方式**

   在新建虚拟机向导的第一步选择\*\*“本地安装介质（ISO 镜像或光盘）”\*\*，点击“前进”。

3. **选择 Ubuntu Server ISO**

   点击“浏览”，在宿主机上选中教师提供的 Ubuntu Server ISO，并确认系统识别为匹配的 Ubuntu 版本。

   ::: tip 先核验再挂载
   挂载前先确认 ISO 的来源和校验值，不要把“文件能打开”当作镜像完整性的证明。文件路径和校验值记入安装记录。
   :::

4. **设置内存与 CPU**

   内存设为 **2048 MiB**，CPU 设为 **2**。

   ::: warning 内存边界
   内存来自宿主物理内存。设置得过大，宿主自身会变卡；本课 2048 MiB 足够 Ubuntu Server 使用。
   :::

5. **创建虚拟磁盘**

   * 选择\*\*“为此虚拟机创建虚拟磁盘映像”\*\*
   * 容量：**25 GiB**
   * 格式：**QCOW2**
   * 总线：**VirtIO**

   ::: tip QCOW2 的含义
   QCOW2 文件按需增长：虚拟机写入多少数据，文件才占用多少空间。25 GiB 是它的上限，不是立刻占满。
   :::

6. **设置名称与网络**

   * 名称：`svr01`
   * 网络：保持 **default（NAT）**
   * 勾选\*\*“安装前自定义配置”\*\*
   * 点击“完成”

   向导默认给 `svr01` 接一张 VirtIO 网卡，连接到 `default` 网络，这些在下一步的复查里确认。

7. **安装前自定义配置“五看”**

   打开虚拟硬件详情页，逐项确认：

   | 检查项 | 应该看到 |
   | --- | --- |
   | Overview | 名称 `svr01`，机器类型为向导推荐值（如 Q35） |
   | CPU | 2 个 vCPU |
   | 内存 | 2048 MiB |
   | 磁盘 | 25 GiB，格式 QCOW2，总线 VirtIO |
   | 网络 | 虚拟网络 `default`，模型 VirtIO |

   另外确认虚拟光驱指向刚选中的 Ubuntu Server ISO。复查无误后，点击\*\*“开始安装”\*\*，virt-manager 会打开控制台窗口，虚拟机从 ISO 启动。

::::

## 2.6 启动并安装 Ubuntu Server

:::: steps

1. **启动安装**

   在“安装前自定义配置”复查完成后点击\*\*“开始安装”\*\*。virt-manager 打开一个新的控制台窗口，虚拟机从 ISO 启动并进入 Ubuntu 安装程序。

2. **选择安装语言和键盘**

   选择你熟悉的语言和键盘布局。键盘布局会影响命令输入，选错可能导致密码或命令字符错误。

3. **配置网络**

   安装程序会自动检测网卡。本课使用 `default` NAT 网络，保持 DHCP 自动获取地址即可，看到网卡获得地址就继续。

4. **配置存储**

   在“磁盘设置”页面，选择\*\*“使用整个磁盘”\*\*。确认目标是约 25 GiB 的虚拟磁盘（页面会显示磁盘容量）。

   ::: danger 安装目标确认
   安装时选择的磁盘是 `svr01` 的虚拟磁盘。页面显示的容量约 25 GiB，如果出现宿主机真实磁盘或其他设备，立即停止并请教师确认。
   :::

5. **设置主机名和用户**

   * 主机名：`svr01`
   * 管理用户：课堂统一虚构用户名 `cloudstudent`
   * 密码：现场自设，不写入任何文档

   ::: tip 为什么用虚构用户名
   统一用 `cloudstudent` 便于后续课程和排错时引用同一套身份。
   :::

6. **安装 OpenSSH Server**

   在安装选项里勾选\*\*“Install OpenSSH Server”\*\*。本课需要从宿主机通过 SSH 完成远程验收。

   ::: tip 为什么要装 OpenSSH
   SSH 是登录 Linux 服务器的标准方式。装上 OpenSSH Server，后续才能从宿主机安全地连接和管理 `svr01`。
   :::

7. **完成安装并重启**

   安装完成后点击“重启”。如果提示移除安装介质，回到 virt-manager 的虚拟硬件详情页，把虚拟光驱设为\*\*“不使用”\*\*（或断开安装介质），再继续启动。ISO 文件本身不要删除。

::::

## 2.7 在窗口内验收 `svr01`

::: tip 验收思路
安装完成只是第一步。要确认 `svr01` 真的可用，需要验证：它是什么系统、有多少资源、网络是否正常、SSH 服务是否在听。
:::

### 在 svr01 控制台里查看

启动并登录 `svr01` 后，在 virt-manager 的控制台窗口内运行少量命令确认基本状态：

```bash
hostnamectl --static
```

```bash
free -h
```

```bash
ip -br addr
```

```bash
ip route
```

```bash
systemctl is-active ssh
```

::: tip 输出含义

* `hostnamectl --static` 显示主机名，应为 `svr01`。
* `free -h` 显示内存总量接近 2GiB。
* `ip -br addr` 显示网卡获得了地址（`default` 网络，通常是 192.168.122.x）。
* `ip route` 应有一条 `default via ...`，说明默认路由正常。
* `systemctl is-active ssh` 输出 `active`，表示 SSH 服务在运行。
  :::

### 用 virsh 核对虚拟机的定义

回到宿主机，用 libvirt 的命令行工具 `virsh` 做只读核对。`dominfo` 显示 libvirt 保存的虚拟机状态和资源定义：

```bash
virsh dominfo svr01
```

`domifaddr` 显示 libvirt 从 DHCP 租约里知道的来宾地址：

```bash
virsh domifaddr svr01 --source lease
```

把这里的地址和来宾里 `ip -br addr` 的输出对照，两边的 MAC 和 IP 应能对应。如果 `domifaddr` 没有输出，也可以查默认网络的 DHCP 租约：

```bash
virsh net-dhcp-leases default
```

### 确认 SSH 服务在监听

```bash
ss -lnt | grep ':22'
```

有输出表示 22 端口在监听，SSH 服务已就绪。

### 首次 SSH 连接前核对主机指纹

首次连接要确认远端身份。先在 `svr01` 控制台查看它的公钥指纹：

```bash
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
```

回到宿主机，扫描同一地址的公开主机键并计算指纹：

```bash
ssh-keyscan -t ed25519 192.168.122.x 2>/dev/null | ssh-keygen -lf -
```

把 192.168.122.x 换成你刚核对的 `svr01` 地址。两边指纹一致后，再连接：

```bash
ssh cloudstudent@192.168.122.x
```

首次提示中的指纹必须与控制台记录一致，再输入现场设置的密码。密码不会显示，这是正常现象。

::: tip 为什么用命令确认
virt-manager 图形界面能看到虚拟机窗口和运行状态，但看不到服务监听、DHCP 租约和 libvirt 保存的定义，所以这些需要用少量命令确认。创建、配置和安装本身都使用图形界面。
:::

## 2.8 故障演练：网络通，但 SSH 拒绝连接

::: warning 故障卡 V2-F1
教师在不通知你的情况下，通过 `svr01` 控制台停止 SSH 服务。`svr01` 仍在运行，也仍有 IP。你需要根据现象逐层定位，不能重装虚拟机、重建默认网络或关闭防火墙碰运气。
:::

### 排错步骤

1. **宿主查虚拟机状态**

   ```bash
   virsh dominfo svr01
   ```

   确认虚拟机仍在运行。

2. **宿主查网络可达性**

   ```bash
   ping -c 2 192.168.122.x
   ```

   网络是通的。

3. **宿主复现 SSH 现象**

   ```bash
   ssh -o ConnectTimeout=5 cloudstudent@192.168.122.x
   ```

   得到连接被拒绝的错误。

4. **来宾控制台查服务和端口**

   ```bash
   systemctl is-active ssh
   ss -lnt | grep ':22'
   sudo journalctl -u ssh --since '-10 minutes' --no-pager
   ```

   `is-active` 不是 active、22 端口没有监听，日志能定位服务为什么停。

5. **最小修复并复验**

   ```bash
   sudo systemctl start ssh
   systemctl is-active ssh
   ss -lnt | grep ':22'
   ```

   回到宿主再次执行 SSH 连接，登录后运行 `hostnamectl --static`，确认连到的是 `svr01`。

::: tip 先写现象，再写原因
`Connection refused`、`No route to host`、`Permission denied` 是三类不同线索，不能都翻译成“网络坏了”。本课的场景是网络通、服务停，所以先查服务状态和端口，再查日志。
:::

### 排错矩阵

| 现象 | 先查 | 常见原因 | 处理 |
| --- | --- | --- | --- |
| virt-manager 里没有本地 QEMU/KVM 连接 | 连接 URI、libvirt 服务 | 打开了用户会话 | 回到第 1 课核对 `qemu:///system` 连接 |
| ISO 不可选或不可读 | 文件路径、权限 | 路径错误或 libvirt 无权读取 | 使用教师提供的可读路径 |
| 安装器找不到磁盘 | 虚拟磁盘设备 | 磁盘未添加或设备配置异常 | 关机后复核虚拟磁盘定义 |
| 安装后又回到安装界面 | 虚拟光驱 | ISO 仍作为第一启动介质 | 断开虚拟光驱介质，不删除 ISO |
| 来宾没有 IP | `domiflist`、`ip -br addr` | 网卡断开；`default` 网络未活动 | 确认网卡连接 `default`，网络处于 active |
| 能 ping 通但 SSH 拒绝连接 | `systemctl is-active ssh`、22 端口 | SSH 服务停止或未安装 | 启动或补装 OpenSSH Server |
| SSH 提示 Permission denied | 用户名、控制台登录 | 用户名或凭据错误 | 核对 `cloudstudent` 用户名，密码现场设置 |
| 宿主变卡 | `free -h` | 内存分配过大或多个来宾同开 | 调低内存，只保留本课 `svr01` |

## 2.9 本章小测

先独立作答，再核对解析。下面的问题组会直接给出反馈。

{{assessment:lesson-02-check}}

## 本章小结

* 用 virt-manager 图形向导创建虚拟机，向导的每一步都在配置“这台电脑要什么”：名称、内存、CPU、磁盘、网络、ISO。
* 真正保存 `svr01` 配置的是 libvirt，virt-manager 只是图形前端；向导结果最终写进虚拟机定义。
* 创建前先看宿主剩余资源，内存和磁盘都从宿主划出，要给宿主留余量。
* QCOW2 虚拟磁盘按需增长，25 GiB 是上限不是立刻占满。
* 网卡接在 libvirt 的 `default` NAT 网络上，来宾获得 `192.168.122.x` 地址并经宿主机上网。
* 安装 Ubuntu Server 时，勾选 OpenSSH Server 才能在后续通过 SSH 远程登录。
* 图形界面能完成创建和安装，但服务监听、DHCP 租约和虚拟机定义需要用少量命令确认。

下一课将用 virt-manager 创建 Ubuntu Desktop 来宾 `desk01`，比较“服务器控制台”和“桌面远程显示”的差异。`svr01` 会继续作为后续网络、存储和迁移课程的基础对象。
