• 虚拟化技术课程实践


    一、虚拟机镜像制作及启动

    实验目的及要求

    • 实验目的:基于课程中讲授的虚拟化基本原理和技术,掌握虚拟化环境的搭建方法,熟悉了解一些典型的虚拟化平台的命令。
    • 实验要求:在Ubuntu操作系统下使用KVM和QUME创建虚拟机镜像、启动虚拟机。

    实验环境

    • VMware Workstation 16 Pro
    • 装有Ubuntu14.04操作系统的VMware虚拟机。

    实验步骤

    第一步:安装KVM、QUME等相关组件

    利用以下指令安装KVM、QUME等相关组件,

    apt‐get install kvm qemu libvirt‐bin virtinst virt‐manager virt‐viewer
    
    • 1

    安装完成后,使用以下两条指令检查相关组件是否已经正确安装,

    kvm-ok
    
    • 1
    virsh -c qemu:///system list
    
    • 1

    校验结果如图1和图2所示:

    KVM、QUME等组件成功安装

    图 1 KVM、QUME等组件成功安装

    初次查看Hypervisior上虚拟机的列表

    图 2 查看 Hypervisor上虚拟机的列表来确认相关组件已经正确安装

    第二步:在当前目录下创建虚拟机磁盘文件

    利用以下指令在当前目录下创建虚拟机磁盘文件,

    qemu-img create -f qcow2 ubuntu.img 10G
    
    • 1

    该指令的作用为创建一个格式为qcow2、大小为10G、文件名为ubuntu的镜像文件。

    该步骤结果如图3所示。

    创建虚拟机磁盘文件

    图 3 创建虚拟机磁盘文件

    第三步:下载系统盘,启动虚拟机并插入系统盘,安装操作系统

    首先使用以下指令下载ubuntu-20.04.4-live-server-amd64系统盘,

    wget https://mirrors.aliyun.com/ubuntu-releases/focal/ubuntu-20.04.4-live-server-amd64.iso
    
    • 1

    然后使用以下指令启动虚拟机,并插入系统盘,安装操作系统,

    machines/ubuntu.img -cdrom /home/huyu/virtual\ machines/ubuntu-20.04.4-live-server-amd64.iso -enable-kvm -boot d -m 1024
    
    • 1

    部分安装过程如图4所示。

    安装操作系统部分截图

    图 4 在虚拟机中安装操作系统

    第四步:配置虚拟机启动参数并启动

    在第三步中我们已经成功安装虚拟机了,因此可以使用以下指令以命令行的形式配置虚拟机的启动参数并启动虚拟机。

    qemu-system-x86_64 ubuntu.img -m 1024
    
    • 1

    启动过程如图5所示。

    启动虚拟机

    图 5 启动虚拟机

    第五步:以XML的形式配置虚拟机启动参数

    为了采用libvirt来管理虚拟机,首先我们要使用vim编辑配置文件demo.xml,指定虚拟机的最大内存、VCPU的个数等详细启动参数。

    紧接着使用下列指令定义虚拟机,即从xml配置文件创建虚拟机,

    sudo virsh define demo.xml
    
    • 1

    随后使用以下指令启动虚拟机,

    sudo virsh start demo
    
    • 1

    通过以下指令可以查看虚拟机是否启动成功,

    sudo virsh -c qemu:///system list
    
    • 1

    最后,可以使用以下指令操作虚拟机,

    virt-viewer -c qemu:///system [Id]
    
    • 1

    从图6和图7中可以看出该步骤已成功实现。

    虚拟机成功启动

    图 6 虚拟机启动成功

    virt-viewer

    图 7 通过virt-viewer使用虚拟机

    第六步:以图形化方式安装虚拟机

    执行以下指令打开Virtual Machine Manager来安装虚拟机,

    sudo virt-manager
    
    • 1

    从图8中可以看出该步骤已顺利完成。

    virt-manager

    图 8 使用Virtual Machine Manager来安装虚拟机

    第七步:查看并转换镜像格式

    使用以下指令可以查看镜像信息,

    qemu-img info ubuntu.img
    
    • 1

    使用以下指令可以转换镜像格式,

    qemu‐img convert ‐f qcow2 –O raw ubuntu.img Ubuntu‐raw.img
    
    • 1

    图9展示了两种镜像格式的详细信息。

    rawqcow2这两种镜像格式之间的比较将在第三部分思考题及答案中给出。

    两种格式的镜像的信息

    图 9 两种格式的镜像的信息

    问题及解决方案

    1. 问题:提示“错误: 将插槽连接到 ‘/var/run/libvirt/libvirt-sock’ 失败: 权限不够”。

      解决方案:重启虚拟机。

    2. 问题:在转换镜像格式时提示磁盘空间不足。

      解决方案:使用Gparted拓展磁盘。

    实验小结

    在该部分实验中,我顺利在装有Ubuntu14.04操作系统的VMware虚拟机上:

    • 安装了kvm、qemu、libvirt‐bin、virtinst、virt‐manager、virt‐viewer等虚拟机制作及管理所需的组件;
    • 利用qemu创建虚拟机磁盘文件,并启动虚拟机、安装Ubuntu20.04操作系统;
    • 以命令行、XML配置文件两种形式配置虚拟机启动参数并启动虚拟机;
    • 查看并比较raw和qcow2这2种格式的虚拟机镜像。

    通过该部分实验,我更加清楚了kvm和qemu这两者之间的关系。kvm是内核虚拟化支持的模块,而qemu是用户层的模拟虚拟机的仿真软件,并没有内核支持。虽然后来的qemu版本已经集成了kvm module,但是在实验中我也体会到了有没有kvm模块支持(即--enable-kvm)的qemu之间的性能差距。同时,通过亲手实验虚拟机镜像的制作、安装以及启动,我对虚拟化技术也有了更深的了解。

    二、Docker环境搭建及镜像制作

    实验目的及要求

    • 实验目的:Ubuntu下使用Docker创建Ubuntu的镜像,并以此为基础镜像创建新的容器镜像。
    • 实验要求
      • 通过Docker hub构建一个容器实例;
      • 注意查看容器镜像各层次的构成;
      • 在构建好的容器实例安装任意软件,使用Docker commit和Dockerfile分别构建镜像;
      • 比较虚拟机和容器的镜像大小、启动速度等方面的区别。

    实验环境

    • VMware Workstation 16 Pro
    • 装有Ubuntu14.04操作系统的VMware虚拟机。

    实验步骤

    第一步:安装 Docker 环境所需的依赖包

    利用以下指令安装 Docker 环境所需的依赖包,

    apt-get update 
    apt-get install -y \
    		apt-transport-https \
    		ca-certificates \
    		curl \
    		gnupg-agent \
    		software-properties-common
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    注意:需要更新apt软件包索引并安装软件包以允许apt通过HTTPS使用存储库

    第二步:添加GPG证书秘钥并验证是否拥有带有指纹的密钥

    执行以下指令添加GPG证书秘钥并验证是否拥有带有指纹的密钥,

    sudo curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | 
    sudo apt-key add –apt-key fingerprint 0EBFCD88
    
    • 1
    • 2

    执行以下指令写入软件源信息

    sudo add-apt-repository \
    		"deb [arch=amd64] https://download.docker.com/linux/ubuntu \ 
    		$(lsb_release -cs) \
    		stable"
    
    • 1
    • 2
    • 3
    • 4
    第三步:安装docker,并运行hello-world容器

    按顺序执行以下三条指令,以安装docker,并运行hello-world容器,

    sudo apt-get update
    sudo apt-get install -y docker-ce docker-ce-cli containerd.io 
    docker run hello‐world
    
    • 1
    • 2
    • 3

    从图10中可以看出hello-world容器已经成功运行。

    hello-world

    图 10 hello-world容器成功运行

    第四步:从Docker-hub上下载ubuntu 20.04镜像

    执行以下指令从Docker-hub上下载ubuntu 20.04镜像,

    sudo docker pull ubuntu:focal
    
    • 1
    第五步:使用该镜像运行一个容器,并在该容器中测试任意Linux命令

    执行以下指令以进行创建一个新的容器等操作,

    sudo docker run -it --name my-container ubuntu:focal bash
    
    • 1

    从图11中可以看出,利用ubuntu:focal镜像创建的容器已经成功运行,并且能够执行Linux命令。

    运行容器并执行任意Linux指令

    图 11 运行容器并执行任意Linux指令

    第六步:基于 ubuntu 20.04基础镜像安装任意软件,并生成新的docker镜像

    在第五步运行的容器中任意安装一个软件(例如OpenSSH-server),结果如图12所示。

    再利用以下指令可以从容器创建一个新的镜像,并给出镜像名称和标签,

    sudo docker commit -m "Just installed a new software" -a "hy" my-container my-image1
    
    • 1

    从图13中可以看出已经成功从上述容器创建出新的镜像my-image1了。

    在容器中安装任意软件

    图 12 在容器中安装任意软件

    在容器中安装任意软件

    图 13 创建新的镜像

    第七步:使用Dockerfile创建虚拟机

    首先使用touch创建Dockerfile并使用vim编辑。

    随后使用下列指令进行基于上述Dockerfile创建镜像的操作,

    docker build -t my-image2 .
    
    • 1

    图14显示了使用docker commit创建的镜像和基于Dockerfile创建的镜像的区别,详细的区别介绍将在第三部分思考题及答案中给出。

    使用docker commit创建的镜像,以及其与基于Dockerfile创建的镜像的区别

    图 14 使用docker commit创建的镜像,以及其与基于Dockerfile创建的镜像的区别

    问题及解决方案

    1. 问题:安装Docker时提示“E: 未发现软件包 docker-ce-cli”。

      解决方案:运行以下代码即可正确安装Docker。

      sudo apt-get update && sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common && curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - && sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" && sudo apt-get update && sudo apt-get install -y docker-ce
      
      • 1
    2. 问题:运行任何docker指令时均会提示“Got permission denied while trying to connect to the Docker daemon socket at …”。

      解决方案:运行docker指令时均添加sudo以使其拥有相应权限。

    实验小结

    在该部分的实验中,通过亲手制作各种Docker容器、镜像,我很好地掌握了Docker的基本使用方法,也明白了利用Docker commit和利用Dockerfile构建镜像之间的区别。同时,通过与实验一所耗费的时间以及宿主机的开销进行比较,我很明显地感受到Docker的便利性、轻量性,我将在第三部分思考题及答案中详细比较虚拟机和容器的镜像大小、启动速度等方面的区别。

    三、思考题及答案

    比较虚拟机镜像格式raw和qcow2的区别

    :虚拟机镜像格式包括raw、vmdk、cow、qcow以及qcow2等,其中raw和qcow2是目前最主流的两种格式。下面将详细比较这两种格式的区别。

    • raw:raw原意为“未经加工”,因此raw格式镜像文件又被称为原始镜像或裸设备镜像。
      • raw格式镜像文件能够直接当作一个块设备(可以直接给虚拟机进行读写的文件)以供GuestOS使用,即KVM的GuestOS可以直接从raw镜像中挂载启动。因此,性能较好
      • 至于稀疏文件(sparse file)里面的空洞,则是由宿主机的文件系统来管理的,例如Linux下的文件系统(ext2/ext3/ext4)或者Windows的文件系统(NTFS)等都可以很好地支持空洞(hole)。所以,如果如果创建了一个100G的raw格式的文件,ls看的时候,可以看到这个文件是100G的,但是如果用du来看的话,这个文件会很小。从图9中也可以看出,raw格式的镜像的虚拟大小是10G,但实际大小只有3.2G。
      • 由于从ls中看起来很大,因此在scp的时候会消耗很多的网络IO,而且tar这么大的文件也是很耗时间跟CPU的。
      • raw格式镜像的简单也带来了很多好处:支持转换成其他格式的虚拟机镜像,甚至其它格式需要转换还需要raw做为中间格式;能够使用dd指令来追加 RAW 镜像文件的空间。
      • 但是,简单也意味着raw格式的镜像并不支持很多复杂的功能,例如snapshot等。
      • 另外,raw不支持动态增长空间,必须一开始就指定空间大小,所以相当的耗费磁盘空间。
    • qcow2:qcow2全称为QEMU copy-on-write 2,是目前qemu推荐的镜像格式,也是功能最多的镜像格式。
      • qcow2的特性主要体现在写时拷贝(copy-on-write)上,即镜像文件只反映底层磁盘的变化。因此,只有在虚拟机实际占用了磁盘空间时,其文件才会增长,能方便的减少迁移花费的流量,更适用于云计算系统。上述提到了raw格式镜像的性能是依赖于宿主机文件系统是否支持空洞,但qcow2格式镜像并不依赖于宿主机文件系统的特性,因此所占用的空间相对于raw格式镜像较少。
      • 从图9中我们可以看到,qcow2格式镜像信息与raw格式镜像信息最大的区别在于多了一个cluster的信息。这意味着qcow2是由多个固定大小的单元组织(即cluster)构成的。无论是实际用户数据还是镜像的元数据,都存储到一个 cluster 单元中。用户系统里所见到的虚拟磁盘实际是被分割成多个同样大小的cluster的集合显示。因此qcow2支持基于 zlib 的压缩方式,即允许每个cluster单独使用 zlib 压缩。
      • 但上述cluster机制的使用,也导致qcow2格式的镜像文件在性能上比raw格式的有一些损失,主要体现在对于文件增量上,qcow2格式的镜像文件为了分配cluster多花费了一些时间。
      • 与raw相比,qcow2还支持以下多种功能:(1)可以选择AES加密,并支持使用128位的AES密钥进行加密;(2)支持snapshot。
      • 从以上特性也可以看出,qcow2相对于raw的一个劣势是过于臃肿,把什么功能都集于一身。

    比较docker build和docker commit创建镜像的区别

    :docker制作镜像的方式主要有经过docker commit制作镜像、经过docker build制作镜像(也就是实验中的Dockerfile)这两种方法。这两种方法都是经过改进已有的镜像来达到本身的目的。

    • docker commit:docker commit是往版本控制系统里提交一次变动,本质上是运行一个基础镜像,而后在基础镜像上进行软件安装和修改,最后再将改动提交到版本系统中。
    • docker build:docker build是维护一个可读性、可理解性都比较强的Dockerfile来创建镜像,但在本质上docker build方法还是调用了docker commit方法进行镜像构建。
    • 区别
      1. 首先,docker build仅需要维护一个Dockerfile即创建自定义的镜像,而docker commit需要在容器内操作(例如安装相应软件),比较麻烦、效率较低,但docker build方法同时也要求用户需要掌握相应的Linux和脚本基础知识,相对较难;
      2. 其次,docker build在可维护性可拓展性比docker commit好,因为docker build方法可以直接在Dockerfile中更改并增长新的特性,而docker commit方法则需要再次运行镜像并对内部软件进行升级或安装新软件来进行增长;
      3. 使用docker build方法创建出来的镜像,通过docker history指令打印出来的历史版本信息中可以看到详细的例如apt-get install的操作,可理解性较好,而使用docker commit方法创建出来的镜像的历史信息则是不可见的;

    综上,利用docker build和docker commit创建镜像各有优劣,需要结合实际状况来具体选择其中一种方法进行镜像构建。

    比较虚拟机和容器的镜像大小、启动速度等方面的区别

    :总体来说,容器相对于虚拟机具有很多优势:

    1. 存储大小方面。容器的镜像非常小,这点我们从图14中可以看出,Ubuntu14.04的系统镜像仅有200M左右,无论是下载还是上传都非常方便;而从图9中我们看到虚拟机的镜像(无论是raw还是qcow2)都是以G为单位的,这也是为什么我在实验中遇到磁盘空间不足的原因。
    2. 操作系统方面。由于docker不需要在宿主机的系统之上再运行新的系统,在运行时与宿主机共享OS,因此启动速度达到秒级,但同时也意味着docker并没有硬件的虚拟化资源;而虚拟机会根据需要加载不同的系统,这些功能完备的系统大小往往高达数个GB,因此启动速度为分钟级。这点我深有体会,因为在实验一上所花费的时间数倍于实验二。
    3. 移植性方面。docker容器轻便、灵活、适应于Linux,而虚拟机相对笨重,与虚拟化技术的耦合度非常高,因此移植性相对较差。
    4. 运行性能方面。这点我们在上课时也提到了,docker几乎没有性能损失,不浪费原本就很珍贵的资源,而虚拟机则需要消耗大量的、额外的CPU和内存资源。

    即便如此,我们也不能完全否定虚拟机,因为在实际应用中二者是适用于自己的场景的。虚拟机更擅长于彻底隔离整个运行环境,例如云计算服务提供商通常采用虚拟机技术隔离不同的用户。而docker通常用于隔离不同的应用,例如前端,后端以及数据库。

    总结

    通过本次虚拟化技术课程实践,

    1. 首先,我对KVM、Qemu和Libvirt这三者之间的相互关系有了进一步的了解,也很好地掌握了利用Qemu、KVM、Libvirt这些积木搭建虚拟机镜像、启动虚拟机的基础方法,同时对于不同的虚拟机镜像格式之间的区别有了初步认识。
    2. 其次,我对容器这一虚拟化技术的新热点有了更深的体会,并掌握了docker环境的搭建、使用docker commit和docker build创建镜像等基本技能,最后通过比较两种创建镜像的方法深化了我对docker基础原理的认识。
    3. 通过带着思考题进行实验,我注意到了传统的虚拟化技术——虚拟机和新兴的虚拟化技术——容器之间的差异,引发了我对虚拟化技术未来发展的一些思考。
  • 相关阅读:
    Netty02 - 回显服务器实例
    麦芽糖-聚乙二醇-人血清白蛋白,HAS-PEG-maltose
    babel转码器
    如何恢复文件夹隐藏文件?超实用的2种技巧来了
    苏宁滑块验证
    Python中的print()
    一款免费无广、简单易用的安全软件:火绒安全软件
    nginx的配置文件概述及简单demo(二)
    7.Gin 路由详解 - 路由分组 - 路由文件抽离
    Pytest简介及jenkins集成
  • 原文地址:https://blog.csdn.net/Mister_Yu/article/details/127596045