自从我第一次接触Docker以来,我就开始编写作为持续部署流程一直在运行的脚本。 我最终得到了Shell脚本,Ansible剧本,厨师食谱,Jenkins Pipelines等。 在不同的上下文中,每个目标都有一个相似的目标(不是说相同)。 我意识到这是浪费时间,因此决定创建一个可执行文件,无论我使用什么工具来执行连续部署管道,我都可以运行该可执行文件。 结果就是Docker Flow项目的诞生。

特征

该项目的目标是添加Docker生态系统中当前缺少的功能和流程。 该项目尚处于起步阶段,目前仅解决蓝绿色部署和相对扩展的问题 。 许多其他功能将很快添加。

因为我已经写了好几篇有关该主题的文章,所以我将避免解释蓝绿色部署 。 如果您不熟悉它,请阅读“ 蓝绿色部署”文章。 有关Jenkins Pipeline的更多动手示例,请阅读使用Jenkins Workflow Plugin进行的蓝绿色部署到Docker Swarm 。 最后,对于在更广泛的上下文中(并且没有Jenkins)的另一个实际示例,请查阅Docker Swarm,Docker Compose和Consul系列的《 扩展到无限 》。

我要介绍的第二个功能是相对缩放 。 Docker Compose使将服务扩展到固定数量变得非常容易。 我们可以指定我们要运行多少个容器实例并观察魔术的发展。 当与Docker Swarm结合使用时,结果是一种管理集群内部容器的简便方法。 根据已经运行的实例数,Docker Compose将增加(或减少)正在运行的容器的数量,从而实现所需的实例数量。 但是,Docker Compose始终期望使用固定数字作为参数。 在处理生产部署时,我发现这非常有限。 在许多情况下,我不需要知道已经运行了多少个实例,而是简单地发送一个将容量增加(或减少)的信号。 例如,我们可能会增加流量,并希望将容量增加三个实例。 同样,如果对某些服务的需求减少,我们可能希望同时减少正在运行的实例的数量,并以此方式为其他服务和进程释放资源。 当我们朝着将人与人之间的互动减少到最低程度的自治和自动化的自我修复系统发展时,这种必要性就更加明显了。

运行Docker Flow

Docker Flow要求是Docker Engine , Docker Compose和Consul 。 该项目的想法不是替代任何Docker功能,而是提供其他功能。 它假定容器在docker-compose.yml文件中定义(可以更改路径),并且Consul用作服务注册表(很快也将扩展到etcd和Zookeeper)。

以下示例将使用Docker Engine和Consul设置环境,并假定您已经安装了Docker Toolbox 。 即使示例将通过Docker Toolbox Terminal运行,也可以将其应用于现有设置。 您可以在任何Docker服务器上执行它们,甚至可以在Docker Swarm集群中执行它们。

让我们开始设置将在本文中使用的环境。 请启动Docker Toolbox Terminal并克隆项目存储库。

git clone https://github.com/vfarcic/docker-flow

cd docker-flow

下一步是下载最新的Docker Flow版本。 请打开“ Docker Flow发行版”页面,下载与您的操作系统匹配的发行版,将其重命名为docker-flow,并确保其具有执行权限(即chmod +x docker-flow )。 本文的其余部分将假定二进制文件在我们克隆存储库时创建的docker-flow目录中。 如果以后选择使用它,请将其放置在PATH包含的目录之一中。

在继续之前,让我们看一下我们将使用的docker-compose.yml文件。

version: '2'

services:
app:
image: vfarcic/books-ms${BOOKS_MS_VERSION}
ports:
– 8080
environment:
– SERVICE_NAME=books-ms
– DB_HOST=books-ms-db

db:
container_name: books-ms-db
image: mongo
environment:
– SERVICE_NAME=books-ms-db

如您所见,它不包含任何特殊内容。 它有两个目标。 应用程序目标定义服务器的主容器。 db是应用程序所需的“目标”目标。 由于版本为2 ,因此Docker Compose将利用其新功能之一,并围绕这些目标创建网络,从而使容器彼此之间进行通信(如果部署到集群,则非常方便)。 最后, 应用程序图像使用BOOKS_MS_VERSION环境变量hich将使我们能够模拟多个版本。 我假设您已经使用了Docker Compose,并且没有理由进一步介绍更多细节。

我们将使用docker-machine创建一个虚拟机 ,该虚拟机将模拟我们的生产环境。

docker-machine create \
    --driver virtualbox docker-flow

eval "$(docker-machine env docker-flow)"

Docker Flow需要存储正在部署的容器的状态,因此我选择在项目的第一个迭代中使用Consul 。 其他注册表( etcd , Zookeeper以及其他人要求的其他注册表)将很快跟进。

让我们提出一个实例。

docker run -d \
    -p "8500:8500" \
    -h "consul" \
    --name "consul" \
    progrium/consul -server -bootstrap

export CONSUL_IP=$(docker-machine ip docker-flow)

现在,我们准备开始部署books-ms服务。

停机停机

