(KVM) 创建方法+常用格式

企业私有云架构运维实战

了解
什么是虚拟化:
虚拟化(Virtualization)技术最早出现在 20 世纪 60 年代的 IBM 大型机系统,在70年代的 System 370 系列中逐渐流行起来,这些机器通过一种叫虚拟机监控器(Virtual Machine Monitor,VMM)的程序在物理硬件之上生成许多可以运行独立操作系统软件的虚拟机(Virtual Machine)实例。随着近年多核系统、集群、网格甚至云计算的广泛部署,虚拟化技术在商业应用上的优势日益体现,不仅降低了 IT 成本,而且还增强了系统安全性和可靠性。

常用的虚拟化产品有哪些

1.Kvm(redhat)企业级
2.Vmware:
Vmware-workstation(windows和linux)桌面级
Vmware-fusion(mac)
Vmware-esxi(企业级别)本身就是一个操作系统。
3.hyper-v(微软)
4.Ovm(oracle公司--Windows linux) virtulbox
5.Xen(rhel6之前所有版本默认用的虚拟化产品)

虚拟化技术的分类:

平台虚拟化(Platform Virtualization),针对计算机和操作系统的虚拟化//针对计算机操作系统。
资源虚拟化(Resource Virtualization),针对特定的系统资源的虚拟化,比如内存、存储、网络资源等。
应用程序虚拟化(Application Virtualization),包括仿真、模拟、解释技术等。把硬件的东西变成了一个应用
  我们通常所说的虚拟化主要是指平台虚拟化技术,通过使用控制程序(Control Program,也被称为 Virtual Machine Monitor(虚拟监控器VMM) 或**Hypervisor**,隐藏特定计算平台的实际物理特性,为用户提供抽象的、统一的、模拟的计算环境(称为虚拟机)。
平台虚拟化类型

操作系统虚拟化

常见的操作系统叫openvz,他的特点是所有虚拟机共享你宿主机的内核。

全虚拟化(Full Virtualization):

全虚拟化是指虚拟机模拟了完整的底层硬件,包括处理器、物理内存、时钟、外设等,使得为原始硬件设计的操作系统或其它系统软件完全不做任何修改就可以在虚拟机中运行。

现在的kvm与vmware都支持全虚拟化

全虚拟化的运行速度要快于硬件模拟,但是性能方面不如裸机,因为Hypervisor需要占用一些资源

半虚拟化(Para Virtualization):

半虚拟化(也叫超虚拟化)是另一种类似于全虚拟化的技术,它使用Hypervisor分享存取底层的硬件,但是它的guest操作系统集成了虚拟化方面的代码。因为操作系统自身能够与虚拟进程进行很好的协作。

半虚拟化需要guest操作系统做一些修改,使guest操作系统意识到自己是处于虚拟化环境的,但是半虚拟化提供了与原操作系统相近的性能。

硬件辅助虚拟化

硬件辅助虚拟化是指借助硬件(主要是主机处理器)的支持来实现高效的全虚拟化。

企业级虚拟化与桌面级虚拟化的区别

桌面级虚拟化:
App  ---在安装APP,通过App实现各种功能
guestos  ---客户机也叫客户操作系统
vmware-workstation(hypervisor(虚拟机管理程序)+图形管理工具)
os
硬件

企业级虚拟化
App(图形管理工具)
guestos
os+hypervisor:在操作系统级别加上了虚拟机管理程序
硬件

KVM虚拟化技术简介

KVM 针对运行在 x86 硬件上的、驻留在内核中的虚拟化基础结构。KVM 是第一个成为原生 Linux 内核(2.6.20)的一部分的 hypervisor,它是由 Avi Kivity 开发和维护的,现在归 Red Hat 所有。
KVM 是作为内核模块实现的

KVM安装

kvm虚拟化平台软件一般装在操作系统为Centos上面
大家不想把电脑装为Centos的操作系统,可以用VMware workstations装一台配置较高的虚拟机(cpu、内存、磁盘)给的尽可能最大,然后需要在开启之前做如下操作

然后打开虚拟机,安装kvm即可

查看cpu是否支持虚拟化
# cat /proc/cpuinfo | grep -E 'vmx|svm'

"关闭防火墙和selinux"   --注:如果虚拟机ping不通就把防火墙开起来

一般企业如果使用kvm虚拟机平台,都会把物理服务器装成Centos的操作系统,然后装上kvm,创建使用虚拟机

1.需求内核(rhel6以上):
[root@kvm-server ~]# uname -r 
3.10.0-1062.el7.x86_64
2.如果之前安装kvm了清理环境:卸载kvm
[root@kvm-server ~]# yum remove `rpm -qa | egrep 'qemu|virt|kvm'` -y
[root@kvm-server ~]# rm -rf /var/lib/libvirt  /etc/libvirt/
3.升级系统:(在安装虚拟机出错的情况下,一般是操作系统的版本问题)
[root@kvm-server ~]# yum upgrade
4.安装软件:
[root@kvm-server ~]# yum install -y librbd1-devel qemu-kvm libvirt virt-manager virt-install

qemu-kvm : 主包
libvirt:api接口
virt-manager:图形化界面

在所谓的kvm技术中,应用到的其实有2个东西:qemu+kvm
kvm负责cpu虚拟化+内存虚拟化,实现了cpu和内存的虚拟化,但kvm不能模拟其他设备;
qemu是模拟IO设备(网卡,磁盘),kvm加上qemu之后就能实现真正意义上服务器虚拟化。
因为用到了上面两个东西,所以一般都称之为qemu-kvm。
libvirt则是调用kvm虚拟化技术的接口用于管理的,用libvirt管理方便,直接用qemu-kvm的接口太繁琐。

5.启动服务:    
centos7:
[root@kvm-server ~]# systemctl start libvirtd
6.查看kvm模块加载:
[root@kvm-server ~]# lsmod | grep kvm
kvm_intel             188644  0 
kvm                   621480  1 kvm_intel
irqbypass              13503  1 kvm
如果看到有这两行,说明支持kvm模块

KVM gustos图形方式部署安装虚拟机—需要掌握

[root@kvm-server ~]# virt-manager
====================
下面就是点点点

安装完成一台虚拟机之后,网络模式默认是NAT的。

完全文本方式安装虚拟机

[root@kvm-server ~]# yum install -y vsftpd  #安装ftp,并配置最后将镜像上传到ftp中
[root@kvm-server ~]# systemctl start vsftpd
[root@kvm-server ~]# mkdir /var/ftp/centos7u4
[root@kvm-server IOS]# mount CentOS-7-x86_64-DVD-1708.iso /var/ftp/centos7u4/
[root@kvm-server ~]# virt-install --connect qemu:///system -n vm10 -r 2050 --disk path=/var/lib/libvirt/images/vm10.img,size=5  --os-type=linux --os-variant=centos7.0 --vcpus=1  --location=ftp://10.0.111.182/centos7u4 -x console=ttyS0 --nographics

用这种方式安装的操作系统有一个毛病:纯文本安装的输入时大小写莫名的变换,远程ssh没问题。kvm 限制:内存不低于2G

注意:
virt-install 
bash: virt-install: 未找到命令...
# yum install libguestfs-tools -y
# yum install virt-install.noarch -y

参数解释:
-n name
-r  以M为单位指定分配给虚拟机的内存大小
--disk 指定作为客户机存储的媒介 size以G为单位的存储
--os-type   系统类型
--os-variant 系统类型版本
--vcpus 指定核数,不能超过物理cpu
--location  客户虚拟机安装源下载,必须为镜像挂载在ftp目录下
-x console=ttyS0 执行终端0
--nographics 无图形,文本模式

注意:命令敲下去,不要误操作退出安装

需要等一会了大约20分钟左右

按空格退出!

下面的操作根据提示点点就可以了

模板镜像+配置文件 方式安装虚拟机—需要掌握

1.虚拟机配置文件
[root@kvm-server ~]# ls /etc/libvirt/qemu
networks  vm2.xml
2.储存虚拟机的介质
[root@kvm-server ~]# ls /var/lib/libvirt/images/
vm2.img
==============================
define方式创建好,不会启动
create方式创建好,会启动
实战:
1.拷贝模板镜像和配置文件
[root@kvm-server ~]# cp /etc/libvirt/qemu/vm2.xml /etc/libvirt/qemu/vm3.xml
[root@kvm-server ~]# cp /var/lib/libvirt/images/vm2.img /var/lib/libvirt/images/vm3.img 
2.修改配置文件
生成新的UUID
[root@kvm-server ~]# uuidgen
2e3fa6db-ff7f-41c3-bc8f-0428e81ebb57
[root@kvm-server ~]# vim /etc/libvirt/qemu/vm3.xml
<domain type='kvm'>
  <name>vm3</name>  #名字不能一样需要修改
  <uuid>2e3fa6db-ff7f-41c3-bc8f-0428e81ebb57</uuid> #uuid不能一样需要修改
  <memory unit='KiB'>1024000</memory>  #内存,可选
  <currentMemory unit='KiB'>1024000</currentMemory>  #当前内存与上面定义一样
  <vcpu placement='static'>2</vcpu>  #cpu可选
  <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='partial'>
    <model fallback='allow'>SandyBridge-IBRS</model>
    <feature policy='require' name='md-clear'/>
    <feature policy='require' name='spec-ctrl'/>
    <feature policy='require' name='ssbd'/>
  </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='/var/lib/libvirt/images/vm3.img'/>   #磁盘镜像需要修改
      <target dev='vda' bus='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
    </disk>
    <controller type='usb' index='0' model='ich9-ehci1'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x7'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci1'>
      <master startport='0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0' multifunction='on'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci2'>
      <master startport='2'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x1'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci3'>
      <master startport='4'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x2'/>
    </controller>
    <controller type='pci' index='0' model='pci-root'/>
    <controller type='virtio-serial' index='0'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
    </controller>
    <interface type='network'>
      <mac address='52:54:00:82:d6:3c'/>  #mac地址不能一样需要修改,只能修改后三段。
      <source network='default'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
    <serial type='pty'>
      <target type='isa-serial' port='0'>
        <model name='isa-serial'/>
      </target>
    </serial>
    <console type='pty'>
      <target type='serial' port='0'/>
    </console>
    <channel type='unix'>
      <target type='virtio' name='org.qemu.guest_agent.0'/>
      <address type='virtio-serial' controller='0' bus='0' port='1'/>
    </channel>
    <channel type='spicevmc'>
      <target type='virtio' name='com.redhat.spice.0'/>
      <address type='virtio-serial' controller='0' bus='0' port='2'/>
    </channel>
    <input type='tablet' bus='usb'>
      <address type='usb' bus='0' port='1'/>
    </input>
    <input type='mouse' bus='ps2'/>
    <input type='keyboard' bus='ps2'/>
    <graphics type='spice' autoport='yes'>
      <listen type='address'/>
      <image compression='off'/>
    </graphics>
    <sound model='ich6'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
    </sound>
    <video>
      <model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='1' primary='yes'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
    </video>
    <redirdev bus='usb' type='spicevmc'>
      <address type='usb' bus='0' port='2'/>
    </redirdev>
    <redirdev bus='usb' type='spicevmc'>
      <address type='usb' bus='0' port='3'/>
    </redirdev>
    <memballoon model='virtio'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
    </memballoon>
    <rng model='virtio'>
      <backend model='random'>/dev/urandom</backend>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
    </rng>
  </devices>
</domain>
必须修改name,uuid,mac地址,其余可选

用vim修改完之后需要define一下配置文件
[root@kvm-server ~]# virsh define /etc/libvirt/qemu/vm3.xml
重启一下:
[root@kvm-server ~]# systemctl restart libvirtd
宿主机开启路由转发:
[root@kvm-server ~]# vim /etc/sysctl.conf 
[root@kvm-server ~]# sysctl -p
net.ipv4.ip_forward = 1
=============
查看虚拟机列表:
[root@kvm-server ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 -     vm2                            关闭
 -     vm3                            关闭
或者如下:

KVM虚拟机管理

虚拟机的基本管理命令:
查看
启动
关闭
重启
重置 
===================
[root@kvm-server ~]# virsh list  #列出在运行状态中的虚拟机
 Id    名称                         状态
----------------------------------------------------
 2     vm3                            running
[root@kvm-server ~]# virsh list --all  #列出所有虚拟机
 Id    名称                         状态
----------------------------------------------------
 2     vm3                            running
 -     vm2                            关闭
查看kvm虚拟机配置文件:
语法:virsh dumpxml name #虚拟机名字
[root@kvm-server ~]# virsh dumpxml vm3

将vm3虚拟机的配置文件保存至vm4.xml
[root@kvm-server ~]# virsh dumpxml vm3 > /etc/libvirt/qemu/vm4.xml


启动
[root@kvm-server ~]# virsh start vm2
域 vm2 已开始

暂停虚拟机(挂起):
[root@kvm-server ~]# virsh suspend vm_name
域 vm2 被挂起

恢复虚拟机:
[root@kvm-server ~]# virsh resume vm_name
域 vm2 被重新恢复

关闭:
方法1:
[root@kvm-server ~]# virsh shutdown vm3
域 vm3 被关闭
    
方法2:
[root@kvm-server ~]# virsh destroy vm3

重启:
[root@kvm-server ~]# virsh reboot vm3
域 vm3 正在被重新启动

重置:
[root@kvm-server ~]# virsh reset vm3   #断电重启。速度快
Domain vm3 was reset

删除虚拟机:
[root@kvm-server ~]# virsh undefine vm2
Domain vm2 has been undefined

注意:虚拟机在开启的情况下undefine是无法删除的只是删除定义将配置文件删除了,不能删除磁盘文件。需要手动rm
======================

虚拟机开机自动启动:
#如果虚拟机开机自启,里面的服务应该设置的有开机自启,不然没有意义
[root@kvm-server ~]# virsh autostart vm3
域 vm3标记为自动开始

[root@kvm-server ~]# ls /etc/libvirt/qemu/autostart/     //此目录默认不存在,在有开机启动的虚拟机时自动创建
vm3.xml

关闭开机启动
[root@kvm-server ~]# virsh autostart --disable vm3
域 vm3取消标记为自动开始
[root@kvm-server ~]# ls /etc/libvirt/qemu/autostart/

如何查看已启动的虚拟机ip地址
假如vm3虚拟机已启动
[root@kvm-server ~]# virsh domifaddr vm3
 名称     MAC 地址           Protocol     Address
-------------------------------------------------------------------------------
 vnet0      52:54:00:82:d6:3c    ipv4         192.168.122.85/24

虚拟机添加设备

1.图形方式:
    首先,关闭要添加硬件的虚拟机
    双击虚拟机,在打开的对话框点击上方的View,点击Details,点击Add Hardware可以选择要添加的虚拟硬件

按需求点点就可以了。

2.修改配置文件方式:

我们给虚拟机vm3添加磁盘为例:

首先需要创建出要添加的磁盘
[root@kvm-server ~]# qemu-img create -f qcow2 /var/lib/libvirt/images/vm2-1.qcow2 5G

注:创建空的磁盘文件:这里我们创建一个5G的磁盘,不过创建出来,通过ll -h查看大小,看不出它是5G,添加上之后才能看到
[root@kvm-server ~]# cd /etc/libvirt/qemu/
[root@kvm-server qemu]# vim vm3.xml

加好之后,启动虚拟机
[root@kvm-server qemu]# virsh define /etc/libvirt/qemu/vm3.xml
[root@kvm-server qemu]# systemctl restart libvirtd
[root@kvm-server qemu]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 6     centos7.0                      running
 -     vm3                            关闭
[root@kvm-server qemu]# virsh start vm3

可以看到我们新添加的磁盘vdb
然后可以正常分区,制作文件系统,进行挂载

补充方法:通过命令方式添加磁盘

提示:不论使用哪种方式,都需要先关闭虚拟机

创建磁盘
qemu-img create -f qcow2 /var/lib/libvirt/images/vm11-1.img 5G
添加磁盘
virsh attach-disk vm11 /var/lib/libvirt/images/vm11-1.img vdc --driver qemu --subdriver qcow2 --config

查看磁盘信息
[root@kvm-sever libvirt]# virsh domblklist vm11
Target     Source
------------------------------------------------
vda        /var/lib/libvirt/images/vm11.img
vdb        /var/lib/libvirt/images/vm11-1.img

虚拟机克隆

1.图形界面:Applications (左上角)-----> System Tools ------>Virtual Machine Manager
   关闭要克隆的虚拟机,右键点击虚拟机选择Clone

2.字符终端,命令克隆
[root@kvm-server ~]# virt-clone -o vm2 --auto-clone
正在分配 'vm2-clone.qcow2'                              | 5.0 GB  00:00     
成功克隆 'vm2-clone'-o       origin-原始
    
[root@kvm-server ~]# virt-clone -o vm2 -n vm5 --auto-clone
正在分配 'vm5.qcow2'                                    | 5.0 GB  00:00     
成功克隆 'vm5'-n :指定新客户机的名字
        
[root@kvm-server ~]# virt-clone -o vm2 -n vm6 -f /var/lib/libvirt/images/vm6.img 
正在分配 'vm6.img'                                      | 5.0 GB  00:00     
成功克隆 'vm6'-f ,--file NEW_DISKFILE:为新客户机使用新的磁盘镜像文件

这条命令在克隆的同时,可以指定镜像文件的位置和名称。

[root@kvm-server ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 -     vm2                            关闭
 -     vm2-clone                      关闭
 -     vm3                            关闭
 -     vm5                            关闭
 -     vm6                            关闭

kvm高级命令

建立虚拟机磁盘镜像文件:
磁盘镜像文件格式:
qed  ----不用了
    raw     原始格式,性能最好 直接占用你一开始给多少 系统就占多少 不支持快照
    qcow  先去网上了解一下cow(写时拷贝copy on write) ,性能远不能和raw相比,所以很快夭折了,所以出现了qcow2(性能低下 早就被抛弃)
    qcow2 性能上还是不如raw,但是raw不支持快照,qcow2支持快照。

现在默认安装好的用的是raw格式,做快照要把他转换成qcow2格式

什么叫写时拷贝?
raw立刻分配空间,不管你有没有用到那么多空间
qcow2只是承诺给你分配空间,但是只有当你需要用空间的时候,才会给你空间。最多只给你承诺空间的大小,避免空间浪费

工作当中用哪个?看你用不用快照。本身做快照也是需要存储空间的。
当然也不一定。数据绝对不会存储到本地。

[root@kvm-server images]# pwd
/var/lib/libvirt/images

建立qcow2格式磁盘文件:
[root@kvm-server images]# qemu-img create -f qcow2 test.img 5G
Formatting 'test.img', fmt=qcow2 size=5368709120 encryption=off cluster_size=65536 lazy_refcounts=off 

qemu-kvm  qemu是早先的一个模拟器,kvm是基于qemu发展出来的。

建立raw格式磁盘文件:
[root@kvm-server images]# qemu-img create -f raw test.raw 5G
Formatting 'test.raw', fmt=raw size=5368709120 

查看已经创建的虚拟磁盘文件:
[root@kvm-server images]# qemu-img info test.img 
[root@kvm-server images]# qemu-img info test.raw 

=============================================================================
挂载磁盘

将vm2虚拟机先关闭
查看vm2的磁盘镜像分区信息:
[root@kvm-server images]# virt-df -h -d vm2
文件系统                                  大小      已用空间    可用空间     使用百分比%
vm2:/dev/sda1                            1014M        92M       922M         10%
vm2:/dev/centos/root                      3.5G       863M       2.6G         25%

1.创建一个挂载目录
[root@kvm-server images]# mkdir /test
2.挂载虚拟机的跟分区到test目录
[root@kvm-server images]# guestmount -d vm2 -m /dev/centos/root --rw /test/
[root@kvm-server images]# cd /test/
[root@kvm-server test]# ls
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var
boot  etc  lib   media  opt  root  sbin  sys  usr
[root@kvm-server test]# cat etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:997:User for polkitd:/:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

取消挂载
[root@kvm-server ~]# guestunmount /test

KVM网络配置

两种网络

nat与isolate()
NAT default方式:支持主机与虚拟机互访,虚拟机访问外界网络,但不支持外界访问虚拟机。
isolate 隔离,host-host-only:仅主机模式。外网不能访问虚拟机,虚拟机也不能访问外网

一种接口

bridge桥接

nat网络

桥接网络

隔离网络

可以通过查看mac地址是否一致来确定是不是一根线上的两个接口
[root@kvm-server ~]# brctl show 
bridge name	bridge id		STP enabled	interfaces
virbr0		8000.525400831963	yes		virbr0-nic
							           vnet0
							           vnet1

注意:这里vnet网卡,是每台启动的虚拟机正在使用的网卡设备,每台虚拟机使用的不同						                             					                             
从交换机上把vnet网卡删除:
    [root@kvm-server ~]# brctl delif virbr0 vnet0

来到vm2的虚拟机,ping不通百度

添加vnet网卡添加到交换机上:
[root@kvm-server ~]# brctl addif virbr0 vnet0
	
来到vm2的虚拟机,恢复正常

配置文件方式配置桥接:在宿主机上

先将kvm虚拟机关闭

配置文件方式配置桥接:在宿主机上
[root@kvm-server ~]# ip a   #先找出宿主机用的哪个网卡设备,我的是enp0s25
[root@kvm-server ~]# cd /etc/sysconfig/network-scripts/
1.定义网卡配置文件
[root@kvm-server network-scripts]# vim ifcfg-br0    #没有此文件新建
[root@kvm-server network-scripts]# cat ifcfg-br0
TYPE=Bridge
NAME=br0
DEVICE=br0
ONBOOT="yes"
BOOTPROTO=static
IPADDR=10.0.111.182   #宿主的ip
GATEWAY=10.0.111.1    #宿主的网关
NETMASK=255.255.255.0
DNS1=114.144.144.144
DNS2=8.8.8.8

然后看清楚宿主机正在使用的网卡,修改配置文件
[root@kvm-server network-scripts]# cp ifcfg-enp0s25 ifcfg-enp0s25.back
[root@kvm-server network-scripts]# vim ifcfg-enp0s25
NAME=enp0s25   #定义网卡设备名称
DEVICE=enp0s25   #宿主机正在使用的网卡设备
ONBOOT=yes
BRIDGE=br0     #和ifcfg-br0文件里面的设备对应,新添加

2.重启libvirtd服务
[root@kvm-server network-scripts]# systemctl restart libvirtd 
3.重启network服务 
[root@kvm-server network-scripts]# systemctl restart network
# 虚拟机使用桥接: 文本模式
vim 编辑虚拟机配置文件
    <interface type='bridge'>
      <mac address='52:54:00:2e:c1:7a'/>
      <source bridge='br0'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>

然后去查看有没有新设备生成

可以看到,我们先添加的网卡设备

移除操作

删除桥接网卡步骤:
1.删除br0的配置文件
2.修改正常网卡的配置文件
3.重启系统

[root@kvm-server network-scripts]# mv ifcfg-br0 ifcfg-br0.bak
[root@kvm-server network-scripts]# mv ifcfg-enp0s25 ifcfg-enp0s25.bak
[root@kvm-server network-scripts]# mv ifcfg-enp0s25.back ifcfg-enp0s25
[root@kvm-server network-scripts]# systemctl restart libvirtd
[root@kvm-server network-scripts]# systemctl restart network
[root@kvm-server network-scripts]# ping www.baidu.com
PING www.a.shifen.com (39.156.66.14) 56(84) bytes of data.
64 bytes from 39.156.66.14 (39.156.66.14): icmp_seq=1 ttl=52 time=13.3 ms

配置文件方式创建nat网络:

配置文件方式创建nat网络:
[root@kvm-server ~]# cd /etc/libvirt/qemu/networks
[root@kvm-server networks]# ls
autostar default.xml
[root@kvm-server networks]# cp default.xml nat1.xml
[root@kvm-server networks]# vim nat1.xml

重启服务

[root@kvm-server netwoeks]# systemctl  restart libvirtd

在某个(比如vm3)虚拟机去添加此设备测试

配置文件方式创建isolated网络(host-only):host-only模式我从来没用过,我们不再操作,有兴趣可以操作一下   
[root@kvm-server networks]# cp default.xml isolated200.xml
[root@kvm-server networks]# vim isolated200.xml

启动:
[root@kvm-server networks]# systemctl restart libvirtd
开机自启动:
[root@kvm-server networks]# virsh net-autostart  isolated200

查看所有的网络:
[root@kvm-server networks]# virsh net-list

KVM存储配置

存储池
概念:
    kvm必须要配置一个目录当作他存储磁盘镜像(存储卷)的目录,我们称这个目录为存储池
    
kvm默认存储池的位置:
    /var/lib/libvirt/images/    

1.创建基于文件夹的存储池(目录,可自定义)
[root@kvm-server ~]# mkdir -p /data/vmfs

2.定义存储池与其目录
[root@kvm-server ~]# virsh pool-define-as vmdisk --type dir --target /data/vmfs
Pool vmdisk defined
解释:vmdisk是新建的存储池的名称。可自定义

3.创建已定义的存储池
(1)创建已定义的存储池
[root@kvm-server ~]# virsh pool-build vmdisk
Pool vmdisk built

(2)查看已定义的存储池,存储池不激活无法使用。
[root@kvm-server ~]# virsh pool-list --all
Name                 State      Autostart 
-------------------------------------------
 default              active     yes       
 ISO                 active     yes       
 vmdisk               inactive   no     

4.激活并自动启动已定义的存储池
[root@kvm-server ~]# virsh pool-start vmdisk
Pool vmdisk started
[root@kvm-server ~]# virsh pool-autostart vmdisk
Pool vmdisk marked as autostarted

[root@kvm-server ~]# virsh pool-list --all
 Name                 State      Autostart 
-------------------------------------------
 default              active     yes       
 ISO                 active     yes       
 vmdisk               active     yes   
这里vmdisk存储池就已经创建好了,可以直接在这个存储池中创建虚拟磁盘文件了。

5.在存储池中创建虚拟机存储卷
[root@kvm-server ~]# virsh vol-create-as vmdisk vm99.qcow2 2G --format qcow2
Vol vm99.qcow2 created


[root@kvm-server ~]# ll /data/vmfs/ -h
总用量 196K
-rw------- 1 root root 193K 1025 16:04 vm99.qcow2

注1:KVM存储池主要是体现一种管理方式,可以通过挂载存储目录,lvm逻辑卷的方式创建存储池,虚拟机存储卷创建完成后,剩下的操作与无存储卷的方式无任何区别了。
注2:KVM存储池也要用于虚拟机迁移任务。

6.存储池相关管理命令
(1)在存储池中删除虚拟机存储卷
[root@kvm-server ~]# virsh vol-delete --pool vmdisk vm99.qcow2
Vol vm99.qcow2 deleted

(2)取消激活存储池
[root@kvm-server ~]# virsh pool-destroy vmdisk
Pool vmdisk destroyed

(3)删除存储池定义的目录/data/vmfs
[root@kvm-server ~]# virsh pool-delete vmdisk
Pool vmdisk deleted

(4)取消定义存储池
[root@kvm-server ~]# virsh pool-undefine vmdisk
Pool vmdisk has been undefined

到此kvm存储池配置与管理操作完毕。

kvm快照

为虚拟机vm2创建一个快照(磁盘格式必须为qcow2)
[root@kvm-server ~]# virsh snapshot-create-as vm2 vm2.snap1


注意:如果在创建快照的时候报错:
error: unsupported configuration: internal snapshot for disk vda unsupported for storage type raw

raw
使用文件来模拟实际的硬盘(当然也可以使用一块真实的硬盘或一个分区)。由于原生的裸格式,不支持snapshot也是很正常的。

qcow2
现在比较主流的一种虚拟化镜像格式,经过一代的优化,目前qcow2的性能上接近raw裸格式的性能,这个也算是redhat的官方渠道了
对于qcow2的格式,几点还是比较突出的:
	•更小的存储空间
	•支持多个snapshot,对历史snapshot进行管理
查看磁盘文件格式
[root@kvm-server images]# qemu-img info /var/lib/libvirt/images/vm2.qcow2
image: /var/lib/libvirt/images/vm2.qcow2
file format: qcow2
virtual size: 5.0G (5368709120 bytes)
disk size: 5.0G
cluster_size: 65536
Format specific information:
    compat: 1.1
    lazy refcounts: true

[root@kvm-server ~]# virsh snapshot-list  vm2   #查看某台虚拟机设备的快照
 Name                 Creation Time             State
------------------------------------------------------------

创建一块磁盘
[root@kvm-server ~]# qemu-img create -f raw /var/lib/libvirt/images/vm2-1.raw 2G
Formatting '/var/lib/libvirt/images/vm2-1.raw', fmt=raw size=2147483648 

[root@kvm-server ~]# ll -h /var/lib/libvirt/images/vm2-1.raw
-rw-r--r-- 1 root root 2.0G 1025 16:25 /var/lib/libvirt/images/vm2-1.raw

将其添加到vm2虚拟机上面
[root@kvm-server ~]# cd /etc/libvirt/qemu/
[root@kvm-server qemu]# vim vm2.xml

[root@kvm-server images]# virsh define /etc/libvirt/qemu/vm2.xml
[root@kvm-server images]# virsh start vm2
[root@kvm-server qemu]# virsh snapshot-create-as vm2 vm2.snap1
错误:不支持的配置:存储类型 vdb 不支持磁盘 raw 的内部快照



磁盘格式的转换
由于raw的磁盘格式,不支持快照功能,我们需要将其转换为qcow2的格式
[root@kvm-server qemu]# qemu-img convert -O qcow2 /var/lib/libvirt/images/vm2-1.raw  /var/lib/libvirt/images/vm2-1.qcow2

[root@kvm-server qemu]# cd /var/lib/libvirt/images/
[root@kvm-server images]# ll -h 
总用量 21G
-rw------- 1 root root 5.1G 1024 18:59 centos7.0.qcow2
-rw-r--r-- 1 root root 193K 1025 16:44 vm2-1.qcow2
-rw-r--r-- 1 root root 2.0G 1025 16:25 vm2-1.raw
-rw------- 1 root root 5.1G 1025 16:13 vm2.qcow2


[root@kvm-server images]# qemu-img info /var/lib/libvirt/images/vm2-1.qcow2
image: /var/lib/libvirt/images/vm2-1.qcow2
file format: qcow2
virtual size: 2.0G (2147483648 bytes)
disk size: 196K
cluster_size: 65536
Format specific information:
    compat: 1.1
    lazy refcounts: false


然后去修改vm2虚拟机的磁盘格式和名称
[root@kvm-server images]# vim /etc/libvirt/qemu/vm2.xml

[root@kvm-server images]# virsh define /etc/libvirt/qemu/vm2.xml

创建快照
[root@kvm-server qemu]# virsh snapshot-create-as vm2 vm2.snap2
已生成域快照 vm2.snap2

然后我们开始做快照,图形化方式不再介绍

登录vm2的虚拟机:
[root@vm2 ~]# mkdir /opt/test
[root@kvm-server ~]# virsh snapshot-create-as vm2 vm2-snap3
已生成域快照 vm2-snap3

再次登录vm2的虚拟:
[root@vm2 ~]# rm -rf /opt/test/
[root@kvm-server ~]# virsh shutdown vm2
[root@kvm-server ~]# virsh snapshot-create-as vm2 vm2-snap4
已生成域快照 vm2-snap4

查看快照
[root@kvm-server ~]# virsh snapshot-list vm2 
 名称               生成时间              状态
------------------------------------------------------------
 vm2-snap3            2019-10-30 15:27:15 +0800 running
 vm2-snap4            2019-10-30 15:29:37 +0800 shutoff

然后将vm2关闭,恢复到快照vm2.snap3
[root@kvm-server ~]# virsh snapshot-revert vm2 vm2-snap3
[root@kvm-server ~]# virsh start vm2
Domain vm2 started

在vm2虚拟机上查看
[root@vm2 ~]# ls /opt/
test
可以再恢复到vm2.snap4测试一下

删除虚拟机快照操作:
[root@kvm-server ~]# virsh shutdown vm2
[root@kvm-server ~]# virsh snapshot-list vm2
 名称               生成时间              状态
------------------------------------------------------------
 vm2-snap3            2019-10-30 15:27:15 +0800 running
 vm2-snap4            2019-10-30 15:29:37 +0800 shutoff

[root@kvm-server ~]# virsh snapshot-delete --snapshotname vm2-snap3 vm2
已删除域快照 vm2-snap3

[root@kvm-server ~]# virsh snapshot-list vm2
 名称               生成时间              状态
------------------------------------------------------------
 vm2-snap4            2019-10-30 15:27:15 +0800 running

kvm迁移(了解)

最简单的方法:
拷贝配置文件,磁盘
热迁移

			  192.168.1.1/24	            192.168.1.2/24
				++++++++++++            	++++++++++++
				+			+			    +		    +		
				+    KVM-A  +  =======>     +	KVM-B 	+
				+	    	+			    +	        +	
				++++++++++++				++++++++++++
			images                              images
		/var/lib/libvirt/images	          /var/lib/libvirt/images

自动化脚本管理kvm(留时间给大家写)

#!/bin/bash
#kvm batch create vm tool
#version:0.1
#author:name
#需要事先准备模板镜像和配置文件模板
echo "1.创建自定义配置单个虚拟机
2.批量创建自定义配置虚拟机
3.批量创建默认配置虚拟机
4.删除虚拟机"

read -p "选取你的操作(1/2/3):" op

batch_self_define() {

        kvmname=`openssl rand -hex 5`

        sourceimage=/var/lib/libvirt/images/vmmodel.img
        sourcexml=/etc/libvirt/qemu/vmmodel.xml

        newimg=/var/lib/libvirt/images/${kvmname}.img
        newxml=/etc/libvirt/qemu/${kvmname}.xml

        cp $sourceimage  $newimg
        cp $sourcexml $newxml

        kvmuuid=`uuidgen`
        kvmmem=${1}000000
        kvmcpu=$2
        kvmimg=$newimg
        kvmmac=`openssl rand -hex 3 | sed -r 's/..\B/&:/g'`

        sed -i "s@kvmname@$kvmname@;s@kvmuuid@$kvmuuid@;s@kvmmem@$kvmmem@;s@kvmcpu@$kvmcpu@;s@kvmimg@$kvmimg@;s@kvmmac@$kvmmac@" $newxml
        virsh define $newxml
        virsh list --all
}
self_define() {
        read -p "请输入新虚机名称:" newname
        read -p "请输入新虚机内存大小(G):" newmem
        read -p "请输入新虚机cpu个数:" newcpu

        sourceimage=/var/lib/libvirt/images/vmmodel.img
        sourcexml=/etc/libvirt/qemu/vmmodel.xml

        newimg=/var/lib/libvirt/images/${newname}.img
        newxml=/etc/libvirt/qemu/${newname}.xml

        cp $sourceimage  $newimg
        cp $sourcexml $newxml

        kvmname=$newname
        kvmuuid=`uuidgen`
        kvmmem=${newmem}000000
        kvmcpu=$newcpu
        kvmimg=$newimg
        kvmmac=`openssl rand -hex 3 | sed -r 's/..\B/&:/g'`

        sed -i "s@kvmname@$kvmname@;s@kvmuuid@$kvmuuid@;s@kvmmem@$kvmmem@;s@kvmcpu@$kvmcpu@;s@kvmimg@$kvmimg@;s@kvmmac@$kvmmac@" $newxml
        virsh define $newxml
        virsh list --all
}

case $op in
1)self_define;;
2)
        read -p "请输入要创建的虚拟机的个数:" num
        read -p "请输入新虚机内存大小(G):" newmem
        read -p "请输入新虚机cpu个数:" newcpu

        for((i=1;i<=$num;i++))
        do
                batch_self_define $newmem $newcpu
        done;;

3)
        read -p "请输入要创建的虚拟机的个数:" num

        for((i=1;i<=$num;i++))
        do
                batch_self_define 1 1
        done;;

