运维号称背锅侠,系统升级出现问题、网络出现问题、系统宕机等都会被推到运维头上,就连各大网络公司平台一旦出现问题,也总是运维人员来背锅,包括前段时间阿里云故障,据说也是运维失误造成的!这些问题说明运维工作的复杂性、重要性以及危险性,稍有不慎就有可能“灾难降临”。我以前的一个运维同事经常说,每次升级的时候都胆战心惊,真应该请尊菩萨来拜拜,而我也何尝不是呢?曾经我们每次升级都不是那么顺利,总会有不同的问题出现,复杂的时候可能会折腾一宿。印象最深刻的一次是因为运维升级的失误差点让我们整个技术团队集体“下课”:那天下午两点当时公司的老板要参加一个互联网大会来宣传我们平台的新产品,而我们由于系统还有一些问题需要临时升级,本来想着挺简单的一次升级,却在升级过程中由于操作不当整个平台被全部宕掉,怎么都无法启动。当时脑子一片混乱、手脚发麻(因为我是技术负责人),却怎么也排查不出问题,我当时都想好了要引咎辞职,幸好在大会开始前半个小时终于查到了原因,顺利的恢复了系统的运行!这次事件给我们所有人都上了一课,一定要重视运维,并且一定要做到全自动化运维,一键部署那种!但是由于当时我们技术的局限性,运维人员也不是太专业,好的运维人员又请不起,我们只能自己研究,自己一点点去完善。

         后来我在搭建新的技术平台做技术选型时采用了spring cloud这种新型微服务架构,在研究这个框架时接触到了docker,在深入了解spring cloud和docker的机制及运行特性后,我看到了一键式部署的曙光!说干就干,我马上召集了我团队的另外一个技术人员,我们分工研究,并结合阿里云平台,最终完美实现了真正的一键部署!下面我主要介绍一下我们的搭建思路,本文仅提供大致的解决方案,不去做深入的理论探讨,由于作者水平有限、平台较小,所以很多问题可能没有考虑到或者没有做到更好,也欢迎大家共同探讨!

        一、采用swarm集群

        由于多docker之间的相互访问只能在同一宿主机,而我们在真正使用中肯定不止一台宿主机,所以我们采用了swarm集群!我的理解是swarm集群将多台宿主机装在一个大的主机盒子里,让docker认为swarm集群就是一台大的宿主机,从而实现只要在这个大的集群中所有的docker均可相互访问。当然,我们宿主机全部采用的是阿里云的ECS,所以我们也就理所应当的采用了阿里云的Swarm集群!

启动docker服务后宿主机断网_一键式部署

       二、将服务打包成镜像

每个服务下面都有一个专门的docker目录,放置了Dockerfile及镜像中需要用到的文件,Dockerfile的内容就不再专门讲解了,你可以根据自己项目情况来编写自己的Dockerfile!需要注意的是截图中的镜像版本号是一个动态的,每次升级可能都会进行改变,方便紧急的时候回退到某个版本。

启动docker服务后宿主机断网_启动docker服务后宿主机断网_02

         三、配置Jenkins

        采用jenkins来进行统一的项目打包、镜像推送。其实我说的一键部署就是指Jenkins中的“立即构建”这一键!jenkins普通的打包编译配置就不再讲了,主要就是下图中来真正实现这关键的一键的。通过下图shell操作后jenkins会将打好的镜像包推送到阿里云容器服务中的镜像库中。

启动docker服务后宿主机断网_一键式部署_03

启动docker服务后宿主机断网_一键式部署_04

        四、用docker-compose进行服务编排

       微服务一般都会有数个、数十个甚至数百个服务在运行,而且每个服务有可能还会同时跑多个,我们不可能手动进行启动运行,那么这时候我们就需要进行服务编排了!

启动docker服务后宿主机断网_spring cloud_05

启动docker服务后宿主机断网_一键式部署_06

这里我们指定了该服务启动时的运行环境、运行数量、数据卷映射(可以创建NAS数据卷做为通用数据存储)、指向的阿里云SLB等,结合着spring cloud的统一配置服务,我们可以通过采用不同的docker-compose编排来区分不同环境

启动docker服务后宿主机断网_docker_07

      五、创建应用

   在服务编排做好之后,就可以直接使用该服务编排去创建一个应用了,创建完成之后即可直接进行启动

启动docker服务后宿主机断网_docker_08

启动docker服务后宿主机断网_运维_09

启动中指定要使用的镜像版本,请关联第二步的镜像版本号

启动docker服务后宿主机断网_docker_10

启动docker服务后宿主机断网_一键式部署_11

补充,第三步的时候并没有真正的完全做到一键部署,除了点击立即构建之外,还需要到阿里云容器服务的应用中点击重新部署,如果需要完全实现一键部署,那就需要在应用中创建触发器,并完善到jenkins配置的脚本中即可

启动docker服务后宿主机断网_docker_12

        六、部署到生产环境

        测试通过之后需要部署到生产环境,传统的部署方式要么是通过对测试通过的代码包进行拷贝,并对配置文件进行更改;要么就是通过svn/git中的版本控制从测试到生产的迁移,再进行jenkins的预生产环境测试,但是无论哪种部署方式都很容易出问题:一、漏改、错改配置文件;二、代码合并/迁移过程中产生新的问题;三、生产、测试服务器环境不同,环境差异造成的问题。但docker镜像是一个单进程的应用,而且只要宿主机运行docker没问题,那么docker重的环境也不会出现任何问题,我们将通过测试的应用从测试环境迁移到生产环境就很简单了,只用提供不同的docker-compose服务编排,生产环境直接通过变更配置更改镜像版本号即可

        七、日志采集

        Docker容器无法进行存储,只要容器重新启动,那么所有在启动过程中产生的数据都不复存在,如何存储日志呢?第四步中我们做的数据卷映射就可以派上用场了,我们采用的是一个网络NAS盘,将这块硬盘同时挂载到另外一台单独的ECS服务器上就可以访问所有的日志文件了,这里我采用的是ELK来进行日志搜集,这里就不再细讲了

启动docker服务后宿主机断网_spring cloud_13

  通过以上操作,我们真正的实现了一键式部署,而且阿里云针对swarm集群提供了各种方式的数据监控,完全可以满足你的要求!对于集群扩容也很简单,只用选择相应的集群,直接选择添加已有节点或扩容即可随时扩容,你需要做的就是点击下相应应用的重新部署即可。我们现在有数十台服务器,而且没有运维人员,只安排了一个研发工程师来进行日常的升级部署,已经稳定运行了一年多。在日常的升级过程中,除了偶尔的服务器硬件不足,从来没有再出现过因部署失误而产生的问题!