前言

虚拟化基础篇讲了 KVM 原理,这篇进入实战进阶:用 cloud-init 云镜像几分钟拉起一台可 SSH 的虚拟机,玩转快照、克隆、桥接——自建小私有云/Malloc 一套测试环境的完整技能。

一、环境准备(宿主机)

dnf install -y qemu-kvm libvirt virt-install virt-top libguestfs-tools
systemctl enable --now libvirtd
lsmod | grep kvm                          # kvm_intel / kvm_amd 已加载

# 默认 NAT 网络(192.168.122.0/24, 自带 DHCP)
virsh net-start default
virsh net-autostart default

二、cloud-init:告别装系统

传统 virt-install 挂 ISO 装系统要 20 分钟;云镜像(Cloud Image)自带 cloud-init,首次开机自动完成:扩盘、设密码、注入密钥、改主机名——1 分钟出机。

# 1. 下载云镜像(以 Rocky 9 为例)
cd /var/lib/libvirt/images
wget https://mirrors.nju.edu.cn/rocky/9/images/x86_64/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2

# 2. 准备"启动配置"
cat > /root/seed.iso.cmd <<'EOF'
cloud-localds /var/lib/libvirt/images/seed.img /root/user-data
EOF

/root/user-data(cloud-init 配置):

#cloud-config
hostname: vm-lab01
users:
  - name: zy
    sudo: ALL=(ALL) NOPASSWD:ALL
    shell: /bin/bash
    ssh_authorized_keys:
      - ssh-ed25519 AAAAC3... your@laptop
ssh_pwauth: true
chpasswd:
  expire: false
  users:
    - name: zy
      password: Passw0rd!
      type: text
runcmd:
  - dnf install -y nginx
  - systemctl enable --now nginx
growpart:
  mode: auto
  devices: ['/']
# 3. 生成 seed 盘(需要 cloud-utils 软件包)
dnf install -y cloud-utils
cloud-localds /var/lib/libvirt/images/seed.img /root/user-data

# 4. 从云镜像启动虚拟机(注意: 用副本, 别直接用原镜像)
cp Rocky-9-GenericCloud-Base.latest.x86_64.qcow2 vm-lab01.qcow2

virt-install \
  --name vm-lab01 \
  --vcpus 2 --memory 2048 \
  --disk vm-lab01.qcow2,bus=virtio,format=qcow2 \
  --disk seed.img,device=cdrom \
  --network network=default,model=virtio \
  --os-variant rocky9 \
  --import --noautoconsole          # --import: 不装系统直接启动

# 5. 一分钟后拿到 IP 并登录
virsh domifaddr vm-lab01
ssh zy@192.168.122.xxx
# nginx 都已经装好了 —— runcmd 的功劳

三、日常生命周期管理

virsh start vm-lab01 / shutdown / destroy     # 优雅关 / 拔电源
virsh reboot vm-lab01
virsh list --all
virsh autostart vm-lab01                      # 宿主机开机自启

# 进控制台(没网络时的救命稻草, 退出 Ctrl+])
virsh console vm-lab01

# 删除虚拟机(先 undefine 再删盘)
virsh undefine vm-lab01 --nvram
rm /var/lib/libvirt/images/vm-lab01.qcow2

四、资源调整

# ---- 内存 ----
virsh setmem vm-lab01 4G --config        # 下次启动生效
virsh setmem vm-lab01 2G --live          # 立即生效(在线! 只能调小于分配值)

# ---- CPU ----
virsh setvcpus vm-lab01 4 --maximum --config   # 上限
virsh setvcpus vm-lab01 2 --live                # 在线减少

# ---- 磁盘扩容三步走 ----
# 1. 扩 qcow2 文件
qemu-img resize vm-lab01.qcow2 +20G
# 2. 通知虚拟机重读磁盘(或重启)
virsh blockresize vm-lab01 /path/vm-lab01.qcow2 40G
# 3. 进虚拟机扩分区和文件系统
growpart /dev/vda 1 && xfs_growfs /      # cloud 镜像自带 growpart

五、快照:虚拟机的"存档点"

# 创建(拍快照前磁盘会自动暂停一下, 建议关机时拍更稳)
virsh snapshot-create-as vm-lab01 before-upgrade "升级前存档"

# 查看 / 恢复 / 删除
virsh snapshot-list vm-lab01
virsh snapshot-revert vm-lab01 before-upgrade     # 时光倒流
virsh snapshot-delete vm-lab01 before-upgrade

# qcow2 快照链原理
qemu-img info vm-lab01.qcow2
# backing file: Rocky-9-GenericCloud...qcow2   ← 我们 cp 出来的其实是"基于模板的差分盘"

注意快照链会让性能下降,重要数据别依赖快照当天备份,还是要走外部备份(qemu-img convert 导出)。

六、模板与克隆:批量开机房

# 1. 把一台调好的机器做成模板(先关机)
virsh shutdown vm-template
virt-sysprep -d vm-template          # 清洗机器指纹(ssh host key、machine-id、日志)

# 2. 基于模板克隆(差分盘, 秒级, 几乎不占空间)
virt-clone \
  --original vm-template \
  --name vm-web01 \
  --file /var/lib/libvirt/images/vm-web01.qcow2

# 3. 改主机名/IP(避免克隆冲突)
virt-customize -a /var/lib/libvirt/images/vm-web01.qcow2 \
  --hostname vm-web01 \
  --run-command 'nmcli con mod eth0 ipv4.addresses 192.168.122.101/24'

virsh start vm-web01
# 重复 2-3 步, 5 分钟拉起一个 10 台机器的实验集群

七、桥接网络:让虚拟机进物理网络

默认 NAT 网络下虚拟机只能"单向出";桥接后虚拟机与宿主机同网段平级,外部可直接访问:

# 宿主机建网桥 br0(把物理网卡 eth0 挂上去)
nmcli con add type bridge ifname br0 ipv4.method auto
nmcli con add type bridge-slave ifname eth0 master br0
nmcli con up br0

# 虚拟机用桥接
virt-install ... --network bridge=br0,model=virtio
# 或修改现有机器: virsh edit vm-lab01 把 interface source 改为 bridge

八、性能观测与常见坑

virt-top                       # 虚拟机版 top(CPU/内存实时)
virsh dominfo vm-lab01         # 配置详情
virsh domstats vm-lab01 --cpu-total

virsh cpu-stats vm-lab01 | head
qemu-img check vm-lab01.qcow2  # 磁盘一致性检查
坑 解
domain is already running virsh destroy 后再 start
cloud-init 没生效 看 /var/log/cloud-init.log;seed 盘必须是 device=cdrom
虚拟机时间漂移 装 chrony;virsh edit 确认 <clock offset='utc'/>
克隆机网络起不来 machine-id 重复,virt-sysprep 或手动 truncate
性能差 确认 virtio 磁盘/网卡、KVM 嵌套没开虚拟化

小结

任务 命令
快速建机 云镜像 + cloud-localds + --import
快照 snapshot-create-as / revert
批量 virt-sysprep 模板 + virt-clone
桥接 nmcli bridge + --network bridge=br0
观测 virt-top / domstats

本文是「云计算」系列第 4 篇。