Docker swarm
几个关键概念
Swarm
Docker Engline 中集成的集群管理和编排功能都是基于 SwarmKit 实现。参与到集群中的 Docker Engine 会进入 swarm 模式。比如初始化一个 swarm 或加入已有的 swarm。
一个 swarm 就是个一个 Docker Engine 集群,你可以在上面部署服务。Docker Engine CLI 提供了用于 swarm 管理的命令,比如添加或移除一个节点。同样还提供了用于部署服务到 swarm 和管理服务编排的命令。
当 Docker Engine 运行在 swarm 模式时,你管理容器。当 Docker Engine 运行在 swarm 模式时,你编排服务。
节点
每个参与到 swarm 中的 Docker Engine 都称之为一个节点。
将服务的定义提交到管理节点即可将应用部署到 swarm。然后管理节点将叫作任务的工作单元分发到工作节点。
为了维持 swarm 的目标状态,管理节点还将承当编排和集群管理的功能。一般有多个管理节点,它们之间会选出一个领导来进行编排任务。
工作节点接收并执行来自管理节点分发的任务。默认情况下,管理节点也是工作节点,你可以把它配置成只当管理节点。代理通知管理节点已分配任务的当前状态,以便管理节点维护所需的状态。
服务和任务
服务定义了需要在工作节点上执行的任务。它是 swarm 系统的中心结构,也是用户和 swarm 交互的主要根源。
服务包括要使用的容器镜像,以及在容器中执行的指令。
对于复制服务,管理节点根据服务的规模和目标状态将一定数量的任务副本分发到各节点上。
对于全局服务,每个节点上都将分发一个任务副本。
任务包含一个容器和需要在容器中执行的指令。它是 swarm 原子调度单位。管理节点根据服务规模中定义的副本数量将任务分配给工作节点。一旦某个任务被分配到某个节点,就不能再移动到其他节点。它只能在分配的节点上运行或者失败。
负载均衡
swarm 管理节点使用 入口负载均衡 的方式暴露你想要让外部访问的服务。Swarm 管理节点可以自动将一个服务分配到某个 发布端口,或者你可以为服务指定一个发布端口。你可以指定任意未使用的端口。如果你没指定端口,swarm 管理节点将为服务指定一个 30000-32757 之间的端口。
外部组件,比如云负载均衡器,可以通过集群中的任意节点访问发布端口上的服务,不管当前节点上是否有服务对应的任务在运行,swarm 中的所有节点都会将进入连接路由到正在运行任务的实例上。
Swarm 模式有一个内置的 DNS 组件,它会自动给 swarm 中的每个服务分配一个 DNS 条目。Swarm 管理器使用internal load balancing 基于服务对应的 DNS 名称在服务之间分发请求。
开始实践
本教程将指导你完成以下任务:
-
在 Docker Engline swarm 模式下初始化一个集群
-
添加节点到 swarm
-
部署服务到 swarm
-
在一切就绪后管理 swarm
准备工作
在开始本教程之前,你需要准备一下几样东西:
三台通过网络连接的主机
每台主机安装 Docker Engine 1.12 或更新版本
充当管理节点的主机 IP
主机之间开发下面提到的端口
主机之间端口开放
主机之间的以下端口必须是开放。某些环境下,这些端口默认是允许的:
TCP 端口 2377 用于集群管理通信(管理节点)
TCP 和 UDP 端口 7946 用于节点间通信(所有节点)
TCP 和 UDP 端口 4789 用于 overlay 网络流量(所有节点)
如果你的这些端口没有打开,可以用iptables命令打开它们
创建 swarm
# 先初始化manager的cluster,宣告地址 docker swarm init --advertise-addr=192.168.205.10
# -advertise-addr 标志配置了管理节点的 IP 地址。如果你的机器只有一个 IP 地址,可以省略--adbertise-addr选项,docker 会自动选择正确的 IP。上输出信息说明了怎样加入新的工作节点。也说明了执行docker swarm join-token manager 可以查询怎样加入新的管理节点。
# docker swarm join-token manager 查看节点加入命令
# docker node ls 查看节点信息
# docker node rm jar 删除节点
# 查看怎么加入swarm
docker swarm join-token worker
# 添加worker到manage cluster
docker swarm join --token SWMTKN-1-5zj189y4mz8yttawc6jlq1vb86hcu4lbzzo1nts1yzu7d9teaa-
# 部署一个服务到swarm
docker service create --replicas 1 --name helloworld busybox:1.25.1-musl /bin/sh -c "while true; do echo hello world; sleep 3; done"
docker service create 命令创建服务。
--name 标志将服务命名为helloworld。
--replicas 标志指定了期望状态为 1 个运行示例。
# 查看服务的详细信息 docker service inspect
# 查看服务列表 docker service ls --pretty helloworld
# 参数--pretty
表示以可读性良好的格式输出。如果想输出详细的 json 格式信息,去掉--pretty
参数即可。
# 查看哪个节点运行该服务 docker service ps helloworld
# 伸缩服务 docker service scale helloworld=5
# 删除服务 docker service rm helloworld
# 滚动更新 docker service create --replicas 3 --name redis --update-delay 10s redis:3.0.7-alpine c3hrsui7svtmzpxxars48tmtx
我们在部署服务指定滚动更新策略。--update-delay 表示更新服务对应的任务或一组任务之间的时间间隔。时间间隔用数字和时间单位表示,m 表示分,h 表示时,所以 10m30s 表示 10 分 30 秒的延时。
默认情况下,调度器一次更新一个任务。你可以使用 --update-parallelism 标志配置调度器每次同时更新的最大任务数量。
默认情况下,如果更新某个任务返回了RUNNING状态,调度器会转去更新另一个任务,直到所有任务都更新完成。如果在更新某个任务的任意时刻返回了FAILED,调度器暂停更新。我们可以在执行 docker service create 命令和 docker service update 命令时使用 --update-failure-action 标志来覆盖这种默认行为。
# 更新容器镜像 docker service update --image redis:3.2.5-alpine redis
# 调度器根据下面默认的策略来应用滚动更新:
- 停止第一个任务。
- 为停止的任务应用更新。
- 为更新的任务启动容器。
- 如果更新任务时返回
RUNNING
,等待一个指定的延时后停止下一个任务。 - 如果,在更新的任意时刻,某个任务返回
FAILED
,暂停更新。
# 下线节点 docker node update --availability drain worker02
# 重置节点状态 docker node update --availability active worker02
# 查看服务运行的节点 docker service ps -f desired-state=running redis
desired-state 表示只列出处于活动状态的任务。说明 worker02 虽然可用,但没被分配任务。
一个可用性为Active的节点在以下情况下可以接收到新任务:
当一个服务在伸缩规模时
滚动更新时
当你把其他某个节点的可用性设为 Drain 时
当某个任务在另外某个 Active 节点上启动失败时
docker stack deploy example --compose-file=docker-compose.yml
docker stack ls
docker stack services example
secret 创建的两种方式
echo "admin" | docker secret create my-pwd2 # STDIN
docker secret create my-pw password # 文件生成
secret 使用 --secret
docker service create --name db --secret my-pw -e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/my-pw mysql