KVM部署复盘

一、环境

操作系统:Ubuntu
CPU:支持硬件虚拟化;验证:egrep -c '(vmx|svm)' /proc/cpuinfo至少返回一行vmx或svm,没有就BIOS开启VT-x/AMD-V
内存:8GB
存储:256GB
网络:支持桥接或NAT的网卡

*碰到的问题:虚拟机启动失败,报错“错误:无法启动域:internal error: ……”之类的。是冲突服务问题,网上找了下,最好关闭冲突服务。
sudo setenforce 0 # 临时关闭 SELinux
sudo sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config # 永久关闭
sudo systemctl disable --now firewalld # 关闭防火墙
swapoff -a && sysctl -w vm.swappiness=0 # 禁用 swap 分区

二、安装

1.核心组件安装

更新软件包列表
sudo apt update
安装KVM libvirt qemu
sudo apt -y install qemu-kvm libvirt-daemon-system virtinst virt-manager bridge-utils

  • qemu-kvm CPU虚拟化核心引擎
  • libvirt 管理API守护进程
  • virt-install 命令行创建虚拟机工具
  • virt-manager 图形化管理
  • bridge-utils 配置桥接

验证
sudo systemctl status libvirtd
显示active (running)就行
需要开机自启可以设置sudo systemctl enable --now libvirtd

2.配置权限

虚拟化相关默认root用户操作,不配置可能直接virt-manager或virsh的时候出现拒绝访问之类的。
sudo usermod -aG libvirt $(whoami)

  • usermode 修改账户信息
  • aG 追加(a)指定附加组(G)
  • libvirt 目标用户组名
  • $(whoami) 自动获取当前登录的用户名。你也可以直接替换成用户名

newgrp libvirt 创建一个新的登录Shell,并切换到指定的用户组

3.验证KVM

lsmod | grep kvm试下KVM有没有加载,输出kvm_intel或kvm_amd就行

三、创建管理虚拟机

1.两种创建方法

(1)命令行

virt-install 命令行快速创建虚拟机

  • Ⅰ:纯文本界面,在当前终端里操作
点击查看代码
sudo virt-install \
 --name=ubuntu-vm \ # 虚拟机名称
 --memory=4096 \ # 分配内存(MB)
 --vcpus=2 \ # 虚拟CPU核心数
 --disk path=/var/lib/libvirt/images/ubuntu-vm.qcow2,size=20 \ # 磁盘路径与大小(GB)
 --os-type=linux \ # 操作系统类型
 --os-variant=ubuntu22.04 \ # 系统发行版版本
 --location=/iso/镜像 \ # ISO 镜像路径
 --network bridge=br0 \ # 桥接到主机网卡
 --graphics none \ # 禁用图形控制台
 --console pty,target_type=serial \ # 启用串行控制台
 --extra-args="console=ttyS0" # 内核参数(文本安装)
  • Ⅱ:安装时会开启VNC服务,需要用VNC客户端连过去看图形安装界面
点击查看代码
virt-install \
  --name=ubuntu-vm \
  --ram=4096 \
  --vcpus=2 \
  --disk path=/var/lib/libvirt/images/ubuntu-vm.qcow2,size=20 \
  --os-type=linux \
  --os-variant=ubuntu22.04 \
  --network bridge=virbr0 \
  --graphics vnc,listen=0.0.0.0 \ #用于开启VNC并允许远程连接
  --cdrom /path/to/ubuntu-22.04-live-server-amd64.iso

(2)图形化

virt-manager
然后就是创建新虚拟机,选择本地iso镜像,分配CPU/内存资源(内存≥2GB,CPU≥1核心),设置虚拟磁盘(默认路径:/var/lib/libvirt/images/),配置网络为 ‌Bridge模式‌(据说性能最优)或 NAT

2.虚拟机管理

启动:virsh start ubuntu-vm
关闭:virsh shutdown ubuntu-vm
查看虚拟机列表:virsh list --all
删除:
强制关闭virsh destroy ubuntu-vm
删除定义virsh undefine ubuntu-vm
删除磁盘文件rm /var/lib/libvirt/images/ubuntu-vm.qcow2

