KVM虚拟化

一,KVM内核级虚拟化

  Kernel-based Virtual Machine的简称,是一个开源的系统虚拟化模块,自Linux 2.6.20之后集成在Linux的各个主要发行版本中。它使用Linux自身的调度器进行管理,所以相对于Xen,其核心源码很少。KVM目前已成为学术界的主流VMM之一。

KVM的虚拟化需要硬件支持(如Intel VT技术或者AMD V技术)。是基于硬件的完全虚拟化。而Xen早期则是基于软件模拟的Para-Virtualization,新版本则是基于硬件支持的完全虚拟化。但Xen本身有自己的进程调度器,存储管理模块等,所以代码较为庞大。广为流传的商业系统虚拟化软件VMware ESX系列是基于软件模拟的Full-Virtualization。
 
  PS:1,云计算不等于虚拟化
     2,云计算需要使用虚拟化计算
 
二,使用VM虚拟机开启虚拟化支持

 

 三,查看虚拟机是否支持KVM
  grep -E '(vmx|svm)' /proc/cpuinfo 

 

 三,安装管理KVM管理软件包

  kvm内置在内核当中,不需要安装但是需要安装管理工具软件包

  yum -y install qemu-kvm libvirt

  安装安装虚拟机用工具virt-install

  yum -y install virt-install

  设置libvirtd开启启动,并且启动libvirt

  systemctl enable libvirtd

  systemctl start libvirtd

  使用ifconfig查看网卡(CentOS7没有这个命令,使用yum -y install net-tools)

  

四,使用kvm安装虚拟机

  1,创建硬盘

      创建raw格式硬盘

 qemu-img create -f raw /opt/CentOS-7-x86_64.raw 10G

      创建qcow2硬盘,一般使用此格式,因为改格式支持快照

 qemu-img create -f qcow2 /opt/CentOS-7-x86_64.qcow2 10G

  创建了一个格式为raw大小为10G的磁盘

  2,使用命令安装

virt-install --virt-type kvm --name CentOS-7-x86_64 --ram 2048 --cdrom=/tmp/CentOS-7.0-1406-x86_64-DVD.iso --disk path=/opt/CentOS-7-x86_64.raw --network network=default --graphics vnc,listen=0.0.0.0 --noautoconsole

  假如硬盘格式是qcow2安装命令为

virt-install --virt-type kvm --name CentOS-7-x86_64 --ram 2048 --cdrom=/tmp/CentOS-7.0-1406-x86_64-DVD.iso --disk /opt/CentOS-7-x86_64.qcow2,format=qcow2 --network network=default --graphics vnc,listen=0.0.0.0 --noautoconsole

   假如网络也使用桥接那么完整的安装命令是

virt-install --virt-type kvm --name test_qcow2 --ram 1024 --cdrom=/tmp/CentOS-7-x86_64-Minimal-1708.iso --disk /opt/test.qcow2,format=qcow2 --network bridge=br0 --graphics vnc,listen=0.0.0.0 --noautoconsole

  --name虚拟机名字

  --ram 分配的内存大小(CentOS内存分配如果是1024可能无法启动图形化界面所以这里分配大一点)

  --cdrom 指定安装系统的镜像

  --disk path 安装的硬盘及第1步创建的硬盘

  --network 使用默认网络

  --graphics 默认图形化界面为vnc

  使用了br0网卡桥接以后安装网络的参数为 --network bridge=br0

  2024-09-11补充开始

  如果是ubuntu22.04系统安装命令是

virt-install --virt-type kvm --name Rocky9Template2 --ram 4096 --cdrom=/data/iso/Rocky/Rocky-9.3-x86_64-dvd.iso --disk /kvm/Rocky9Template2.qcow2,format=qcow2 --network=bridge --graphics vnc,listen=0.0.0.0 --noautoconsole

  

  2024-09-11补充结束

  2024-05-24补充开始

  先创建磁盘在执行安装命令,否则报错

ERROR '选项'

  从这个报错信息可以知道是参数错误但是无法确认是磁盘没有创建

  2024-05-24补充结束

  3,使用Tighrvnc快速连接(默认开始端口是5900如果如新建端口5901以此类推)

    使用vnc连接之前需要关闭防火墙及selinux

systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed 's#enforcing#disabled#g' /etc/selinux/config  -i

  

 

  在界面按tab输入一下命令可以让CentOS7的网卡命名和6一样

   4,虚拟机的管理命令

    虚拟机的配置文件在/etc/libvirt/qemu文件夹下面,无法直接使用vim编辑需要使用以下命令编辑

    virsh edit CentOS-7-x86_64

    CentOS7支持cpu热添加需要

    修改以下行(代表cpu是自动的最大为4个目前是一个)

    

    然后在命令行输入以下命令热添加cpu(单独使用kvm有点用,使用openstack不支持热添加删除,最后还是不要使用这种功能)

