持续集成持续部署持续交付
本文是“ 持续集成,交付和部署”系列的一部分。
上一篇文章描述了几种持续部署策略 。 在这一部分中,我们将尝试提供一种可能的解决方案,以进行可靠,快速和自动的连续部署,并能够在新版本发布给普通用户之前对其进行测试。 如果出现问题,我们应该能够轻松回滚。 最重要的是,我们将尝试实现零停机时间。 无论我们部署应用程序多少次,都永远不会有一个时刻无法运行。
总而言之,我们的目标是:
- 在每次提交时或根据需要进行部署
- 要快
- 自动化
- 能够回滚
- 零停机时间
搭建舞台
让我们设置故事的技术部分。
应用程序将部署为Docker容器。 它是一个开放源代码平台,可用于构建,交付和运行分布式应用程序。
尽管Docker可以部署在任何操作系统上,但我更喜欢使用CoreOS 。 它是Linux发行版,提供了运行现代体系结构堆栈所需的功能。 CoreOS与其他产品相比的一个优点是它非常轻巧。 它只有很少的工具,而这些正是我们持续部署所需的工具。 我们将使用Vagrant通过CoreOS创建虚拟机。
预装在CoreOS上的两个特别有用的工具是etcd (用于共享配置和服务发现的键值存储)和systemd (一套系统管理守护程序,库和实用程序)。
我们将使用nginx作为反向代理服务器。 它的模板将由confd维护, confd旨在使用etcd中的模板和数据来管理应用程序配置文件。
最后,作为示例应用程序,我们将部署(多次) BDD Assistant 。 它可以用作BDD开发和测试的帮助工具。 之所以要包含它,是因为我们需要一个成熟的应用程序,该应用程序可用于演示我们将要探索的部署策略。
我正在寻找应用程序的早期采用者。 如果您有兴趣,请与我联系,我们将为您提供所有可能的帮助。
酷睿
如果尚未启动并运行CoreOS实例,则连续部署存储库包含Vagrantfile,可用于启动该实例。 请克隆该存储库,或下载并解压缩ZIP文件。 要运行操作系统,请安装Vagrant并从具有克隆(或解压缩)存储库的目录中运行以下命令。
vagrant up
VM的创建和启动完成后,我们可以使用以下命令进入CoreOS:
vagrant ssh
从现在开始,您应该在CoreOS内部。
码头工人
我们将使用BDD Assistant作为持续部署的示例模拟。 对BDD Assistant存储库的每次提交都会创建带有应用程序的容器。 现在,我们将直接在Docker上运行它。 进一步,我们将改进部署以使其更具弹性。
一旦执行了以下命令,它将开始下载容器映像。 第一次运行可能需要一段时间。 好消息是,缓存了图像,以后在有新版本的情况下更新速度很快,只需几秒钟即可运行。
# Run container technologyconversationsbdd and expose port 9000
docker run --name bdd_assistant -d -p 9000:9000 vfarcic/technologyconversationsbdd
首次下载所有Docker映像可能需要一段时间。 从那里开始,启动和停止服务非常快。 要查看结果,请在浏览器中打开http:// localhost:9000 / 。
那很简单。 通过一个命令,我们下载了带有AngularJS前端的完全可运行的应用程序Play! Web服务器,REST API等。容器本身是自给自足且不可变的。 新版本将是一个全新的容器。 无需配置(除了端口应用程序正在运行),并且在制作新版本时也无需更新。 它很简单。
等
让我们进入etcd。
etcd &
从现在开始,我们可以使用它来存储和检索所需的信息。 例如,我们可以存储端口BDD Assistant正在运行。 这样,任何需要与之集成的应用程序都可以检索端口,例如,使用它来调用应用程序API。
# Set value for a give key
etcdctl set /bdd-assistant/port 9000
# Retrive stored value
etcdctl get /bdd-assistant/port
这是一种非常简单(快速)的方式来存储我们可能需要的任何键/值。 它将很快派上用场。
Nginx的
目前,我们的应用程序正在端口9000上运行。与其打开localhost:9000(或它正在运行的任何端口),不如直接在localhost上运行会更好。 我们可以使用nginx反向代理来完成该任务。
这次我们不会直接调用Docker,而是通过systemd将其作为服务运行。
# Create directories for configuration files
sudo mkdir -p /etc/nginx/{sites-enabled,certs-enabled}
# Create directories for logs
sudo mkdir -p /var/log/nginx
# Copy nginx service
sudo cp /vagrant/nginx.service /etc/systemd/system/nginx.service
# Enable nginx service
sudo systemctl enable /etc/systemd/system/nginx.service
nginx.service文件告诉systemd当我们想要启动,停止或重新启动某些服务时该怎么做。 在我们的例子中,该服务是使用Docker nginx容器创建的。
让我们启动nginx服务(第一次可能需要一段时间才能提取Docker映像)。
# Start nginx service
sudo systemctl start nginx.service
# Check whether nginx is running as Docker container
docker ps
如您所见,nginx作为Docker容器运行。 让我们停止它。
# Stop nginx service
sudo systemctl stop nginx.service
# Check whether nginx is running as Docker container
docker ps
现在它从Docker进程中消失了。 就这么简单。 我们可以立即启动和停止任何Docker容器(假设已经下载了映像)。
在本文的其余部分,我们将需要启动并运行nginx,因此让我们重新启动它。
sudo systemctl start nginx.service
confd
当需要BDD Assistant时,我们需要一些信息告诉nginx重定向到哪个端口。 我们将使用confd。 让我们进行设置。
# Download confd
wget -O confd https://github.com/kelseyhightower/confd/releases/download/v0.6.3/confd-0.6.3-linux-amd64
# Put it to the bin directory so that it is easily accessible
sudo cp confd /opt/bin/.
# Give it execution permissions
sudo chmod +x /opt/bin/confd
下一步是配置confd,以在每次部署应用程序时修改nginx路由并重新加载它们。
# Create configuration and templates directories
sudo mkdir -p /etc/confd/{conf.d,templates}
# Copy configuration
sudo cp /vagrant/bdd_assistant.toml /etc/confd/conf.d/.
# Copy template
sudo cp /vagrant/bdd_assistant.conf.tmpl /etc/confd/templates/.
bdd_assistant.toml和bdd_assistant.conf.toml都在您已经下载的存储库中。
让我们看看它是如何工作的。
sudo confd -onetime -backend etcd -node 127.0.0.1:4001
cat /etc/nginx/sites-enabled/bdd_assistant.conf
wget localhost; cat index.html
我们刚刚更新了nginx模板,以使用先前在etcd中设置的端口。 现在,您可以在浏览器中打开http:// localhost:8000 / (Vagrant设置为将默认80公开为8000)。 即使应用程序在端口9000上运行,我们仍将nginx设置为将请求从默认端口80重定向到端口9000。
让我们停止并删除BDD Assistant容器。 我们将使用到目前为止看到的所有工具再次创建它。
docker stop bdd_assistant
docker rm bdd_assistant
docker ps
BDD助理部署程序
现在您已经熟悉了这些工具,是时候将它们捆绑在一起了。
我们将练习蓝绿色部署 。 这意味着我们将启动一个版本并运行(蓝色)。 部署新版本(绿色)后,它将并行运行。 一旦启动并运行,nginx会将所有请求重定向到它,而不是旧请求。 每个连续的发行将遵循相同的过程。 在蓝色上部署,将请求从绿色重定向到蓝色,在绿色上部署,将请求从蓝色重定向到绿色,等等。回滚将很容易实现。 我们只需要更改反向代理即可。 由于新版本将在启动重定向请求之前启动并运行,因此将需要零停机时间。 一切都将完全自动化并且非常快。 完成所有这些操作后,我们将能够根据需要进行多次部署(最好是对存储库的每次提交)。
sudo cp /vagrant/bdd_assistant.service /etc/systemd/system/[email protected]
sudo cp /vagrant/bdd_assistant.service /etc/systemd/system/[email protected]
sudo systemctl enable /etc/systemd/system/[email protected]
sudo systemctl enable /etc/systemd/system/[email protected]
# sudo systemctl daemon-reload
etcdctl set /bdd-assistant/instance none
sudo chmod 744 /vagrant/deploy_bdd_assistant.sh
sudo cp /vagrant/deploy_bdd_assistant.sh /opt/bin/.
我们刚刚创建了两个BDD Assistant服务:蓝色和绿色。 它们每个都将在不同的端口(9001和9002)上运行,并将相关信息存储到etcd。 deploy_bdd_assistant.sh是一个简单的脚本,用于启动服务,使用conf更新nginx模板并最终停止旧服务。 BDD Assistant服务和deploy_bdd_assistant.sh在已下载的存储库中均可用。
让我们尝试一下。
sudo deploy_bdd_assistant.sh
每次我们运行脚本deploy_bdd_assistant.sh都会部署新版本。 我们可以通过检查etcd中存储了什么值,查看Docker进程以及最后在浏览器中运行该应用程序来确认这一点。
docker ps
etcdctl get /bdd-assistant/port
Docker进程应该从在端口9001上运行蓝色部署更改为在端口9002上运行绿色部署, 反之亦然 。 etcd中存储的端口应从9001更改为9002,反之亦然。 无论部署了哪个版本,无论我们是在部署过程中还是已经完成部署, http:// localhost:8000 /都将始终在您的浏览器中运行。
根据需要重复执行脚本deploy_bdd_assistant.sh的次数。 它应该始终部署最新的新版本。
为简洁起见,我排除了部署验证。 在“现实世界”中,在运行新容器之后并且在设置反向代理指向它之前,我们应该运行各种测试(功能,集成和压力),以验证代码更改是否正确。
持续交付和部署
上述过程应绑定到您的CI / CD服务器( Jenkins , Bamboo , GoCD等)。 一种可能的“持续交付”程序为:
- 将代码提交到VCS( GIT ,SVN等)
- 运行所有静态分析
- 运行所有单元测试
- 构建Docker容器
- 部署到测试环境
- 使用新版本运行容器
- 运行自动化的功能,集成(即BDD )和压力测试
- 执行手动测试
- 更改反向代理以指向新容器
- 部署到生产环境
- 使用新版本运行容器
- 运行自动化的功能,集成(即BDD )和压力测试
- 更改反向代理以指向新容器
理想情况下,不应进行任何手动测试,在这种情况下,不需要第5点。 我们将拥有持续部署 ,该部署将自动部署将所有测试传递给生产的每个提交。 如果不可避免地需要手动验证,则我们可以连续交付以测试环境,并且只需单击我们使用的CI / CD服务器内的按钮,即可将软件部署到生产环境中。
摘要
无论我们选择连续交付还是部署,当我们的流程完全自动化(从构建到测试,再到部署本身)时,我们都可以花时间在可以带来更多价值的事情上,而让脚本为我们工作。 上市时间应该大大减少,因为一旦将代码提交到存储库,我们就可以为用户提供可用的功能。 这是一个非常强大且有价值的概念。
如果在练习后遇到任何麻烦,则可以跳过它们,直接进入运行deploy_bdd_assistant.sh脚本。 只需从Vagrantfile中删除注释(#)。
如果VM已启动并正在运行,请销毁它。
vagrant destroy
创建新的VM并运行deploy_bdd_assistant.sh脚本。
vagrant up
vagrant ssh
sudo deploy_bdd_assistant.sh
希望您能在Docker中看到它的价值。 与构建和部署软件的更传统方式相比,它可以改变游戏规则。 新的门已经为我们打开了,我们应该一步步通过。
BDD Assistant及其在Docker上的部署甚至可以更好。 我们可以将应用程序拆分为较小的微服务。 例如,它可以将前端作为单独的容器。 后端可以分为较小的服务(故事管理,故事运行者等)。 这些微服务可以部署到相同或不同的机器上,并与Fleet一起编排。 微服务将是下一篇文章的主题。
翻译自: https://www.javacodegeeks.com/2014/12/continuous-deployment-implementation.html
持续集成持续部署持续交付