深入浅出Docker 读书笔记(七)

            第14章:使用Docker Stack部署应用

大规模场景下的多服务部署和管理是一件很难的事情。Docker Stack 通过提供期望状态、滚动升级、简单易用、扩缩容、健康检查等特性简化了应用的管理,这些功能都封装在一个完美的声明式模型当中。Stack 能够在单个声明文件中定义复杂的多服务应用。Stack 还提供了简单的方式来部署应用并管理其完整的生命周期:初始化部署 -> 健康检查 -> 扩容 -> 更新 -> 回滚,以及其他功能!步骤很简单。在 Compose 文件中定义应用,然后通过 docker stack deploy 命令完成部署和管理。Compose 文件中包含了构成应用所需的完整服务栈。此外还包括了卷、网络、安全以及应用所需的其他基础架构。然后基于该文件使用 docker stack deploy 命令来部署应用。Stack 是基于 Docker Swarm 之上来完成应用的部署。因此诸如安全等高级特性,其实都是来自 Swarm。简而言之,Docker 适用于开发和测试。Docker Stack 则适用于大规模场景和生产环境。从体系结构上来讲,Stack 位于 Docker 应用层级的最顶端。Stack 基于服务进行构建,而服务又基于容器,如下图所示。
 

AtSea商店架构图

以以下应用为例详解stack。服务架构架构如下图所示。
 

AtSea商店架构图


如上该应用由 5 个服务、3 个网络、4 个密钥以及 3 组端口映射构成。具体细节将会结合 Stack 文件进行分析。这里服务指的是 Docker 服务(由若干容器组成的集合,作为一个整体进行统一管理,并且在 Docker API 中存在对应的服务对象)。获取源码命令$ git clone https://github.com/dockersamples/atsea-sample-shop-app.git Cloning 该应用的代码由若干目录和源码文件组成。重点关注的文件是 docker-stack.yml。该文件通常被称为 Stack 文件,在该文件中定义了应用及其依赖。在该文件整体结构中,定义了 4 种顶级关键字。1)version:代表了Compose文件格式的版本号。为了应用于Stack,需要3.0或者更高的版本。2——)services:中定义了组成当前应用的服务都有哪些。3)networks:列出了必需的网络。4)secrets:定义了应用用到的密钥。
如果展开顶级的关键字,可以看到类似上图中的结构。Stack 文件由 5 个服务构成,“reverse_proxy” “database” “appserver” “visualizer” “payment_gateway”。Stack 文件中包含 3 个网络,分别为“front-tier”“back-tier”“payment”。最后,Stack 文件中有 4 个密钥,分别为“postgres_password”“staging_token”“revprox_key”“revprox_cert”。Stack 文件定义了应用的很多依赖要素,因此Stack 文件是应用的一个自描述文件,并且作为一个很好的工具弥合了开发和运维之间的隔阂。

Stack文件详解: stack文件就是 Docker Compose 文件。唯一的要求就是 version:一项需要是“3.0”或者更高的值。1)网络:在Docker 根据某个Stack文件部署应用的时候,首先会检查并创建networks:关键字对应的网络。如果对应网络不存在,Docker会进行创建。上例中定义了 3 个网络:front-tier、back-tier 以及 payment。默认情况下,这些网络都会采用 overlay 驱动,新建对应的覆盖类型的网络。但是 payment 网络比较特殊,需要数据层加密。默认情况下,覆盖网络的所有控制层都是加密的。如果需要加密数据层,有两种选择。一种是在 docker network create 命令中指定 -o encrypted 参数。另一种是在 Stack 文件中的 driver_opts 之下指定 encrypted:'yes'。数据层加密会导致额外开销,而影响额外开销大小的因素有很多,比如流量的类型和流量的多少。但是,通常额外开销会在 10% 的范围之内。正如前面提到的,全部的 3 个网络均会先于密钥和服务被创建。2)密钥:密钥属于顶级对象,在上例Stack 文件中定义4 个密钥都被定义为 external。这意味着在 Stack 部署之前,这些密钥必须存在,当然在应用部署时按需创建密钥也是可以的,只需要将 file: <filename> 替换为 external: true。但该方式生效的前提是,需要在主机文件系统的对应路径下有一个文本文件,其中包含密钥所需的值,并且是未加密的。这种方式存在明显的安全隐患。3)服务:部署中的主要操作都在服务这个环节。每个服务都是一个JSON集合(字典)其中包含了一系列关键字。如1) reverse_proxy 服务,此服务定义了镜像、端口、密钥以及网络。

reverse_proxy:                           image是服务对象中唯一必填项,定义用于构建服务的镜像。
image: reverse_proxy                除非指定其他值,否则镜像会从 Docker Hub 拉取可以通过
ports:                                          也可在镜像前添加对应第三方镜像仓库服务 API 的 DNS 名
- "80:80"                                     称的方式,ports 关键字定义了两个映射80:80 将 Swarm
- "443:443"                                 节点的80端口映射到每个服务副本的80端口。同理理解443
secrets:                                      secret 定义了两个密钥revprox_cert 以及revprox_key这两
- source: revprox_cert               个密钥必须在顶级关键字 secrets 下定义,并且必须在系统
target: revprox_cert                   上已经存在。密钥以普通文件的形式被挂载到服务副本当中
- source: revprox_key                文件的名称就是 stack 文件中定义的 target 属性的值。
target: revprox_key                    networks确保服务所有副本都会连接到 front-tier 网络。网
networks:                                   络相关定义必须位于顶级关键字 networks 之下如果定义的
- front-tier                                  网络不存在,Docker 会以 Overlay 网络方式新建一个网络
Docker Stack 和 Docker Compose 的一个区别是,Stack 不支持构建。这意味着在部署 Stack 之前,所有镜像必须提前构建完成,关于端口映射默认情况下,所有端口映射都采用 Ingress 模式。这意味着 Swarm 集群中每个节点的对应端口都会映射并且是可访问的,即使是那些没有运行副本的节点。另一种方式是 Host 模式,端口只映射到了运行副本的 Swarm 节点上。但是Host 模式需要使用完整格式的配置。