其他:

网络配置、优化及排障参考这两个
从零搭建KVM虚拟服务器:完整指南与实战技巧
KVM虚拟化

四、KVM存储

存储池默认位置:/var/lib/libvirt/images/

1.自定义存储池

可以自定义一个基于目录的存储池
创建个目录 mkdir -p /data/vmfs
定义个存储池名字为vmdisk,目录类型 virsh pool-define-as vmdisk --type dir --target /data/vmfs
创建已定义的存储池 virsh pool-build vmdisk
查看下 virsh pool-list --all
刚创建的可能是未启动,需要开一下
virsh pool-start vmdisk
virsh pool-autostart vmdisk
创建虚拟机存储卷
virsh vol-create-as vmdisk(指定池) test(自定义名字).qcow2 20G(指定空间) --format qcow2

2.存储池相关管理命令

(1)在存储池中删除虚拟机存储卷

virsh vol-delete --pool vmdisk test(之前定义的名字).qcow2

(2)取消激活存储池

virsh pool-destroy vmdisk

(3)删除存储池定义的目录/data/vmfs

virsh pool-delete vmdisk

(4)取消定义存储池

virsh pool-undefined vmdisk

3.磁盘格式

raw 原始格式,性能最好
qcow2 性能不如raw,但raw不支持快照,qcow2支持
现在默认安装好用的raw,做快照要改成qcow2
写时拷贝:raw立刻分配空间,不管是否有用到这么多。qcow2是承诺分配空间,需要用的时候再分配

4.创建磁盘文件

建立qcow2格式磁盘文件
qemu-img create -f qcow2 test.qcow2 20G
建立raw格式磁盘文件:
qemu-img create -f raw test.raw 20G
查看已经创建的虚拟磁盘文件
qemu-img info test.qcow2

5.挂载

碰到过虚拟机无法启动的情况,要对内部排查,网上搜了下一般是用Libguestfs Linux工具集
Libguestfs允许在虚拟机上挂载任何类型的文件系统,以便修复启动故障
使用Libguestfs,首先要用Libvirt(管理接口)
*如果是vmware的ESXI虚拟机,为将虚拟机迁移到Linux中,可以使用SSH连接到ESXI主机。这样首先要启用ESXI主机的ssh访问方式,完成后在Linux平台上scp一下

查看磁盘镜像分区
virt-df -h -d vm1(虚拟机名字)
vir-filesystems -d vm1
挂载磁盘镜像分区
gustmount -d vm1 -m /dev/ubuntu/root --rw /mnt
df -Th查看
查看挂出来的passwd文件cat /mnt/etc/passwd
拷贝到宿主机opt cp passwd /opt
取消挂载 guestunmount /mnt
这时候进mnt就是空目录了

六、KVM管理

1.基本管理

查看虚拟机 virsh list仅列出运行ing的,加--all看所有的
查看虚拟机配置文件 virsh dumpxml name
将node4虚拟机的配置文件保存至node6.xml(x) virsh dumpxml node4 > /etc/libvirt/qemu/node6.xml
修改node6配置文件(x) virsh edit node6
edit是直接修改,不用重启。如果用vim修改,要virsh start node6
暂停虚拟机 virsh suspend vm_name
恢复虚拟机 virsh resume vm_name
关闭 第一种 virsh shutdown vm1一般用这种
第二种 virsh destroy vm1
重启 virsh reboot vm1
重置 virsh reset vm1
删除虚拟机 virsh undefine vm1
虚拟机开机自启动 virsh autostart
域vm1标记为自动开始 ls /etc/libvirt/qemu/autostart目录默认不存在,有开机启动的虚拟机时自动创建
域取消vm1标记为自动开始 virsh autostart --sidable vm1
查看所有开机自启动的guest os ls /etc/libvirt/qemu/autostart/
virsh list --all --autostart

2.虚拟机克隆

(1)图形界面

Application-System Tools-Virtual Machine Manager
或者输入命令virtual-manager
确保机器关机状态,右键克隆

(2)终端命令克隆

