如何更好地使用容器技术实现不可变基础设施
不可变基础设施的构想
不可变基础设施(Immutable Infrastructure)是由 Chad Fowler 于2013年提出的一个很有前瞻性的构想:在这种模式中,任何基础设施的实例(包括服务器、容器等各种软硬件)一旦创建之后便成为一种只读状态,不可对其进行任何更改。如果需要修改或升级某些实例,唯一的方式就是创建一批新的实例以替换。这种思想与不可变对象的概念是完全相同的。
实现这种模式的好处是显而易见的,这意味着配置工作可实现重复性,减少了配置管理工作的负担,让持续集成与持续部署过程变得更流畅。同时它也更易于应对部署环境间的差异及版本管理,包括在部署出错时可进行快速回滚 —— 只要旧版本的镜像文件还有备份,就可以快速地生成旧版本的实例进行替换。否则的话,就只能老老实实地重新构建旧版本的实例,并且祈祷能够赶在老板掀桌之前完成回滚。
实现这一模式需要满足两点基本需求,首先应用程序必须是 无状态的 ,不可依赖于本地的文件上传、会话与缓存。基本上,如果应用程序要实现负载均衡,都必须满足这一点。而更重要的一点是,能够通过某种 模板 (或指令)将实例快速地部署到生产环境中。后一点无疑是关键所在,也是这一模式的最大挑战。
虽然这种模式能够带来很大的好处,但实现它的难度也是很高的,传统的虚拟化技术在应对这一模式时显得有些力不从心。幸运的是,DevOps社区发现Docker(或者说容器)正是实现这一模式的优秀选择。
使用容器实现不可变基础设施
来自Tutum的 Fernando Mayo 近期在一篇博客中详细地论述了使用容器技术实现不可变基础设施的优点。他首先指出,容器并不是实现这一模式的唯一选择,使用虚拟机模板、或者通过Chef 与Puppet这样的配置管理工具同样可以实现这一目的。但这些方式都面临着一些负面因素,前者需要为不同的云环境创建针对不同版本的大量虚拟机模板,后者则需要对配置管理脚本进行持续地测试,其负担是显而易见的。
Fernando推荐使用容器作为实现不可变基础设施的途径,因为通过它进行实例创建、测试与部署比起虚拟机与配置脚本快得多。而且使用容器能够消除应用程序依赖的问题,因为所有的依赖都与应用程序一起封装在容器中,因而进一步缩短了整体部署时间。同时,容器也解决了对特定云环境的依赖,只要能够运行 Docker,无论是哪种Linux环境都可以一视同仁( Windows Server也快了 )。
接下来要做的是使用容器实现自动化的部署,包含两个步骤。第一步是创建容器镜像文件,Fernando推荐使用 经优化 的Dockerfile,这种方式非常简便快速,可以在持续集成或持续交付平台中对其进行测试后再进行部署。第二步就是最后的部署工作了,常见的做法是手动将容器部署到服务器上,然后将负载均衡器指向这些服务器以接受用户访问。这一点可在实例级别实现(例如在每个AWS EC2实例中配置一个应用程序的容器,通过Elastic Load Balancer在实例间进行切换),也可以在容器级别实现(通过Haproxy或Nginx容器将访问转发到应用程序容器)。那么如何通过自动化方式完成第二步呢?Fernando在此推荐了自家的产品 Tutum !
使用Tutum实现容器的自动化部署
Tutum为Docker容器提供了托管服务,通过使用Tutum,部署应用程序的新版本变成了一件非常简单的任务,只需在服务定义中修改镜像的标签,然后点击“ 重新部署 ”即可。
而在非生产环境中(例如QA或UAT环境),回滚到应用程序的某个特定版本并不是非常重要的任务,这种情况下甚至可以选择对“重新部署”进行自动化,可以通过使用Tutum的“ 自动重新部署 ”特性,或使用DockerHub的重新部署 触发器 。
在重新部署流程启动之后,Tutum将会逐个地用新的容器替换旧的容器,随后通过 tutum/haproxy 镜像实现访问的转发,这个镜像会根据所链接的容器进行自动配置。这种方式还能够实现新版本与旧版本的服务的同时运行,只需在tutum/haproxy服务中添加一个到新镜像的链接就可以将访问同时转发给新版本与旧版本的服务。
Tutum还能够实现数据卷的重用,因为在多次部署之间的数据卷是持久化的。如果你重新部署了一个 tutum/mysql 容器,它就会自动在/var/lib/mysql路径下创建一个数据卷,Tutum将重用这个数据卷,并保持所有数据不会丢失。
来自社区的其它声音
虽然Docker为代码的部署与不可变环境的创建提供了一个坚实的基础,但人们也开始反思:绝对的不可变性是否能够应对应用程序的复杂性与多样性?就在去年,Docker 推出 了一个新的特性,允许“可写的 /etc/hosts,/etc/hostname,以及/etc/resolv.conf”,这就意味着可以对运行中的容器进行修改。这不由令人心生疑惑,难道Docker打算远离“不可变基础设施”这一思想,还是说这一思想本身尚有不足之处?
对此,VisualOps的创始人兼CEO赵鹏在 一篇博客 中表达了他的观点,他认为Docker虽然能够跨多个不同的部署平台保证一致性,但许多配置信息是特定于上下文的,因此不必死守纯粹的不可变性这一思想。而Docker的这一特性能够避免配置信息对于代码及应用程序产生的侵入性,可以通过某种编排工具使用这一特性,在运行时对应用程序进行特定的配置。
而来自Chef的产品经理 Julian Dunn 也 表达 了类似的看法,他认为纯粹的不可变性既不实际,也并非一种理想状态,在使用应用程序的过程中仍然会产生可变的部分。在这种情况下,配置管理工具(例如Chef)仍有用武之地,它可以对其中“可变”的部分配置进行有效地管理。