Skip to content

Instantly share code, notes, and snippets.

@jschwinger233
Last active May 25, 2020 15:52
Show Gist options
  • Select an option

  • Save jschwinger233/cc93ce80fba8d17972dabbe298df9dd9 to your computer and use it in GitHub Desktop.

Select an option

Save jschwinger233/cc93ce80fba8d17972dabbe298df9dd9 to your computer and use it in GitHub Desktop.

KVM 极简入门

一. QEMU

QEMU (Quick Emulator) 提供了硬件和处理器虚拟化, 它跑在用户态, 无需内核.

话不多说, 直接用起来. 我使用的 OS 是 Ubuntu16.

1.1 安装

apt-get update
apt-get install qemu

然后检查一下

dpkg --list | grep qemu

1.2 拉个镜像

curl -OL https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2

经过漫长的等待, 检查一下

qemu-img info CentOS-7-x86_64-GenericCloud.qcow2

会输出 format qcow2, virtual size 8G.

1.3 第一个虚拟机

qemu-system-x86_64 -name zc -cpu Nehalem -m 1024 -drive format=qcow2,file=CentOS-7-x86_64-GenericCloud.qcow2 -vnc 0.0.0.0:0 -daemonize

-cpu Nehalem Nahalem Intel Core i7, -m 1024 1G 内存, -drive 指定刚才下载的镜像, -vnc 绑定一个端口让你访问虚拟机

然后检查一下

pgrep -la qemu

如果要停止的话直接

pkill -9 qemu

1.4 登录

我 macOS 下载了一个 VNC Viewer, 然后在 GUI 上连接 Ubuntu 的 IP:5900, 顺利连接, 然后让我登录, 但我不知道 root 和密码.

改镜像密码, 先下载

apt install -y libguestfs-tools

然后设置 root 密码为 root

virt-customize -a CentOS-7-x86_64-GenericCloud.qcow2 --root-password password:root

会报错 virt-customize: error: libguestfs error: guestfs_launch failed., 这是因为在这个镜像上正跑着一个 VM 呢, 关掉先.

改好密码后最后重新启动一个虚拟机, VNC 连接登录, 成了.

进去后检查一下 cpu, memory, disk

free -h
lscpu
df -h

应该是和我们指定的一样的, 分别是 1G, 1C, 8G.

1.5 KVM

KVM (Kernel-based Virtual Machine) 和 QEMU 最大的不同是它跑在内核态, 所以需要内核支持.

先检查 cpu 支持 KVM 虚拟化:

lscpu | grep vmx | uniq

然后检查内核模块

modprobe kvm
lsmod | grep kvm

那么来吧

qemu-system-x86_64 -name zc -cpu Nehalem -m 1024 -drive format=qcow2,file=CentOS-7-x86_64-GenericCloud.qcow2 -vnc 0.0.0.0:0 -enable-kvm -daemonize

注意新增的 -enable-kvm.

另一种做法是下载 kvm 二进制

apt install qemu-kvm
kvm -name zc -cpu Nehalem -m 1024 -drive format=qcow2,file=CentOS-7-x86_64-GenericCloud.qcow2 -vnc 0.0.0.0:0 -daemonize

不过本质上 kvm 二进制只是把 qemu-system-x86_64 包了一下, pgrep -la qemu 看到两种拉起来的进程是一样的.

二. libvirt

libvirt 对不同的虚拟化技术提供了统一的上层接口, 比方说管理 QEMU/KVM, XEN, LXC.

2.1 安装

apt install -y libvirt0-dbg/xenial-updates
apt install -y libvirt-bin

然后 libvirtd daemon 就起来了

systemctl status libvirtd

看看配置

cat /etc/libvirt/libvirtd.conf | grep -v '^#\|^$'

很多东西在 /etc/libvirt/ 里, 猫一眼

# ls -lF /etc/libvirt/
total 84
drwxr-xr-x 2 root root  4096 Mar 11 21:52 hooks/
-rw-r--r-- 1 root root   450 Mar 11 21:52 libvirt-admin.conf
-rw-r--r-- 1 root root   547 Mar 11 21:52 libvirt.conf
-rw-r--r-- 1 root root 15276 Mar 11 21:52 libvirtd.conf
-rw-r--r-- 1 root root   834 Mar 11 21:52 libxl.conf
-rw-r--r-- 1 root root  2169 Mar 11 21:52 libxl-lockd.conf
-rw-r--r-- 1 root root  1235 Mar 11 21:52 lxc.conf
drwxr-xr-x 2 root root  4096 May 19 22:23 nwfilter/
drwxr-xr-x 3 root root  4096 May 19 22:23 qemu/
-rw------- 1 root root 19536 Mar 11 21:52 qemu.conf
-rw-r--r-- 1 root root  2169 Mar 11 21:52 qemu-lockd.conf
-rw-r--r-- 1 root root  2134 Mar 11 21:52 virtlockd.conf
-rw-r--r-- 1 root root  1802 Mar 11 21:52 virtlogd.conf
-rw-r--r-- 1 root root  1217 Mar 11 21:52 virt-login-shell.conf