在深入探讨Docker Flow功能之前,让我们看看部署如何与Docker Compose一起工作。

我们将从部署1.0版本开始。

BOOKS_MS_VERSION=:1.0 docker-compose up -d app db

docker-compose ps

docker-compose ps命令的输出如下。

Name                Command          State            Ports
--------------------------------------------------------------------------
books-ms-db        /entrypoint.sh mongod   Up      27017/tcp
dockerflow_app_1   /run.sh                 Up      0.0.0.0:32771->8080/tcp

我们还没有做任何特别的事情。 两个容器( mongo和books-ms 1.0版)正在运行。

让我们看看如果部署新版本会发生什么。

export BOOKS_MS_VERSION=:latest

docker-compose up -d app db

docker-compose up命令的输出如下。

Recreating dockerflow_app_1
books-ms-db is up-to-date

问题在于第一行指出正在重新创建dockerflow_app_1 。 它可能会引起很多问题,其中两个主要问题是停机时间和无法在将新版本投入生产之前对其进行测试。 该服务不仅(希望)在短时间内不可用,而且还未经测试。 在这种特殊情况下,我不想说该服务根本没有经过测试,但是部署没有经过测试。 即使您在过渡环境中运行一组集成测试,也不能保证相同的测试会在生产中通过。 出于这个原因,处理这种情况的一种更好的方法是应用蓝绿色部署过程。 我们应该与旧版本并行运行新版本,执行一组测试以确认部署正确完成并且服务已与系统的其余部分集成,并且,如果一切按预期进行,请切换代理从旧版本到新版本。 通过此过程,我们避免了停机时间,并同时确保新版本在对用户可用之前确实能够按预期运行。

在看到如何使用Docker Flow完成蓝绿色部署之前 ,让我们销毁刚刚运行并重新开始的容器。

docker-compose down

蓝绿色部署

Docker Flow是位于Docker Compose之上的单个二进制文件,它利用服务发现来确定应执行的操作。 它允许三种输入的组合。 命令行参数,环境变量和docker-flow.yml定义。 我们将从命令行参数开始。

./docker-flow \
    --consul-address=http://$CONSUL_IP:8500 \
    --target=app \
    --side-target=db \
    --blue-green

让我们看看哪些容器正在运行。

docker ps \
    --format "table{{.Image}}\t{{.Status}}\t{{.Names}}"

docker ps命令的输出如下。

IMAGE                     STATUS              NAMES
vfarcic/books-ms:latest   Up About a minute   dockerflow_app-blue_1
mongo                     Up About a minute   books-ms-db
progrium/consul           Up 32 minutes       consul

与没有Docker Flow的示例相比,最大的不同之处在于已部署目标的名称。 这次,该容器的名称是dockerflow_app-blue_1 。 由于这是第一个部署,因此只有蓝色版本正在运行。

让我们看看在部署第二个版本时会发生什么。 这次,我们将结合使用环境变量和docker-flow.yml文件。 后者如下。

target: app
side_targets:
– db
blue_green: true

如您所见, docker-flow.yml文件中的参数(几乎)与我们在命令行中使用的参数相同。 不同之处在于,键使用的是破折号( - )而不是下划线( _ ),以便它们遵循YML约定。 第二个区别是在YML中定义列表(在这种情况下为side_targets )的方式。

环境变量也遵循相同的命名,但是就像YML一样,其格式也要遵循适当的命名约定。 全部用大写字母表示。 另一个区别是FLOW前缀。 添加它是为了使Docker Flow使用的环境变量不会覆盖系统可能正在使用的其他变量。

您可以选择是选择命令行参数,YML规范,环境变量还是这三者的组合。

让我们重复部署。 这次,我们将Consul地址指定为环境变量,并将docker-flow.yml用于其余参数。

export FLOW_CONSUL_ADDRESS=http://$CONSUL_IP:8500

./docker-flow --flow=deploy

docker ps \
    --format "table{{.Image}}\t{{.Status}}\t{{.Names}}"

docker ps命令的输出如下。

IMAGE                     STATUS              NAMES
vfarcic/books-ms:latest   Up 24 seconds       dockerflow_app-green_1
vfarcic/books-ms:latest   Up 4 minutes        dockerflow_app-blue_1
mongo                     Up About an hour    books-ms-db
progrium/consul           Up 2 hours          consul

如您所见,这次,两个发行版并行运行。 绿色版本已加入我们先前运行的蓝色版本。 此时,您应该运行集成测试 (我倾向于称它们为部署后测试 ),并且,如果一切似乎都正常进行,请更改代理以指向新版本( 绿色 )。 如何执行此操作是您的选择(我倾向于使用Consul Template重新配置我的nginx或HAProxy )。 该计划是将代理重新配置和重新加载合并到Docker Flow中 ,但是在那之前,您应该自己做。

在测试完部署并重新配置代理后,您的用户将被重定向到新版本,并且您可以停止旧版本。 Docker Flow也可以帮助您。

./docker-flow --flow=stop-old