virt-clone -o vm1(机器名) --auto-clone这样克隆出来名字是vm1-clone
加-n会指定名字,-f为新客户机使用新的磁盘镜像文件,如下
virt-clone -o vm1(机器名) -n vm2(自定义机器名) -f /var/lib/libvirt/images/vm2.img

3.增量镜像

……这个就不写了,没搞过

4.快照

创建快照

(1)图形界面方式

(2)命令行方式

创建 virsh snapshot-create-as vm2 vm2.snap
恢复 比如恢复到第四个快照,先关闭再操作这条 virsh snapshot-revert vm2(虚拟机名字) vm2.snap4(快照名)
这个快照得是qcow2,raw不行
qcow2可以写时复制,还支持zlib磁盘压缩、支持AES加密
raw格式转qcow2qemu-img convert -O qcow2 /var/lib/libvirt/images/vm2-1.raw /var/lib/libvirt/images/vm2-1.qcow2
可以看下格式
ll -h找到vm2-1.qcow2
查看qemu-img info vm2-1.qcow2看到file fomat是qcow2就行
虚拟机硬盘也要指向转换后的,这里要关掉机器,再配置
vim /etc/libvirt/qemu/vm2.xml
以下框住和划横线的地方改成qcow2
image
可以进入图形化查看信息,可以找到快照

七、网络管理

网络:nat、isolated
接口:bridge
虚拟交换机:linux-bridge(Linux自带)、ovs(open-Vswitch)

ip a命令查看虚拟接口之类的
brctl show查看有多少虚拟机

1.配置文件方式配置桥接

点击查看代码
在宿主机上
1.修改配置文件
cat ifcfg-bro
TYPE=BridgeNAME=br0
DEVICE=br0
ONBOOT="yes"
BOOTPROTO=static
IPADDR=宿主机IP地址
GATEWAY=宿主机网关(route查网关)
NETMASK=255.255.255.0
DNS1=114.114.114.114
DNS2=8.8.8.8

备份
cp ifcfg-enp3s0 ifcfg-enp3s0.bak
打开文件
vim ifcfg-enp3s0
编辑以下内容
DEVICE="enp3s0"
ONBOOT="yes"
BRIDGE=br0

重启libvirtd服务
重启network服务

2.配置文件方式创建nat网络

点击查看代码
cp /etc/libvirt/qemu/networks/default.xml
/etc/libvirt/qemu/networks/nat1.xml


vim /etc/libvirt/qemu/networks/nat1.xml
<network>
<name>nat1(不能有冲突,随便改一个)</name>
<uuid>4d8b9b5c-748f-4e16-a509-848202b9c83b(不能有冲突,随便改一个)</uuid>
<forward mode='nat'/>
#和隔离模式的区别
<bridge name='virbr4(不能有冲突,随便改一个)' stp='on' delay='0'/>
<mac address='52:57:00:62:0c:d4'(不能有冲突,修改后三段)/>
<domain name='natl'/>
<dhcp></dhcp></ip></network>
<ip address='192.168.104.1(可以自定义)' netmask='255.255.255.0'>
<range start='192.168.104.128' end='192.168.104.254'/>
重启服务:
systemctl
restart libvirtd

3、配置isolated隔离网络模式

点击查看代码
cp default.xml isolated200.xml

vim isolated200.xml
<network>
<name>isolated200(要修改)</name>
<uuid>6341d3a6-7330-4e45-a8fe-164a6a68929a(要修改)</uuid>
<bridge name='virbr2'(要修改) stp='on' delay='0'/>
<mac address='52:54:00:6b:39:0c'(要修改)/>
<domain name='isolatel'/>
<ip address='192.168.101.1'(自定义) netmask='255.255.255.0'>
<dhcp>
<range start='192.168.101.128' end='192.168.101.254'/>
</dhcp>
</ip>
</network>

systemctl restart libvirtd
查看所有的网络:
virsh net-list
启动网络:
virsh net-start isolated200
开机自启动:
virsh net-autostart
isolated200
网络相关基本命令
查看一个guest主机的网络接口信息:
virsh domiflist vm2

4.Virbro的DHCP

