1. 虚拟化介绍
虚拟化是云计算的基础。简单的说,虚拟化使得在一台物理的服务器上可以跑多台虚拟机,虚拟机共享物理机的 CPU、内存、IO 硬件资源,但逻辑上虚拟机之间是相互隔离的。
物理机我们一般称为宿主机(Host),宿主机上面的虚拟机称为客户机(Guest)。
那么 Host 是如何将自己的硬件资源虚拟化,并提供给 Guest 使用的呢?
这个主要是通过一个叫做 Hypervisor 的程序实现的。
根据 Hypervisor 的实现方式和所处的位置,虚拟化又分为两种:
- 全虚拟化
- 半虚拟化
全虚拟化:
Hypervisor 直接安装在物理机上,多个虚拟机在 Hypervisor 上运行。Hypervisor 实现方式一般是一个特殊定制的 Linux 系统。Xen 和 VMWare 的 ESXi 都属于这个类型
半虚拟化:
物理机上首先安装常规的操作系统,比如 Redhat、Ubuntu 和 Windows。Hypervisor 作为 OS 上的一个程序模块运行,并对管理虚拟机进行管理。KVM、VirtualBox 和 VMWare Workstation 都属于这个类型
理论上讲:
全虚拟化一般对硬件虚拟化功能进行了特别优化,性能上比半虚拟化要高;
半虚拟化因为基于普通的操作系统,会比较灵活,比如支持虚拟机嵌套。嵌套意味着可以在KVM虚拟机中再运行KVM。
2. kvm介绍
kVM 全称是 Kernel-Based Virtual Machine。也就是说 KVM 是基于 Linux 内核实现的。
KVM有一个内核模块叫 kvm.ko,只用于管理虚拟 CPU 和内存。
那 IO 的虚拟化,比如存储和网络设备则是由 Linux 内核与Qemu来实现。
作为一个 Hypervisor,KVM 本身只关注虚拟机调度和内存管理这两个方面。IO 外设的任务交给 Linux 内核和 Qemu。
大家在网上看 KVM 相关文章的时候肯定经常会看到 Libvirt 这个东西。Libvirt 就是 KVM 的管理工具。
其实,Libvirt 除了能管理 KVM 这种 Hypervisor,还能管理 Xen,VirtualBox 等。
Libvirt 包含 3 个东西:后台 daemon 程序 libvirtd、API 库和命令行工具 virsh
- libvirtd是服务程序,接收和处理 API 请求;
- API 库使得其他人可以开发基于 Libvirt 的高级工具,比如 virt-manager,这是个图形化的 KVM 管理工具;
- virsh 是我们经常要用的 KVM 命令行工具
环境说明
系统类型 | IP |
---|---|
RedHat 8 | 192.168.152.135 |
3. Kvm安装
部署前请确保你的CPU虚拟化功能已开启。分为两种情况:
- 虚拟机要关机设置CPU虚拟化
- 物理机要在BIOS里开启CPU虚拟化
设置虚拟机的内存和内核运行
//配置网络源
//关闭防火墙和seLinux
//安装依赖包
[root@localhost ~]# yum -y install epel-release vim wget net-tools unzip zip gcc gcc-c++
安装过程略...
//验证CPU是否支持KVM;如果结果中有vmx(Intel)或svm(AMD)字样,就说明CPU的支持
[root@localhost ~]# egrep -o 'vmx|svm' /proc/cpuinfo
svm
svm
svm
svm
//kvm安装
[root@localhost ~]# yum -y install qemu-kvm qemu-img virt-manager libvirt libvirt-client virt-install virt-viewer libguestfs-tools
[root@localhost ~]# wget http://mirror.centos.org/centos/7/updates/x86_64/Packages/qemu-kvm-tools-1.5.3-175.el7_9.1.x86_64.rpm
[root@localhost ~]# wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libvirt-python-4.5.0-1.el7.x86_64.rpm
[root@localhost ~]# wget http://mirror.centos.org/centos/7/os/x86_64/Packages/bridge-utils-1.5-9.el7.x86_64.rpm
[root@localhost ~]# rpm -ivh --nodeps qemu-kvm-tools-1.5.3-175.el7_9.1.x86_64.rpm
[root@localhost ~]# yum -y localinstall bridge-utils-1.5-9.el7.x86_64.rpm
[root@localhost ~]# yum -y localinstall libvirt-python-4.5.0-1.el7.x86_64.rpm
//因为虚拟机中网络,我们一般都是和公司的其他服务器是同一个网段,
所以我们需要把KVM服务器的网卡配置成桥接模式。
这样的话KVM的虚拟机就可以通过该桥接网卡和公司内部其他服务器处于同一网段
//此处我的网卡是ens160,所以用br0来桥接ens160网卡
[root@localhost ~]# cd /etc/sysconfig/network-scripts/
[root@localhost network-scripts]# ls
ifcfg-ens160
[root@localhost network-scripts]# cp ifcfg-ens160 ifcfg-br0
[root@localhost network-scripts]# ls
ifcfg-br0 ifcfg-ens160
[root@localhost network-scripts]# cat ifcfg-br0
TYPE=Bridge
BOOTPROTO=static
NAME=br0
DEVICE=br0
ONBOOT=yes
IPADDR=192.168.152.135
NETMASK=255.255.255.0
GATEWAY=192.168.152.2
DNS1=114.114.114.114
[root@localhost network-scripts]# cat ifcfg-ens160
TYPE=Ethernet
BOOTPROTO=static
BRIDGE=br0
NAME=ens160
DEVICE=ens160
ONBOOT=yes
//重启网卡
[root@localhost ~]# systemctl restart NetworkManager
[root@localhost ~]# ifdown ens160;ifup ens160
[root@localhost network-scripts]# ifdown br0;ifup br0
[root@localhost ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master br0 state UP group default qlen 1000
link/ether 00:0c:29:5c:c3:18 brd ff:ff:ff:ff:ff:ff
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:0c:29:5c:c3:18 brd ff:ff:ff:ff:ff:ff
inet 192.168.152.135/24 brd 192.168.152.255 scope global noprefixroute br0
valid_lft forever preferred_lft forever
inet6 fe80::b0ed:49ff:fe9e:241c/64 scope link
valid_lft forever preferred_lft forever
//libvirtd设置开机自启服务
[root@localhost ~]# systemctl enable --now libvirtd
[root@localhost ~]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:111 0.0.0.0:*
LISTEN 0 32 192.168.122.1:53 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 0.0.0.0:5355 0.0.0.0:*
LISTEN 0 128 [::]:111 [::]:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 128 [::]:5355 [::]:*
//检验安装结果
[root@localhost ~]# lsmod|grep kvm
kvm_amd 110592 0
ccp 98304 1 kvm_amd
kvm 753664 1 kvm_amd
irqbypass 16384 1 kvm
//检测并验证安装结果
[root@localhost ~]# virsh -c qemu:///system list
Id Name State
----------------------------------------------------
[root@localhost ~]# virsh --version
4.5.0
[root@localhost ~]# virt-install --version
2.2.1
[root@localhost ~]# ln -s /usr/libexec/qemu-kvm /usr/bin/qemu-kvm
[root@localhost ~]# ll /usr/bin/qemu-k
qemu-keymap qemu-kvm
[root@localhost ~]# ll /usr/bin/qemu-kvm
lrwxrwxrwx 1 root root 21 Dec 1 18:42 /usr/bin/qemu-kvm -> /usr/libexec/qemu-kvm
[root@localhost ~]# lsmod |grep kvm
kvm_amd 110592 0
ccp 98304 1 kvm_amd
kvm 753664 1 kvm_amd
irqbypass 16384 1 kvm
[root@localhost ~]# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.000c295cc318 no ens160
virbr0 8000.5254002c81fe yes virbr0-nic
4. kvm web管理界面安装
kvm 的 web 管理界面是由 webvirtmgr 程序提供的。
//安装依赖包
[root@localhost ~]# wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libxml2-python-2.9.1-6.el7.5.x86_64.rpm
[root@localhost ~]# wget https://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/p/python-websockify-0.6.0-2.el7.noarch.rpm
[root@localhost ~]# yum -y install python2-devel python2-pip git libvirt-python supervisor nginx
[root@localhost ~]# rpm -ivh --nodeps libxml2-python-2.9.1-6.el7.5.x86_64.rpm
[root@localhost ~]# rpm -ivh --nodeps python-websockify-0.6.0-2.el7.noarch.rpm
//升级pip
[root@localhost ~]# pip2 install --upgrade pip
WARNING: Running pip install with root privileges is generally not a good idea. Try `pip2 install --user` instead.
100% |████████████████████████████████| 1.5MB 62kB/s
Installing collected packages: pip
Found existing installation: pip 9.0.3
Uninstalling pip-9.0.3:
Successfully uninstalled pip-9.0.3
Successfully installed pip-20.3
//从github上下载webvirtmgr代码
[root@localhost ~]# cd /usr/local/src/
[root@localhost src]# ls
[root@localhost src]# git clone git://github.com/retspen/webvirtmgr.git
Cloning into 'webvirtmgr'...
remote: Enumerating objects: 5614, done.
remote: Total 5614 (delta 0), reused 0 (delta 0), pack-reused 5614
Receiving objects: 100% (5614/5614), 2.98 MiB | 108.00 KiB/s, done.
Resolving deltas: 100% (3602/3602), done.
[root@Kvm132 src]# ls
webvirtmgr
//安装webvirtmgr
[root@localhost src]# cp -r webvirtmgr{,-bak} //备份
[root@localhost src]# ls
webvirtmgr webvirtmgr-bak
[root@localhost webvirtmgr]# pip2 install -r requirements.txt
DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support pip 21.0 will remove support for this functionality.
Collecting django==1.5.5
Downloading Django-1.5.5.tar.gz (8.1 MB)
|████████████████████████████████| 8.1 MB 309 kB/s
Collecting gunicorn==19.5.0
Downloading gunicorn-19.5.0-py2.py3-none-any.whl (113 kB)
|████████████████████████████████| 113 kB 347 kB/s
Collecting lockfile>=0.9
Downloading lockfile-0.12.2-py2.py3-none-any.whl (13 kB)
Using legacy 'setup.py install' for django, since package 'wheel' is not installed.
//检查sqlite3是否安装
[root@Kvm132 src]# python2
Python 2.7.17 (default, Jun 5 2020, 03:38:32)
[GCC 8.3.1 20191121 (Red Hat 8.3.1-5)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlite3 //此处没有报错就表示成功
>>> exit()
//初始化账号信息
[root@localhost webvirtmgr]# python2 manage.py syncdb
WARNING:root:No local_settings file found.
Creating tables ...
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_groups
Creating table auth_user_user_permissions
Creating table auth_user
Creating table django_content_type
Creating table django_session
Creating table django_site
Creating table servers_compute
Creating table instance_instance
Creating table create_flavor
You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): yes //是否创建超级管理员帐号
Username (leave blank to use 'root'): admin //指定超级管理员帐号用户名,默认留空为root
Email address: 1@2.com //管理员邮箱
Password: //输入密码
Password (again): //再次输入密码
Superuser created successfully.
Installing custom SQL ...
Installing indexes ...
Installed 6 object(s) from 1 fixture(s)
//拷贝web网页至指定目录
[root@localhost ~]# mkdir /var/www
[root@localhost ~]# cp -r /usr/local/src/webvirtmgr /var/www/
[root@localhost ~]# chown -R nginx.nginx /var/www/webvirtmgr/
[root@localhost ~]# ll /var/www/
total 4
drwxr-xr-x 20 nginx nginx 4096 Dec 1 19:05 webvirtmgr
//生成密钥
[root@localhost ~]# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:qr73VX7piF5EPVP0ddVib1G0vQACcTX8cHcrEl0WkMA root@localhost.localdomain
The key's randomart image is:
+---[RSA 3072]----+
| ooo+=o.+*&|
| . .Eo=++O|
| *o=+*|
| o o.++|
| S + .o |
| . + . |
| . . o o |
| .. . o + |
| .+o ...o . . |
+----[SHA256]-----+
//由于这里webvirtmgr和kvm服务部署在同一台机器,所以这里本地信任。如果kvm部署在其他机器,那么这个是它的ip
[root@localhost ~]# ssh-copy-id 192.168.152.135
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
authenticity of host '192.168.152.135 (192.168.152.135)' can't be established.
ECDSA key fingerprint is SHA256:Tn9uio7GeWfMbUauL3IqLznnH7BPKIud6/VgjYwncas.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.152.135's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh '192.168.152.135'"
and check to make sure that only the key(s) you wanted were added.
[root@localhost ~]# ls .ssh/
authorized_keys id_rsa id_rsa.pub known_hosts
//配置端口转发
[root@localhost ~]# ssh 192.168.152.135 -L localhost:8000:localhost:8000 -L localhost:6080:localhost:60
Last login: Tue Dec 1 18:43:55 2020 from 192.168.152.1
[root@localhost ~]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:111 0.0.0.0:*
LISTEN 0 32 192.168.122.1:53 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 127.0.0.1:6080 0.0.0.0:*
LISTEN 0 128 127.0.0.1:8000 0.0.0.0:*
LISTEN 0 128 0.0.0.0:5355 0.0.0.0:*
LISTEN 0 128 [::]:111 [::]:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 128 [::1]:6080 [::]:*
LISTEN 0 128 [::1]:8000 [::]:*
LISTEN 0 128 [::]:5355 [::]:*
//配置nginx
[root@localhost ~]# cat > /etc/nginx/nginx.conf <<'EOF'
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';>
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
server_name localhost;
include /etc/nginx/default.d/*.conf;
location / {
root html;
index index.html index.htm;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
EOF
[root@localhost ~]# cat > /etc/nginx/conf.d/webvirtmgr.conf <<'EOF'
server {
listen 80 default_server;
server_name $hostname;
#access_log /var/log/nginx/webvirtmgr_access_log;
location /static/ {
root /var/www/webvirtmgr/webvirtmgr;
expires max;
}
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-for $proxy_add_x_forwarded_for;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Forwarded-Proto $remote_addr;
proxy_connect_timeout 600;
proxy_read_timeout 600;
proxy_send_timeout 600;
client_max_body_size 1024M;
}
}
EOF
//确保bind绑定的是本机的8000端口
[root@localhost ~]# vim /var/www/webvirtmgr/conf/gunicorn.conf.py
bind = '0.0.0.0:8000' #确保此处绑定的是本机的8000端口,这个在nginx配置中定义了,被代理的端口
backlog = 2048
//启动nginx并设置开机自启
[root@localhost ~]# systemctl enable --now nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
//设置supervisor
[root@localhost ~]# cat >> /etc/supervisord.conf <<EOF
[program:webvirtmgr]
command=/usr/bin/python2 /var/www/webvirtmgr/manage.py run_gunicorn -c /var/www/webvirtmgr/conf/gunicorn.conf.py
directory=/var/www/webvirtmgr
autostart=true
autorestart=true
logfile=/var/log/supervisor/webvirtmgr.log
log_stderr=true
user=nginx
[program:webvirtmgr-console]
command=/usr/bin/python2 /var/www/webvirtmgr/console/webvirtmgr-console
directory=/var/www/webvirtmgr
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/webvirtmgr-console.log
redirect_stderr=true
user=nginx
EOF
//启动supervisor并设置开机自启
[root@localhost ~]# systemctl enable --now supervisord
Created symlink /etc/systemd/system/multi-user.target.wants/supervisord.service → /usr/lib/systemd/system/supervisord.service.
[root@localhost ~]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:111 0.0.0.0:*
LISTEN 0 128 0.0.0.0:80 0.0.0.0:*
LISTEN 0 32 192.168.122.1:53 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 127.0.0.1:6080 0.0.0.0:*
LISTEN 0 128 127.0.0.1:8000 0.0.0.0:*
LISTEN 0 128 0.0.0.0:5355 0.0.0.0:*
LISTEN 0 128 [::]:111 [::]:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 128 [::1]:6080 [::]:*
LISTEN 0 128 [::1]:8000 [::]:*
LISTEN 0 128 [::]:5355 [::]:*
//配置nginx用户
[root@localhost ~]# su - nginx -s /bin/bash
[nginx@localhost ~]$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/var/lib/nginx/.ssh/id_rsa):
Created directory '/var/lib/nginx/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /var/lib/nginx/.ssh/id_rsa.
Your public key has been saved in /var/lib/nginx/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:LdiEEKUGiiCDmPsPH/wuWo9kRKBVBiWU9MsVRQTMx+M nginx@localhost.localdomain
The key's randomart image is:
+---[RSA 3072]----+
|*+O=*=+*+ |
|B=.* ooo+ |
|+. = oo.. |
|. + o +E. |
| . .+ . S . |
| o.o . |
| ++o |
| ++o. |
| ...oo |
+----[SHA256]-----+
[nginx@localhost ~]$ touch ~/.ssh/config && echo -e "StrictHostKeyChecking=no\nUserKnownHostsFile=/dev/null" >> ~/.ssh/config
[nginx@localhost ~]$ chmod 0600 ~/.ssh/config
[nginx@localhost ~]$ ssh-copy-id root@192.168.152.135
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/var/lib/nginx/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
Warning: Permanently added '192.168.152.135' (ECDSA) to the list of known hosts.
root@192.168.152.135's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'root@192.168.152.135'"
and check to make sure that only the key(s) you wanted were added.
[nginx@localhost ~]$
[nginx@localhost ~]$ ls .ssh/
config id_rsa id_rsa.pub
[nginx@localhost ~]$ exit
logout
[root@localhost ~]# cat > /etc/polkit-1/localauthority/50-local.d/50-libvirt-remote-access.pkla <<'EOF'
[Remote libvirt SSH access]
Identity=unix-user:root
Action=org.libvirt.unix.manage
ResultAny=yes
ResultInactive=yes
ResultActive=yes
EOF
[root@localhost ~]# ll /etc/polkit-1/localauthority/50-local.d/50-libvirt-remote-access.pkla
-rw-r--r-- 1 root root 133 Dec 1 19:15 /etc/polkit-1/localauthority/50-local.d/50-libvirt-remote-access.pkla
[root@localhost ~]# chown -R root.root /etc/polkit-1/localauthority/50-local.d/50-libvirt-remote-access.pkla
[root@localhost ~]# systemctl restart nginx
[root@localhost ~]# systemctl restart libvirtd
5. Kvm web页面管理
- 页面访问,通过ip地址在浏览器上访问kvm
Kvm 连接管理
- 创建ssh连接
Kvm存储管理
- 创建存储
- 通过XFTP远程传输把ISO镜像传输到/var/lib/libvirt/images/下
[root@localhost ~]# cd /var/lib/libvirt/images/
[root@localhost images]# ls
CentOS-8.2.2004-x86_64-dvd1.iso
- 创建系统安装镜像
Kvm网络管理
- 添加桥接网络
实例管理
- 实例虚拟机创建