@xishuixixia
2016-06-05T14:04:14.000000Z
字数 2551
阅读 2317
Docker
运维
容器
应用运维需要考虑的一个重要问题就是迁移,在不同机器、机房、环境间迁移。迁移的原因有很多,比如硬件过保(硬件故障),机房迁移,应用扩缩容等。
应用迁移的核心需求是:
许多公司还在使用古老的 RHEL 5/6 和 Linux 2.6.x 内核,难以充分发挥现代操作系统和硬件的能力,部分原因也是受制于应用迁移技术不成熟,不能保证快速无损迁移应用,不敢迁移。
具备快速迁移的能力,同样可将应用快速切换到任意版本,实现快速回滚。
我们看一下一个基于 Tomcat 部署的 Java webapp 应用部署结构如下:
apache-tomcat-8.0.35/
├── bin/
├── conf/
├── lib/
├── logs/
├── temp/
├── webapps/
├── work/
├── LICENSE
├── NOTICE
├── RELEASE-NOTES
└── RUNNING.txt
其主要分为两个部分:
bin/
,lib/
。这部分是三方软件包 Tomcat 自带的内容。对应用而言,这部分内容是只读访问的,不会修改。conf/
,logs/
,temp/
,webapps/
,work/
。这里的“外部”是指从 Tomcat 软件包的角度来看,对应用来说,这部分才是真正的应用软件包。注意:Tomcat 软件包也包含 conf/
。但应用可能会对 conf/
进行修改,所以应用使用了一个独立维护的 conf/
副本,而不是 Tomcat 软件包自带的 conf/
内容。
很显然,要迁移这个应用,只需要迁移第 2 部分,即外部配置和数据即可。为了简化迁移,许多应用被设计为无状态的,即 logs/
,temp/
,work/
等外部数据目录不包含任何影响应用功能的配置或数据,这部分内容不需要迁移。只需要迁移 conf/
,webapps/
目录,这部分内容可打包为应用软件包。
这样,在新环境部署应用,只需要安装 Tomcat 软件包和应用软件包即可。
在新环境上完成应用部署,有两种玩法:
列一个软件包清单(如上例中的 Tomcat 和应用),在新环境上按照清单完成软件包安装,这是 juju 的玩法。
将所有软件包安装好并打包成一个二进制镜像,拷贝到新环境上部署运行,这是 Docker 的玩法。Dockerfile 描述如何创建镜像,类似于软件包清单。
Docker 镜像不止是预安装软件包,还包含基础操作系统环境,统一的日志、数据路径,环境变量等标准化应用运行环境。这可难不倒 juju,juju 同样基于一个标准镜像创建 VM 或 LXC 容器,再安装软件包,同样提供标准化的运行环境。这两种方式各有优缺点,在此不作深究。但就使用成本来说,Docker 目前在国内外发展火热,技术和实践经验相对成熟,更容易使用。
使用 Docker 应用容器部署应用,Docker 容器为应用提供了标准一致且相互独立的运行环境,这样应用使用相同的配置和路径,也可以在单个宿主机上实现多实例部署。与 VM 的单机单部署模式相比,应用容器要做的足够轻,消除 VM 的额外开销,并且完美支持微服务编排。
有些软件包很好的实现了软件包默认配置与应用自定义配置的分离,如 Tomcat,只需指定 CATALINA_BASE
目录与 CATALINA_HOME
目录分开,将应用部署到 CATALINA_BASE
下,即可实现应用自定义配置和 Tomcat 软件包默认配置分离,两者独立维护,互不影响。
许多软件包没有实现这样的能力,Docker 通过分层文件系统解决这个问题,同时可以避免每个软件包都去考虑设计配置分离功能。
应用自定义配置在软件包安装层的上层,运行容器时覆盖默认配置,但在软件包安装层升级软件包时看不到应用自定义配置,不会受应用自定义配置影响。需要注意的是,软件包升级后是否兼容旧的应用自定义配置,是否需要更新自定义配置,需要应用负责人关注和测试。
按照 Docker 的分层设计思想,越基础越固定不变的东西越要放到底层,越容易变化的东西越要放到上层,因此应用依赖的软件包和基础配置要放到底层,可以独立为一个 base 镜像,应用本身和自定义配置放在上层。如果应用本身或配置更新更频繁,可将这两者再分成两层。
假设我们要修改一个应用配置,一种方式是登陆一台机器修改,测试 ok 后将修改同步到所有其它机器。这种方式很原始并且缺乏监管,容易出错。比如新扩容了 100 台机器每台都要更新一遍,如果操作有遗漏,哪些机器配置已经更新,哪些机器还是旧的配置也缺乏监管。
按 Docker 的玩法,应该是先更新镜像,测试 ok 后分发镜像到所有机器更新容器。Docker 监管了所有容器部署的镜像版本和容器状态,从而可以很方便的检查哪些容器更新了,哪些没有更新。对于很少变化的静态配置,应该固化到镜像中。
对于一些经常变化的配置,重新打镜像和更新容器成本太高, 应该设计成预定义的开关,通过开关平台进行监控和管理。或者通过 diamond 等专门的配置管理平台来管理。
Docker 容器内的文件系统伴随容器而生,销毁或更新容器时(如升级镜像或修改容器配置),原有数据将会丢失。并且受分层文件系统设计影响,其性能可能更差(与存储引擎实现有关)。
因此,需要持久化保存的配置和数据,或有高写性能要求的,如 logs/
,data/
等外部数据目录,应使用 Docker 数据卷 挂载到宿主机上。
Dockerfile 中使用 VOLUME
指定容器中需要挂载为数据卷的目录列表。
综上所述,Docker 化运维需要将应用拆分为 3 部分:
部署运维时,使用 Docker 分发镜像,配置平台推送配置,即可实现应用快速部署、迁移、更新、回滚、扩缩容等运维操作。