Virbr0是KVM默认创建的一个Bridge,其作用是为连接其上的虚机网卡提供NAT访问外网的功能。
Virbr0默认分配了一个P192.168.122.1,并为连接其上的其他虚拟网卡提供DHCP服务。

点击查看代码
Virbr0使用 dnsmasq提供 DHCP服务,可以在宿主机中查看该进程信息
ps -elf | grep dnsmasq
会显示/usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf

在/var/lib/libvirt/dnsmasq/目录下有一个virbr0.status 文件,当 VM1 成功获得
DHCP的IP后,可以在该文件中查看到相应的信息
cat virbr0.status
[
 {
  "ip-address":"192.168.122.28",
  "mac-address": "52:54:00:94:a7:a1",
  "hostname":"vm1",
  "expiry-time": 1511626337
  }
 ]

八、脚本管理

批量创建虚拟机

1.准备:模板镜像和配置文件模板

# 下载官方云镜像(以 Rocky Linux 9 为例) wget https://download.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-GenericCloud.latest.x86_64.qcow2 -O /var/lib/libvirt/images/rocky9-template.qcow2
给模板做一个快照(后续基于此快照创建,不破坏原文件) qemu-img create -f qcow2 -b /var/lib/libvirt/images/rocky9-template.qcow2 /var/lib/libvirt/images/rocky9-base.qcow2

自己创建下目录
~/kvm-ansible/
├── ansible.cfg # Ansible 配置文件
├── inventory.ini # 主机清单
├── create-vms.yml # 主 Playbook
├── files/
│ └── cloud-init/
│ ├── user-data.template # cloud-init 模板(配置用户和密码)
│ └── network-config # 网络配置模板
└── vars/
└── main.yml # 变量定义(虚拟机参数)

2.ansible配置文件

ansible.cfg

点击查看代码
[defaults]
host_key_checking = False
inventory = inventory.ini
remote_user = root
timeout = 30
log_path = /var/log/ansible-kvm.log

inventory.ini

点击查看代码
[kvm_hosts]
kvm-host-1 ansible_host=192.168.1.10
kvm-host-2 ansible_host=192.168.1.11

vars/main.yml

点击查看代码
# 虚拟机通用配置
vm_defaults:
  memory: 4096          # 内存 MB
  vcpus: 2              # vCPU 核心数
  disk_size: 40G        # 磁盘大小
  network: default      # libvirt 网络名称
  os_variant: rocky9    # 系统类型 (用 osinfo-query os 查看)

# 要创建的虚拟机列表
vms:
  - name: web-01
    memory: 4096
    vcpus: 2
    disk_size: 50G
    ip: 192.168.122.101
    hostname: web-01.example.com

  - name: web-02
    memory: 4096
    vcpus: 2
    disk_size: 50G
    ip: 192.168.122.102
    hostname: web-02.example.com

  - name: db-01
    memory: 8192
    vcpus: 4
    disk_size: 100G
    ip: 192.168.122.201
    hostname: db-01.example.com

  - name: cache-01
    memory: 2048
    vcpus: 1
    disk_size: 20G
    ip: 192.168.122.251
    hostname: cache-01.example.com

files/cloud-init/user-data.template

点击查看代码
#cloud-config
hostname: {{ hostname }}
manage_etc_hosts: true

users:
  - name: admin
    sudo: ALL=(ALL) NOPASSWD:ALL
    ssh_authorized_keys:
      - {{ ssh_pub_key | default('') }}
    shell: /bin/bash

password: {{ password | default('Welcome123!') }}
chpasswd:
  expire: false

package_update: true
package_upgrade: false

runcmd:
  - systemctl enable --now sshd

files/cloud-init/network-config

点击查看代码
version: 2
ethernets:
  eth0:
    dhcp4: false
    addresses:
      - {{ ip }}/24
    gateway4: {{ gateway | default('192.168.122.1') }}
    nameservers:
      addresses:
        - {{ dns | default('223.5.5.5') }}
        - {{ dns2 | default('223.6.6.6') }}

3.编写主 Playbook

create-vms.yml

