我一直在重读Docker文档,试图理解Docker和完整VM之间的区别。它是如何设法提供一个完整的文件系统、隔离的网络环境等而不那么沉重的?
为什么将软件部署到Docker映像(如果这是正确的术语)比简单地部署到一致的生产环境更容易?
我一直在重读Docker文档,试图理解Docker和完整VM之间的区别。它是如何设法提供一个完整的文件系统、隔离的网络环境等而不那么沉重的?
为什么将软件部署到Docker映像(如果这是正确的术语)比简单地部署到一致的生产环境更容易?
当前回答
在我看来,这取决于你的应用程序的需求,为什么决定部署到Docker,因为Docker根据其功能将应用程序分解为小部分,这变得有效,因为当一个应用程序/功能出现错误时,它对其他应用程序没有影响,与使用完整的vm相比,它的配置会更慢、更复杂,但在某些方面比码头工人更安全
其他回答
Docker不是一种虚拟化方法。它依赖于实际实现基于容器的虚拟化或操作系统级虚拟化的其他工具。为此,Docker最初使用的是LXC驱动程序,然后转移到libcontainer,现在改名为runc。Docker主要致力于自动化应用程序容器内的应用程序部署。应用程序容器设计用于打包和运行单个服务,而系统容器设计用于运行多个进程,如虚拟机。因此,Docker被认为是容器化系统上的容器管理或应用程序部署工具。
为了了解它与其他虚拟化的区别,我们来了解一下虚拟化及其类型。那么,更容易理解两者之间的区别。
虚拟化
在其构想形式中,它被认为是一种逻辑上划分大型机以允许多个应用程序同时运行的方法。然而,当公司和开源社区能够提供一种以某种方式处理特权指令的方法,并允许多个操作系统在一个基于x86的系统上同时运行时,情况发生了巨大变化。
管理程序
管理程序负责创建来宾虚拟机运行的虚拟环境。它监督宾客系统,并确保在必要时为宾客分配资源。管理程序位于物理机和虚拟机之间,并向虚拟机提供虚拟化服务。为了实现它,它拦截虚拟机上的来宾操作系统操作,并模拟主机操作系统上的操作。
虚拟化技术(主要是云技术)的快速发展进一步推动了虚拟化的使用,允许在虚拟机管理程序(如Xen、VMware Player、KVM等)的帮助下,在单个物理服务器上创建多个虚拟服务器,并将硬件支持纳入商品处理器(如Intel VT和AMD-V)。
虚拟化类型
虚拟化方法可以根据其模拟客户操作系统的硬件和模拟客户操作环境的方式进行分类。主要有三种类型的虚拟化:
仿真准虚拟化基于容器的虚拟化
仿真
仿真(也称为完全虚拟化)完全在软件中运行虚拟机OS内核。此类型中使用的管理程序称为类型2管理程序。它安装在主机操作系统的顶部,负责将来宾操作系统内核代码转换为软件指令。翻译完全由软件完成,不需要硬件参与。仿真使运行任何支持被仿真环境的未修改操作系统成为可能。这种虚拟化的缺点是额外的系统资源开销,与其他类型的虚拟化相比,这会导致性能下降。
此类别中的示例包括VMware Player、VirtualBox、QEMU、Bochs、Parallels等。
准虚拟化
准虚拟化(Paravirtualization)也称为第1类虚拟机管理程序,直接在硬件或“裸机”上运行,并直接向其上运行的虚拟机提供虚拟化服务。它帮助操作系统、虚拟化硬件和真实硬件协作以实现最佳性能。这些虚拟机监控程序通常占地面积很小,本身不需要大量资源。
此类别中的示例包括Xen、KVM等。
基于容器的虚拟化
基于容器的虚拟化,也称为操作系统级虚拟化,支持在单个操作系统内核中执行多个独立的执行。它具有最佳的性能和密度,并具有动态资源管理功能。这种类型的虚拟化提供的隔离虚拟执行环境被称为容器,可以被视为一组可跟踪的进程。
通过添加到Linux内核2.6.24版本中的命名空间特性,容器的概念成为可能。容器将其ID添加到每个进程,并将新的访问控制检查添加到每个系统调用。它由clone()系统调用访问,该系统调用允许创建先前全局命名空间的单独实例。
命名空间可以以多种不同的方式使用,但最常见的方法是创建一个独立的容器,该容器对容器外部的对象没有可见性或访问权限。在容器内运行的进程似乎在正常的Linux系统上运行,尽管它们与位于其他命名空间中的进程共享底层内核,其他类型的对象也是如此。例如,当使用命名空间时,容器内的根用户不会被视为容器外的根用户,从而增加了额外的安全性。
Linux控制组(cgroups)子系统是实现基于容器的虚拟化的下一个主要组件,用于对进程进行分组并管理其总资源消耗。它通常用于限制容器的内存和CPU消耗。由于容器化的Linux系统只有一个内核,并且内核对容器具有完全的可见性,因此只有一个级别的资源分配和调度。
Linux容器有多种管理工具,包括LXC、LXD、systemd nspawn、lmctfy、Warden、Linux VServer、OpenVZ、Docker等。
容器与虚拟机
与虚拟机不同,容器不需要启动操作系统内核,因此可以在不到一秒钟的时间内创建容器。这一特性使基于容器的虚拟化比其他虚拟化方法更为独特和可取。
由于基于容器的虚拟化几乎不会或根本不会增加主机的开销,因此基于容器的虚化具有接近本机的性能
对于基于容器的虚拟化,与其他虚拟化不同,不需要额外的软件。
主机上的所有容器共享主机的调度程序,从而节省了额外的资源。
与虚拟机映像相比,容器状态(Docker或LXC映像)的大小较小,因此容器映像易于分发。
容器中的资源管理是通过cgroups实现的。Cgroups不允许容器消耗比分配给它们的资源更多的资源。然而,到目前为止,主机的所有资源在虚拟机中都是可见的,但无法使用。这可以通过同时在容器和主机上运行top或htop来实现。所有环境的输出看起来都很相似。
更新:
Docker如何在非Linux系统中运行容器?
如果由于Linux内核中的可用特性,容器是可能的,那么显而易见的问题是非Linux系统如何运行容器。Docker for Mac和Windows都使用Linux虚拟机来运行容器。Docker工具箱用于在Virtual Box VM中运行容器。但是,最新的Docker在Windows中使用Hyper-V,在Mac中使用Hypervisor.framework。
现在,让我详细描述Docker for Mac如何运行容器。
Docker for Mac使用https://github.com/moby/hyperkit为了模拟hypervisor功能,Hyperkit在其核心中使用hypervisor.framework。Hypervisor.framework是Mac的本地管理程序解决方案。Hyperkit还使用VPNKit和DataKit分别命名网络和文件系统。
Docker在Mac上运行的Linux VM是只读的。但是,您可以通过运行以下命令来实现:
screen~/Library/Containers/com.docker.docker/Data/vms/0/tty。
现在,我们甚至可以检查此VM的内核版本:
#uname-aLinux linuxkit-025000000001 4.9.93-linuxkit-aufs#1 SMP 6月6日星期三16:86_64 Linux。
所有容器都在此VM内运行。
hypervisor.framework有一些限制。因为Docker没有在Mac中公开docker0网络接口。因此,您无法从主机访问容器。目前,docker0仅在VM中可用。
Hyper-v是Windows中的本机管理程序。他们还试图利用Windows 10的功能以本机方式运行Linux系统。
好答案。为了获得容器与VM的图像表示,请查看下面的一个。
来源
Docker最初使用LinuX Containers(LXC),但后来改用runC(以前称为libcontainer),后者与主机在同一操作系统中运行。这允许它共享大量主机操作系统资源。此外,它使用分层文件系统(AuFS)并管理网络。
AuFS是一个分层文件系统,因此可以将只读部分和写部分合并在一起。可以将操作系统的公共部分设置为只读(并在所有容器中共享),然后为每个容器提供自己的装载以供编写。
假设您有一个1GB的容器映像;如果要使用完整的虚拟机,则需要有1 GB x所需数量的虚拟机。使用Docker和AuFS,您可以在所有容器之间共享1GB的空间,如果您有1000个容器,那么容器操作系统的空间可能只有1GB多一点(假设它们都运行同一个操作系统映像)。
一个完整的虚拟化系统得到了它自己的一组资源分配,并且实现了最小的共享。你得到了更多的隔离,但它更重(需要更多的资源)。使用Docker可以减少隔离,但容器是轻量级的(需要更少的资源)。因此,您可以轻松地在主机上运行数千个容器,而且它甚至不会闪烁。试着用Xen做这件事,除非你有一个非常大的主机,否则我认为这是不可能的。
一个完整的虚拟化系统通常需要几分钟的启动时间,而Docker/LXC/runC容器需要几秒钟,甚至不到一秒钟。
每种类型的虚拟化系统都有利弊。如果您希望使用有保证的资源进行完全隔离,那么完整的VM是最佳选择。如果您只想将进程彼此隔离,并希望在一个大小合理的主机上运行大量进程,那么Docker/LXC/runC似乎是一个不错的选择。
有关更多信息,请查看这组博客文章,它们很好地解释了LXC的工作原理。
为什么将软件部署到docker映像(如果这是正确的术语)比简单地部署到一致的生产环境更容易?
部署一致的生产环境说起来容易做起来难。即使您使用Chef和Puppet等工具,主机和环境之间也总是会有操作系统更新和其他变化。
Docker使您能够将操作系统快照到共享映像中,并使其易于在其他Docker主机上部署。本地、dev、qa、prod等:都是相同的图像。当然,你可以用其他工具来完成这项工作,但不是那么容易或快速。
这非常适合测试;假设您有数千个测试需要连接到数据库,每个测试都需要数据库的原始副本,并将对数据进行更改。经典的方法是在每次测试后使用自定义代码或使用Flyway等工具重置数据库-这可能非常耗时,意味着测试必须连续运行。然而,使用Docker,您可以创建数据库的映像,并为每个测试运行一个实例,然后并行运行所有测试,因为您知道它们都将针对数据库的同一快照运行。由于测试是在Docker容器中并行运行的,它们可以在同一时间在同一个盒子上运行,并且应该完成得更快。尝试使用完整的虚拟机执行此操作。
来自评论。。。
有趣的我想我仍然对“快照操作系统”的概念感到困惑。如果不制作操作系统的图像,那么如何做到这一点?
好吧,看看我能不能解释一下。您从一个基本图像开始,然后进行更改,并使用docker提交这些更改,然后创建一个图像。此图像仅包含与基础的差异。当你想运行你的镜像时,你也需要基础,它使用一个分层文件系统将你的镜像分层在基础之上:如上所述,Docker使用AuFS。AuFS将不同的层合并在一起,您可以得到所需的内容;你只需要运行它。你可以继续添加越来越多的图像(层),它将继续只保存差异。由于Docker通常基于注册表中的现成图像构建,因此您很少需要自己“快照”整个操作系统。
我喜欢肯·科克伦的回答。
但我想补充一点观点,这里没有详细介绍。在我看来,Docker在整个过程中也有所不同。与虚拟机不同,Docker不仅仅是硬件的最佳资源共享,而且它还为打包应用程序提供了一个“系统”(作为一组微服务是可取的,但不是必须的)。
对我来说,它正好填补了面向开发人员的工具(如rpm、Debian包、Maven、npm+Git)与操作工具(如Puppet、VMware、Xen)之间的差距,你可以这么说。。。
为什么将软件部署到docker映像(如果这是正确的术语)比简单地部署到一致的生产环境更容易?
您的问题假定了某种一致的生产环境。但如何保持一致?考虑一些数量(>10)的服务器和应用程序,这是管道中的阶段。
为了保持同步,您将开始使用类似木偶、厨师或您自己的供应脚本、未发布的规则和/或大量文档。。。理论上,服务器可以无限期运行,并保持完全一致和最新。实践无法完全管理服务器的配置,因此存在很大的配置漂移和运行服务器的意外更改空间。
因此,有一种已知的模式可以避免这种情况,即所谓的不可变服务器。但不可变的服务器模式并不受欢迎。主要是因为Docker之前使用的VM的限制。处理几个千兆字节的大图像,移动这些大图像,只是为了改变应用程序中的一些字段,这是非常费力的。可以理解。。。
有了Docker生态系统,你永远不需要在“小改动”上移动千兆字节(感谢aufs和Registry),也不必担心在运行时将应用程序打包到Docker容器中会导致性能下降。您不必担心该图像的版本。
最后,即使在您的Linux笔记本电脑上,您也可以经常复制复杂的生产环境(如果在您的情况下不起作用,请不要打电话给我;)
当然,您可以在VM中启动Docker容器(这是一个好主意)。减少VM级别的服务器资源调配。所有这些都可以由Docker管理。
同时Docker使用自己的实现“libcontainer”而不是LXC。但LXC仍然可用。
1.重量轻
这可能是许多码头工人学习者的第一印象。
首先,docker映像通常比VM映像小,因此易于构建、复制和共享。
第二,Docker容器可以在几毫秒内启动,而VM可以在几秒钟内启动。
2.分层文件系统
这是Docker的另一个关键特性。图像具有图层,不同的图像可以共享图层,从而更节省空间,构建速度更快。
如果所有容器都使用Ubuntu作为它们的基本映像,那么不是每个映像都有自己的文件系统,而是共享相同的下划线Ubuntu文件,并且只在它们自己的应用程序数据上有所不同。
3.共享OS内核
将容器视为进程!
在主机上运行的所有容器实际上都是一堆具有不同文件系统的进程。它们共享相同的OS内核,只封装系统库和依赖项。
这在大多数情况下都很好(没有额外的OS内核维护),但如果容器之间需要严格隔离,则可能会出现问题。
为什么重要?
所有这些似乎都是进步,而不是革命。好吧,数量的积累导致质量的转变。
考虑应用程序部署。如果我们想部署一个新的软件(服务)或升级一个,最好是更改配置文件和进程,而不是创建一个新VM。因为创建一个具有更新服务的VM,测试它(开发人员和QA之间共享),部署到生产需要几个小时,甚至几天。如果出了什么问题,你必须重新开始,浪费更多的时间。因此,使用配置管理工具(木偶、盐堆、厨师等)安装新软件,最好下载新文件。
说到docker,不可能使用新创建的docker容器来替换旧容器。维护更容易!构建一个新映像,与QA共享,测试,部署它只需要几分钟(如果一切都是自动化的),最坏的情况下需要几个小时。这被称为不可变基础设施:不要维护(升级)软件,而是创建一个新的。
它改变了服务的交付方式。我们需要应用程序,但必须维护VM(这是一个难题,与我们的应用程序无关)。Docker让你专注于应用程序,让一切变得流畅。