一起牛网_苹果安卓手游族群聚集地!
发布时间:2021-06-29 11:07:00来源:一起牛手游网作者:一起牛手游网
这篇文章是一系列文章的第一篇,在这一系列文章中,我们想要分享我们如何使用Docker、Docker-Compose和Rancher完成容器部署工作流的故事。我们想带你从头开始走过pipeline的革命历程,重点指出我们这一路上遇到的痛点和做出的决定,而不只是单纯的回顾。
幸好有很多优秀的资源可以帮助你使用Docker设置持续集成和部署工作流。这篇文章并不属于这些资源之一。一个简单的部署工作流相对比较容易设置。但是我们的经验表明,构建一个部署系统的复杂性主要在于原本容易的部分需要在拥有很多依赖的遗留环境中完成,以及当你的开发团队和运营组织发生变化以支持新的过程的时候。希望我们在解决构建我们的pipeline的困难时积累下的经验会帮助你解决你在构建你的pipeline时遇到的困难。
在这第一篇文章里,我们将从头开始,看一看只用Docker时我们开发的初步的工作流。在接下来的文章中,我们将进一步介绍Docker-compose,最后介绍如何将Rancher应用到我们的工作流中。
为了为之后的工作铺平道路,假设接下来的事件都发生在一家SaaS提供商那里,我们曾经在SaaS提供商那里提供过长时间服务。仅为了这篇文章的撰写,我们姑且称这家SaaS提供商为Acme Business Company, Inc,即ABC。这项工程开始时,ABC正处在将大部分基于Java的微服务栈从裸机服务器上的本地部署迁移到运行在AWS上的Docker部署的最初阶段。这项工程的目标很常见:发布新功能时更少的前置时间(lead time)以及更可靠的部署服务。
为了达到该目标,软件的部署计划大致是这样的:
这个过程从代码的变更、提交、推送到git仓库开始。当代码推送到git仓库后,我们的CI系统会被告知运行单元测试。如果测试通过,就会编译代码并将结果作为产出物(artifact)存储起来。如果上一步成功了,就会触发下一步的工作,利用我们的代码产出物创建一个Docker镜像并将镜像推送到一个Docker私有注册表(private Docker registry)中。最后,我们将我们的新镜像部署到一个环境中。
要完成这个过程,如下几点是必须要有的:
这样去看的话,这个过程表面上简单,然而实际过程中会复杂一些。像许多其它公司一样,ABC曾经(现在仍然是)将开发团队和运营团队划分为不同的组织。当代码准备好部署时,会创建一个包含应用程序和目标环境详细信息的任务单(ticket)。这个任务单会被分配到运营团队,并将会在几周的部署窗口内执行。现在,我们已经不能清晰地看到一个持续部署和分发的方法了。
最开始,部署任务单可能看起来是这样的:
DEPLOY-111: App: JavaService1, branch “release/1.0.1” Environment: Production
部署过程是:
docker pull registry.abc.net/javaservice1:release-1.0.1
docker ps
docker stop [container_id]
开启一个新容器,这个容器必须拥有所有正确启动容器所需的标志。这些标志可以从之前运行的容器那里,主机上的shell历史,或者其它地方的文档借鉴。
docker run -d -p 8080:8080 … registry.abc.net/javaservice1:release-1.0.1
curl localhost:8080/api/v1/version
不可否认的是,这个部署过程并不怎么让人印象深刻,但这是通往持续部署伟大的第一步。这里有好多地方仍可改进,但我们先考虑一下这么做的优点:
好吧,现在看一看痛点:
基于以上的情况,我们开始做出一些改变,解决这些痛点。
第一个改进是写一个bash脚本将部署中相同的步骤包装起来。
一个简单的包装脚本可以是这样的:
一个源代码仓库。ABC已经将他们的代码存放在GitHub私有仓库上了。
一个持续集成和部署的工具。ABC已经在本地安装了Jenkins。
一个私有registry。我们部署了一个Docker registry容器,由Amazon S3支持。
一个主机运行Docker的环境。ABC拥有几个目标环境,每个目标环境都包含过渡性(staging)部署和生产部署。
部署工程师用了一周时间在Jenkins上工作,对相关的工程执行”Build Now“,将分支名作为参数传递。之后弹出了一个被标记的Docker镜像。这个镜像被自动的推送到了注册表中。工程师选择了环境中的一台当前没有在负载均衡器中被激活的Docker主机。工程师登陆到这台主机并从注册表中获取新的版本。
找到现存的容器。
终止现存容器运行。
连接这个服务并做一些手工测试确定服务正常工作。
在生产维护窗口中,更新负载均衡器使其指向更新过的主机。
一旦通过验证,这个更新会被应用到环境中所有其它主机上,以防将来需要故障切换(failover)。
运营工程师有一套部署的方案,并且每个应用的部署都使用相同的步骤。在Docker运行那一步中需要为每个服务查找参数,但是大体步骤总是相同的:Docker pull、Docker stop、Docker run。这个过程非常简单,而且很难忘掉其中一步。
当环境中最少有两台主机时,我们便拥有了一个可管理的蓝绿部署(blue-green deployment)。一个生产窗口只是简单地从负载均衡器配置转换过来。这个生产窗口拥有明显且快速的回滚方法。当部署变得更加动态时,升级、回滚以及发现后端服务器变得愈发困难,需要更多地协调工作。因为部署是手动的,蓝绿部署代价是最小的,并且同样能提供优于就地升级的主要优点。
重复输入相同的命令。或者更准确地说,重复地在bash命令行里敲击输入。解决这一点很简单:使用自动化技术!有很多工具可以帮助你启动Docker容器。对于运营工程师,最明显的解决方案是将重复的逻辑包装成bash脚本,这样只需一条命令就可以执行相应逻辑。如果你将自己称作一个开发-运营(devops)工程师,你可能会去使用Ansible、Puppet、Chef或者SaltStack。编写脚本或剧本(playbooks)很简单,但是这里仍有几个问题需要说明:部署逻辑到底放在那里?你怎样追踪每个服务的不同参数?这些问题将带领我们进入下一点。
即便一个运营工程师拥有超能力,在办公室工作一整天后的深夜里仍能避免拼写错误,并且清晰的思考,他也不会知道有一个服务正在监听一个不同的端口并且需要改变Docker端口参数。问题的症结在于开发者确实了解应用运行的详细信息(但愿如此),但是这些信息需要被传递给运营团队。很多时候,运营逻辑放在另外的代码仓库中或这根本没有代码仓库。这种情况下保持应用相关部署逻辑的同步会变得困难。由于这个原因,一个很好的做法是将你的部署逻辑只提交到包含你的Dockerfile的代码仓库。如果在一些情况下无法做到这点,有一些方法可以使这么做可行(更多细节将在稍后谈到)。把细节信息提交到某处是重要的。代码要比部署任务单好,虽然在一些人的脑海中始终认为部署任务单更好。
可见性。对一个容器进行一个故障检测须要登陆主机并且运行相应命令。在现实中,这就意味着登陆许多主机然后运行“docker ps”和“docker logs –tail=100”的命令组合。有很多解决方案可以做到集中登陆。如果你有时间的话,还是相当值得设置成集中登陆的。我们发现,通常情况下我们缺少的能力是查看哪些容器运行在那些主机上的。这对于开发者而言是个问题。开发者想要知道什么版本被部署在怎样的范围内。对于运营人员来说,这也是个主要问题。他们须要捕获到要进行升级或故障检测的容器。
食物语手游腊味合蒸高阶阵容打法思路一览
神雕侠侣2手游氪金玩家消费指南
王牌战士幽灵实战技巧讲解
爱江山更爱美人游戏中宫论战攻略
王牌战士团战如何切入详细讲解
和平精英通讯塔是什么 和平精英通讯塔玩法详细解析
暴走英雄坛延生保命丹怎么用 延生保命丹平民用法攻略
凌烟诀新手前期武学学习与主线攻略
梦幻西游三维版每日日常活动任务安排流程攻略
王者荣耀
角色扮演
坠落星界
其它游戏
炽姬无双
角色扮演
梦三国
角色扮演
跑跑卡丁车官方竞速版
体育竞技
邪恶疯人院
休闲益智
征途永恒
角色扮演
传奇世界3D
角色扮演
一刀传世
角色扮演