点击查看代码
- name: 批量创建 KVM 虚拟机
  hosts: kvm_hosts
  gather_facts: yes
  vars_files:
    - vars/main.yml

  tasks:
    - name: 1. 确保基础镜像存在
      stat:
        path: /var/lib/libvirt/images/rocky9-base.qcow2
      register: base_image

    - name: 1.1 如果基础镜像不存在则报错
      fail:
        msg: "基础镜像 /var/lib/libvirt/images/rocky9-base.qcow2 不存在,请先准备"
      when: not base_image.stat.exists

    - name: 2. 确保 cloud-init 目录存在
      file:
        path: /var/lib/libvirt/cloud-init/{{ item.name }}
        state: directory
        recurse: yes
      loop: "{{ vms }}"

    - name: 3. 生成 cloud-init 配置文件(user-data)
      template:
        src: files/cloud-init/user-data.template
        dest: /var/lib/libvirt/cloud-init/{{ item.name }}/user-data
      loop: "{{ vms }}"

    - name: 4. 生成 cloud-init 配置文件(network-config)
      template:
        src: files/cloud-init/network-config
        dest: /var/lib/libvirt/cloud-init/{{ item.name }}/network-config
      loop: "{{ vms }}"

    - name: 5. 创建虚拟机磁盘(基于基础镜像)
      command:
        cmd: qemu-img create -f qcow2 -b /var/lib/libvirt/images/rocky9-base.qcow2 /var/lib/libvirt/images/{{ item.name }}.qcow2 {{ item.disk_size | default(vm_defaults.disk_size) }}
        creates: /var/lib/libvirt/images/{{ item.name }}.qcow2
      loop: "{{ vms }}"

    - name: 6. 创建虚拟机(使用 virt-install)
      command:
        cmd: >
          virt-install
          --name {{ item.name }}
          --memory {{ item.memory | default(vm_defaults.memory) }}
          --vcpus {{ item.vcpus | default(vm_defaults.vcpus) }}
          --disk path=/var/lib/libvirt/images/{{ item.name }}.qcow2,format=qcow2
          --disk path=/var/lib/libvirt/cloud-init/{{ item.name }}/user-data,device=cdrom,format=raw
          --disk path=/var/lib/libvirt/cloud-init/{{ item.name }}/network-config,device=cdrom,format=raw
          --network network={{ item.network | default(vm_defaults.network) }}
          --os-variant {{ item.os_variant | default(vm_defaults.os_variant) }}
          --import
          --noautoconsole
          --wait=-1
      args:
        creates: /etc/libvirt/qemu/{{ item.name }}.xml
      loop: "{{ vms }}"
      register: vm_create

    - name: 7. 等待虚拟机获得 IP 地址
      shell: |
        virsh domifaddr {{ item.name }} --source lease | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' | head -1
      register: vm_ip
      until: vm_ip.stdout != ""
      retries: 30
      delay: 10
      loop: "{{ vms }}"

    - name: 8. 输出创建结果
      debug:
        msg: |
          虚拟机: {{ item.item.name }}
          IP地址: {{ item.stdout }}
          SSH登录: ssh admin@{{ item.stdout }}
      loop: "{{ vm_ip.results }}"

4.执行部署

点击查看代码
cd ~/kvm-ansible

# 1. 先测试 SSH 连通性
ansible kvm_hosts -i inventory.ini -m ping

# 2. 执行 Playbook(创建虚拟机)
ansible-playbook create-vms.yml

容易碰到的问题
virt-install 命令不存在:yum install -y virt-install
基础镜像不存在:提前下载并放置到 /var/lib/libvirt/images/
cloud-init 未生效:确保 user-data 和 network-config 正确挂载为 cdrom
虚拟机无法联网:检查 libvirt 默认网络:virsh net-start default
SSH 无法登录:检查 cloud-init 是否成功设置密码/密钥
虚拟机名字已存在:先 virsh undefine 删除旧虚拟机
磁盘空间不足检查 /var/lib/libvirt/images 可用空间

posted @ 2026-07-02 16:18  CCLluvia  阅读(12)  评论(0)    收藏  举报