【编者的话】在以Docker为代表的容器技术普及之前,CFEngine、Puppet、Chef、Ansible之类的配置管理工具曾是运维的神器。在容器化以后,这些传统的配置管理工具还是否适用?用了容器后还需要配置管理吗?容器中的服务该如何运维?本次分享将对这些问题进行逐一探讨。
@Container容器技术大会将于6月4日在上海光大会展中心国际大酒店举办,来自Rancher、携程、PPTV、蚂蚁金服、京东、浙江移动、海尔电器、唯品会、eBay、道富银行、麻袋理财、土豆网、阿里百川、腾讯游戏、数人云、点融网、华为、轻元科技、中兴通讯、中国民生银行、长安汽车等公司的技术负责人将带来实践经验分享,欢迎感兴趣的同学参加。
传统的配置管理工具对容器是否适用?
Docker开源的早期,确实有不少人尝试使用Puppet、Ansible之类的配置管理工具来管理容器。比如Puppet的Docker模块,可以完成Docker Daemon的安装配置、容器的创建等操作,这个模块相当于对yum/apt等包管理工具和Docker CLI的封装。
Ansible也有Docker模块,相当于对docker run命令的封装。
由此可见,通过传统的配置管理工具确实可以在一定程度上管理Docker。
但问题是Docker的命令行本身已经足够简单,再用各种基于DSL的配置文件封装一层有必要吗?这不是简单问题复杂化了吗?
也许有人可能会说通过这些配置管理工具可以批量管理多台机器上的Docker。但我觉得与其学习那些繁琐的DSL配置文件,还不如果直接写个简单的脚本批量在多台机器上执行Docker命令来的快。
说到用Puppet管理Docker,以前还有人尝试通过Puppet来制作Docker镜像。
大致做法是先制作个安装了Puppet的镜像作为Base镜像,然后基于这个Base镜像创建容器,把现有的Puppet配置文件添加进去,然后在容器里执行puppet apply,最后把容器commit成镜像。
这种做法的问题是制作出来的镜像会非常大,不利于存储和传输。而且镜像的详细构建过程无法通过docker history命令查看到。
通过Puppet之类的工具确实可以批量完成Docker Daemon的部署,但仍然存在问题:
- 安装完操作系统后先装个Puppet,再通过Puppet模块安装Docker,安装Puppet的成本其实已经大于直接通过执行yum install或者apt-get install安装Docker的成本了。
- 系统中多了个Puppet软件,Puppet本身也需要维护,无疑增加了维护成本。
以上案例说明用传统配置管理工具管理容器确实有些鸡肋。
用了容器以后,还需要配置管理吗?
起初我们跟Docker官方一样,属于理想主义派。天真的认为容器就应该是inmutable的,当需要配置变更的时候,重新构建镜像重新部署。基于这一思路,我们在cSphere中添加了个镜像自动构建模块,用户可以配置代码仓库的地址。服务的配置文件保存于Git或者SVN库中,需要配置变更时,向版本库中Push一下,自动通过hook触发镜像构建,并自动完成线上容器的重建。
通过这套系统,用户可以非常方便的批量更新线上的服务,并不局限于配置文件的变更,代码的变更也天生支持。
经过实际使用,这套系统能够很好的满足开发和测试环境的需求,提升工作效率。
但是,在生产环境中使用的时候,我们发现这种流程其实并不那么完美,主要表现在:
- 镜像构建和部署虽然自动化了,但构建是针对VCS中的某个仓库的,改一行配置就得整体重新构建一下,在更新容器时还需要把镜像重新分发到所有机器上,配置变更速度太慢。
- 这种方式的配置变更会涉及到服务的重启,这在生产环境某些场景下是不可接受的 ,有可能引起短暂的服务中断。
综上,我们认为即使用了容器,对容器内部的配置文件的管理仍然需要一套自动化的工具来完成。
我们如何打造Docker Native的配置管理系统
前面提到用传统的配置管理工具来管理容器是鸡肋的,那么容器里的配置文件到底该如何管理呢?根据我们一贯的作风,轮子不好用时,就创造个改良版的轮子。
下面我来简单介绍一下cSphere平台的配置管理系统。
容器配置管理的需求:
- 一致性(用不用容器这都是个硬需求)
- 模板化(同上)
- 尽可能在配置变更时不重启容器
- 配置文件与容器的强绑定(容器销毁重建时,其配置文件应该自动跟随)
- 配置参数动态获取(如:数据库的域名、端口)
- 需要保证容器创建之后、启动之前配置文件已经Ready
- 易用性(包括配置变更成本、配置文件管理系统本身的维护成本)
一致性方面,我们通过一个分布式的中心存储来保存所有配置文件的模板。
配置文件下发时,统一由分布于每个Docker主机上的Agent从中心获取。
同时对每个Docker主机进行监控,在配置下发前确认每个agent的健康状态。
cSphere本身是全部使用go语言开发的,配置文件也采用go template进行模板化管理。
控制器收到Agent的“获取配置文件”请求后,先读取配置文件模板,然后加载相关的各种参数以及用户自定义参数,解析模板生成目标配置文件返回给Agent。
Agent收到控制器返回的配置文件内容后,把目标配置文件“装”到容器里并根据配置设置配置文件的权限、执行用户自定义的脚本或者内置动作让配置文件生效(如:向容器里的nginx发送HUP信号、重启容器,执行任意命令等)。
控制器会自动把与该容器相关的各种参数暴露给配置模板,用户可以在配置文件模板里引用包括容器所在主机的内存、与容器关联的服务的各种参数等
示例:
通过上图中的配置文件模板,可以生成一个智能的haproxy配置文件。
该配置模板下发时,会自动把haproxy这个容器环境变量中“BackendSrv”这个Key对应的服务下所有容器的IP添加到haproxy这个配置文件里,后端端口由{{.BACKEND_PORT}}这个用户自定义变量指定。
用户自定义变量在部署的时候,可以Web管理面板指定。
配置文件通过应用名+服务名与容器绑定,在新建或者重建容器时自动生效。
创建容器时,我们不直接使用Docker CLI的docker run命令来创建容器,而是通过三步完成:
这样确保容器启动之前已经加载了正确的配置文件。
Create -> 下发配置 -> Start
配置变更后,agent会自动通过docker exec到容器里执行用户定义的相关动作,如:killall -HUP nginx,尽可能避免了强制重启容器生成的服务中断。
这种容器原生的配置文件管理机制的优点:
- 通过利用编程语言自身的模板语法,让配置文件的编写像写代码一样简单,灵活度高,学习成本低。
- 与cSphere产品整合度高,无需安装额外的软件包,易维护。
- 可视化,包括配置文件的编辑、模板变量的定义、配置文件下发都通过可视化界面完成。
- 内置版本管理,方便一键回滚。
- 高效,可以在秒级完成成百上千个容器的配置变更。
Q&A
Q:有两个问题,基础镜像的继承管理和如何处理多个技术栈的应用版本。举个例子,我们对于CentOS 7,做了公司级别的基础OS镜像A,基于这个镜像加入了JDK成为镜像B,基于B加入了JBOSS成为C,在C的基础上再构建项目的APP镜像D。问题来了1,有没有办法针对A镜像修改了,B,C和D去级连更新。2,由于是继承关系,各层软件的版本不同,导致镜像种类就特别多,例如JDK有3种,jboss有三种,那么镜像C就有九种,技术栈深了,命名又成为了问题。求指导解决思路?Q:我有个问题。现在这个平台只是Web服务级的PaaS平台么?
A:镜像如果涉及到继承,需要通过Jenkins之类的工具实现链式自动构建。 Jenkins中的任务可以设置触发条件,在某个任务完成后自动触发本任务。依赖关系可以在Jenkins的Jobs里面定义清楚。
镜像命名问题,可以用镜像名+tag的方式,如:tomcat:8-jre-7
Q:有没有打算开源你们这套容器的配置管理系统?
A:cSphere目前除支持Web服务外,还支持任意复杂度的企业级应用。可以实现多个相互关联的服务的一键快速部署和环境Clone。
Q:这里Agent能否理解成通过伙伴进程的方式来实现的配置管理?那是否连带有服务发现的功能?
A:目前我们有企业版和免费版。其中免费版可以根据我们官方网站上的文档自己安装部署。开源方面我们主要以向Docker的开源项目中贡献代码为主。
Q:请问据你所知其他类似平台如何解决刚刚提到的配置问题呢?
A:这里的Agent就是cSphere在每台主机上的Agent,该Agent与控制器协同处理所有管理工作,包括配置引擎。配置引擎本身支持应用、服务、容器、节点四种对象的发现,不仅仅是服务发现。
Q:请问嘉宾,你们这个配置管理系统是自己完全独立开发的,还是借鉴了哪个开源项目?
A:据我所知,包括Docker官方产品在内的一些产品还是主要以修改配置后重启容器或者通过-v参数映射配置文件的方法解决。这样做主要问题是配置文件的更新与容器的生命周期联动不起来
Q:能否详细讲解下Agent如何装载配置文件的
A:配置管理系统完全是我们自己独立开发的。配置管理的Agent除负责配置管理外,还负责控制器与各主机上的Docker Daemon的通信、监控数据采集等工作。
Q:Create -> 下发配置 -> Start这样确保容器启动之前已经加载了正确的配置文件。这一步的下发配置是怎么做的,因为那个时候容器还没启动?
A:Docker 1.9为了支持所谓的“完全客户端镜像构建”能力,为docker cp命令添加了向容器传文件的API。我们通过这种机制把配置文件“装”到容器里
Q:支持批量部署上百台服务吗?自定义部署到不同的环境。
A:向容器里copy文件并不需要容器处于运行状态,只要容器存在就能copy。
A:cSphere的配置引擎,支持批量下发,可以选择某个服务或多个服务,也可以针对个别容器做灰度下发,同时支持上千容器没有问题。另外针对不同环境部署,可以通过配置模版化能力,解决环境之间的微小差异,既可以通过用户定义变量,也可以通过类似发现的技术自动计算出对应参数,比如MySQL InnoDB的Buffer需要根据内存做一个公式计算。
Q:请问Agent在发现新的配置后,针对不同容器是执行不同命令是怎么管理的?执行的命令和容器中应用运行状态有关系吗?
A:在配置文件下发后执行的命令是与容器所属的应用关联的,要执行的命令并不是配置文件的一个属性。比如:某个配置文件同时在A应用和B应用里都用到,可以配置为在A应用下发后执行restart container,同时在B应用中下发后什么也不干。
Q:cSphere是企业PaaS平台,请问Agent程序是否开源?如果不是企业在自己的机器上安装闭源程序会不会有担忧。
以上内容根据2016年5月19日晚微信群分享内容整理。分享人 魏世江,云栈科技(希云cSphere)技术负责人,Docker代码贡献者,目前在Docker开源项目中代码贡献量全球排名50名左右。创业之前在新浪负责PasS平台(SAE)的各种基于Web的服务管理系统的设计及开发,全程参与了SAE从无到有、从3台虚拟机到后来支撑30多万应用和十几亿日PV(13年数据)的整个过程,在PaaS建设及DevOps方面积累了丰富的经验。2013年底离开新浪,与前SAE总监王利俊先生一起创立了云栈科技,主要做基于Docker的企业级私有PaaS产品(cSphere)及容器相关解决方案。 DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesz,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。
A:我们的客户没有过这方面担忧。首先客户基本都是内网。其次客户在过去大量使用vSphere,同样没有这样的担心。客户关心的是你的产品是否能解决自己的实际问题。
有疑问加站长微信联系(非本文作者)