*)echo "输入错误,请重新执行脚本"
  exit;;
esac

配置文件模板

# vim /etc/libvirt/qemu/vmmodel.xml
<domain type='kvm'>
  <name>kvmname</name>
  <uuid>kvmuuid</uuid>
  <memory unit='KiB'>kvmmem</memory>
  <currentMemory unit='KiB'>kvmmem</currentMemory>
  <vcpu placement='static'>kvmcpu</vcpu>
  <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='partial'>
    <model fallback='allow'>Haswell-noTSX</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>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='kvmimg'/>
      <target dev='vda' bus='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
    </disk>
    <controller type='usb' index='0' model='ich9-ehci1'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x7'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci1'>
      <master startport='0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0' multifunction='on'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci2'>
      <master startport='2'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x1'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci3'>
      <master startport='4'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x2'/>
    </controller>
    <controller type='pci' index='0' model='pci-root'/>
    <controller type='virtio-serial' index='0'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
    </controller>
    <interface type='network'>
      <mac address='52:54:00:kvmmac'/>
      <source network='default'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
    <serial type='pty'>
      <target type='isa-serial' port='0'>
        <model name='isa-serial'/>
      </target>
    </serial>
    <console type='pty'>
      <target type='serial' port='0'/>
    </console>
    <channel type='unix'>
      <target type='virtio' name='org.qemu.guest_agent.0'/>
      <address type='virtio-serial' controller='0' bus='0' port='1'/>
    </channel>
    <input type='mouse' bus='ps2'/>
    <input type='keyboard' bus='ps2'/>
    <memballoon model='virtio'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
    </memballoon>
  </devices>
