上周,作为对我们所做之事的分享过程的一部分,我们说明了我们是如何使用Docker Swarm的,并简要提及作为部署过程一部分的Jenkins。现在是时候对它及其他工具做进一步说明,这些工具不仅协助我们交付应用程序,还能处理运行它的基础设施。
首先,什么是Jenkins?Jenkins是一个使用Java编写的持续集成和持续交付应用程序。Jenkins拥有丰富的插件生态系统,可以与不同类型的工具和进程进行整合:版本控制、云基础设施、配置管理等等。Jenkins最初专注于Java应用程序,现在则可以用于不同类型的应用程序和系统。
在我们将Jenkins添加进来时,我们的关注点在于围绕它构建我们的持续交付过程,将它与我们在使用的工具整合,并添加新的工具。
对我们来说,持续交付(Continuous Delivery,CD)始于版本控制。我们使用GitHub作为应用程序的中央仓库及基础设施,因此Jenkins任务的第一步都是从GitHub仓库拉取代码。
想部署一项应用程序更新?从仓库拉取。想更新基础设施?从仓库拉取。想执行我们平台里的任务?从仓库拉取。大体就是这样。如果在这个流程之外发生了变更,将执行一组不同的任务将这些变更推送到它所属的仓库。
为了与基础设施交互,我们使用了Ansible,这是一个基于playbook和角色的自动化和配置管理工具,可以在服务器上或通过云供应商提供的API直接执行任务。
我们关键的基础设施对象之一是Swarm结点,这在此前的文章中做了说明。在之前,当我们需要添加一个新结点(访问量一直在上升!)时,我们需要进入AWS控制台,从正在运行的实例创建一个AMI,启动这个新实例并对其进行配置。
如果在AMI创建与启动新实例之间发生了变更,这个过程就不可靠了,而且如果在需要该实例同时才触发速度很慢。
使用新的架构,AWS Auto Scaling会在需要时启动新结点以提升Swarm集群的容量。
为此,需要准备好一个装有所有组件的亚马逊机器镜像(Amazon Machine Image,AMI):Ubuntu、Docker、Nginx、EBS数据卷等等。其配置是使用一个Ansible playbook完成的,它将启动一个临时的EC2实例,安装并配置所需所有组件,创建一个基于新实例的AMI然后终止它。新的AMI准备就绪,将用于AWS AutoScaling启动新实例。
当我们想要更新一个组件(比如,更新Docker引擎),我们就修改Ansible的角色,推送到仓库中然后执行Jenkins构建任务。
我们的用户可以选择基于不同编程语言、框架和数据库来创建新的控制台。全部都是基于一个特殊仓库中的Dockerfile的Docker镜像。当我们想构建一个新的镜像或更新旧的镜像时,我们会启动一个Jenkins任务,将镜像推送到我们的私有Docker Registry上,然后分发给所有Swarm节点。我们也可以同时构建多个镜像。
为了部署主要的应用程序,我们使用了Capistrano,它具有部署Rails应用程序所需的所有选项。
任何有权限的人都可以部署应用程序,不过团队的其他人并不总是知道部署的准确时间或是否发生了失败。使用Jenkins启动Capistrano任务增加了可见性。现在,通过讨论应用程序更新的同一Slack通道,整个团队都知道什么时候做了部署、花了多少时间、部署了什么变更等等。对于某些应用程序,Github上有Webhook用于在向仓库推送时触发Jenkins上的部署。
要是需要在用户容器上部署一项更新怎么办?这比较有趣。在之前,我们不得不提取出数千个需要更新的容器的列表,启动它们,使用git从仓库拉取更新,重启应用,让人抓狂。要避免这个痛苦,我们创建了一个新的Jenkins任务,从仓库拉取代码,替换容器中的文件并重新构建、重新启动应用程序。我们只须将列表作为参数传递给该任务,并可在任何时刻查看升级状态。
对于基础设施,我们遵循了与应用程序部署类似的模式。
要部署一个新的实例和服务,GitHub仓库中有几个具有用于启动和配置基础设施所需所有信息的Ansible playbook。
要是需要新的环境(比如,用于测试的新的Swarm集群)怎么办?简单:通过Jenkins使用更新的参数再次运行playbook,新的基础设施将在几分钟内就绪。
有时,问题出现在应用程序的变更上,不过基础设施的变更也会造成严重的问题。
“我们的应用程序无法与数据库通信。你知道前几天修改了什么吗?”我们使用一个定时的Jenkins任务来跟踪基础设施的变更,该任务从AWS读取所有的信息:EC2实例、ELB、EBS数据卷、安全组等等。这些信息会被保存为JSON文件,然后推送到仓库中。提交的是基础设施的变更,比如更新的安全规则、ELB配置等等。这带来了可见性,我们能清楚知道造成错误的缘由,更重要的是,解决所需的时间和方法。
那文档怎么办?系统管理员需要一直查找变更并更新Wiki么?当然不。同一个Jenkins任务会以环境和项目为实例分组处理数据、添加markdown格式并将这些信息公开给团队中任何需要它的人。
如你所见,我们将常见的和手工的任务转换成了Jenkins任务,不过重要的是要知道,这个方法着重于给我们的团队和客户分发更好的服务。我们尽量不强制已投入使用的系统应用这类变更或为其增加更多复杂度。我们的规则是为过程增加自动化、可见性及秩序,但同时保持简单。
原文链接: Code and Infrastructure: our approach to Continuous Delivery (翻译: 梁晓勇 )