virsh setvcpus CentOS-7-x86_64 2 --live

     

    查看当前虚拟机的内存大小

virsh qemu-monitor-command CentOS-7-x86_64 --hmp --cmd info balloon

     

   热修改内存大小

virsh qemu-monitor-command CentOS-7-x86_64 --hmp --cmd balloon 512

    内存的最大大小在配置文件里面配置(编辑xml文件需要生效的话需要重启虚拟机)

  

   设置开机自启动虚拟机

virsh autostart CentOS-7-x86_64 
域 CentOS-7-x86_64标记为自动开始
取消开机自启动

 virsh autostart CentOS_Stream --disable

 

  设置虚拟机桥接

  默认的虚拟机是使用nat连接的只能使用vnc连接宿主机的5900及往后推的端口

  宿主机用于桥接的网卡

  

  查看桥接模式

  

  增加一块桥接的网卡

brctl addbr br0

   桥接物理网卡这里的eth0为当前宿主机的物理网卡名

brctl addif br0 eth0

   PS:这个时候网络就会断了,生产不能这样玩,可以写一个脚本

brctl addbr br0 && brctl addif br0 eth0 && ip addr del dev eth0 192.168.0.112/24 && ifconfig br0 192.168.0.112/24 up

  脚本第一步添加桥接网卡,第二步桥接网卡与物理网卡绑定,第三步删除原物理网卡IP,第四步启动桥接网卡

  使用虚拟机终端连接查看br0桥接到物理网卡eth0上面

  把eth0的地址删掉设置在br0上面

ip add del dev eth0 192.168.0.112
ifconfig br0 192.168.0.112/24 up

   这个时候ip地址已经配置到br0上面了但是还是无法连接公网设置以下网关

route add default gw 192.168.0.1

   宿主机重启后以上设置的桥接会失效,写成一个脚本,类似于以下内容

brctl addbr br0 && brctl addif br0 em1 && ip addr del dev em1 192.168.3.198/24 && ifconfig br0 192.168.3.198/24 up && route add default gw 192.168.3.1

  添加权限设置成开机自启动

 

  修改xml配置文件修改以下两个地方

  重启虚拟机

virsh shutdown CentOS-7-x86_64
virsh start CentOS-7-x86_64

   在vnc设置静态ip地址

  重启网卡

systemctl restart network

   这个时候就可以在本机使用xshell直接连接虚拟机里面的虚拟机了

 

五,kvm性能优化

  1,cpu优化

  CPU Ring 0 内核空间 Ring用户空间

  为了减少cpu 的cache miss可以使用taskset把cpu绑定到对应的进程(可提高性能10%只有)

  taskset -cp 1 进程id

  

  2,内存优化

  虚拟机的物理内存其实是宿主机的虚拟内存

  影子页表技术

  Intel 使用EPT 技术 AMD使用RVI技术

  

  大页内存 默认宿主机是开启的

  配置文件 /sys/kernel/mm/transparent_hugepage/enabled

  内存重复合并ksm(默认开启)

  

  

  3,I/O优化

  virto半虚拟化技术优化I/O

  I/O调度算法(2.6内核又四种调度算法3.10为三种)

dmesg | grep -i scheduler

   

  查看当前的I/O调度算法

cat /sys/block/sda/queue/scheduler 

   几种IO调度算法比较

1,Noop算法 (SSD硬盘选择)

     Noop调度算法是内核中最简单的IO调度算法。Noop调度算法也叫作电梯调度算法,它将IO请求放入到一个FIFO队列中,然后逐个执行这些IO请求,当然对于一些在磁盘上连续的IO请求,Noop算法会适当做一些合并。这个调度算法特别适合那些不希望调度器重新组织IO请求顺序的应用。

     这种调度算法在以下场景中优势比较明显:

     1)在IO调度器下方有更加智能的IO调度设备。如果您的Block Device Drivers是Raid,或者SAN,NAS等存储设备,这些设备会更好地组织IO请求,不用IO调度器去做额外的调度工作;

     2)上层的应用程序比IO调度器更懂底层设备。或者说上层应用程序到达IO调度器的IO请求已经是它经过精心优化的,那么IO调度器就不需要画蛇添足,只需要按序执行上层传达下来的IO请求即可。

     3)对于一些非旋转磁头氏的存储设备,使用Noop的效果更好。因为对于旋转磁头式的磁盘来说,IO调度器的请求重组要花费一定的CPU时间,但是对于SSD磁盘来说,这些重组IO请求的CPU时间可以节省下来,因为SSD提供了更智能的请求调度算法,不需要内核去画蛇添足。这篇文章提及了SSD中使用Noop效果会更好。
