该文为《深入浅出Docker》的学习笔记,感谢查看,如有错误,欢迎指正

一、简介

Docker Stack 是为了解决大规模场景下的多服务部署和管理,提供了期望状态滚动升级简单易用扩缩容健康检查等特性,并且都封装在一个声明式模型当中。

  • Docker Stack 部署应用的生命周期:初始化部署 > 健康检查 > 扩容 > 更新 > 回滚
  • 使用单一声明式文件即可完成部署,即只需要docker-stack.yml文件,使用docker stack deploy命令即可完成部署。
  • stack 文件其实就是 Docker compose 文件,唯一的要求就是 version 需要为 3.0 或者更高的值。
  • Stack 完全集成到了 Docker 中,不像 compose 还需要单独安装。

Docker 适用于开发和测试,而 Docker Stack 则适用于大规模场景和生产环境

二、docker-stack.yml文件详解

从 GitHub 中拉取示例代码,分析其中的 docker-stack.yml 文件

[root@huanzi-001 daemon]# git clone https://github.com/dockersamples/atsea-sample-shop-app.git

可以看到有 5 个服务,3 个网络,4 个秘钥,3 组端口映射;

services:
reverse_proxy:
database:
appserver:
visualizer:
payment_gateway:
networks:
front-tier:
back-tier:
payment:
secrets:
postgres_password:
staging_token:
revprox_key:
revprox_cert:
2.1 网络

Docker 根据 stack 文件部署的时候,第一步会检查并创建 networks:关键字对应的网络。默认会创建覆盖网络(overlay),并且控制层会加密,如果需要对数据层加密,可以在 stack 文件的 driver_opts 之下指定 encrypted:'yes',数据层加密会导致额外开销,但是一般不会超过10%。

networks:
front-tier:
back-tier:
payment:
driver: overlay
driver_opts:
encrypted: 'yes'

3 个网络都会先于秘钥和服务被创建

2.2 秘钥

当前 Stack 文件中定义了 4 个秘钥,并且都是external,这表示在 Stack 部署前,这些秘钥必须已存在

secrets:
postgres_password:
external: true
staging_token:
external: true
revprox_key:
external: true
revprox_cert:
external: true
2.3 服务

总共有 5 个服务,我们依次进行分析

2.3.1 reverse_proxy 服务

reverse_proxy:
image: dockersamples/atseasampleshopapp_reverse_proxy
ports:
- "80:80"
- "443:443"
secrets:
- source: revprox_cert
target: revprox_cert
- source: revprox_key
target: revprox_key
networks:
- front-tier
  • image:必填项,指定了用于构建服务副本的 Docker 镜像
  • ports:Swarm 节点的 80 端口映射到副本的 80 端口,443 端口映射到副本的 443 端口
  • secrets:2 个秘钥以普通文件形式挂载至服务副本中,文件名称就是 target 属性的值,路径为/run/secrets
  • networks:所有副本都会连接到 front-tier 网络,如果定义的网络不存在,Docker 会以 Overlay 的网络方式新建一个

2.3.2 database 服务

database:
image: dockersamples/atsea_db
environment:
POSTGRES_USER: gordonuser
POSTGRES_DB_PASSWORD_FILE: /run/secrets/postgres_password
POSTGRES_DB: atsea
networks:
- back-tier
secrets:
- postgres_password
deploy:
placement:
constraints:
- 'node.role == worker'

多了以下几项:

  • environment:环境变量,定义了数据库用户,密码位置,数据库名称
  • deploy:部署约束,服务只运行在 Swarm 集群的 Worker 节点上

Swarm 目前允许以下几种部署约束方式:

  • 节点 ID :node.id == 85v90bioyy4s2fst4fa5vrlvf
  • 节点名称:node.hostname == huanzi-002
  • 节点角色:node.role != manager
  • 节点引擎标签:engine.labels.operatingsystem == Centos 7.5
  • 节点自定义标签:node.labels.zone == test01

支持==!=操作。

2.3.3 appserver 服务

appserver:
image: dockersamples/atsea_app
networks:
- front-tier
- back-tier
- payment
deploy:
replicas: 2
update_config:
parallelism: 2
failure_action: rollback
placement:
constraints:
- 'node.role == worker'
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
secrets:
- postgres_password
  • deploy-replicas:部署的服务副本数量
  • deploy-update_config:滚动升级时的操作,每次更新 2 个副本(parallelism:2),升级失败以后回滚(failure_action: rollback)
  • failure_action默认为 pause ,即服务升级失败后阻止其它副本的升级,还支持 continue
  • restart_policy:容器异常退出的重启策略,当前策略为:如果某个副本以非 0 返回值退出(condition: on-failure),会立即重启当前副本,重启最多重试 3 次,每次最多等待 120s,每次重启间隔是 5s。