</domain>

随机生成mac地址

其中方式如下:
# echo `openssl rand -hex 1`:`openssl rand -hex 1`:`openssl rand -hex 1`
99:6e:67

# openssl rand -hex 3 | sed -r 's/(..)(..)(..)/\1:\2:\3/g'
94:89:e3

# openssl rand -hex 3 | sed -r 's/..\B/&:/g'
c5:66:90

Centos设置输入法

虚拟机开启虚拟化无法启动

http://www.win7zhijia.cn/win10jc/win10_20680.html

kvm 无法安装虚拟机解决

1、查看安装的kvm主包

2、出现异常解决办法

方法1、
将问题包[带有ev的包卸载掉],然后重新安装,但是这里存在一个问题,可能在重装的时候还是会将ev的包进行安装,这时候我们选择第二种方法

方法2、
使用文档上面的卸载语句将kvm全部卸载
[root@kvm-server ~]# yum remove `rpm -qa | egrep 'qemu|virt|kvm'` -y
[root@kvm-server ~]# rm -rf /var/lib/libvirt  /etc/libvirt/
然后重新安装kvm,并检查是否带有ev字样。

随机

KVM

image-20240618100339099
  • 1、启用关闭windows功能
    取消勾选
    hyper-v
    windows虚拟机平台
    虚拟机监控平台
    支持linux的windows子系统
    2、打开防火墙配置
    内核隔离-关闭
    3、管理员权限执行
    bcdedit /set hypervisorlaunchtype off
  • 进去之后可能遇到image-20240618143700764
  • pkill -9 yum
  • 关闭防火墙 和· selinux
  • [root@kvm-server ~]# yum install -y librbd1-devel qemu-kvm libvirt virt-manager virt-install
  • 下载一些依赖

