本文转载自微信公众号「 jameswhale的技术人生」,转载本文请联系 jameswhale的技术人生公众号。
原文链接:https://mp.weixin.qq.com/s/LOXB36aevXoH9EQHFr5E9Q
原文出处: jameswhale的技术人生
微信公众号的ID:jameswhale的技术人生
前言
近几年容器(Container)、Kubernetes等技术在数据中心、云计算、各互联网公司的业务服务中得到广泛应用,和20世纪60年代就兴起的虚拟机(Virtual Machine,VM)技术一样,容器也是一种服务虚拟化技术(Server Virtualization),但是它更加轻量,同时将焦点从Machine转移到Application,极大提高了开发、测试、生产环境部署的效率,不过其安全性和隔离性比虚拟机稍逊一筹,在一些场景下也无法完全替代虚拟机。本文主要从以下几部分来梳理虚拟机和容器技术,详细讲一下他们的区别与联系。
- 为何需要服务虚拟化技术
- 虚拟化技术分类
- Host-based server virtualization(虚拟机)架构
- OS virtualization(容器)架构
- 内核对容器的支持
- 虚拟机技术举例(VMWare ESXi)
- 容器技术举例(Docker Container)
- 虚拟化技术在云平台的应用( Google Cloud Platform, GCP )
为何需要服务虚拟化技术?
- 节省硬件资源(机房、服务器、冷却系统等),提高资源利用率:12306网站的负载存在明显的峰值和低谷(节日前夕较大,春运最为明显,而在平时则比较低),若完全用实体服务器去抗峰值流量,在平时则会出现巨大浪费。通过服务虚拟化(Server Virtualization/Machine Virtualization)技术构建的云计算平台(Cloud Computer Platform)则可以有效解决这一难题,峰值时增加算力去满足购票需求,低谷时则将算力售卖出去以提高资源的利用率。腾讯云可以按照CPU、内存、存储(比如1C/1G/50GB)等方式对外提供服务,普通用户不用为购买服务器、搭建机房、规划网络访问、数据容灾而烦劳,就像购买水、电、煤气等基本市政服务一样。
- 逻辑资源整合:通过虚拟机(Virtual Machine,简称VM)技术,多个不同的Guest操作系统(及运行在其上的各种应用程序)可以运行在一台物理服务器上面,例如,邮件服务器、数据库服务器、Web服务器等应用可以部署在一起,同时可以做到有效的隔离(资源和访问)。
- 服务器可移植性:Virtual Machine Monitor/Hypervisor屏蔽底层差异,同一Guest操作系统可以在硬件架构完全不同的服务器上运行(Mac,X86等),没有硬件依赖,它可以从一种硬件服务器迁移到另外一台完全不同的硬件服务器,不需要做改变和适配,用户无感知。
- 应用程序可靠性:虚拟机(VM)所在的硬件服务器损坏后,可以快速迁移到另外一台硬件服务器(都部署有Virtual Machine Monitor/Hypervisor),极大提高了其中运行的应用程序的可靠性。容器(Container)所在的Linux服务器无法访问后,容器管理者(比如,K8s)可以在另外一台Linux服务器创建一个新容器,业务不会受到影响。(借助虚拟机技术,容器也可以在非Linux服务器上运行,Guest操作系统为Linux即可。)
- 网络和存储也在采用虚拟化技术:从使用独立磁盘冗余阵列(RAID)开始,存储虚拟化已经出现了很多年,RAID提供了一种对物理磁盘进行逻辑分组并将这些分组作为一个或多个虚拟磁盘呈现给操作系统的方法。华为的OceanStor系列存储阵列属于存储区域网络(SAN),通过DevLun(设备逻辑单元号)来呈现给上层主机访问,内部封装了各种算法(SmartVirtualiztion,SmartQos,smartPartition等)保障主机的I/O访问质量。网络虚拟化是另一种已经存在了几十年的虚拟化形式,例如,虚拟局域网(VLAN)长期以来提供了一种对物理网络交换机进行逻辑细分的方法。因此,主机对其本地交换机的视图并不局限于它所连接的交换机的物理组成,而是由VLAN本身的逻辑表示来确定。
服务虚拟化技术的分类
- 基于主机的服务器虚拟化技术(Host-based server virtualization ,虚拟机)允许具有不同操作系统的多个虚拟机(Virtual Machine)在同一物理主机系统上并发运行,又可以细分为如下三类。
- 完全虚拟化(Full virtualization):完全虚拟化提供了完整的硬件模拟,这有一个优势,即完全的虚拟机可移植性,例如,允许在Dell服务器上运行的虚拟机重新定位到HP服务器,而不会出现任何问题。代价是性能会降低,内存读写大概损失2%,网络和硬盘I/O大概损失8%~20%。
- 半虚拟化(Paravirtualizaton):虚拟机中的Guest操作系统需要重新编译,让其知道处于虚拟化环境中,以便可以和 Host 操作系统或者VMM/Hypervisor协调工作。可以通过两种方式来实现半虚拟化:1)重新编译操作系统内核,这需要操作系统品牌商提供和半虚拟化环境兼容的OSbuild;2)安装半虚拟化的内核模式驱动,通过安装半虚拟化的内核模式存储和网络驱动,可以有效降低硬盘和网络读写延迟(从完全虚拟化的8%~20%降到2%)。
- 硬件辅助虚拟化( Hardware-Assisted Virtualization ):英特尔和AMD都积极致力于使其处理器实现虚拟化,意识到虚拟环境的存在,CPU可以直接和VMM/Hypervisor交互,让其运行在Ring-1,这样一来,Guest操作系统可以运行在Ring0,从而不需要借助于VMM/Hypervisor的Trap中断来执行特权指令,极大降低了特权指令的执行延迟。在提高处理性能的同时,通过分配不同的硬件地址空间给虚拟机从而在硬件层面实现有效隔离。
综合以上,直接访问资源可以提供本机级别的性能,但是会牺牲可移植性,为了获得更好的可移植性,虚拟化供应商将进一步开发可感知VMM/Hypervisor的半虚拟化Guest操作系统驱动程序,这些驱动程序将表示合成虚拟设备,如网卡和存储控制器。使用合成设备驱动程序将允许 Guest 操作系统看到一组一致的硬件资源(即使迁移到不同的Host),同时仍然能够提供接近本机的性能。
- 操作系统虚拟化技术(OS virtualization ,容器)
操作系统虚拟化以应用程序为中心,允许多个虚拟环境(VE)共享一个通用操作系统,每个环境的运行开销比完全虚拟化的主机少得多。单就内存而言,虚拟机的需求就相当大。例如,假设八个虚拟机在一个Host服务器上运行,并且每个 Guest操作系统使用512MB的RAM。这意味着,在不计算应用程序或VMM开销的情况下,虚拟化的成本将是8x512 MB,或者是4GB的RAM。假设每个操作系统安装需要4GB的磁盘空间,那么物理主机系统上需要32GB的磁盘空间来存储所有Guest操作系统。
操作系统虚拟化的另一个好处是它不需要虚拟环境中的任何驱动程序或完整硬件仿真。这允许虚拟环境中的I/O以接近本机的性能运行。由于VE作为应用程序外壳运行,它们提供了与VM相同的可移植性,不需要依赖于主机系统硬件(但是必须都在Linux操作系统上)。
安全性和隔离性不如虚拟机(操作系统提供的应用级别隔离),单就这一点,容器技术无法替代虚拟机技术。
Host-based server virtualization(虚拟机)架构
根据有无 Host 操作系统,虚拟机分为两大类。
Type2(有操作系统)
VMM(Virtual Machine Monitor)/Hypervisor的作用
- 为VM提供硬件模拟(完全虚拟化场景下,其他场景是直接访问硬件)。
- 隔离VM彼此之间的访问(只可以通过网络进行通信,例如socket)。
- 限制单个VM对系统资源的访问,防止不稳定的VM影响整个系统性能。
指令的执行等级
指令执行等级分为Ring0~Ring3,通常操作系统内核运行在Ring0,设备驱动运行在Ring1~Ring2(也可都运行在Ring0),应用程序运行在Ring3。
- 传统X86架构
- 虚拟机场景下(CPU硬件未协助)
- 虚拟机场景下(CPU硬件协助)
操作系统虚拟化技术(OS virtualization ,容器)
架构OS虚拟化层借助Linux操作系统内核的特性(比如namespace,cgroup等)为每个应用程序构建独立的虚拟环境(VE-id),各自拥有独立的根文件系统、启动脚本、init、进程ID(同一虚拟环境下的进程ID不重复,不同虚拟环境下的进程ID可以重复),使其认为独占了整个硬件系统。虚拟环境(VE)不需要安装操作系统、设备驱动等,相比虚拟机,要省去了很多内存和硬盘开销。同时,不需要模拟硬件指令(直接调用操作系统的system Call),虚拟环境中的应用程序执行性能接近本机。
内核对容器的支持
基于容器的虚拟化使用了内核提供的许多功能,以便隔离进程或实现其他有助于实现此目的的目标,大多数解决方案都基于Linux内核,由于内核提供了所需的大部分功能,容器工具包通常不必再次实现它们,内核代码已经被其他被认为是稳定的并且已经在生产中使用的软件所使用。如果内核提供的机制存在安全问题,则会随着内核更新而分发修复程序,这意味着不需要修补容器软件,用户只需保持内核的最新状态。
- chroot:chroot机制允许更改进程及其所有子进程的根目录,用于限制对单个文件夹的文件系统访问,目标进程及其子进程将该文件夹视为根文件夹(/)(不提供进程隔离)。
- namespace(by IBM):内核命名空间是进程隔离的基础,是实现基于容器的虚拟化的关键概念之一,它能够隔离进程、进程组甚至完整的子系统(如进程间通信或者内核的网络子系统)。每个命名空间中的进程ID分配是独立的,不同命名空间中的进程可能具有相同的进程ID。
- Control group(by Google ):cgroup是一种跟踪进程和进程组(包括创建的子进程)的机制,它提供的钩子允许其他子系统扩展这些功能,并实现细粒度的资源控制和限制。将资源分配给进程、进程组并管理这些分配的能力允许规划和控制容器的使用。同样,若有进程已声明了对某些资源的占用,其他进程则无法使用。
- Mandatory Access Control :MAC策略通常用于限制对敏感资源的访问(而这些访问在一定上下文下是不需要的),以减轻从容器内部对主机和其他容器的攻击,从而提高容器虚拟化技术的安全性。
虚拟机技术举例(VMWare ESXi)
VMWare在虚拟机市场处于领导地位,以VMWare的ESXi举例。
VMkernel提供与操作系统类似的功能,例如,进程创建与控制,信号,文件系统,进程和线程等,它是专门设计用来支持运行多个虚拟机,提供如下核心功能:资源调度,设备驱动,输入输出栈等。直接运行在硬件设备上面,不再需要借助通用的操作系统。
VMWareESXi优势(相比其他虚拟机平台)
- 极少的状态信息:ESXi系统可以作为无状态计算节点来处理,所有的状态信息都可以从保存的配置文件中轻松上传。
- 更好的安全性:ESXi仅使用少量的内存(32MB),接口少,从而使得被攻击的危险降到最低。
- 硬件级的可靠性:当它集成到固件中时,软件比存储在磁盘上时更不容易损坏,通过消除本地磁盘驱动器可以提供更高的系统可靠性。
容器技术举例(Docker)
Docker镜像样例
从镜像到容器(实例化)
镜像内容分发
容器虚拟化技术从FreeBSD jails,solaris Zones,到Linux Containers(LXC),再到这几年名声大噪的Docker Containers,极大的提高了开发、测试、生产环境部署的效率。Docker容器技术通常是指如下三个部分。
- 镜像(image):镜像是一个静态规范,包括应用程序代码和运行时配置设置,规定了容器运行起来后是什么样子,它由若干个只读层组成,一旦创建完成就不能修改(除非基于此镜像再创建一个新镜像),可通过Dockerfile来组织创建镜像的多个命令。
- 容器(Container):容器是指镜像的实例化,每个运行的容器在只读的镜像基础上有一个可写层,在容器运行期间发生变化的数据都保存在这个可写层,容器被删除后,这个可写层内容也会被删除。通过Docker–commit可显示的进行保存(生成另外一个新的镜像),不过,在实际业务场景,一般不会也不需要这么做。
- Docker Daemon(或者叫Docker Engine):介于容器和Linux操作系统之间的一个廋层,用于管理容器的持久运行时环境,正因为通过这一层来屏蔽底层差异,才可以让Docker容器运行在任何Linux服务器上。
虚拟化技术在云平台的应用(Google Cloud Platform,GCP)
Google Compute Engine(GCE,Google计算引擎)是Google云平台的基础设施即服务(IaaS)组件,它建立在运行Google搜索引擎、Gmail、YouTube和其他服务的全球基础设施之上。GCE允许用户按需启动虚拟机(VMs),VMs可以从用户创建的标准图镜像或自定义镜像启动。
GCE采用KVM作为其虚拟机的VMM/Hypervisor,KVM(Kernel-based Virtual Machine)是一个完全虚拟化方案,同时包含了CPU硬件提供的虚拟化技术扩展(IntelVT或AMD-V),适用于x86硬件上的Linux。可加载的内核模块(kvm.ko,intel的是kvm-intel.ko,amd的是kvm-amd.ko)提供核心虚拟化基础架构。使用KVM,可以运行多个含有未经修改的Linux或Windows Guest OS的虚拟机,每个虚拟机都有专用的虚拟硬件:网卡、磁盘、图形适配器等。
通过K8s容器编排系统在VMs之上部署多个容器,一方面可以快速启动程序(容器比虚拟机启动时间要小很多),二是可以有效降低虚拟机的额外负载(容器可以部署多个,虚拟机则只能部署少量的),三是可以实现容器的自动升级、节点修复、自动扩缩容等特性。