Docker Stack 部署练习:部署应用之前有几个前置处理需要完成。1)Swarm 模式:应用将采用 Docker Stack 部署,而 Stack 依赖 Swarm 模式。2)标签:某个 Swarm worker 节点需要自定义标签。3)密钥:应用所需的密钥需要在部署前创建完成。实验环境如下图所示。
 

实例环境


接下来内容分为 3 个步骤。1)创建新的三节点 Swarm 集群。在任意 Swarm 管理节点的机器上,运行$ docker swarm init    2) 添加工作节点,复制前面输出中出现的 docker swarm join 命令。将复制内容粘贴到工作节点上并运行。3) 确认当前 Swarm 由一个管理节点和两个工作节点构成$ docker node ls,至此payment_gateway 服务配置了部署约束,限制该服务只能运行在有 pcidss=yes 标签的工作节点之上。在实际操作中,添加该标签之前必须将某个 Docker 节点按 PCI 规范进行标准化。但是这只是一个实验环境,所以就暂且跳过这一过程,直接将标签添加到 wrk-1 节点。在 Swarm 管理节点运行下面的命令。

1) 添加节点标签到 wrk-1    $ docker node update --label-add pcidss=yes wrk-1Node 标签只在 Swarm 集群之内生效。2) 确认节点标签$ docker node inspect wrk-1,工作节配置完成,该节点可以运行 payment_gateway 服务副本了。应用定义了 4 个密钥,这些都需要在应用部署前创建。postgress_password。staging_token。revprox_cert。revprox_key。在管理节点运行下面的命令,来创建这些密钥。1) 创建新的键值对:密钥中有 3 个是需要加密 key 的。在本步骤中会创建加密 key,下一步会将加密 key 放到 Docker 密钥文件当中。$ openssl req -newkey rsa:4096 -nodes -sha256 \     2) 创建 revprox_cert、revprox_key 以及 postgress_password 密钥  $ docker secret create revprox_cert domain.crt     $ docker secret create revprox_key domain.key
$ docker secret create postgres_password domain.key   3) 创建 stage_token 密钥$ echo staging | docker secret create staging_token -     4) 列出所有密钥  $ docker secret ls。下面是部署应用,Stack 通过 docker stack deploy 命令完成部署。基础格式下,该命令允许传入两个参数,Stack 文件的名称和Stack 的名称。Docker 将 Stack 名称附加到由他创建的任何资源名称前作为前缀。另一个需要注意的点是出现了新的名为 seastack_default 的网络。该网络并未在Stack文件中定义,但每个服务都需要连接到网络,但是 visualizer 服务并没有指定具体的网络。因此Docker 创建了名为seastack_default 的网络,并将 visualizer 连接到该网络。可以通过两个命令来确认当前 Stack 的状态。docker stack ls 列出了系统中全部 Stack,包括每个 Stack 下面包含多少服务。docker stack ps <stack-name> 针对某个指定 Stack 展示了更详细的信息,例如期望状态以及当前状态。如果想查看具体某个服务的详细信息,可以使用 docker service logs 命令。要将服务名称 /ID 或者副本 ID 作为参数传入。如果传入服务名称或 ID,可以看到所有服务副本的日志信息。如果传入的是副本 ID,则只会看到对应副本的日志信息。

Stack 是一组相关联的服务和基础设施,需要进行统一的部署和管理。虽然这句话里充斥着术语,但仍提醒我们 Stack 是由普通的Docker资源构建而来:网络、卷、密钥、服务等。这意味着可以通过普通的 Docker 命令对其进行查看和重新配置,例如 docker network、docker volume、docker secret、docker service 等。在此前提之下,通过 docker service 命令来管理 Stack 中某个服务是可行的。一个简单的例子是通过 docker service scale 命令来扩充 appserver 服务的副本数。但是,这并不是推荐的方式!推荐通过声明式方式修改,即将 Stack 文件作为配置的唯一声明。这样,所有 Stack 相关的改动都需要体现在 Stack 文件中,然后更新重新部署应用所需的 Stack 文件。下面对实际操作中经常用到的 Docker Stack 相关的命令做了一下总结,如下所示。1) docker stsack deploy  用于根据 Stack 文件(通常是 docker-stack.yml)部署和更新 Stack 服务的命令。 2) docker stack ls   会列出 Swarm 集群中的全部 Stack,包括每个 Stack 拥有多少服务。3) docker stack ps   列出某个已经部署的 Stack 相关详情。该命令支持 Stack 名称作为其主要参数,列举了服务副本在节点的分布情况,以及期望状态和当前状态。4) docker stack rm  命令用于从 Swarm 集群中移除 Stack。移除操作执行前并不会进行二次确认。

发布了105 篇原创文章 · 获赞 86 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/dingyahui123/article/details/104581057