三种创建小小虚拟机方法

第一种:点点点

然后windterm也可以实现image-20240618145640725

第二种:ftp 完全命令行
  • [!]需要修改
  • [x]是不需要设置的
  • 如果到最后面了还有一个叹号(就需要进去再出来)
  • 成功进入系统之后,想退出来和docker很像 ctrl+] 即可退到宿主机(退出不关闭)
第三种:模板镜像+配置文件 方式安装虚拟机—需要掌握

image-20240618194950426

用vim修改完之后需要define一下配置文件
[root@kvm-server ~]# virsh define /etc/libvirt/qemu/vm3.xml
重启一下:
[root@kvm-server ~]# systemctl restart libvirtd
宿主机开启路由转发:
[root@kvm-server ~]# vim /etc/sysctl.conf
[root@kvm-server ~]# sysctl -p

net.ipv4.ip_forward = 1

查看虚拟机列表:
[root@kvm-server ~]# virsh list --all

Id 名称 状态

  • vm2                            关闭
    
  • vm3                            关闭
    
第四种:克隆方式

virsh 常用操作

virsh list --all == docker ps 查看

virsh start vmname 启动

virsh shutdown vmname 关闭

virsh reboot vmname 重启

virsh suspend vmname 挂起

virsh resume vmname 恢复

