工作过程中需要使用kvm来进行测试环境搭建。因为需要用到多台kvm虚机,所以写了个快速创建的脚本。
KVM 基本命令
KVM的命令非常繁杂,但是一般工作过程中只需要用到几个基本的命令即可。可以根据需要选择交互式命令运行或者非交互式。
-
查看当前有哪些虚机在运行
virsh list
-
查看当前有哪些虚机(包括没有运行的)
virsh list --all
-
查看虚机的title
virsh list --title
-
启动虚机,假设虚机名称是
vm-name
virsh start vm-name
-
停止虚机,假设虚机名称是
vm-name
virsh destroy vm-name
-
清除虚机(从管理列表中删除,不删除时间虚机数据),假设虚机名称是
vm-name
virsh undefine vm-name
-
查看虚机配置信息,假设虚机名称是
vm-name
virsh dumpxml --domain vm-name
-
编辑虚机配置信息,假设虚机名称是
vm-name
virsh edit --domain vm-ming
-
创建一个虚机,假设虚机配置文件名称是
vm-name.xml
virsh define vm-name.xml
-
查看虚机网络
virsh net-list
-
查看特定网络配置,假设网络名称为
manage
virsh net-dumpxml --network manage
-
停止网络,假设网络名称为
manage
virsh net-destroy --network manage
-
启动网络,假设网络名称为
manage
virsh net-start --network manage
KVM 磁盘创建
空磁盘创建,假设在 /var/vm/vm1/
目录中,创建一个大小为 100G
的磁盘文件 sys.qcow2
qemu-img create -f qcow2 /var/vm/vm1/sys.qcow2 100G
以现有磁盘作为基础镜像
-
backimg: 基础镜像磁盘文件
-
vm_disk_path: 新创建的磁盘位置
-
vm_disk_size: 新创建的磁盘大小,单位由后面的字母
G
决定。
qemu-img create -f qcow2 -o backing_file=${backimg} ${vm_disk_path} ${vm_disk_size}G
KVM 虚机配置文件编写
下面配置中用 %..%
表示需要调整的地方。
-
vm_id: 虚机唯一id,不可重复
-
vm_name: 虚机名称
-
vm_title: 虚机标题
-
vm_mem: 虚机内存大小
-
vm_cpu: 虚机cpu数量
-
vm_disk_path: 虚机磁盘位置
-
vm_mac_wan: 虚机wan口mac地址
-
vm_mac_mgr: 虚机管理口mac地址
-
vm_mac_fwd0: 虚机0号转发口mac地址
-
vm_mac_fwd1: 虚机1号转发口mac地址
默认情况下,虚机中的接口在宿主机中的名称都是 vnetX
形式的, X
为数字编号,这样很难识别该接口属于哪个虚机。经过尝试发现可以自行指定接口名称。
<interface type='bridge'>
<source bridge='br-vms'/>
<mac address='%vm_mac_mgr%'/>
<model type='virtio'/>
<target dev='%vm_name%-mgr'/>
</interface>
需要注意的是:
接口名称不能以 =vnet*=开头,否则该名称无效,KVM会进行自动编号。
接口名称不能太长,否则KVM会忽略该名称。
接口名称中分隔符
-
不能超过3个。
<domain type='kvm' id='%vm_id%'>
<name>%vm_name%</name>
<title>%vm_title%</title>
<memory unit='GiB'>%vm_mem%</memory>
<currentMemory unit='GiB'>%vm_mem%</currentMemory>
<vcpu placement='static'>%vm_cpu%</vcpu>
<resource>
<partition>/machine</partition>
</resource>
<os>
<type arch='x86_64' machine='pc-i440fx-rhel7.0.0'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<acpi/>
<apic/>
</features>
<cpu mode='custom' match='exact' check='full'>
<model fallback='forbid'>Haswell-IBRS</model>
<feature policy='disable' name='hle'/>
<feature policy='disable' name='rtm'/>
<feature policy='require' name='hypervisor'/>
<feature policy='require' name='xsaveopt'/>
</cpu>
<clock offset='utc'>
<timer name='rtc' tickpolicy='catchup'/>
<timer name='pit' tickpolicy='delay'/>
<timer name='hpet' present='no'/>
</clock>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<pm>
<suspend-to-mem enabled='no'/>
<suspend-to-disk enabled='no'/>
</pm>
<devices>
<emulator>/usr/libexec/qemu-kvm</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='%vm_disk_path%'/>
<backingStore/>
<target dev='vda' bus='virtio'/>
</disk>
<interface type='bridge'>
<source bridge='virbr0'/>
<mac address='%vm_mac_wan%'/>
<model type='virtio'/>
<target dev='%vm_name%-wan'/>
</interface>
<interface type='bridge'>
<source bridge='br-vms'/>
<mac address='%vm_mac_mgr%'/>
<model type='virtio'/>
<target dev='%vm_name%-mgr'/>
</interface>
<interface type='bridge'>
<source bridge='br-fwd'/>
<mac address='%vm_mac_fwd0%'/>
<model type='virtio'/>
<target dev='%vm_name%-fwd0'/>
</interface>
<interface type='bridge'>
<source bridge='br-fwd'/>
<mac address='%vm_mac_fwd1%'/>
<model type='virtio'/>
<target dev='%vm_name%-fwd1'/>
</interface>
<graphics type='vnc' port='5900' autoport='yes' listen='0.0.0.0'>
<listen type='address' address='0.0.0.0'/>
</graphics>
<video>
<model type='cirrus' vram='16384' heads='1' primary='yes'/>
<alias name='video0'/>
</video>
<memballoon model='virtio'>
<alias name='balloon0'/>
</memballoon>
</devices>
</domain>
KVM 网络配置文件编写
<network>
<name>br-fwd</name>
<bridge name='br-fwd' stp='on' delay='0'/>
<mac address='fe:c0:a8:de:01:00'/>
<ip address='192.168.222.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.222.2' end='192.168.222.254'/>
</dhcp>
</ip>
</network>
KVM 虚机创建
手动执行步骤
-
创建虚机目录
mkdir vm-name
-
创建虚机磁盘
qemu-img create -f qcow2 -o backing_file=${backimg} ${vm_disk_path} ${vm_disk_size}G
-
编辑虚机配置文件
vm-name.xml
-
创建虚机
virsh define vm-name.xml
-
启动虚机
virsh start vm-name
脚本实现
#!/bin/zsh
#
# custom const
#
vm_id=$(date "+%s")
vm_root=/home/vms/
vm_ip_fix_prefix=192.168.111.
vm_ip_mgr_prefix=172.16.115.
vm_disk_size=40
backimg=/home/vms/base/backimg/common.qcow2
vm_cfg_tmpl=/home/vms/base/cfg/tmpl.xml
vm_net_cfg=/home/vms/base/cfg/net-tmpl.xml
# interactivity
read "vm_name?Enter VM Name: "
read "vm_cpu?Enter CPU Num: "
read "vm_mem?Enter Mem Size(GB): "
read "vm_ip_suffix?Enter IP addr: $vm_ip_mgr_prefix"
vm_ip_fix=${vm_ip_fix_prefix}${vm_ip_suffix}
vm_ip_mgr=${vm_ip_mgr_prefix}${vm_ip_suffix}
hex_ip=$(gethostip -x ${vm_ip_fix})
hex_ip=$(sed 's/../&:/g' <<< ${hex_ip})
vm_mac_wan=80:${hex_ip}EE
vm_mac_mgr=80:${hex_ip}FF
vm_mac_fwd0=80:${hex_ip}00
vm_mac_fwd1=80:${hex_ip}01
vm_path=${vm_root}${vm_name}
vm_disk_path=${vm_path}/vm-sys.qcow2
vm_cfg=/home/vms/${vm_name}/${vm_name}.xml
vm_info=$(cat <<EOF
> Name: $vm_name
> CPU: $vm_cpu
> Mem: $vm_mem GB
> Disk: $vm_disk_size GB
> VM Path: $vm_path
> Disk Path: ${vm_disk_path}
> Config: ${vm_cfg}
> Mgr IP: ${vm_ip_mgr}
> Fix IP: ${vm_ip_fix}
> Mac Mgr : $vm_mac_mgr
> Mac Wan : $vm_mac_wan
> Mac FWD0: $vm_mac_fwd0
> Mac FWD1: $vm_mac_fwd1
EOF
)
echo
echo "We are going to create ${vm_name}:"
echo ${vm_info}
echo
read -q "ans?Are you sure?"
if [ "$ans" != "y" ]; then
exit 0
fi
if [ -d ${vm_path} ]; then
echo "${vm_path}" already EXISTS, please REMOVE it first or CHANGE VM name!
exit 1
fi
mkdir -p ${vm_path}
echo ${vm_info} > ${vm_path}/README
# Create sys-disk
qemu-img create -f qcow2 -o backing_file=${backimg} ${vm_disk_path} ${vm_disk_size}G
#qemu-img create -f qcow2 ${vm_disk_path} ${vm_disk_size}G
# Prepare define xml
cp ${vm_cfg_tmpl} $vm_cfg
sed -i "s/%vm_id%/$vm_id/g" $vm_cfg
sed -i "s/%vm_name%/$vm_name/g" $vm_cfg
sed -i "s/%vm_title%/$vm_ip_fix/g" $vm_cfg
sed -i "s/%vm_cpu%/$vm_cpu/g" $vm_cfg
sed -i "s/%vm_mem%/$vm_mem/g" $vm_cfg
sed -i "s+%vm_disk_path%+$vm_disk_path+g" $vm_cfg
sed -i "s/%vm_mac_mgr%/$vm_mac_mgr/g" $vm_cfg
sed -i "s/%vm_mac_wan%/$vm_mac_wan/g" $vm_cfg
sed -i "s/%vm_mac_fwd0%/$vm_mac_fwd0/g" $vm_cfg
sed -i "s/%vm_mac_fwd1%/$vm_mac_fwd1/g" $vm_cfg
# Update network
sed -i "/%static-mac-ip%/ a <host mac='${vm_mac_mgr}' name='${vm_name}' ip='${vm_ip_fix}'/>" $vm_net_cfg
virsh net-update manage add ip-dhcp-host \
"<host mac='${vm_mac_mgr}' \
name='$vm_name' ip='${vm_ip_fix}' />" \
--live --config
virsh define ${vm_cfg}
virsh start ${vm_name}