欢迎来到魔幻小生的博客

Docker 和虚拟机的区别

虚拟机

  • 基础设施(Infrastructure)。它可以是你的个人电脑,数据中心的服务器,或者是云主机。
  • 主操作系统(Host Operating System)。你的个人电脑之上,运行的可能是 MacOS,Windows 或者某个 Linux 发行版。
  • 虚拟机管理系统(Hypervisor)。利用 Hypervisor,可以在主操作系统之上运行多个不同的从操作系统。类型1的 Hypervisor 有支持 MacOS 的 HyperKit,支持 Windows 的 Hyper-V 以及支持 Linux 的 KVM。类型2的 Hypervisor 有 VirtualBox 和 VMWare。
  • 操作系统(Guest Operating System)。假设你需要运行3个相互隔离的应用,则需要使用 Hypervisor 启动3个从操作系统,也就是3个虚拟机。这些虚拟机都非常大,也许有700MB,这就意味着它们将占用2.1GB的磁盘空间。更糟糕的是,它们还会消耗很多CPU和内存。
  • 各种依赖。每一个从操作系统都需要安装许多依赖。如果你的的应用需要连接 PostgreSQL 的话,则需要安装 libpq-dev;如果你使用 Ruby 的话,应该需要安装 gems;如果使用其他编程语言,比如 Python 或者 Node.js,都会需要安装对应的依赖库。

Docker 容器

  • 主操作系统(Host Operating System)。所有主流的 Linux 发行版都可以运行 Docker。对于 MacOS 和 Windows,也有一些办法"运行" Docker。
  • Docker守护进程(Docker Daemon)。Docker 守护进程取代了 Hypervisor,它是运行在操作系统之上的后台进程,负责管理 Docker 容器。
  • 各种依赖。对于 Docker,应用的所有依赖都打包在 Docker 镜像中,Docker 容器是基于 Docker 镜像创建的。
  • 应用。应用的源代码与它的依赖都打包在 Docker 镜像中,不同的应用需要不同的 Docker 镜像。不同的应用运行在不同的 Docker 容器中,它们是相互隔离的。

image

对比

虚拟机是在物理资源层面实现的隔离,相对于虚拟机,Docker 是你 APP 层面实现的隔离,并且省去了虚拟机操作系统(Guest OS),从而节省了一部分的系统资源;Docker 守护进程可以直接与主操作系统进行通信,为各个 Docker 容器分配资源;它还可以将容器与主操作系统隔离,并将各个容器互相隔离。虚拟机启动需要数分钟,而 Docker 容器可以在数毫秒内启动。由于没有臃肿的从操作系统,Docker 可以节省大量的磁盘空间以及其他系统资源。

虚拟机与 docker 的区别,在于 vm 多了一层 guest OS,虚拟机的 Hypervisor 会对硬件资源也进行虚拟化,而容器 Docker 会直接使用宿主机的硬件资源。

下面我们采用形象的比喻区分两者的隔离级别:

  • 服务器:比作一个大型的仓管基地,包含场地与零散的货物——相当于各种服务器资源。
  • 虚拟机技术:比作仓库,拥有独立的空间堆放各种货物或集装箱,仓库之间完全独立——仓库相当于各种系统,独立的应用系统和操作系统。
  • Docker:比作集装箱,操作各种货物的打包——将各种应用程序和他们所依赖的运行环境打包成标准的容器,容器之间隔离。

隔离性

在于隔离性上面,由于 vm 对操作系统也进行了虚拟化,隔离的更加彻底。而 Docker 共享宿主机的操作系统,隔离性较差。

运行效率

由于 vm 的隔离操作,导致生成虚拟机的速率大大低于容器 Docker 生成的速度,因为 Docker 直接利用宿主机的系统内核。比如 openstack 能够以 10台/min 的速度创建虚拟机,而 docker 可以做到在几秒钟之内创建大量容器,它们的启动速度是在数量级上的差距。

因为虚拟机增加了一层虚拟硬件层,运行在虚拟机上的应用程序在进行数值计算时是运行在 Hypervisor 虚拟的CPU上的;另外一方面是由于计算程序本身的特性导致的差异。虚拟机虚拟的 cpu 架构不同于实际 cpu 架构,数值计算程序一般针对特定的 cpu 架构有一定的优化措施,虚拟化使这些措施作废,甚至起到反效果。

资源利用率

在资源利用率上虚拟机由于隔离更彻底,因此利用率也会相对较低。

因为虚拟机增加了一层虚拟硬件层,运行在虚拟机上的应用程序在进行数值计算时是运行在 Hypervisor 虚拟的 CPU 上的;另外一方面是由于计算程序本身的特性导致的差异。虚拟机虚拟的 cpu 架构不同于实际 cpu 架构,数值计算程序一般针对特定的 cpu 架构有一定的优化措施,虚拟化使这些措施作废,甚至起到反效果。

image

在这个对比图里,我们应该把 Docker 画在跟应用同级别并且靠边的位置。这意味着,用户运行在容器里的应用进程,跟宿主机上的其他进程一样,都由宿主机操作系统统一管理,只不过这些被隔离的进程拥有额外设置过的 Namespace 参数。而 Docker 项目在这里扮演的角色,更多的是旁路式的辅助和管理工作。

这样的架构也解释了为什么 Docker 项目比虚拟机更受欢迎的原因。这是因为,使用虚拟化技术作为应用沙盒,就必须要由 Hypervisor 来负责创建虚拟机,这个虚拟机是真实存在的,并且它里面必须运行一个完整的 Guest OS 才能执行用户的应用进程。这就不可避免地带来了额外的资源消耗和占用。

而相比之下,容器化后的用户应用,却依然还是一个宿主机上的普通进程,这就意味着这些因为虚拟化而带来的性能损耗都是不存在的;而另一方面,使用 Namespace 作为隔离手段的容器并不需要单独的 Guest OS,这就使得容器额外的资源占用几乎可以忽略不计。

首先,既然容器只是运行在宿主机上的一种特殊的进程,那么多个容器之间使用的就还是同一个宿主机的操作系统内核。

尽管你可以在容器里通过 Mount Namespace 单独挂载其他不同版本的操作系统文件,比如 CentOS 或者 Ubuntu,但这并不能改变共享宿主机内核的事实。这意味着,如果你要在 Windows 宿主机上运行 Linux 容器,或者在低版本的 Linux 宿主机上运行高版本的 Linux 容器,都是行不通的。

而相比之下,拥有硬件虚拟化技术和独立 Guest OS 的虚拟机就要方便得多了。最极端的例子是,Microsoft 的云计算平台 Azure,实际上就是运行在 Windows 服务器集群上的,但这并不妨碍你在它上面创建各种 Linux 虚拟机出来。

转载地址:https://zhuanlan.zhihu.com/p/487824422

posted @ 2023-06-05 21:08  魔幻小生  阅读(704)  评论(0编辑  收藏  举报