中国开源云联盟容器工做组成立后的第一次活动——数人云对话Docker&Mesos沙龙活动圆满落下帷幕。本篇文章是活动的实录分享,介绍了CNTV容器技术的探索与实践,在以高安全、高可用和弹性伸缩为需求的前提下,容器技术具体在CNTV是如何落地的。php
本文内容主要有如下五点:第一,CNTV为何要用容器,第二,CNTV容器管理平台的选型,第三,容器在CNTV的发展与现状,第四,案例分享,第五,容器将来发展。前端
张航源,CNTV技术中心高级工程师
2009年加入CNTV,现任技术中心高级工程师,主要负责CNTV容器化的探索和平台搭建,存储平台的架构和运维,以及ELK平台的建设等工做。web
CNTV是中国网络电视台的简称,是中国中央电视台旗下的一个网络媒体播出机构,于2009年12月28日正式开播。中国网络电视台能够理解为基于视频内容为主的一个互联网网站。在今年6月,CNTV很荣幸地加入了中国开源云联盟容器工做组,咱们有更多的机会来参与容器技术的讨论,与你们一块儿学习。数据库
首先来谈一谈CNTV为何要用容器,主要是要解决哪方面的问题或者说咱们的痛点在哪里。其实咱们当时的想法很简单,就是为了更好的应对CNTV面临的重大活动。怎么来理解这个“重大活动”?好比像去年的“九三阅兵”,刚刚结束的“欧洲杯”,即将要开始的奥运会,“世界杯”,以及每一年的春节联欢晚会,这些都是CNTV传统的一些重要保障活动。在活动重保期间,咱们主要面临三个问题,即高安全、高可用和弹性伸缩。后端
高安全怎么理解呢?我相信每一个企业都会把安全放在第一位,咱们公司也一样是这样,咱们把安全放在一个高强度和常态化的现象当中。在重保期间内,安全方面的调整并非特别多。在高可用方面,咱们更多的理解是系统的底层架构,它在重保期间每每也不会变更。因此,咱们的重心就放在了弹性伸缩,也就是说,如何在重大活动期间更合理、更快速、更平稳地分配咱们的资源,这也是咱们这几年制定的奋斗目标。缓存
这是咱们私有云团队提供的一张PPT,以IaaS资源申请为例,和你们阐述目前在CNTV申请资源的工做流的状况。咱们有传统的一些虚拟化工具,KVM、Xen、VMware等等,包括咱们目前在大力发展的OpenStack平台。当有业务申请资源时,咱们会根据业务的需求,开出一台虚机,而后开发或运维人员经过SSH登陆到机器上部署程序和代码。平台工程师将把这个虚机作成模板,用来批量制做、测试上线、后期资源回收,并部署其它业务。其实,在活动的重保期,每一个环节基本上是不须要过多调整的,每每就是在资源如何弹性伸缩方面,咱们会作一些事情。所以,基于业务上的压力,以及领导给的一些任务指标和咱们系统工程师对新技术的渴望,咱们调研了容器技术。安全
在咱们前期调研容器和搭建测试环境的时候,咱们发现容器资源池一直从申请到下线,整个工做流和咱们的IaaS平台没有太大的区别,工做流方向大体是同样的,都是提交代码、Build镜像、Push Pull镜像、启用容器、测试上线、删除容器、资源回收。而不一样则在于,容器具备动态扩容和缩容的特性,也就是你们说的弹性伸缩。同时,容器的建立速度,以及更少的人为干预这两点,也是咱们这几年一直在追求的地方,因此咱们认为容器技术与咱们在重大活动期间每每常态要调整的操做是很是契合的。服务器
肯定了容器这个方向,接下来就是内部讨论容器接下来要如何作,平台如何选型,咱们的业务如何调整,以及须要哪些部门来配合。Mesos、Kubernetes、Swarm是你们在容器里面常常能听到的一些编排工具,所以,咱们当时主要基于前三个(Mesos、Kubernetes、Swarm)来作调研,包括和业界、以及互联网的一些从业朋友进行讨论,包括与去哪儿网的徐磊同窗也进行了深度的交流,他们给了咱们好多中肯的建议。最终,咱们选定了能够支持多种frameworks、组件众多、部署相对容易、高可用、能支持更庞大架构的Mesos,并选定了数人云做为合做厂商,和咱们一块儿创建CNTV的容器平台。网络
简单介绍下咱们的发展,真正启动容器项目是从2015年8月开始,Docker的版本是从1.7开始,而后到1.8.一、1.9.1,咱们前两天升级到1.11.2版本;Registry版本也是从V1到V2;日志管理测试了log-driver、logspout、logging,logging是数人云的日志采集工具,把它放在咱们的ELK日志分析系统上面。在容器监控方面,咱们先测试了小米的open-falcon,第二个是你们最熟悉的Cadvisor+Influxdb+Grafana。目前整个业务的容器实例大概是1000+左右,物理服务器大概是30台左右。这个容器实例跟物理服务器没有比例关系,只是说咱们当时给容器申请更多的资源而已。架构
咱们主要改造的是如下三个系统,第一,央视网图文源站;第二,Time系统,用于PC端和移动端节目时间表的调用,以及网站的年月日时间显示;第三,API接口项目,全部央视网APP在回调素材时都会访问这个统一接口平台,包括央视影音、央视新闻、央视体育等APP。
最终的平台是这个样子,首先是监控平台,咱们目前使用的是Cadvisor+Influxdb+Grafana。日志系统是经过log-driver模式,而后打到一台logstash,最终经过logstash入口,再入ES,这是咱们本身的一套日志分析系统。编排工具是Mesos+Marathon+Docker,用数人云作底层的技术支持。镜像仓库,咱们目前选用了开源的组件,带UI界面,是V2的版本。后端咱们挂了一个GlusterFS,作了高可用。
从容器监控提及,在阶段一咱们用了Cadvisor,第二阶段咱们用了Cadvisor+Influxdb+Grafana这套架构,保证数据的持久化。到第三阶段,咱们的ELK系统是在容器平台以前搭建完成的,咱们把容器、物理机、虚拟机都统一放到Grafana上作统一的展示。
容器日志方面,阶段一跟你们走过的路都差很少,就是volume模式到宿主机的路径。第二个阶段,由于当时咱们的经验也不是特别多,咱们把logstash_agent打到了容器里面。第三个阶段,是经过log-driver、logspout或数人云的logging等模式,log-driver经过-log-opt参数到syslog,包括HTTP协议或TCP协议,IP,端口,直接就收走了。
容器日志大概的模型是这样,方式一:log-driver把日志打到syslog里面。方式二在宿主机上会有一个logspout的容器,最终入到ELK系统上面。
容器进程管理方面,咱们和去哪儿的兄弟也沟通了很长时间,由于你们更倾向于一个容器里面一个应用,由于这样的使用方式对容器是最好的。可是程序每每不是一个,咱们如今以两个居多,包括Nginx加php这两种状况。容器长时间运行须要前台进程,所以,咱们一开始前期测试也是经过top或tail-f保持长时间运行,可是里面的Nginx服务死掉的话是感知不到的,这样应用会受影响。所以,在阶段二咱们就用了supervisor,supervisor在CNTV已经使用了几年了,不少都是用supervisor来管理的,后来咱们又发现了S6进程管理,supervisor每次拉服务就三次,而S6有一个好处是无限拉、无限起这个服务,并且还有一个finish,也就是说,若是容器的进程死掉的话就把容器干掉,不必再重复的去拉里面的进程或服务,包括Nginx也好,PHP也好,直接干掉就OK了,咱们通过对比认为,S6比supervisor要好一些,所以咱们用S6来管理这两个前台进程。
镜像仓库用了AppHouse,咱们把它的配置文件,包括数据镜像的相关数据放在GlusterFS上,前面顶了Nginx作负载均衡,暂时实现了一个高可用。后期咱们也许会逐渐转到Harbor上,据说Harbor 0.3的功能仍是比较好的,包括mirror等功能,因此,咱们后期可能要转过去。
CI/CD方面,咱们在这个架构上没有作过多的调整,咱们把Dockerfile打到SVN,SVN会上传代码到Jenkins Build镜像,而后Push到镜像仓库里,包括如何与数人云或其余平台作CD。咱们的Jenkins作的是单机部署,没有作集群部署,咱们的应用如今仍是比较少,后期包括Jenkins on Mesos或一些集群部署和一些其它类的CI工具,咱们也在逐渐进行尝试。
这是一个案例分享,就是刚才前面说到的移动端回调素材的时候访问的一个统一的接口方。咱们这个业务主要分为五层,第一层就是web层,主要是Nginx+PHP的应用,第二层是一个接口缓存层Memcache,第三个是Tomcat,也是一个接口层,第四层是数据库的缓存,第五层是Oracle。三个机房提供服务的支撑,咱们目前已经作到了第三层,可是第三层尚未上线,咱们上线的是前两层。咱们打算再作一下第四层,近期一到四层全能改造完,中间是用VIP来调度或者是DNS来调度,可能咱们还得进一步去讨论。
这里把API项目的Dockerfile列出来了,比较简单,就是一个基础镜像包括一个Time的时间区域,yum安装一些必要的程序,在这个位置咱们把S6封装进来了,下面是咱们Nginx业务的一个脚本,这是后端的一个启动脚本。咱们web前端的Dockerfile大概是这样。为了更好的区别日志来自哪里,咱们就在Nginx日志里面加了四个字段,即类型、地点、业务类型和Container ID。咱们的Container ID封装在S6 run的文件夹里面,最后用sed给它替换掉,由于容器起来的时候,咱们获取它的Hostname。真实的日志打出来就是这样,就是咱们线上ELK的日志就是这样。
这里面有一个小插曲,一下子到后面我可能有时间会提一下。
主要业务就分享完了。咱们发现一个问题,之前咱们用的是1.9.1的版本,咱们在用log-driver的时候有一个OPT的参数,咱们相关系统工程师把镜像名字打进去了,他认为看日志的人有可能想知道这个容器是从哪一个镜像出来的。可是如今回头想一想其实没有任何做用。升级到1.11.2这个版本的时候,咱们发现经过Log-driver出来的时候,它前面会带出来一个时间、Docker和一个Container ID,它自己就会有这些属性,因此咱们后期会把Nginx里面加的Container ID去掉,直接从Log-driver里面出来的Container ID用Logstash作切割匹配就OK了。
这是一个将来发展,这段时间咱们跟数人云也在作进一步的沟通,包括咱们的业务如何作配置中心,容器ENV化,把更多的环境变量或者参数从镜像里面提取出来,由于咱们好可能是彻底打到镜像里面,可能有一些改动包括配置文件等等就要从新打一遍镜像,太繁琐,跟数人云也在进一步沟通这件事情。
对于咱们来讲,咱们选用一个底层平台,包括咱们是否是之后用Docker,咱们还在继续探索,可能咱们后期也会尝试一下其它的容器。
我大概分享就是这些内容,谢谢你们!