2.3.4 visualizer 服务

visualizer:
image: dockersamples/visualizer:stable
ports:
- "8001:8080"
stop_grace_period: 1m30s
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
update_config:
failure_action: rollback
placement:
constraints:
- 'node.role == manager'
  • stop_grace_period:设置容器优雅停止时长(Docker 停止某个容器时,会给容器内 PID 为 1 的进程发送一个 SIGTERM 信号,容器内 PID 为 1 的进程有 10s 的优雅停止时长来执行清理操作)
  • volumes:挂载提前创建的卷或者主机目录至某个服务副本中,本例中/var/run/docker.sock为Docker 的 IPC 套接字,Docker daemon 通过该套接字对其它进程暴露 API 终端,如果某个容器有该文件的访问权限,即允许该容器访问所有的 API 终端,并且可以查询及管理 Docker daemon。生产环境严禁使用该操作

2.3.5 payment_gateway 服务

payment_gateway:
image: dockersamples/atseasampleshopapp_payment_gateway
secrets:
- source: staging_token
target: payment_token
networks:
- payment
deploy:
update_config:
failure_action: rollback
placement:
constraints:
- 'node.role == worker'
- 'node.labels.pcidss == yes'

node.labels:自定义节点标签,可以通过docker node update自定义,并添加至 Swarm 集群的指定节点。这说明,node.labels 配置只适用于 Swarm 集群中指定的节点。

三、部署docker stack
3.1 准备工作
  • 自定义标签(payment_gateway 服务需要用到)
  • 密钥(提前创建 4 个)

给工作节点 huanzi-002 新建一个自定义标签,在管理节点上操作