关注 libvirt.conf 是给 libvirt client 用的, libvirtd.conf 是给 libvirtd 用的, qemu.conf 是 libvirtd 驾驭 QEMU/KVM 的配置, qemu/ 里是创建的 VM 配置

2.2 第二个虚拟机

先安装工具

apt install virtinst/xenial-updates

然后生成 libvirt domain xml

virt-install --name v2 --ram 1024 --disk path=CentOS-7-x86_64-GenericCloud.qcow2,format=qcow2 --print-xml > v2.xml

看一下 v2.xml

<domain type="kvm">
  <name>v2</name>
  <uuid>27144641-23ff-42ad-9bd5-6ab0a4ff6ec7</uuid>
  <memory>1048576</memory>
  <currentMemory>1048576</currentMemory>
  <vcpu>1</vcpu>
  <os>
    <type arch="x86_64">hvm</type>
    <boot dev="hd"/>
  </os>
  <features>
    <acpi/>
    <apic/>
  </features>
  <cpu mode="custom" match="exact">
    <model>Broadwell-IBRS</model>
  </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>restart</on_crash>
  <pm>
    <suspend-to-mem enabled="no"/>
    <suspend-to-disk enabled="no"/>
  </pm>
  <devices>
    <emulator>/usr/bin/kvm-spice</emulator>
    <disk type="file" device="disk">
      <driver name="qemu" type="qcow2"/>
      <source file="/root/CentOS-7-x86_64-GenericCloud.qcow2"/>
      <target dev="hda" bus="ide"/>
    </disk>
    <controller type="usb" index="0" model="ich9-ehci1"/>
    <controller type="usb" index="0" model="ich9-uhci1">
      <master startport="0"/>
    </controller>
    <controller type="usb" index="0" model="ich9-uhci2">
      <master startport="2"/>
    </controller>
    <controller type="usb" index="0" model="ich9-uhci3">
      <master startport="4"/>
    </controller>
    <interface type="network">
      <source network="default"/>
      <mac address="52:54:00:d5:af:0b"/>
    </interface>
    <input type="mouse" bus="ps2"/>
    <graphics type="spice" port="-1" tlsPort="-1" autoport="yes">
      <image compression="off"/>
    </graphics>
    <console type="pty"/>
    <channel type="spicevmc">
      <target type="virtio" name="com.redhat.spice.0"/>
    </channel>
    <sound model="ich6"/>
    <video>
      <model type="qxl"/>
    </video>
    <redirdev bus="usb" type="spicevmc"/>
    <redirdev bus="usb" type="spicevmc"/>
  </devices>
</domain>

关注里面的 disk, vcpu, memory 的值; 你也可以直接编辑文件修改.

然后用 libvirt client virsh

virsh define v2.xml

检查一下, 启动起来

virsh list --all
virsh start v2

发现报错 error: Cannot access storage file '/root/CentOS-7-x86_64-GenericCloud.qcow2' (as uid:64055, gid:121): Permission denied, 看一下 uid 64055 是用户 libvirt-qemu, 读不了 /root/, 所以把镜像放在 /opt/qemu-img/

mkdir /opt/qemu-img/
cp /root/CentOS-7-x86_64-GenericCloud.qcow2 /opt/qemu-img/v2.qcow2

然后改下 xml 里的镜像路径到 /opt/qemu-img/v2.qcow2, 重来一遍

virsh undefine v2
virsh define v2.xml
virsh start v2
virsh list

成功!

创建好的 vm 的 xml 都在 /etc/libvirt/qemu/ 里.

pgrep qemu -la 能看到启动的进程依然是 qemu-system-x86_64 那一套, 只不过 flag 爆多