virsh destroy vmname 强制关闭

virsh reset vmname 重置(强制关闭再启动)

virsh define 配置文件路径 (定义虚拟器)

virsh undefine vmname (取消定义)

virsh dumpxml vmname 查看看小小虚拟机配置文件

virsh autostart --disable vmname 开机启动 开机关闭 加上 --disable

virsh domifaddr vmname 查看虚拟机地址

virsh console vmname 进入虚拟机

virsh dumpxml vmname 查看小小虚拟机的配置文件

添加磁盘

第一种:点点点
第二种:修改配置文件
第三种:先创建磁盘大小

虚拟机就是两个配置文件构成的,使用undefine即可,如果想要直接删掉那两个文件,理论上是可以的,但是会有一个问题,删除之后不知道会不会显示,不确定会不会有缓存·

image-20240619005328976

什么叫写时拷贝?
raw立刻分配空间,不管你有没有用到那么多空间
qcow2只是承诺给你分配空间,但是只有当你需要用空间的时候,才会给你空间。最多只给你承诺空间的大小,避免空间浪费

镜像格式

raw

直接分配资源全部,会有资源的浪费,但是效率高

qcow(前身)
qcow2(写时拷贝)

用多少占多少,效率相对低一点

查看格式

qemu-img info vm.img

image-20240619010405376

