引言 我们今天的话题是中小企业如何实现自动化部署。那么,为什么定位中小企业呢? 因为往往中小企业面临着运维人员有限,成本投入有限,但是版本更新快,而且服务器数量却并不少的情况。 中小企业甚至,基本不会投入运维开发来开发自动化部署平台。那么,我们今天就拿运维工程师都熟悉的Shell进行举例,谈谈如何来进行一个自动化部署的设计。 本次分享主要包括如下内容: 1. 中小企业自动化部署的设计 2. 如何在资源有限时开发自动化部署平台 3. 部署的技巧与流程 4. FAQ(有彩蛋哟,不容错过:) 统一认识
在开始之前我们需要先统一认识,在IT管理里面有三大核心要素,简称PPT,即: · 人员/组织架构(People); · 流程(Process); · 技术/工具(Tech/Tool)。 所以说设计一个自动化部署系统,并不简单是上线几个工具,写几个自动化脚本这么简单。不过本文我们简化流程,主要是聊聊生产环境的自动化部署系统。 同时通过这个“PPT”,我们也认识到了,设计一个流程,除了流程本身要和我们的组织架构、人员和技术挂钩,也需要根据企业的实际情况来做,不能好高骛远,梦想着一上来就设计一个庞大的自动化部署平台。这可能并不符合企业现状,又浪费了资源。 同时还有一点就是流程思路很重要,具体的实现方法很多,看团队的技术水平,可以使用Python、Shell、PHP等来实现。 确定目标
好的,我们统一了认识,下面来确定下目标。中小企业的部署现状就是更新快,可能经常性的测试不到位(所以,就需要快速回滚)。单业务的集群规模在基本上在100台以内。那么我们的主要目标是: · 一键上线 · 秒级回滚 流程设计
本文的重点就是流程设计。上面说了,由于篇幅有限我们简化流程。完整的上线流程,可能经历开发环境、测试环境(功能测试、性能测试、预生产测试)、生产环境。 本次我就来谈谈生产环境如何自动化部署(假设现在新的功能已经在开发和测试环境就绪,Git或者svn仓库已经存放了可以上线的代码)。 我相信有读者目前的上线是使用管理工具,批量在所有服务器上执行svn update或者git pull。当然,我还见过每次上线执行rsync进行代码部署的。 我们下面的流程或许会彻底改变你的思路。不要惊讶,原本上面的方法也没有什么错,只要符合企业需求就可以,但是我们可以做的更好。 直接上部署流程图: 流程分析
我想,看到这样的流程可能很多朋友在心中会有一些疑问,我们慢慢来分别阐述下,这样设计的思路、设计原则和目的。 1. 获取代码这一步的疑问最少,我们可以通过svn或者git进行获取,也可以指定svn版本号或者git的tag,commit id,或者直接获取最新代码都可以。 注意,你需要在专用的部署服务器进行这样的操作,而不是各个Web服务器。 2. 编译这个是可选的,如果你是Java,则需要进行编译,比如Ant或Maven就可以方便的帮你完成,Python和PHP则不需要进行编译操作,可以忽略。 总之,最后你有了一个目录,这个目录里面是准备上线的代码。需要注意的细节是,包名(目录名)的设计,可以涉及到环境、包名、版本号和时间。如下面的名称: prod_web_xxxxx_2015-09-09-10:103. 匹配环境配置文件
这样,你这个部署系统(脚本)可以支持多个环境。这里有人会问配置文件不应该在代码仓库里面吗? 不是的!至少重要的和差异性的配置文件是需要单独进行管理的,尤其是涉及到支付、验证类的配置。 最佳实践是:最好给配置文件单独做一个版本库进行管理,同时可以通过目录来区分是测试还是生产,只有相关的负责人才有权限进行更新和提交。这样的话,你需要将配置文件copy到代码目录下。 4. 打包直接使用tar czf 打一个包就可以了。 5. COPY代码包到目标服务器:现在可以将需要部署的代码包COPY到目标服务器,比如你可以使用SCP。同时你可以在打包的时候给这个包生成一个md5文件,scp完毕后可以使用md5sum验证一下包的完整性。 6. 将部署节点拿出集群:先举一个反例,有些朋友可能这样操作,在部署时,直接部署和重启Web服务,让负载均衡的健康检查工作自动将节点踢出集群? 想这么搞的话的朋友,需要想一想了,这做法也太暴力了。 我们知道负载均衡的健康检查也是有时间间隔、次数的,如果你直接重启了后端Web服务,那么在负载均衡做判断后端主机是否下线的时间范围内,用户的请求可能就会失败。 所以,我们要提前将要部署的后端节点拿出集群,比如Haproxy,你可以通过socat和Haproxy Unix Socket进行通信,实现部署节点的开启和关闭,如下所示: 关闭节点: echo "disable server www_example_com/web-node1" | socat /usr/local/haproxy/haproxy.sock stdio 启用节点: echo "enable server www_example_com/web-node1" | socat /usr/local/haproxy/haproxy.sock stdio7. 解压软件包在目标服务器上解压这个软件包,无论你是用管理工具如Saltstack还是SSH都可以轻松搞定。 8. 创建软连接好的,这就是我们设计的重点了,我们使用软连接的方式来管理包的更新。比如我们的Web根路径是/var/www/html/webroot,我们把所有的代码都存放在/data目录下,那么webroot实际上是一个软连接,它链接到当前的版本,比如prod_web_xxxxx_2015-09-09-10-10。这样的话,webroot实际是这样 webroot -> /data/prod_web_xxxxx_2015-09-09-10-10/我想,很多朋友,看到这里就明白了,这回滚绝对是秒级啊,只需要重新创建一个软连接即可。 9. COPY差异文件同一个集群中,存在不同的配置文件,这很常见,比如我需要在某个节点跑一些定时任务,比如Java可以使用Quartz来实现,只需要一个crontab.xml即可,那么我们就需要把这个差异文件在这个时候scp进去。 10. 重启Web服务这个是可选的,如果是Java,运行的Tomcat,就需要重启Tomcat,别忘记清理相关的Tomcat缓存哦。 11. 自动化测试如果有的话,当然好了,你调用一个接口就可以进行测试。然后等待测试完毕再继续。如果没有测试团队提供这样的接口,那么curl可以帮你轻松的实现,把重要的接口访问一遍,判断下返回码或者返回内容即可。 12. 加入集群好的,这个节点部署完毕了,把他加入集群吧。还记得刚才说的socat吗。 13. 继续下一个节点说了这么多,原来只是一个节点啊。那么继续吧,可能这个只是for循环中的一部分哦,是不是想到了shell该怎么写了。 部署小技巧
这里把实际使用的时候可能有用的小技巧分享下: 分组部署: 为什么要分组?上面的流程中,你会发现,每次部署都会在重启和自动化测试那里等待好久。 因为你要等待Web服务的重启,比如Tomcat。那么如何减少这个时间呢? 答案就是分组部署,将该业务的服务器进行分组,比如group1、group2、group3: · 那么部署group1到重启那里后,流程不往下走了,直接部署group2; · 当group2部署完毕,停下来开始对group1进行自动化测试,测试完毕添加到集群;然后继续部署group3。 · 当group3部署完毕后,再来自动化测试group2,然后你懂的。 日志记录: 没有日志记录功能的脚本就是耍流氓!你必须清楚的知道目前脚本在干啥,干到哪里了,如果有报错就可以及时的定位问题。 部署服务器双机:如果这台部署服务器宕机会怎么样?所以这台部署服务器必须是双机的。包括部署脚本应该是使用svn或者git来做版本控制。应该有详细的部署脚本的设计、使用文档。别忘了,文档化建设是流程设计必备的内容之一。 回滚流程
我想经过部署流程,大家很容易就想到了下面的流程,我们主要可以简单的阐述下: · 列出回滚版本:ls –l可以了吧,只要列出能回滚的版本即可。 · 目标服务器移除集群:同部署操作。 · 执行回滚:删除旧的软连接,创建到指定版本的软连接 · 重启:可选的 · 自动化测试:同部署操作 · 加入集群:同部署操作 · Next:继续下一个节点 OK,这是一个回滚的流程。如果仅仅这样是远远不够的,别忘了我们的定位是中小企业,往往我见到更多的情况是回滚是遇到了没有测试出来的比较大的bug。 那么我们就需要一个紧急的回滚流程。这种情况下,暴力一点可能是最佳选择了。 · 执行回滚:对,不要列出来了,直接就用上一个版本即可。所以注意,部署的时候你需要记录上一个版本是什么。 · 重启:可选。顾不了那么多了,现在是和时间赛跑。那么注意了,你的上一个版本需要是一个可用的版本,如果你无法记录,那么可能需要把列出版本再加上了。 好的,我们的流程设计结束了,先在脑子里想明白,然后拿起Shell开始实现吧。会有很多小细节需要注意哦,我相信这难不倒你。 FAQ
问:有没有完整的自动化部署的流程图可以参考? 还真有,之前画过一个,请大家参考。目前我们IAAS这块主要以Open Stack为主,Mesos+Docker也正在研究中。 问:你们是否考虑使用Jenkins来实现自动化部署呢? 实际上,我们测试环境的自动化部署是使用的Jenkins。开发可以自助进行部署操作,同时也集成了代码审查和代码质量管理的流程。 但是我们生产环境没有使用Jenkins,主要是我们自动化测试还跟不上,往往很多发布需要人肉测试。整个流程无法完美衔接,所以就分开了。所以我们生产部署其实产品发起,测试审核(测试),然后测试人员进行部署上线。 而且生产环境并不是测试人员ssh到服务器执行我们编写的脚本(他们没有权限),我们基于SaltStack开发了Job管理平台,测试人员在Job管理平台上进行部署操作。 问:部署的一致性怎么保证的,比如刚更新的服务器和集群中的其它服务器版本不一致? 首先,日常的变动和更新是不会有这样的问题,如果有大的变动,不推荐在运维部门来实现,更好的实现方法是:比如在SOA的各个服务之间,加入API版本号的实现,实现多个版本并存。 如果你发现有不一致的情况,试试Nginx的ip_hash,或者Haproxy的source的负载均衡算法,让某个用户的请求一直落在某个节点,即实现了会话保持,也解决了你的疑虑。这样做当然也有很多缺点,看你的选择了。 问:我们是否可以将线上部署修改为本文设计的流程? 欢迎使用,而且我们后期还会提供Shell脚本模板。 这个流程的设计背景是一个电商的架构,物理机+虚拟机,供300多台的规模,使用了SOA。 但是,当时重构部署流程也经历了很长一段的时间,而且需要运维顶着很大的压力和责任,一定要充分测试,分批上线。(赵舜东原创)
|