该文为《深入浅出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. idea搭建springmvc(maven版)

    一.创建maven项目 (1)选择 file > new > project (2)填写对应信息,一路点击next 配置自己本地的maven,继续next 命名项目名(随意写,但要易懂), ...

  2. zabbix3.4源码安装步骤

    zabbix3.4源码安装步骤1.安装环境: 安装机器:22.224.9.227 以下简称监控机: 操作系统信息:内核版本: Linux version 2.6.18-194.1.AXS3 (pack ...

  3. HDFS NameNode重启优化

    http://tech.meituan.com/namenode-restart-optimization.html 一.背景 在Hadoop集群整个生命周期里,由于调整参数.Patch.升级等多种场 ...

  4. Nacos 配置MySQL8.0持久化

    问题描述 官网下载的Nacos mysql由于驱动过低只支持5.X版本,使用8.X版本的mysql时无法正常启动 解决办法 克隆nacos源码(branch 1.0.0-RC3) master等分支也 ...

  5. Leetcode 题目整理-5 Valid Parentheses & Merge Two Sorted Lists

    20. Valid Parentheses Given a string containing just the characters '(', ')', '{', '}', '[' and ']', ...

  6. Leetcode 题目整理-4 Longest Common Prefix & Remove Nth Node From End of List

    14. Longest Common Prefix Write a function to find the longest common prefix string amongst an array ...

  7. 1757: 成绩稳定的学生(武汉科技大学结构体oj)

    #include<stdio.h>#include<string.h>struct student{ long no; char name[9]; int ch[20]; in ...

  8. python如何从内存地址上加载pythn对象

    python如何从内存地址上加载pythn对象 在python中我们可以通过id函数来获取某个python对象的内存地址,或者可以通过调用对象的__repr__魔术函数来获取对象的详细信息 def t ...

  9. 构建一个学生Student,根据类Student的定义,创建五个该类的对象,输出每个学生的信息,计算并输出这五个学生Java语言成绩的平均值,以及计算并输出他们Java语言成绩的最大值和最小值。

    定义一个表示学生信息的类Student,要求如下: (1)类Student的成员变量: sNO 表示学号: sName表示姓名: sSex表示性别: sAge表示年龄: sJava:表示Java课程成 ...

  10. qt连接mysql数据库实例

    qt5.2版本已经封装进去了mysql驱动,所以省去了我们现编译的麻烦!!! #include <QCoreApplication> #include <QDebug> #in ...