有容云
作者有容云·2016-06-24 15:38
其它·有容云

有容云:实战总结之利用Docker、Docker Compose &Rancher构建持续部署2

字数 5041阅读 1637评论 0赞 1

前言:本文由John Patterson 、 Chris Lunsford写于2016年4月20日,译者有容云向波,转载请注明出处。

在本系列文章的第一部分,我们搭建了基本的构建和部署流水线(pipeline)。容器不再是靠登陆服务器,然后输入记忆中的Docker命令来部署。镜像的构建也已经由Jenkins服务器实现了自动化。我们将Docker命令写成Bash脚本,保存在Git中,实现了版本追踪。应该说,我们对原有流程做了很大的改进。但是,仍然有一些痛点我们需要关注,在本文中,我们将看一下如何使用Docker Compose和Ansible来优化持续部署工作。

阅读前文请点击:有容云:实战总结之利用Docker、Docker Compose &Rancher构建持续部署

为了部署一个容器镜像,运维工程师需要登录到服务器中,在shell 中执行含有Docker命令的脚本。这太土了,同时还需要运维等待命令执行完毕。这种模式对整个团队没有任何益处。(作为一个工程师,有多少次你需要盯着本来可以自动化完成的任务?)另外,大多数情况下,运维人员从笔记本上发起的SSH会话中执行命令,部署过程也没有实现可视化记录和日志保留。

如果你还记得,我们的部署脚本应该是如下的样子:

1.png

我们已经做到了从Docker run命令中抽象了一层,工程师不需要知道每个镜像成功运行所需要的具体参数。这是一个显著的改进,但我们也意识到在如下部分存在的一些问题。


存在问题

1.每一个容器的逻辑存放在同一个文件中,对应用部署逻辑的变更更难去跟踪;

2. 开发人员测试和修改参数时,只能在脚本中理清逻辑,而不能为某个特定的应用很容易地读取和修改参数。

在我们工作流中, Docker Compose是一款更合适的工具,它允许我们对部署参数进行代码化,这些参数可以在YAML文件里指定,该文件称之为docker-compose.yml。

Docker Compose不仅仅可以帮助我们解决上面提到的痛点,也可以使得我们从社区的未来工作中受益。接下来让我们开始理清部署逻辑,为我们的Jave示例程序创建一个Compose文件。做为开始,我们需要基于我们原先的部署脚本创建一个docker-compose.yml文件:

2.png

现在部署一个容器只需要在包含docker-compose.yml文件的路径下执行如下命令:

3.png

该命令会按照在Compose文件中指定的参数启动一个容器。该例子中需要解决如何输入${VERSION}的问题。Docker Compose能够从当前shell环境中接受在Compose文件中指定的变量。为设置该变量,我们可以很简单地运行如下命令:

<img src="http://s14.sinaimg.cn/mw690/002D2VS1zy72JhUsFyJcd&690" width="554" height="58" alt="有容云:实战总结之利用Docker、Docker Compose &Rancher构建持续部署2">

该命令将会从我们的私有镜像库里拉取标记为1.0.0的镜像,启动java-service-1应用。如果VERSION变量没有设置,Docker Compose将会输出告警信息,并将之替换为空字符串,从而将拉取latest镜像。因此,正确设置VERSION变量非常重要。

作为部署流程的一部分,我们想让开发人员能够在本地构建和测试他们开发的服务。但是,因为docker-compose.yml文件指向是私有镜像库的镜像,所以执行docker-compose up命令将不会使用本地资源,而是使用事先做好的镜像。 比较理想的情况是,开发人员可以用如下命令来使用标准的docker-compose 工作流程:

<img src="http://p3.pstatp.com/large/97000009850f78315ec" alt="有容云:实战总结之利用Docker、Docker Compose &Rancher构建持续部署2">Docker Compose提供了一个方式让我们做到这一点,而不用修改生产环境中的docker-compose.yml文件。我们可以使用多个Compose文件,在本地机上测试时,可以利用docker-compose.override.yml来替换我们希望改动的任意参数。在该文件中,我们指定Build键值而不是镜像名称,同时移除VERSION变量。因为它是一个覆盖文件,我们不需要复制任何例如端口等额外的设置:

<img src="http://p2.pstatp.com/large/96c0000935f94aceebe" alt="有容云:实战总结之利用Docker、Docker Compose &Rancher构建持续部署2">通过将我们之前的部署脚本转化为Docker Compose文件,现在我们能够得到不少收获。


收获

1.将compose文件和源代码存在一个代码库里,和Dockerfile一样;

2. 再不需要编写复杂的部署脚本;

3. 允许开发者很容易地在本地测试和修改应用。

现在我们为java-service-1应用创建了Compose文件,我们可以从我们的部署脚本里去掉它,我们的存储库里大概会存放如下内容:

<img src="http://p1.pstatp.com/large/96e0002115200ce1c81" alt="有容云:实战总结之利用Docker、Docker Compose &Rancher构建持续部署2">

到目前为止,我们依旧没有完全将镜像创建和部署之间的差距拉平。我们有docker-compse.yml文件,包含了所有的部署逻辑,但是到底在我们的环境里如何执行它呢?让我们稍微偏离一下主题,谈一下运行Docker daemon时关于UNIX和TCP socket的一些安全顾虑。