docker ps -a \
    --format "table{{.Image}}\t{{.Status}}\t{{.Names}}"

docker ps命令的输出如下。

IMAGE                     STATUS                        NAMES
vfarcic/books-ms:latest   Up 5 minutes                  dockerflow_app-green_1
vfarcic/books-ms:latest   Exited (137) 38 seconds ago   dockerflow_app-blue_1
mongo                     Up About an hour              books-ms-db
progrium/consul           Up 2 hours                    consul

如您所见,它停止了旧版本( 蓝色 )。 故意只停止而不删除容器,以便在重新配置代理后发现出现问题的情况下轻松回滚。

让我们看一下第二个Docker Flow功能。

相对比例

就像Docker Compose一样, Docker Flow允许您将服务扩展到固定数量的实例。

让我们将服务扩展到两个实例。

./docker-flow \
    --flow=deploy \
    --scale=2

docker ps \
    --format "table{{.Image}}\t{{.Status}}\t{{.Names}}"

docker ps命令的输出如下。

IMAGE                     STATUS              NAMES
vfarcic/books-ms:latest   Up 4 seconds        dockerflow_app-blue_2
vfarcic/books-ms:latest   Up 4 seconds        dockerflow_app-blue_1
vfarcic/books-ms:latest   Up About a minute   dockerflow_app-green_1
mongo                     Up 4 hours          books-ms-db
progrium/consul           Up 5 hours          consul

正如预期的那样,已部署了新版本的两个实例( blue )。 此行为与Docker Compose提供的行为相同(除了增加了蓝绿色部署)。 Docker Flow允许我们在比例值前加上正号( + )或负号( – )。 在讨论好处之前,让我们先看看它的实际作用。

./docker-flow \
    --flow=deploy \
    --scale=+2

docker ps \
    --format "table{{.Image}}\t{{.Status}}\t{{.Names}}"

docker ps命令的输出如下。

IMAGE                     STATUS              NAMES
vfarcic/books-ms:latest   Up 6 seconds        dockerflow_app-green_4
vfarcic/books-ms:latest   Up 7 seconds        dockerflow_app-green_3
vfarcic/books-ms:latest   Up 7 seconds        dockerflow_app-green_2
vfarcic/books-ms:latest   Up 22 minutes       dockerflow_app-blue_2
vfarcic/books-ms:latest   Up 22 minutes       dockerflow_app-blue_1
vfarcic/books-ms:latest   Up 24 minutes       dockerflow_app-green_1
mongo                     Up 5 hours          books-ms-db
progrium/consul           Up 5 hours          consul

由于先前版本有两个实例,因此部署了新版本,实例数量增加了两个(总数为四个)。 虽然这在我们要部署新版本并事先知道应该扩展实例数量时很有用,但更常用的选项是使用–flow = scale参数运行Docker Flow 。 它将遵循相同的缩放(和缩放)规则,但不部署新版本。 在尝试之前,让我们停止旧版本。

./docker-flow --flow=stop-old

让我们尝试--flow scale将实例数减少1。

./docker-flow --scale=-1 --flow=scale

docker ps \
    --format "table{{.Image}}\t{{.Status}}\t{{.Names}}"

docker ps命令的输出如下。

IMAGE                     STATUS              NAMES
vfarcic/books-ms:latest   Up 19 minutes       dockerflow_app-green_3
vfarcic/books-ms:latest   Up 19 minutes       dockerflow_app-green_2
vfarcic/books-ms:latest   Up 43 minutes       dockerflow_app-green_1
mongo                     Up 5 hours          books-ms-db
progrium/consul           Up 5 hours          consul

运行实例的数量减少了一个(从四个减少到三个)。 通过使用相对值进行缩放和除比例具有许多用途。 例如,您可能计划将每个服务安排在每个星期一早上进行扩展,因为从经验中可以知道,那是该服务获得增加流量的时候。 在相同的情况下,您可能想在每个星期一下午进行除垢,因为那时流量趋于恢复正常,并且您想释放资源用于其他服务。 自动执行缩放/除垢操作时,使用绝对数会很危险。 您可能拥有一个脚本,该脚本在高峰时段可从四个实例扩展到六个实例。 一段时间后,正常时间可能需要8个实例,而将高峰时间缩减为6个实例实际上会产生相反的效果。 在自愈系统的情况下,相对缩放和除垢的需求更加明显。

路线图

即使本文中的示例使用的是单个服务器,这些功能的主要用例还是在Docker Swarm集群内部。 有关可以使用的所有参数的信息,请参阅Docker Flow README 。

这是Docker Flow项目的开始。 其背后的主要思想是提供一种简单的方法来执行流程(如蓝绿色部署)并提供与其他工具(如Consul)的轻松集成。 我有大量计划添加的功能。 但是,在我宣布它们之前,我想获得一些反馈。 您认为这个项目有用吗? 您接下来想看哪些功能? 您希望将其与哪些工具集成?

翻译自: https://www.javacodegeeks.com/2016/03/docker-flow-blue-green-deployment-relative-scaling.html