[root@huanzi-001 atsea-sample-shop-app]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
8bet9fg0tnoqlfp0ebrrqdapn * huanzi-001 Ready Active Leader 19.03.5
85v90bioyy4s2fst4fa5vrlvf huanzi-002 Ready Active 19.03.5
8hxs2p5iblj19xg9uqpu8ar8g huanzi-003 Ready Active 19.03.5
[root@huanzi-001 atsea-sample-shop-app]# docker node update --label-add pcidss=yes huanzi-002
huanzi-002
[root@huanzi-001 atsea-sample-shop-app]# docker node inspect huanzi-002
[
{
"ID": "85v90bioyy4s2fst4fa5vrlvf",
"Version": {
"Index": 726
},
"CreatedAt": "2020-02-02T08:11:34.982719258Z",
"UpdatedAt": "2020-02-06T10:22:25.44331302Z",
"Spec": {
"Labels": {
"pcidss": "yes"
<...>

可以看到自定义标签已经成功创建。

接下来创建密钥,先创建加密 key

[root@huanzi-001 daemon]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout damain.key -x509 -days 365 -out domain.crt
Generating a 4096 bit RSA private key
....................................++
...........................................++
writing new private key to 'damain.key'
-----
<...>
Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:
Email Address []:
[root@huanzi-001 daemon]# ls
atsea-sample-shop-app damain.key domain.crt
[root@huanzi-001 daemon]#

创建需要加密 key 的revprox_certrevprox_keypostgres_password这 3 个密钥

[root@huanzi-001 daemon]# docker secret create revprox_cert domain.crt
lue5qk6ophxrr6aspyhnkhvsv
[root@huanzi-001 daemon]# docker secret create revprox_key damain.key
glvfk78kn6665lmkci7tslrw6
[root@huanzi-001 daemon]# docker secret create postgres_password damain.key
pxdfs28hb2897xuu7f3bub7ex
[root@huanzi-001 daemon]#

创建不需要加密 key 的staging_token密钥

[root@huanzi-001 daemon]# echo staging | docker secret create staging_token -
cyqfn9jocvnxd2vr57gn5pioj
[root@huanzi-001 daemon]# docker secret ls
ID NAME DRIVER CREATED UPDATED
pxdfs28hb2897xuu7f3bub7ex postgres_password 15 minutes ago 15 minutes ago
lue5qk6ophxrr6aspyhnkhvsv revprox_cert 16 minutes ago 16 minutes ago
glvfk78kn6665lmkci7tslrw6 revprox_key 16 minutes ago 16 minutes ago
cyqfn9jocvnxd2vr57gn5pioj staging_token About a minute ago About a minute ago
[root@huanzi-001 daemon]#

现在自定义标签,及密钥全部创建完毕。

3.2 开始部署

命令:docker stack deploy -c <docker-stack.yml> <stack name>

[root@huanzi-001 atsea-sample-shop-app]# docker stack deploy -c docker-stack.yml huanzi-stack
Creating network huanzi-stack_front-tier
Creating network huanzi-stack_back-tier
Creating network huanzi-stack_default
Creating network huanzi-stack_payment
Creating service huanzi-stack_payment_gateway
Creating service huanzi-stack_reverse_proxy
Creating service huanzi-stack_database
Creating service huanzi-stack_appserver
Creating service huanzi-stack_visualizer
[root@huanzi-001 atsea-sample-shop-app]#

可以看出,先创建了 4 个网络,再创建的服务,我们验证一下网络是否创建了

[root@huanzi-001 atsea-sample-shop-app]# docker network ls
NETWORK ID NAME DRIVER SCOPE
34306420befb bridge bridge local
ac57c15024c7 docker_gwbridge bridge local
e863472805b3 host host local
ojt9cxg2qsxe huanzi-net overlay swarm
o74roe621idx huanzi-stack_back-tier overlay swarm
k55m237m11ct huanzi-stack_default overlay swarm
idpvc5xg2g2t huanzi-stack_front-tier overlay swarm
uvphcut0a825 huanzi-stack_payment overlay swarm
7d6iv5ilwbcn ingress overlay swarm
d302c895b455 lovehuanzi bridge local
eefd134326c4 none null local
[root@huanzi-001 atsea-sample-shop-app]#

看到了 4 个 huanzi-stack 前缀的网络。为什么多了一个huanzi-stack-default,因为visualizer 服务没有指定网络,因此 Docker 创建了一个 defalut 的网络给它用。

再验证下服务

root@huanzi-001 atsea-sample-shop-app]# docker stack ls
NAME SERVICES ORCHESTRATOR
huanzi-stack 5 Swarm
[root@huanzi-001 atsea-sample-shop-app]#
[root@huanzi-001 atsea-sample-shop-app]# docker stack ps huanzi-stack
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
ex55yaz21mra huanzi-stack_appserver.1 dockersamples/atsea_app:latest huanzi-003 Running Preparing 2 minutes ago
jshmzquzxi8p huanzi-stack_database.1 dockersamples/atsea_db:latest huanzi-002 Running Preparing 2 minutes ago
k7mi1419ahwd huanzi-stack_reverse_proxy.1 dockersamples/atseasampleshopapp_reverse_proxy:latest huanzi-003 Running Preparing 2 minutes ago
09ocoutjfc70 huanzi-stack_payment_gateway.1 dockersamples/atseasampleshopapp_payment_gateway:latest huanzi-002 Running Preparing 2 minutes ago
y6lftn8g95b8 huanzi-stack_visualizer.1 dockersamples/visualizer:stable huanzi-001 Running Preparing 2 minutes ago
5twm1k4uj5ps huanzi-stack_appserver.2 dockersamples/atsea_app:latest huanzi-002 Running Preparing 2 minutes ago
[root@huanzi-001 atsea-sample-shop-app]#

可以看到满足 stack 文件的要求:

  • reverse_proxy:副本数量 1
  • database:副本数量 1,位于worker
  • appserver:副本数量 2,位于worker
  • visualizer:副本数量 1,位于manager
  • payment_gateway:副本数量 1,位于worker,自定义标签pcidss == yes(即 huanzi-002 )
3.3 管理 Stack

3.3.1 扩容

appserver的副本数从 2 扩至 10,有 2 种方式:

  • 通过docker service scale appserver=10
  • 直接修改docker-stack.yml文件,再通过docker stack deploy重新部署

所有的变更都应该通过 Stack 文件进行声明,然后通过 docker stack deploy 进行部署



修改docker-stack.yml文件

appserver:
image: dockersamples/atsea_app
networks:
- front-tier
- back-tier
- payment
deploy:
replicas: 10

重新部署

[root@huanzi-001 atsea-sample-shop-app]# docker stack deploy -c docker-stack.yml huanzi-stack
Updating service huanzi-stack_reverse_proxy (id: i2yn8l50ofnmbx0a55mum1dw0)
Updating service huanzi-stack_database (id: ubrtixblmj685pnc97wql42cm)
Updating service huanzi-stack_appserver (id: yy447jdp1eiwb03ljdsqtyg1g)
Updating service huanzi-stack_visualizer (id: rhzzxov0jh1y38rxcj6bwe89y)
Updating service huanzi-stack_payment_gateway (id: niobpxv5vr1njoo37vnje8zic)
[root@huanzi-001 atsea-sample-shop-app]#
[root@huanzi-001 atsea-sample-shop-app]# docker stack ps huanzi-stack
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
wrser9r5bbrz huanzi-stack_visualizer.1 dockersamples/visualizer:stable huanzi-001 Running Preparing 3 minutes ago
ex55yaz21mra huanzi-stack_appserver.1 dockersamples/atsea_app:latest huanzi-003 Running Preparing 20 minutes ago
jshmzquzxi8p huanzi-stack_database.1 dockersamples/atsea_db:latest huanzi-002 Running Preparing 20 minutes ago
k7mi1419ahwd huanzi-stack_reverse_proxy.1 dockersamples/atseasampleshopapp_reverse_proxy:latest huanzi-003 Running Preparing 20 minutes ago
09ocoutjfc70 huanzi-stack_payment_gateway.1 dockersamples/atseasampleshopapp_payment_gateway:latest huanzi-002 Running Preparing 20 minutes ago
5twm1k4uj5ps huanzi-stack_appserver.2 dockersamples/atsea_app:latest huanzi-002 Running Preparing 20 minutes ago
aydzla0zzv3p huanzi-stack_appserver.3 dockersamples/atsea_app:latest huanzi-003 Running Preparing 2 minutes ago
n3312auusvxi huanzi-stack_appserver.4 dockersamples/atsea_app:latest huanzi-002 Running Preparing 2 minutes ago
kg8jy3ei0beo huanzi-stack_appserver.5 dockersamples/atsea_app:latest huanzi-003 Running Preparing 2 minutes ago
tgai33mhlxyv huanzi-stack_appserver.6 dockersamples/atsea_app:latest huanzi-002 Running Preparing 2 minutes ago
n69nunaur3lz huanzi-stack_appserver.7 dockersamples/atsea_app:latest huanzi-003 Running Preparing 2 minutes ago
mqubx8hoddn8 huanzi-stack_appserver.8 dockersamples/atsea_app:latest huanzi-002 Running Preparing 2 minutes ago
p3mo3k8a5jvs huanzi-stack_appserver.9 dockersamples/atsea_app:latest huanzi-003 Running Preparing 2 minutes ago
xw8tvi5bwh53 huanzi-stack_appserver.10 dockersamples/atsea_app:latest huanzi-002 Running Preparing 2 minutes ago
[root@huanzi-001 atsea-sample-shop-app]#

扩容完成。

3.3.2 删除

命令:docker stack rm <stack name>

[root@huanzi-001 atsea-sample-shop-app]# docker stack rm huanzi-stack
Removing service huanzi-stack_appserver
Removing service huanzi-stack_database
Removing service huanzi-stack_payment_gateway
Removing service huanzi-stack_reverse_proxy
Removing service huanzi-stack_visualizer
Removing network huanzi-stack_front-tier
Removing network huanzi-stack_default
Removing network huanzi-stack_back-tier
Removing network huanzi-stack_payment

可以看出,rm会删除服务及网络,但是密钥和卷不会删除

root@huanzi-001 atsea-sample-shop-app]# docker secret ls
ID NAME DRIVER CREATED UPDATED
pxdfs28hb2897xuu7f3bub7ex postgres_password 53 minutes ago 53 minutes ago
lue5qk6ophxrr6aspyhnkhvsv revprox_cert 55 minutes ago 55 minutes ago
glvfk78kn6665lmkci7tslrw6 revprox_key 54 minutes ago 54 minutes ago
cyqfn9jocvnxd2vr57gn5pioj staging_token 40 minutes ago 40 minutes ago
[root@huanzi-001 atsea-sample-shop-app]#

一般一个环境需要一个stack文件。比如dev,test,prod。

感谢阅读,有兴趣的小伙伴可以关注我的微信公众号DevOps探索之旅,大家一起学习进步

Docker Stack 学习笔记的更多相关文章

  1. Docker&K8S学习笔记(一)—— Docker安装

    最近一年在工作上经常使用Docker与K8S,除了利用其打镜像,部署服务外,还基于Docker与K8S开发了一套CICD流水线平台,为了加深相关知识点的理解,所以从今天开始会定期更新学习笔记,本套学习 ...

  2. Docker的学习笔记(一)基础知识

    概述 本人最近在学习docker相关的知识,既是工作本身的需要也是自己对技术的追求的必要,以后我也会推出容器相关的随笔,既可以增长自己的知识,也可以和读者广泛交流,岂不乐乎?话不多说.第一篇先介绍do ...

  3. docker容器学习笔记

    docker是通过内核虚拟化技术来提供容器的资源隔离与安全保障. docker组成: docker client.docker server.docker组件(镜像(image).容器(contain ...

  4. Docker的学习笔记(开发的技术分享转发)

    我的Docker学习记录一.安装dockeryum install -y docker-io二.使用docker1.下载镜像docker pull <image>2.查询镜像docker ...

  5. Docker(Linux)学习笔记以及Redis/MariaDB的容器使用后台全自动启动

    1:Docker安装,由于Docker后续pull镜像的服务器默认是在国外的,速度实在是太慢,这里使用阿里云的镜像 阿里云的Docker CE 镜像源站进行安装 docker ===========U ...

  6. docker(学习笔记)

    # 1. Docker介绍## 1.1 什么是容器?## 1.2 容器的前世今生FreeBASE jail ------> Linux vserverchroot ----> 完整的根文件 ...

  7. 字节跳动内部微服务架构-Docker实战学习笔记分享 真香

    前言 基于 Spring Cloud 的微服务设计和开发,已经越来越多地得到了更多企业的推广和应用,而 Spring Cloud 社区也在不断的迅速发展壮大之中,近几年时间,Spring Cloud ...

  8. docker入门-学习笔记

    docker可以类比成window下的VMware或者virtualbox软件.docker有两个基本的概念:容器(container)和镜像(image),分别对应为VMware中的系统镜像和系统镜 ...

  9. Docker compose学习笔记

    一.compose compose 作用 你的应用可能需要很多个服务,比如web服务,数据库服务,缓存服务等等.我们可以把这些服务放到单独的容器里面,如果手工去配置这些服务会有些麻烦,docker c ...

随机推荐

  1. mysql 常用sql操作总结

    批量修改表的引擎,从MyISAM修改为InnoDB 生成执行语句: select CONCAT('alter table ',table_name,' engine=InnoDB;') FROM in ...

  2. Quantitative Trading with R(一):两个简单的策略

    下面是两个使用R中的Quantstrat包进行策略构建的例子,都是对600550.ss.600192.ss.600152.ss.600644.ss.600885.ss.600151.ss六只股票进行投 ...

  3. 什么是LakeHouse?

    1. 引入 在Databricks的过去几年中,我们看到了一种新的数据管理范式,该范式出现在许多客户和案例中:LakeHouse.在这篇文章中,我们将描述这种新范式及其相对于先前方案的优势. 数据仓库 ...

  4. Ubuntu 获取 root 用户权限并以 root权限登录

    操作步骤: 1.打开终端,使用 sudo passwd root 命令进行 Ubuntu 中密码的重置        2.切换到 /usr/share/lightdm/lightdm.conf.d 目 ...

  5. js----UTC时间于本地时间相差8小时问题

    js----UTC时间于本地时间相差8小时问题 js获取周几有两个方法getDay() getUTCDay(),但是它们是有区别的,前者返回的本地时间,后者返回的UTC时间,一般情况下,两者相差8个小 ...

  6. hadoop-2.10.0安装hive-2.3.6

    公司建立数仓,hive是必不可少的,hive是建立在hadoop基础上的数据库,前面已经搭建起了hadoop高可用,要学习hive,先从搭建开始,下面梳理一下hive搭建过程 1.下载hive安装包 ...

  7. SpringBoot学习遇到的问题(1) - 配置文件有日志的debug模式等配置项,为什么不起作用

    这个问题困扰我近乎两天,通过查找N多资料后终于解决,写下来共享给大家. logging.level.root=DEBUG ... 一系列的日志配置项,都不起作用的原因是springboot启动加载不到 ...

  8. copy constructor和copy assignment operator的区别

    拷贝构造函数(copy constructor)被用来以一个对象来初始化同类型的另一个对象,拷贝赋值运算符(copy assignment operator)被用来将一个对象中的值拷贝到同类型的另一个 ...

  9. qt creator源码全方面分析(2-6)

    目录 User Interface Text Guidelines 语法和风格 标点 编写工具提示tooltips 编写消息 UI文本大写 使用书本样式大写 使用句子样式大写 准备本地化 标记UI文本 ...

  10. HDU 1004 Let the Balloon Rise(STL初体验之map)

    Problem Description Contest time again! How excited it is to see balloons floating around. But to te ...