在我们这个项目中,工程师登录到每台服务器中来执行部署脚本,启动相应的容器。缺省情况下,当在本地执行Docker命令时,它会使用Unix socket /var/run/docker.sock 来连接到Docker daemon。 除了这样做,我们可以让daemon监听TCP socket。这样使得客户端可以远程连接每个Docker daemon,然后就好像已经登录该节点一样运行命令。这种方法使得我们拥有了一些灵活性,但是也带来了一些安全问题。


安全问题

1. 允许从网络上远程连接带来的安全问题;

2. 增加了一些需求,来设置基于节点或基于网络的ACL;

3. 保护daemon需要分发CA和客户端证书。

另外一个方式是在SSH之上来执行我们的命令。我们已经有了ACL来保护SSH端口,只有指定的授权用户才能通过SSH 访问Docker daemon。 这也许不是一个最好的方法,但它能够减少我们的运维负担,将安全风险降到最低。 这确实为我们带来很多好处,尤其是工作负担已经很大的团队。

为了协助在SSH之上运行Docker命令,我们可以使用Ansible,一个广受欢迎的编排和配置管理工具。 Ansible不需要在服务器上安装代理,允许在SSH之上运行PlayBook(服务器端任务的集合)。一个简单的PlayBook可以执行我们的docker-compose命令,其格式大概如下所示:

<img src="http://p3.pstatp.com/large/96c000094a0a3bc8b95" alt="有容云:实战总结之利用Docker、Docker Compose &Rancher构建持续部署2">

不需要对Ansible懂太多,你都能够对如上的PlayBook到底要做什么有一个大概了解。每一行要执行的动作和步骤可以描述如下:

1. Ansible连接目标服务器(使用变量DESTINATION定义服务器);

2. 在每台服务器上,Ansible执行一个shell命令,登录到公司的私有代码仓库;

3. Ansible从Jenkins服务器上(也就是执行Ansible PlayBook的服务器)上拷贝docker-compose.yml文件到目标服务器的本地/tmp/docker-compose.yml;

4. 在目标服务器上执行docker-compose命令;

5. 移除临时文件/tmp/docker-compose.yml。

当然,可以写一个shell脚本做同样的事情。不同的是,利用Ansible,我们可以得到一个并行执行、完美测试的脚本模块。通过Ansible和PlayBook文件,我们能够远程启动容器,相对于手动登录远程节点、执行命令来说前进了一大步。为了近一步加强该流程的可视化,我们将配置Jenkins作业来执行Ansible代码。使用Jenkins,我们也得到了额外的收益,能够在未来将我们的构建和部署紧密联系在一起。

Jenkins作业将需要两个参数:目标服务器(传递给PlayBook的DESTINATION变量)以及需要部署的镜像版本(传递给docker-compose.yml文件中的VERSION 变量)。该作业的构建部分是一个shell构建脚本,它将试图为该应用找到docker-compose.yml文件,然后运行ansible-playbook命令,传递变量给PlayBook:

<img src="http://p3.pstatp.com/large/7fd000938db94bdb408" alt="有容云:实战总结之利用Docker、Docker Compose &Rancher构建持续部署2">

尽管看上去好像我们只是在工作流中做了一点小的改变,但整个持续部署模式却有了很好的进步。

 


进步

1. 部署现在可以被审计。 日志中记录了什么被执行,何时被执行,在哪些节点上执行,这些归功于Jenkins作业;

2. 部署逻辑更严密。应用部署逻辑从单一脚本分解为多个单独的Docker docker-compose.yml文件,这些文件和应用代码存放在一起。这意味着我们可以通过Git来跟踪应用部署逻辑的变化。另外,我们也可以通过应用源代码的修改或者部署文件的修改,来触发构建和部署。

当然,尽管这些改进解决了一些问题,同时也带来了一些新的问题:

• 哪些容器被部署了?部署在哪台主机?部署了哪几个版本?

• 部署完成以后,容器是什么状态?

• 我们如何确定哪些节点应该是某个应用的 DESTINATION?

在下一篇文章中,将探讨我们为什么引入以及如何使用Rancher,特别是该平台如何帮助我们解决如上问题。我们也将探讨该平台如何助力运维和开发一体化。

 同时,你也可以下载有容云团队编译的白皮书: 基于Docker的构建流程 (第一部分) - 持续集成及测试》,该文档详细阐述了在CI/CD流程中容器带来的价值。

 目前可以通过以下链接访问本系列4篇文章:

 Part  1: CI/CD 和 Docker入门

Part 2: 使用Docker Compose

Part 3: Rancher助力容器编排

Part 4: 服务发现

 

原文地址:Lessons learned building a continuous deployment pipeline with Docker, Docker-Compose and Rancher (Part 2)

温馨提示

对Docker容器技术或容器生产实施感兴趣的朋友欢迎加群454565480讨论。我们汇集了Docker容器技术落地实施团队精英及业内技术派高人,在线为您分享Docker技术干货。我们的宗旨是为了大家拥有更专业的平台交流Docker实战技术,我们将定期邀请嘉宾做各类话题分享及回顾,共同实践研究Docker容器生态圈。

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

1

添加新评论0 条评论

Ctrl+Enter 发表

作者其他文章

相关文章

相关问题

相关资料

X社区推广