简谈程序猿不得不知道的Docker容器

Docker 主要解决什么问题:

Docker对外宣称的是Build、Ship 和Run,Docker 要解决的核心问题就是快速地干这三件事情。
它通过将运行环境和应用程序打包到一起,来解决部署的环境依赖问题,真正做到跨平台的分发和使用。
而这一点和DevOps不谋而合,通过Docker可以大大提升开发、测试和运维的效率。在这个移动互联网的时代,
如果一个工具能够节省人力,提升效率,必定会流行起来。
百科是这样描述Docker的。“Docker是dotCloud开源的应用容器引擎,让开发者可以打包他们的应用以及
依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。容器是完全
使用沙箱机制,相互之间不会有任何接口。”而更为通俗的说法是,Docker是轻量的虚拟化技术,它拥有
“统一、一次操作和随处运行”的特性。

Docker 的历史:

之前提到一家公司叫DotCloud,这家公司是一家法国的公司,最初也是提供PaaS服务的,他们提供了对多种语言
的运行环境支持,如Java、Python、Ruby、Node.js等。但是,可能叫生不逢时吧,在PaaS领域有太多的巨头
和大企业了,有一天SolomonHykes(Docker之父)就召集了公司的哥儿几个来商量了一下,最后得出的结论是,
如果要和那些大厂商硬干肯定是不行的,那么干脆就把他们做的项目Docker开源了。即使赚不到钱,至少也在
开源社区得到一个好名声。
因此,在20133月,Docker正式以开源软件形式发布了。正是由于这次开源,让容器领域焕发了第二春,
截至201511月,Docker在GitHub上收到了25600个赞,超过6800次克隆,以及超过1100名的贡献者,
成为20个最具影响力的GitHub开源项目。可以说,Docker是继Linux之后,最让人感到兴奋的系统层面的
开源项目。据不完全统计,包括Docker公司、Red Hat、IBM、Google、Cisco、亚马逊及国内的华为等,
都在为它贡献代码。在美国,几乎所有的云计算厂商都在拥抱Docker这个生态圈。

Docker 是什么:

Docker 其实是容器化技术的其中一种实现,根据我们之前的介绍,容器化技术并不是最近才出现的,那为什么Docker
会如此的火爆呢?还是这个时代造就的,因为我们处在一个云计算发展异常迅猛的时代,而云计算又是所有移动互联网、
IT,以及未来消费者行业的基础。从云计算服务的三层架构可以看出,传统的IaaS层、虚拟机是基础组成部分,而虚拟机
都是基于Hyper-V架构的,也就是说,每一个虚拟机都会运行一个完整的操作系统,一个操作系统至少需要占用5GB左右
的磁盘空间,但是操作系统对于我们来说是完全无用的,我们关心的是虚拟主机所能提供的服务。因此,迫切需要轻量级
的主机,那就是Docker容器。我们可以看一下,Docker和虚拟机的区别。

这里写图片描述

容器由于省去了操作系统,整个层级更简化,可以在单台服务器上运行更多的应用,而这正是IaaS所需要的,
可能5GB左右的空间对你来说不是什么大事,但是如果需要对外提供成千上万的主机,那就是不得不考虑的问题,
而这正是容器虚拟化要解决的问题。

容器和镜像

容器和镜像是Docker 最核心的部分,使用Docker时实际就是在容器里面运行一个镜像。

什么是容器

很多用户在接触Docker之初都会认为容器就是一种轻量级的虚拟机,但实际上,容器和虚拟机有非常大的区别。
从根本形态上来看,容器其实就是运行在操作系统上的一个进程,只不过加入了对资源的隔离和限制。在学习操作
系统时,都会学习什么是进程,简单地讲,进程就是一个运行的程序。传统上,在运行一个进程时,如果里面出现
死循环,CPU就会一下被占用完;如果出现内存泄露或者大内存分配,就可能会把系统的内存用完,这是因为默认
进程间共用了CPU和内存。但是这种不进行任何隔离的处理方式,就会遇到相互间干扰的问题,在企业级产品环境中,
这一点是非常致命的,任何一个小程序都可能导致整个系统的不可用。
因此,早在2006年就出现了进程间的资源隔离技术,后来Linux也同样有了类似的实现。最初,Linux的容器技术
是基于LXC的,Docker在易用性和稳定性方面做了很大改善,其三大核心功能就是CGroups、Namespace 和UnionFS。
CGroups技术用来限定一个进程的资源使用;在一个操作系统之上,用户ID、机器名等资源是全局的,运行的进程间都是
访问同一份资源,为了达到隔离的目的,Linux又出现了Namespace 技术用来划分不同的命名空间;而UnionFS则是用
来处理分层镜像的功能。
说明:LXC是Docker早期使用的技术,后来Docker自行开发了libcontainer,二者都是对Linux内核功能的封装。
在安装了Docker的机器上,可以通过run命令启动容器,并通过ps命令查看已存在的容器。

什么是镜像?

容器是一个动态的概念,而镜像是一个相对静止的概念。简单来说,镜像就是容器中的文件系统。早在1980 年
就出现了文件系统管理技术,那就是chroot系统调用。通过该技术可以改变进程运行的工作目录,并将其限定
在这个目录中,不过它只能做简单的隔离,而且存在安全隐患。因此Docker就使用了,注意不是设计了一个
Layered FS,它把文件系统分成多个层,使多个容器间可以使用公共的部分。而镜像就是由Layered FS组成的,
并且它是只读的。当容器运行时,会在镜像之上再加上一层可读可写层。
说明:镜像除了包含文件系统,还集成了一部分容器运行的参数,可以将镜像看作容器的模板。

容器和镜像的关系

容器和镜像是密切相关的,二者缺一不可,也是可以相互进行转换的。

这里写图片描述

Docker 的镜像最初是从官方的仓库拉取获得的,之后通过docker run 即可启动一个容器运行。当需要将
容器转化为镜像时,可以通过docker commit 进行转化。

虚拟化技术的“进化史”

从虚拟化技术的演进来看,许多人将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与虚拟机的差异
这里写图片描述

左图虚拟机的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的文章说由于
HypervisorCPU指令集、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的优势与劣势
优势

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

劣势

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

本文参考博客:https://yq.aliyun.com/articles/48695
http://www.broadview.com.cn/article/90

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值