网络配置

  • brctl show 查看nat网络
  • brctl delif virbr0 vnet0 删除网络 小小虚拟机就ping不通了
  • brctl addif virbr0 vnet0 就加回来了
创建桥接模式

配置文件方式配置桥接:在宿主机上

先将kvm虚拟机关闭

配置文件方式配置桥接:在宿主机上
[root@kvm-server ~]# ip a   #先找出宿主机用的哪个网卡设备,我的是enp0s25
[root@kvm-server ~]# cd /etc/sysconfig/network-scripts/
1.定义网卡配置文件
[root@kvm-server network-scripts]# vim ifcfg-br0    #没有此文件新建
[root@kvm-server network-scripts]# cat ifcfg-br0
TYPE=Bridge
NAME=br0
DEVICE=br0
ONBOOT="yes"
BOOTPROTO=static
IPADDR=10.0.111.182   #宿主的ip
GATEWAY=10.0.111.1    #宿主的网关
NETMASK=255.255.255.0
DNS1=114.144.144.144
DNS2=8.8.8.8

然后看清楚宿主机正在使用的网卡,修改配置文件
[root@kvm-server network-scripts]# cp ifcfg-enp0s25 ifcfg-enp0s25.back
[root@kvm-server network-scripts]# vim ifcfg-enp0s25
NAME=enp0s25   #定义网卡设备名称
DEVICE=enp0s25   #宿主机正在使用的网卡设备
ONBOOT=yes
BRIDGE=br0     #和ifcfg-br0文件里面的设备对应,新添加

2.重启libvirtd服务
[root@kvm-server network-scripts]# systemctl restart libvirtd 
3.重启network服务 
[root@kvm-server network-scripts]# systemctl restart network
# 虚拟机使用桥接: 文本模式
vim 编辑虚拟机配置文件
    <interface type='bridge'>
      <mac address='52:54:00:2e:c1:7a'/>
      <source bridge='br0'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>

然后去查看有没有新设备生成

存储

定义磁盘的存储位置

快照

建议关机后打快照比较快

开机也可以,但是慢一点

[root@kvm-server ~]# virsh snapshot-create-as vm2 vm2-snap3

[root@kvm-server ~]# virsh snapshot-revert vm2 vm2-snap3

virsh snapshot-delete --snapshotname vm2-snap3 vm2

  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值