有了Docker的程序猿们就能开启“上帝视角”?-阿里云开发者社区

开发者社区> 云原生> 正文

有了Docker的程序猿们就能开启“上帝视角”?

简介: 现在,如果有程序猿说不知道Docker,这将是难以想象的。
现在,如果有程序猿说不知道Docker,这将是难以想象的。

百科是这样描述Docker的。“Docker是dotCloud开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。”而更为通俗的说法是,Docker是轻量的虚拟化技术,它拥有“统一、一次操作和随处运行”的特性。
bd3ce47e42709a04ac5a6c08a9c81baa3b3d43d5
在很多程序媛心中,这应该是男神级的程序猿了吧

今年是Docker三周年,Docker之父Solomon Hykesgo说出了自己的愿望,“希望Docker社区能够围绕在它的一些核心理念下不断地发展壮大,特别是我希望能够看到在社区里的每一个人更加理解彼此。这是一个非常庞大并且多元化的社区,我们有开发者、运维人员、企业、狂热爱好者、新手以及专家,我们会有不同的观点、不同的目标、不同的专业背景,这对于我们来说实际上是一件非常好的事情 。和所有社区一样,你会有争执,有时候大家会有强烈的情绪因为大家都关心事情会怎么样发展。我的愿望是这些不同的观点最后能够让我们互相学习,每一个人都能在这个社区里面成长。”

我们来看一组数据。仅2015年,Docker的贡献者增长了183%;GitHub上关于Docker的项目增长了515%;采用Docker构建的应用程序增长了934%;根据DockerHub上镜像下载量统计,容器的下载量增加了18082%!

这里放一张老图,让乃们随意感受一下。
c769091dd2b14cfb21aea1574e3190bcf978ec28

虚拟化技术的“进化史”

从虚拟化技术的演进来看,许多人将Dcoker视为第三代虚拟化解决方案,但这一观点并不是所有人都赞同。从最早的硬件虚拟化,只有特定厂商,特殊的硬件支持的操作系统多租户访问,到运行在通用硬件上的Hypervisor技术,再到当前通过内核特性,以进程方式运行多个容器。

无论技术如何“进化”,都脱离不开性能、成本和隔离等几个关键词。

1990年,应用程序服务提供者服务(application service provider)模式出现。它的运作模式与租用大型主机相同,但租用的资源是在软件层面,包括操作系统以及运行其中的应用程序,例如ERP系统或是CRM等应用。系统可能会运行在数台不同的机器上,或是在相同的主机但共享不同的数据库,以区分并计算客户的资源使用量,藉以作为计费的标准,而此技术也有效地缩减了供应商的实体机器成本。

十年之后,也就是2000年,Hypervisor开始崭露头角。Hypervisor可叫做VMM(virtual machine monitor)即虚拟机监视器。 一种运行在基础物理服务器和操作系统之间的中间软件层,可允许多个操作系统和应用共享硬件。Hypervisors是一种在虚拟环境中的“元”操作系统,它可以访问服务器上包括磁盘和内存在内的所有物理设备。Hypervisors不但协调着这些硬件资源的访问,也同时在各个虚拟机之间施加防护。当服务器启动并执行Hypervisor时,它会加载所有虚拟机客户端的操作系统同时会分配给每一台虚拟机适量的内存、CPU、网络和磁盘。

2010年,应用虚拟化进入人们视野,利用Linux Kernel中的资源分离机制,Cgroups,Namespaces,来建立独立的软件容器(Containers)。这可以在单一Linux实体下运作,避免启动一个虚拟机造成的额外负担。Kernel对命名空间的支援完全隔离了工作环境中应用程序的视野,包括进程树、网络、用户ID与挂载档案系统,而Kernel的Cgroups提供资源隔离,包括CPU、内存、block I/O与网络。从0.9版本起,Docker由Libvirt的LXC与Systemd nspawn提供支持,改为开始采用Libcontainer库直接使用由Kernel提供的虚拟化设施。

Docker与虚拟机的差异

6211deb57678bc08becefe444bc80e7e0b2dd5a2
左图虚拟机的Guest OS层和Hypervisor层在docker中被Docker Engine层所替代。虚拟机的Guest OS即为虚拟机安装的操作系统,它是一个完整操作系统内核;虚拟机的Hypervisor层可以简单理解为一个硬件虚拟化平台,它在Host OS是以内核态的驱动存在的。 虚拟机实现资源隔离的方法是利用独立的OS,并利用Hypervisor虚拟化CPU、内存、IO设备等实现的。

对比虚拟机实现资源和环境隔离的方案,Docker就显得轻量很多,只是对已有技术的封装,Docker利用的是目前Linux Kernel本身支持的方式实现资源和环境隔离。简单的说,Docker利用Namespaces实现系统环境的隔离,利用Cgroups实现资源限制,利用镜像实现根目录环境的隔离。

计算效率上,Docker有着比虚拟机更少的抽象层。由于不需要Hypervisor实现硬件资源虚拟化,运行在Docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上Docker将会有明显优势(最少提高10%,IBM的文章说由于Hypervisor对CPU指令集、NUMA支持的不完整性,浮点运算会提高50%,个人感觉也没那么多)。在IO设备虚拟化上,Docker的镜像管理有多种方案,比如利用Aufs文件系统或者DeviceMapper实现文件管理。

启动效率上,由于不需要Guest OS,当新建一个容器时,Docker不需要和虚拟机一样重新加载一个操作系统内核。我们知道,引导、加载操作系统内核是一个比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载Guest OS,这个新建过程是分钟级的。而Docker由于直接利用宿主机的操作系统,省略了这个过程,因此新建一个Docker容器只需要几秒钟。快速启动、低系统资源消耗的优点使Docker在弹性云平台和自动化运维系统方面有着很好的应用前景。

交付与部署上,Docker做到一次创建或配置,可以在任意地方运行,大量地节约开发、测试、依赖部署等的时间。

相较于虚拟机,Docker也有一些“缺憾”。第一个是资源隔离方面,Docker利用Cgroups实现资源限制,只能限制资源消耗的最大值,而不能完全隔绝其它程序占用自己的资源。第二个是安全性方面,包括鉴权管控、fork炸弹防范等等Docker还是有一些短板,网络资源管理相对简单。另外,Docker对宿主机OS的兼容性也是短板,毕竟现在企业级部署还处在Redhat 5时代。

Docker的工作原理

典型的Linux文件系统由bootfs和rootfs两部分组成。bootfs(boot file system)主要包含Bootloader和Kernel,Bootloader主要是引导加载Kernel,当Kernel被加载到内存中后bootfs就被umount了。rootfs (root file system) 包含的就是典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。
传统的Linux加载bootfs时会先将rootfs设为read-only,然后在系统自检之后将rootfs从read-only改为read-write,然后就可以在rootfs上进行写和读的操作了。

但Docker的镜像却不是这样,它在bootfs自检完毕之后并不会把rootfs的read-only改为read-write。而是利用union mount(UnionFS的一种挂载机制)将一个或多个read-only的rootfs加载到之前的read-only的rootfs层之上。在加载了这么多层的rootfs之后,仍然让它看起来像是一个文件系统,在Docker的体系里把union mount的这些read-only的rootfs叫做Docker的镜像。但是,此时的每一层rootfs都是read-only的,此时还不能对其进行操作。当创建一个容器,也就是将Docker镜像进行实例化时,系统会在一层或是多层read-only的rootfs之上分配一层空的read-write的rootfs。

仓库是一个存储容器镜像的地方,包括搜索、下载、上传三个功能。