29915 qemu-system-x86_64 -enable-kvm -name v2 -S -machine pc-i440fx-xenial,accel=kvm,usb=off -cpu Broadwell-IBRS -m 1024 -realtime mlock=off -smp 1,sockets=1,cores=1,threads=1 -uuid ab376ac8-20bf-43cb-abdd-a43cfb472f2f -no-user-config -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/domain-v2/monitor.sock,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc,driftfix=slew -global kvm-pit.lost_tick_policy=discard -no-hpet -no-shutdown -global PIIX4_PM.disable_s3=1 -global PIIX4_PM.disable_s4=1 -boot strict=on -device ich9-usb-ehci1,id=usb,bus=pci.0,addr=0x6.0x7 -device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x6 -device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,addr=0x6.0x1 -device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,addr=0x6.0x2 -device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x5 -drive file=/opt/qemu-img/v2.qcow2,format=qcow2,if=none,id=drive-ide0-0-0 -device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=1 -netdev tap,fd=26,id=hostnet0 -device rtl8139,netdev=hostnet0,id=net0,mac=52:54:00:d8:a3:e7,bus=pci.0,addr=0x3 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -chardev spicevmc,id=charchannel0,name=vdagent -device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,name=com.redhat.spice.0 -spice port=5900,addr=127.0.0.1,disable-ticketing,image-compression=off,seamless-migration=on -device qxl-vga,id=video0,ram_size=67108864,vram_size=67108864,vgamem_mb=16,bus=pci.0,addr=0x2 -device intel-hda,id=sound0,bus=pci.0,addr=0x4 -device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0 -chardev spicevmc,id=charredir0,name=usbredir -device usb-redir,chardev=charredir0,id=redir0 -chardev spicevmc,id=charredir1,name=usbredir -device usb-redir,chardev=charredir1,id=redir1 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x7 -msg timestamp=on

2.3 登录

注意到第二个虚拟机并没有开放端口和 vnc 服务, 我们用 virsh console

virsh console v2

输入密码 root.

2.4 管理内存

当前的内存状态

xmllint --xpath 'string(//memory)' /etc/libvirt/qemu/v2.xml
xmllint --xpath 'string(//currentMemory)' /etc/libvirt/qemu/v2.xml

输出是一样的 1048576

currentMemory 必须比 memory 小, 出现两个内存值的目的是让 VM 可以调整内存 on the fly

virsh setmem v2 --size 500000

这时候通过 console 进去 free -m 就会发现内存减少了

同样可以把 memory 调大, 以增加 currentMemory, 不过必须停机先

virsh destroy v2
virsh setmaxmem v2 --size 2097152
virsh start v2
virsh setmem v2 --size 2097152

通过 virsh setmem 命令修改资源是不会同步修改到 xml 里的, 要注意

2.5 管理 disk

在镜像里 df -h 能看到

/dev/sda1       8.0G  850M  7.2G  11% /

这里的 8G 是镜像里定义的

qemu-img info /opt/qemu-img/v2.qcow2

要修改的话

qemu-img resize -f qcow2 /opt/qemu-img/v2.qcow2 +2GB

重启

virsh destroy v2
virsh start v2

然后 fdisk 传统技能走一套

fdisk -l /dev/sda

看到已经是 10G 了, 接下来是传统杂技时间, fdisk /dev/sda 分区, 不表演.

2.6 管理 CPU

直接改 xml

virsh edit v2

修改 vcpu 的值为 2

<vcpu placement='static'>2</vcpu>

然后重启

virsh destroy v2 && virsh start v2

再进去检查 lscpu 可以看到已经是 2 核

2.7 管理网络

我们玩传统点, 网桥+TUN/TAP.

先创建 TUN/TAP

ip tuntap a dev tap0 mode tap
ip l s tap0 up

然后创建网桥

ip l a name bri0 type bridge
ip l s bri0 up
ip a a 10.16.0.1/16 dev bri0

然后把 tap0 连到 bri0

ip l s tap0 master bri0

然后创建 KVM

kvm -name v3 -cpu Nehalem -m 1024 -drive format=qcow2,file=/opt/qemu-img/v3.qcow2 -vnc 0.0.0.0:1 -net tap,ifname=tap0,script=/bin/true -net nic,macaddr=c6:3a:0d:2a:2e:b1  -daemonize

然后通过 vnc 登录上去, 在 vm 里配置 ip 和路由

ip a a 10.16.0.2 dev eth0
ip r a default dev eth0

然后在 vm 和 host 可以互 ping 了.

就是这么简单.


然后 cmgs 润逼后成了这么一篇骗钱文章: https://mp.weixin.qq.com/s?__biz=Mzg4MDEwOTcxMw==&mid=2247483726&idx=1&sn=427936ff0282a5574555c523ad969fd8&chksm=cf7b70b0f80cf9a6ce01fbf8eb1277b6de27e1355e86dd71b081942f606d79e347b89fc3afd2&scene=21#wechat_redirect

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment