阿里技术专家:持续交付与微服务背后的实践逻辑(4)
答案是自动化加可视化.自动化就是部署一个应用时,应该有脚本能够一键从构建物仓库拉取出正确版本的构建物,然后部署到相应的机器(或者多台机器)上.更重要的是这个自动化脚本不应该藏在一个秘密机器的角落,因为这样的话,就很难告诉团队成员如何去使用它们.所以应该把它可视化,而可视化的最好的平台就是上面提到的那个持续集成流水线,在流水线的后面再加上一个部署线上的环节. 这样,开发人员就能够在一个统一的入口去了解从验证、打包,再到生产环境部署的的全流程.当然我们的持续集成流水线也就顺理成章的变成了持续交付流水线. 在发布方面,还有一个重要的课题就是环境管理. 现在大多的线上部署模式是:申请几台虚拟机,标明每一台的用途,然后开始在各个虚拟机上安装各自需要的基础软件,比如nginx、tomcat等.然后写一个脚本进行各个应用程序的部署(这个脚本最终会集成到持续交付流水线中),注意这里的脚本仅仅负责应用程序的部署,而不包含前面提到的基础软件.如果基础软件需要升级,或者安装新的基础软件,或者需要调整系统参数,这些过程都需要手动进行.这种模式在大多数情况下是没有问题的,但一旦机器出了问题,或者需要扩容时,就需要花费大量时间来重新安装一台和之前那台一模一样的机器,再修改部署脚本把软件部署上去.这个过程不但耗时,而且非常不可靠,因为你没法保证你装出来的这台机器就和之前的那台一模一样,很有可能就给未来埋下了一颗定时炸弹. 解决这个问题的思路就是所谓的“基础设施即代码”.也就是把环境的创建过程使用代码的形式描述出来,并且提交到代码库中.任何的环境变更都必须通过修改代码、提交,然后总是使用代码库中的最新版本重新构建环境.禁止直接在机器上进行任何环境变更,比如装软件,升级软件,该软件配置等.这样所有机器的状态就是可预测的,并且是一致的. 基础设施及代码的相关工具有很多,比如最早流行的chef和puppet,到后来的Ansible.这里我们就拿Ansible为例子讲一讲环境管理和部署自动化. Ansible是一个Agent Less的通用部署及环境管理工具.也就是说不需要在目标机器上预先安装任何客户端软件,这点与chef有所差别.它依赖的就是简单的ssh命令.你说这跟我直接写shell或者ruby脚本ssh到目标机器,然后执行一些脚本有什么差别呢? 差别当然是有的,它会在以下几个方面给你提供便利: 第一:Inventory管理.Inventory,即你要管理的那些机器.使用Ansible,你可以在一个集中的文件中,以结构化的形式列出所有你需要管理的机器,及如何登陆它们,也就是ssh的用户名和密码 等信息.不同机器的用途不同,比如这三台是web服务器,那两台是搜索引擎等.那么Ansible也提供了对机器进行分组的能力.有了这些分组后,就可以很容易的在命令行中指明我这次要对那些机器做变更.并且Ansible会自动地对所有这些机器做变更,省去了自己做循环的工作. 下面看几个Ansible官方的Inventory例子: 第二个重要的点叫做变更操作的幂等性.举个例子,某一次对机器的变更是在~/.bash_profile中添加一行对JAVA_HOME的配置:“export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_71.jdk/Contents/Home/”.那么我可以写一个shell脚本完成这件事情:“echo export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_71.jdk/Contents/Home/ >> ~/.bash_profile”.但是如果下次我的shell脚本里面多了安装apache web server的代码.我就需要把这整个脚本再对目标机器运行一次.那么就会出现~/.bash_profile中出现两行JAVA_HOME的配置的问题.虽然不至于引入错误,但也是很没有必要的操作. 所谓幂等性,就是同一个脚本对同一台机器运行多次后,机器的状态应该都是一致的.Ansible中模块(module)的概念就覆盖了“幂等性”这个概念.所谓模块是预先写好的一些库,然后可以在Ansible的脚本中进行调用.上面的在一个文件中添加一行的操作就可以使用“lineinfile”这个module来做.在Ansible脚本中的写法是:“lineinfile: dest=~/.bash_profile line=/Library/Java/JavaVirtualMachines/jdk1.8.0_71.jdk/Contents/Home/”.再比如还有一个module,叫做service,Ansible脚本中对于service的一个调用示例是这样的: “service: name=httpd state=started”.这个描述的含义就是:“保证名为httpd的service是started状态”.所以你可以想象到它的具体实现就是先检查下httpd这个service的状态,如果已经是started的就什么都不做,否则就启动它. 这种幂等性在配置管理方面是非常有用的,这样我就可以放心的运行这些脚本,知道最终一定可以得到某个一致的状态.而且可以节省运行这些脚本的时间,比如发现JDK已经装好了,就不需要再装一遍. 上面提到的Ansible编写的脚本被称作Playbook,下面是几个playbook的例子: 这个playbook是一个完整的例子,其中包括了我要部署那些机器(hosts).是用什么账户登录(root),运行哪些任务(tasks)等等.task中的name只是描述信息. 但是遗憾的是这种幂等性是不能完全保证的,有的module可以保证,比如上面提到的service和lineinfile.但有些是不行的,比如command module,它做的事情就是运行一条命令.Ansible无法判断这条命令是否执行过. 所以在使用Ansible的过程中需要尽量使用能够保证幂等性的module.这样才能保证所有的机器在运行一段时间之后配置是相同的,避免“配置漂移”.当然还有一个避免配置漂移的方法就是每次都重新申请一台新的机器,然后对着它运行一遍这些脚本.这也是可行的,我们后面对此进行讨论. Ansible作为一个完备的工具,在错误处理,回滚,调试等方面也都提供了便利的支持.详情大家可以参看Ansible的官网.上面有关于Ansible本身的介绍,和一系列的扩展module. 最后再看一看Ansible整体的结构: (编辑:ASP站长网) |