Docker Engine作为容器中的主体部分,首先提供Server的功能使其可以接受Docker Client的请求,而后Engine执行Docker内部的一系列工作,每一项工作都以一个Job的形式存在。Job运行过程中,当需要容器镜像时,则从Docker Hub中下载镜像,并通过镜像管理驱动GraphDriver将下载的镜像以Graph的形式存储。当需要为Docker创建网络环境时,通过网络管理驱动NetworkDriver创建并配置Docker容器网络环境;当需要限制Docker容器运行资源或执行用户指令等操作时,则通过ExecDriver来完成。

而NetworkDriver以及ExecDriver都是通过Libcontainer来实现具体的对容器进行的操作。Libcontainer是一个独立的容器管理包,Docker刚发布的时候,它是一款基于LXC的开源容器管理引擎。把LXC复杂的容器创建与使用方式简化为Docker自己的一套命令体系。随着Docker的不断发展,它开始将底层实现都抽象化到Libcontainer接口。这就意味着,底层容器的实现方式变成了一种可变的方案,无论是使用Namespaces、Cgroups技术,抑或是使用Systemd等其他方案,只要实现了Libcontainer定义的一组接口,Docker都可以运行。这也为Docker实现全面的跨平台带来了可能。

目前版本的Libcontainer,功能实现上涵盖了包括Namespaces使用、Cgroups管理、Rootfs的配置启动、默认的Capability权限集、以及进程运行的环境变量配置等。内核版本最好是3.8以上,这与内核对Namespaces的支持有关。目前除User Namespace没完全开放以外,其他五个Namespace都是默认开启的,通过Clone系统调用进行创建。

再谈Docker的优势与劣势

毋庸置疑,Docker当然是好处多多,否则也不可能在几年内发展得如此蓬勃。那么,Docker究竟有哪些好处呢?先归纳一下。

优势

  1. 因为不需要启动内核,所以应用扩缩容时可以秒速启动。
  2. 一键启动所有依赖服务,测试不用为搭建环境犯愁,PE也不用为建站复杂担心。
  3. Docker命令简单、易用,社区十分活跃,Bug提交一周内就改好,且周边组件丰富。
  4. 镜像增量分发,由于采用了Union FS, 简单来说就是支持将不同的目录挂载到同一个虚拟文件系统下,并实现一种layer的概念,每次发布只传输变化的部分,节约带宽。
  5. 直接使用宿主机内核调度资源,性能损失小。
  6. 通过Docker能实现物理机的冷迁移(docker commit 、docker push)。
  7. 动态CPU、内存资源调整。
  8. 使用的人再也不用担心如何搭建服务,清理还原服务。镜像一次固化,随处使用,多个应用版本可以并存在机器上。Jenkins已经支持自动化构建镜像,解决了打包发布麻烦的问题。
  9. 测试、生产环境高度一致(数据除外)。
  10. 应用的运行环境和宿主机环境无关,完全由镜像控制,一台物理机上部署多种环境的镜像测试。
  11. 能实现秒级快速回滚。
  12. 在高性能计算的场景中,容器热迁移可以保证运行了许多天的计算结果不会丢失,只要周期性的进行检查点快照保存就可以。

劣势

  1. 缺乏成熟的开源资源调度、集群管理产品,目前的K8s自成体系,性能问题,使用成本高,Swarm作为官方推荐,功能相对单一,Mesos使用太复杂。
  2. Engine发展速度快、平滑升级困难,一般不支持业务无感知升级。
  3. 存在隔离与安全的问题。
  4. 网络资源管控稍微差一些。
  5. 容器中加载、卸载内核模块会影响其他容器。
  6. 无法像qemu那样模拟嵌入式系统运行环境。
  7. Docker的App Container体系对现有运维体系有着巨大的冲击,在企业级领域推进有很大的阻力(观念、实操等多个层面)。

本文源自微信公众号:IT焦点与评论
9eab8d6c02247df1d144bf3e01ce6f2e78d64505

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
云原生
使用钉钉扫一扫加入圈子
+ 订阅

云原生时代,是开发者最好的时代

其他文章