2,Deadline算法

     Deadline算法的核心在于保证每个IO请求在一定的时间内一定要被服务到,以此来避免某个请求饥饿。

     Deadline算法中引入了四个队列,这四个队列可以分为两类,每一类都由读和写两类队列组成,一类队列用来对请求按起始扇区序号进行排序,通过红黑树来组织,称为sort_list;另一类对请求按它们的生成时间进行排序,由链表来组织,称为fifo_list。每当确定了一个传输方向(读或写),那么将会从相应的sort_list中将一批连续请求dispatch到requst_queue的请求队列里,具体的数目由fifo_batch来确定。只有下面三种情况才会导致一次批量传输的结束:

    1)对应的sort_list中已经没有请求了

    2)下一个请求的扇区不满足递增的要求

    3)上一个请求已经是批量传输的最后一个请求了。

     所有的请求在生成时都会被赋上一个期限值(根据jiffies),并按期限值排序在fifo_list中,读请求的期限时长默认为为500ms,写请求的期限时长默认为5s,可以看出内核对读请求是十分偏心的,其实不仅如此,在deadline调度器中,还定义了一个starved和writes_starved,writes_starved默认为2,可以理解为写请求的饥饿线,内核总是优先处理读请求,starved表明当前处理的读请求批数,只有starved超过了writes_starved后,才会去考虑写请求。因此,假如一个写请求的期限已经超过,该请求也不一定会被立刻响应,因为读请求的batch还没处理完,即使处理完,也必须等到starved超过writes_starved才有机会被响应。为什么内核会偏袒读请求?这是从整体性能上进行考虑的。读请求和应用程序的关系是同步的,因为应用程序要等待读取的内容完毕,才能进行下一步工作,因此读请求会阻塞进程,而写请求则不一样,应用程序发出写请求后,内存的内容何时写入块设备对程序的影响并不大,所以调度器会优先处理读请求。

     默认情况下,读请求的超时时间是500ms,写请求的超时时间是5s。

     这篇文章说在一些多线程应用下,Deadline算法比CFQ算法好。这篇文章说在一些数据库应用下,Deadline算法比CFQ算法好。
3,Anticipatory算法

    Anticipatory算法的核心是局部性原理,它期望一个进程昨晚一次IO请求后还会继续在此处做IO请求。在IO操作中,有一种现象叫“假空闲”(Deceptive idleness),它的意思是一个进程在刚刚做完一波读操作后,看似是空闲了,不读了,但是实际上它是在处理这些数据,处理完这些数据之后,它还会接着读,这个时候如果IO调度器去处理另外一个进程的请求,那么当原来的假空闲进程的下一个请求来的时候,磁头又得seek到刚才的位置,这样大大增加了寻道时间和磁头旋转时间。所以,Anticipatory算法会在一个读请求做完后,再等待一定时间t(通常是6ms),如果6ms内,这个进程上还有读请求过来,那么我继续服务,否则,处理下一个进程的读写请求。

     在一些场景下,Antocipatory算法会有非常有效的性能提升。这篇文章有说,这篇文章也有一份评测。

      值得一提的是,Anticipatory算法从Linux 2.6.33版本后,就被移除了,因为CFQ通过配置也能达到Anticipatory算法的效果。
4,CFQ算法

    CFQ(Completely Fair Queuing)算法,顾名思义,绝对公平算法。它试图为竞争块设备使用权的所有进程分配一个请求队列和一个时间片,在调度器分配给进程的时间片内,进程可以将其读写请求发送给底层块设备,当进程的时间片消耗完,进程的请求队列将被挂起,等待调度。 每个进程的时间片和每个进程的队列长度取决于进程的IO优先级,每个进程都会有一个IO优先级,CFQ调度器将会将其作为考虑的因素之一,来确定该进程的请求队列何时可以获取块设备的使用权。IO优先级从高到低可以分为三大类:RT(real time),BE(best try),IDLE(idle),其中RT和BE又可以再划分为8个子优先级。实际上,我们已经知道CFQ调度器的公平是针对于进程而言的,而只有同步请求(read或syn write)才是针对进程而存在的,他们会放入进程自身的请求队列,而所有同优先级的异步请求,无论来自于哪个进程,都会被放入公共的队列,异步请求的队列总共有8(RT)+8(BE)+1(IDLE)=17个。

 

作业

1,下载一个IOS

2,创建虚拟机磁盘

3,virt-install安装虚拟机

  1,不适应swap分区

  2,只分一个/

  3,不使用LVM等

 

4,安装完毕后

  1,关闭Selinux,iptables 

  2,修改网卡配置取得UUID,MAC等

  3,安装必备软件zabbix-agent等

posted @ 2018-01-14 10:53  minseo  阅读(408)  评论(0编辑  收藏  举报