Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app)。几乎没有性能开销,可以很容易地在机器和数据中心中运行。最重要的是,他们不依赖于任何语言、框架包括系统。
起源
Docker 是 PaaS 提供商 dotCloud 开源的一个基于 LXC 的高级容器引擎,源代码托管在 Github 上,基于go语言并遵从 Apache2.0 协议开源。
Docker 自2013年以来非常火热,无论是从 github 上的代码活跃度,还是 Redhat 在 RHEL 6.5 中集成对 Docker 的支持,就连 Google 的 Compute Engine 也支持 docker 在其之上运行。
一款开源软件能否在商业上成功,很大程度上依赖三件事:1)成功的user case,2)活跃的社区,3)一个好故事。 dotCloud 自家的 PaaS 产品建立在 docker 之上,长期维护且有大量的用户,社区也十分活跃,接下来我们看看 docker 的故事。
-
环境管理复杂:从各种OS到各种中间件到各种App,一款产品能够成功作为开发者需要关心的东西太多,且难于管理,这个问题几乎在所有现代IT相关行业都需要面对。
-
云计算时代的到来:AWS的成功,引导开发者将应用转移到 Cloud 上,解决了硬件管理的问题,然而中间件相关的问题依然存在 (所以OpenStack HEAT和 AWS CloudFormation 都着力解决这个问题)。为开发者思路变化提供了可能性。
-
虚拟化手段的变化:Cloud 时代采用标配硬件来降低成本,采用虚拟化手段来满足用户按需使用的需求以及保证可用性和隔离性。然而无论是KVM还是Xen在 docker 看来,都在浪费资源,因为用户需要的是高效运行环境而非OS,GuestOS既浪费资源又难于管理,更加轻量级的LXC更加灵活和快速。
-
LXC的移动性:LXC在 Linux 2.6 的 Kernel 里就已经存在了,但是其设计之初并非为云计算考虑的,缺少标准化的描述手段和容器的可迁移性,决定其构建出的环境难于迁移和标准化管理(相对于KVM之类image和snapshot的概念)。docker 就在这个问题上做出实质性的革新。这是docker最独特的地方。
VM技术和容器技术对比
面对上述几个问题,docker设想是交付运行环境如同海运,OS如同一个货轮,每一个在OS基础上的软件都如同一个集装箱,用户可以通过标准化手段自由组装运行环境,同时集装箱的内容可以由用户自定义,也可以由专业人员制造。这样,交付一个软件,就是一系列标准化组件的集合的交付,如同乐高积木,用户只需要选择合适的积木组合,并且在最顶端署上自己的名字(最后个标准化组件是用户的app)。这也就是基于docker的PaaS产品的原型。
特性
在docker的网站上提到了docker的典型场景:
-
Automating the packaging and deployment of applications
-
Creation of lightweight, private PAAS environments
-
Automated testing and continuous integration/deployment
-
Deploying and scaling web apps, databases and backend services
由于其基于LXC的轻量级虚拟化的特点,docker相比KVM之类最明显的特点就是启动快,资源占用小。因此对于构建隔离的标准化的运行环境,轻量级的PaaS(如dokku),构建自动化测试和持续集成环境,以及一切可以横向扩展的应用(尤其是需要快速启停来应对峰谷的web应用)。
-
构建标准化的运行环境,现有的方案大多是在一个baseOS上运行一套puppet/chef,或者一个image文件,其缺点是前者需要base OS许多前提条件,后者几乎不可以修改(因为copy on write 的文件格式在运行时rootfs是read only的)。并且后者文件体积大,环境管理和版本控制本身也是一个问题。
-
PaaS环境是不言而喻的,其设计之初和dotcloud的案例都是将其作为PaaS产品的环境基础。
-
因为其标准化构建方法(buildfile)和良好的REST API,自动测试和持续集成/部署能够很好的集成进来。
-
因为LXC轻量级的特点,其启动快,而且docker能够只加载每个container变化的部分,这样资源占用小,能够在单机环境下与KVM之类的虚拟化方案相比能够更加快速和占用更少资源。
局限
Docker并不是全能的,设计之初也不是KVM之类虚拟化手段的替代品,简单总结几点:
-
Docker是基于Linux 64bit的,无法在Windows/Unix或32bit的Linux环境下使用。
-
LXC是基于cgroup等linux kernel功能的,因此container的guest系统只能是linux base的。
-
隔离性相比KVM之类的虚拟化方案还是有些欠缺,所有container公用一部分的运行库。
-
网络管理相对简单,主要是基于namespace隔离。
-
cgroup的cpu和cpuset提供的cpu功能相比KVM的等虚拟化方案相比难以度量(所以dotcloud主要是按内存收费)
-
docker对disk的管理比较有限
-
container随着用户进程的停止而销毁,container中的log等用户数据不便收集。
针对1-2,有windows base应用的需求的基本可以pass了。3-5主要是看用户的需求,到底是需要一个container还是一个VM,同时也决定了docker作为IaaS不太可行。针对6-7,虽然是docker本身不支持的功能,但是可以通过其他手段解决(disk quota, mount --bind)。总之,选用container还是vm,就是在隔离性和资源复用性上做权衡。
另外,即便docker 0.7能够支持非AUFS的文件系统,但是由于其功能还不稳定,商业应用或许会存在问题,而AUFS的稳定版需要kernel 3.8,所以如果想复制dotcloud的成功案例,可能需要考虑升级kernel或者换用ubuntu的server版本(后者提供deb更新)。这也是为什么开源界更倾向于支持ubuntu的原因(kernel版本)。
原理
Docker核心解决的问题是利用LXC来实现类似VM的功能,从而利用更加节省的硬件资源提供给用户更多的计算资源。同VM的方式不同, LXC其并不是一套硬件虚拟化方法 —— 无法归属到全虚拟化、部分虚拟化和半虚拟化中的任意一个,而是一个操作系统级虚拟化方法,理解起来可能并不像VM那样直观。所以我们从虚拟化要docker要解决的问题出发,看看它是怎么满足用户虚拟化需求的。
用户需要考虑虚拟化方法,尤其是硬件虚拟化方法,需要借助其解决的主要是以下4个问题:
-
隔离性:每个用户实例之间相互隔离,互不影响。 硬件虚拟化方法给出的方法是VM,LXC给出的方法是container,更细一点是kernel namespace。
-
可配额/可度量:每个用户实例可以按需提供其计算资源,所使用的资源可以被计量。硬件虚拟化方法因为虚拟了CPU, memory可以方便实现,LXC则主要是利用cgroups来控制资源。
-
移动性:用户的实例可以很方便地复制、移动和重建。硬件虚拟化方法提供snapshot和image来实现,docker(主要)利用AUFS实现。
-
安全性:这个话题比较大,这里强调是host主机的角度尽量保护container。硬件虚拟化的方法因为虚拟化的水平比较高,用户进程都是在KVM等虚拟机容器中翻译运行的,然而对于LXC,用户的进程是lxc-start进程的子进程,只是在Kernel的namespace中隔离的,因此需要一些kernel的patch来保证用户的运行环境不会受到来自host主机的恶意入侵,dotcloud(主要是)利用kernel grsec patch解决的。
方法
随着Docker在云计算市场中领先地位的日益稳固,容器技术也成为了一种主流技术。为了对用户的应用程序使用容器技术,可遵循以下五个步骤。
Docker容器技术已在云计算市场中风靡一时了,而众多主流供应商则面临着技术落后的窘境。那么,是什么让Docker容器技术变得如此受欢迎呢?对于刚入门的新手来说,容器技术可实现不同云计算之间应用程序的可移植性,以及提供了一个把应用程序拆分为分布式组件的方法。此外,用户还可以管理和扩展这些容器成为集群。
在企业用户准备把应用程序迁往容器之前,理解应用程序的迁移过程是非常重要的。这里将介绍把用户应用程序迁往Docker容器的五个基本步骤。
步骤1:分解
一般来说,应用程序都是复杂的,它们都有很多的组件。例如,大多数应用程序都需要数据库或中间件服务的支持以实现对数据的存储、检索和集成。所以,需要通过设计和部署把这些服务拆分成为它们自己的容器。如果一个应用程序能够被拆分成为越多的分布式组件,那么应用程序扩展的选择则越多。但是,分布式组件越多也意味着管理的复杂性越高。
步骤2:选择一个基础映像
当执行应用程序迁移时,应尽量避免推倒重来的做法。搜索Docker注册库找到一个基本的Docker映像并将其作为应用程序的基础来使用。
随着时间的推移,企业将会发现这些Docker注册库中基本映像的价值所在。请记住,Docker支持着一个Docker开发人员社区,所以项目的成功与否很大程度上取决于用户对于映像管理和改良的参与度。
步骤3:解决安全性和管理问题
安全性和管理应当是一个高优先级的考虑因素。企业用户不应再把它们当作应用程序迁移至容器的最后一步。反之,企业必须从一开始就做好安全性和管理的规划,把它们的功能纳入应用程序的开发过程中,并在应用程序运行过程中积极主动地关注这些方面。这就是企业应当花大功夫的地方。
基于容器的应用程序是分布式应用程序。企业应当更新较老的应用程序以支持联合身份管理方法,这将非常有利于确保分布式应用程序的安全性。为了做到这一点,应为每一个应用程序组件和数据提供一个唯一的标识符,这个标识符可允许企业在一个细粒度的级别上进行安全性管理。企业用户还应当增加一个日志记录的方法。
步骤4:增加代码
为了创建映像,企业用户需要使用一个Dockerfile来定义映像开发的必要步骤。一旦创建了映像,企业用户就应将其添加至Docer Hub。
步骤5:配置、测试、部署
应对在容器中运行的应用程序进行配置,以便于让应用程序知道可以在哪里连接外部资源或者应用程序集群中的其他容器。企业用户可以把这些配置部署在容器中或使用环境变量。
对基于容器的应用程序进行测试类似于对其他分布式应用程序的测试。企业可以对每个容器进行组件测试,并将容器集群作为一个整体进行测试。 确定应用程序应如何能够在负载增加的情况下进行扩展。如果用户正在使用一个集群管理器(例如Swarm),则可测试其性能。
最后,把容器部署到实际生产环境中。为了积极主动地关注基于容器的应用程序的运行状况,可考虑实施必要的监控和管理机制。确保打开日志记录功能。
很多应用程序迁移至云计算都是采用容器技术的。虽然迁移有一点复杂,但是容器可以保护应用程序投资并赋予了它一个更长的使用寿命。
安全
1. 确保Docker环境安全
Docker十分火热,很多人表示很少见到如此能够吸引行业兴趣的新兴技术。然而,当兴奋转化为实际部署时,企业需要注意Docker的安全性。
了解Docker的人都知道,Docker利用容器将资源进行有效隔离。因此容器相当于与Linux OS,和hypervisor有着几乎相同的安全运行管理和配置管理级别。但当涉及到安全运营与管理,以及具有保密性、完整性和可用性的通用控件的支持时,Docker可能会让你失望。
当容器运行在本地系统上时,企业可以通过其安全规则确保安全性。但一旦容器运行在云端,事实就不会如此简单了。
当Docker运行在云提供商平台上时,安全性变得更加复杂。你需要知道云提供商正在做什么,或许你正在与别人共享一台机器。
虽然容器没有内置的安全因素,而且像Docker这样的新兴技术很难有比较全面的安全措施,但这并不意味着以后也不会出现。
2. 确保容器部署安全性
也有专家将Docker安全问题的实质定位于配置安全,认为Docker目前的问题是很难配置一个安全的容器。虽然现在Docker的开发人员通过创建非常小的容器来降低攻击面,但问题在于大型企业内部在生产环境中运行Docker容器的员工需要有更多的可见性和可控性。
专家认为,大约90%的外部网络攻击并不是超级复杂的,攻击者多是利用了管理员的行为漏洞,比如配置错误或者未及时安装补丁。
因此,企业在部署数千或数万台容器时,能够确保这些容器都遵守企业安全策略进行配置是至关重要的事情。
为解决这个问题,就需要增加Docker容器部署的实时可见性,同时实施企业制定的安全策略。
3. 硬件上的Docker安全中心
在新的功能中有硬件的部分,可以跨任何基础架构,允许开发和随后的升级中的数字编码签名。构建在Docker Trust框架之上用来进行镜像发布者认证,同时进行新的镜像扫描和官方漏洞检测,以便能够更好地理解容器内部是什么。
命名空间是本周发布的另外一个Docker安全升级。允许IT运用来为基于用户群组的容器指派授权,约束了主机的访问根源,并指定了系统管理员,限制了群组对于指定服务的访问。
镜像扫描对于Docker Hub上的所有官方版本都可用,同时命名空间和硬件签名则在Docker的实验渠道提供。
安全问题仍旧是容器采纳要解决的最大问题,尤其是如果大量容器是便携的,IDC研究经理Larry Carvalho说道。通过硬件解决这个问题很明智,因为这样更难以介入,并且提供了未来可能被使用的大量容器的效率。
Carvhalho说:“他们还应该解决的一个问题是容量,你没有办法在软件层面做大量的安全,因为要有很多开支。”
应用
有了docker这么个强有力的工具,更多的玩家希望了解围绕docker能做什么。
1. Sandbox
作为sandbox大概是container的最基本想法了 —— 轻量级的隔离机制,快速重建和销毁,占用资源少。用docker在开发者的单机环境下模拟分布式软件部署和调试,可谓又快又好。
同时docker提供的版本控制和image机制以及远程image管理,可以构建类似git的分布式开发环境。可以看到用于构建多平台image的packer以及同一作者的vagrant已经在这方面有所尝试了。
2. PaaS
dotcloud、heroku以及cloudfoundry都试图通过container来隔离提供给用户的runtime和service,只不过dotcloud采用docker,heroku采用LXC,cloudfoundry采用自己开发的基于cgroup的warden。基于轻量级的隔离机制提供给用户PaaS服务是比较常见的做法,PaaS 提供给用户的并不是OS而是runtime+service,因此OS级别的隔离机制向用户屏蔽的细节已经足够。而docker的很多分析文章提到『能够运行任何应用的“PaaS”云』,只是从image的角度说明docker可以从通过构建image实现用户app的打包以及标准服务service image的复用,而非常见的buildpack的方式。
由于对Cloud Foundry和docker的了解,接下来谈谈笔者对PaaS的认识。PaaS号称的platform一直以来都被当做一组多语言的runtime和一组常用的middleware,提供这两样东西,即可被认为是一个满足需求的PaaS。然而PaaS对能部署在其上的应用要求很高:
-
运行环境要简单 - buildpack虽然用于解决类似问题,但仍然不是很理想。
-
要尽可能的使用service - 常用的mysql, apache倒能理解,但是类似log之类的如果也要用service就让用户接入PaaS平台,让用户难以维护。
-
要尽可能的使用"平台” - 单机环境构建出目标PaaS上运行的实际环境比较困难,开发测试工作都离不开"平台”。
-
缺少可定制性 - 可选的中间件有限,难于调优和debug。
综上所述部署在PaaS上的应用几乎不具有从老平台迁移到之上的可能,新应用也难以进入参数调优这种深入的工作。个人理解还是适合快速原型的展现,和短期应用的尝试。
然而docker确实从另一个角度(类似IaaS+orchestration tools)实现了用户运行环境的控制和管理,然而又基于轻量级的LXC机制,确实是一个了不起的尝试。 笔者也认为IaaS + 灵活的orchestration tools(深入到app层面的管理,如bosh)是交付用户环境最好的方式。