Docker Swarm 集群编排
什么是Swarm
Swarm是Docker公司自研发的容器集群管理系统,Swarm在早期是作为一个独立服务存在,在Docker Engine v1.12中集成了Swarm的集群管理,和编排功能。可以通过初始化Swarm或加入现有Swarm来启用Docker引擎的Swarm模式。
Docker Engine CLI和API包括了管理Swarm节点命令,比如添加、删除节点,以及在Swarm中部署和编排服务,也增加了服务栈(Stack)、服务(Service)、任务(Task)概念
Swarm能干什么
Swarm是Docker 引擎内置(原生)的集群管理和编排工具。Docker Swarm是 Docker 官方三剑客项目之一,swarm是基于docker平台实现的集群技术,他可以通过几条简单的指令快速的创建一个docker集群,接着在集群的共享网络上部署应用,最终实现分布式的服务。
swarm节点
swarm是一系列节点的集合,而节点可以是一台裸机或者一台虚拟机。一个节点能扮演一个或者两个角色,manager或者worker。
manager节点
Docker Swarm集群需要至少一个manager节点,节点之间使用**
Raft consensus protocol
**进行协同工作。
通常,第一个启用docker swarm的节点将成为leader,后来加入的都是follower。当前的leader如果挂掉,剩余的节点将重新选举出一个新的leader。
每一个manager都有一个完整的当前集群状态的副本,可以保证manager的高可用。
worker节点
worker节点是运行实际应用服务的容器所在的地方。理论上,一个manager节点也能同时成为worker节点,但在生产环境中,我们不建议这样做。
worker节点之间,通过control plane
进行通信,这种通信使用gossip
协议,并且是异步的。
运行机制
名词解释
集群中经常谈到的stacks, services, tasks,他们之间的关系。
下面简单解释一下这三者的含义:
services
swarm service是一个抽象的概念,它只是一个对运行在swarm集群上的应用服务,所期望状态的描述。它就像一个描述了下面物品的清单列表一样:
- 服务名称
- 使用哪个镜像来创建容器
- 要运行多少个副本
- 服务的容器要连接到哪个网络上
- 应该映射哪些端口
task
在Docker Swarm中,task是一个部署的最小单元,task与容器是一对一的关系。
stack
stack是描述一系列相关services的集合。我们通过在一个YAML文件中来定义一个stack。
如何工作的
要在集群中部署镜像,创建一个服务。在一些更大的应用上下文中,服务通常称之为微服务。服务可能是一个HTTP服务器、数据库、或者分布式环境中运行的任何其他可执行的程序。
在创建服务时,可以指定要使用的容器镜像以及容器中要运行的命令。服务还可以定义下面选项:
- 集群要对外服务的端口
- 在集群中用于服务之间相连的overlay网络
- 滚动更新策略
- 集群总运行的副本数量
服务、任务和容器
当将服务部署到集群时,管理者将服务定义视为服务所需状态。然后将服务调度为一个或多个副本任务。这些任务在集群的节点上彼此独立运行。
例如下图有三个副本的HTTP服务,每个服务实例就是一个任务。
容器是一个独立的进程。在swarm模型中,每个任务调用一个容器。任务类似于插槽,调度器将容器放入其中。一旦容器运行,调度器认为该任务处于运行状态。如果容器出现健康监测失败或者终止,那么任务也终止。
任务和调度
任务是集群内调度的原子单位。当创建或者更新服务声明所需的服务状态时,协调者通过调度任务来实现这些所需的状态。
任务是一个单向机制,通过这些状态单独进行:分配、准备、运行等等。如果任务失败,协调者将删除任务以及容器,然后根据服务指定的所需状态创建一个新的任务来代替它。
Docker swarm模式的基础逻辑是通用调度器和编排器。
下图显示集群如何接受服务创建请求并将任务调度到工作节点上。
待处理的服务
一个服务可以这样配置,使得当前集群中的节点不能运行其任务。在这种情况下,服务仍处于待处理状态。
以下是服务可能保留在待处理状态的示例:
如果所有节点被暂停或Drain,并且你创建一个服务,将被挂起,知道节点可用。实际上,第一个可用的节点将会获得所有的任务,这在生产环境中不是件好事。
可以为服务预留特定数量的内存。如果集群中没有节点满足所需的内存量,则服务将处于待处理状态,知道可用的节点运行其任务。如果指定了非常大的值,则任务将永久挂起,除非确实有一个满足该条件的节点。
可以对服务施加放置约束,并且可能无法在给定时间履行约束。
此行为说明您的任务的要求和配置与当前的群组状态并不紧密。作为集群管理员,你可以声明集群所需状态,并且管理者可以使用集群中的节点来创建该状态。在集群中你不需要微管理任务。
如果你唯一的目的是阻止部署服务,请将服务扩展为0,而不是尝试将其配置成保持待处理状态。
副本和全局服务
有两种类型的服务部署:副本和全局。
对于副本服务,指定要运行的相同任务的数量,每个副本都是相同的内容。
全局服务是在每个节点上运行一个任务的服务。不需要预先指定任务数量。每当将一个节点添加到集群中,协调者将创建一个任务,并且调度器将任务分配给该新加入的节点。全局服务最好是监控代理、反病毒扫描程序等等想要在集群中每个节点上运行的容器。
下图显示三个副本服务(黄色)和全局服务(灰色):
在swarm模式下运行Docker Engine
当首次安装并使用Docker Engine时,默认情况下swarm模式是禁用的。当启用swarm模式时,可以使用docker service 服务管理命令。
有两种方式在swarm模式下运行引擎:
创建一个新的集群
加入现有集群
在生成环境中,集群模式提供具有集群管理功能的容错平台,以保证服务的可靠运行。
功能特点
集成的集群管理
使用Docker Engine CLI创建一组Docker引擎,您可以在其中部署应用程序服务。您不需要其他编排软件来创建或管理群集。
节点分散式设计
Docker Engine不是在部署时处理节点角色之间的差异,而是在运行时处理角色变化。您可以使用Docker Engine部署两种类型的节点,管理节点和工作节点。这意味着您可以从单个服务器构建整个群集。
声明性服务模型
Docker Engine使用声明性方法来定义应用程序堆栈中各种服务的所需状态。例如,您可以描述由具有消息队列服务和数据库后端的Web前端服务组成的应用程序。
可扩容与缩放容器
对于每个服务,您可以声明要运行的任务数。当您向上或向下缩放时,swarm管理器通过添加或删除任务来自动适应,以保持所需的任务数量来保证集群的可靠状态。
容器容错状态协调
群集管理器节点不断监视群集状态,并协调您表示的期望状态的实际状态之间的任何差异。
例如,如果设置一个服务以运行容器的10个副本,并且托管其中两个副本的工作程序计算机崩溃,则管理器将创建两个新副本以替换崩溃的副本。 swarm管理器将新副本分配给正在运行和可用的worker节点上。
多主机网络
您可以为服务指定覆盖网络。当swarm管理器初始化或更新应用程序时,它会自动为覆盖网络上的容器分配地址。
服务发现
Swarm管理器节点为swarm中的每个服务分配唯一的DNS名称,并负载平衡运行的容器。您可以通过嵌入在swarm中的DNS服务器查询在群中运行的每个容器。
负载平衡
您可以将服务的端口公开给外部负载平衡器。在内部,swarm允许您指定如何在节点之间分发服务容器。
缺省安全
群中的每个节点强制执行TLS相互验证和加密,以保护其自身与所有其他节点之间的通信。您可以选择使用自签名根证书或来自自定义根CA的证书。
滚动更新
在已经运行期间,您可以增量地应用服务更新到节点。 swarm管理器允许您控制将服务部署到不同节点集之间的延迟。如果出现任何问题,您可以将任务回滚到服务的先前版本。
准备环境
服务器准备
我的三台测试机
IP地址 | 角色 | 主机名 |
---|---|---|
192.168.64.153 | manager | node1 |
192.168.64.154 | worker | node2 |
192.168.64.155 | worker | node3 |
服务器端口开放
在创建集群前,如果开启了防火墙,请确认三台主机的防火墙能让swarm需求的端口开放,需要打开主机之间的端口,以下端口必须可用。在某些系统上,这些端口默认为打开。
- 2377:TCP端口2377用于集群管理通信
- 7946:TCP和UDP端口7946用于节点之间的通信
- 4789:TCP和UDP端口4789用于覆盖网络流量
可以直接禁用系统防火墙来让这些端口通信不受限制,一般测试环境我们都会禁用防火墙
1 | systemctl stop firewalld(立即生效) |
添加节点标签
因为我们用到了节点约束,所有启动服务之前需要添加节点标签
1 | 添加标签 |
搭建Swarm集群
下面我们就来搭建一个
swarm
集群
初始化集群
1 | docker swarm init --advertise-addr 192.168.64.153(本机地址) |
生成口令
生成管理节点口令
1 | docker swarm join-token manager |
生成执行节点口令
1 | docker swarm join-token worker |
其他节点加入集群
在第一个从节点执行加入 work的指令
1 | docker swarm join --token SWMTKN-1-53p5t2rt9ud5j0owkl14boj2z8im6r60ddlzotgc4a8y93u1c2-8f6crxgyc9umayhxva1jv9t1w 192.168.64.153:2377 |
第二个节点执行加入work的命令
1 | docker swarm join --token SWMTKN-1-53p5t2rt9ud5j0owkl14boj2z8im6r60ddlzotgc4a8y93u1c2-8f6crxgyc9umayhxva1jv9t1w 192.168.64.153:2377 |
查看swarm的节点
执行
docker node ls
查看swarm节点信息
1 | docker node ls |
AVAILABILITY状态说明
Active 意味着调度程序可以将任务分配给节点。
Pause 意味着调度程序不会将新任务分配给节点,但现有任务仍在运行。
Drain 意味着调度程序不会向节点分配新任务。调度程序关闭所有现有任务并在可用节点上调度它们。
MANAGER STATUS状态说明
显示节点是属于manager或者worker
没有值 :表示不参与群管理的工作节点。
Leader :意味着该节点是使得群的所有群管理和编排决策的主要管理器节点。
Reachable: 意味着节点是管理者节点正在参与Raft共识。如果领导节点不可用,则该节点有资格被选为新领导者。
Unavailable :意味着节点是不能与其他管理器通信的管理器。如果管理器节点不可用,您应该将新的管理器节点加入群集,或者将工作器节点升级为管理器。
修改主机名
默认
centos
的主机名是localhost
,我们看上面,节点的主机名都是localhost
,我们修改以下
查看主机名
hostnamectl status
可以查看主机名
1 | hostnamectl status |
修改主机名
修改主机名使用
hostnamectl set-hostname NAME
命令可以进行修改,我们使用 node1,node2…方式命名我们的节点
1 | 修改主机名 |
其他节点依次操作就可以
再次查看节点
再次查看swarm节点信息
1 | docker node ls |
管理节点
升降级节点
无论您升级或降级节点,您应该始终在群中维护奇数个管理器节点,
升降级节点角色只能在管理节点上运行,应先升级工作节点为被选举者,再降级领导者为工作节点,然后被选举者成为领导者完成替换;
您可以将工作程序节点提升为manager角色。这在管理器节点不可用或者您希望使管理器脱机以进行维护时很有用。 类似地,您可以将管理器节点降级为worker角色。
升级节点
要降级一个节点或一组节点,请从管理器节点运行
docker node promote 节点名称
1 | docker node promote pbui0rdry85e25i3bvhzmqw8h |
升级节点后不会马上生效,会进入
Reachable
状态,如果leader节点关掉,当前节点会参与主节点竞争
降级节点
要升级一个节点或一组节点,请从管理器节点运行
docker node demote 节点名称
1 | docker node demote r7cv7prw1h2to9h1cpwxs9jhl |
swam将节点降级后,再次查看节点命令不生效,需要到管理节点查看
节点退出swarm集群
docker swarm leave 命令可在所有节点上运行,值得注意的是,工作节点退出swarm集群后,在管理节点上依然保存着工作节点的节点信息,状态为down,要删除节点信息,可使用docker node rm 命令,当所有的节点都退出并且被删除时,在管理节点上使用docker swarm leave,然后退出整个集群;
工作节点
在工作节点执行以下命令可以退出
swarm
节点
1 | docker swarm leave |
管理节点
在管理节点查看节信息
1 | docker node ls |
根据退出节点前后查看节点信息,可以发现退出的节点是down的状态,并没有删除节点
删除节点信息
在管理节点执行删除命令
docker node rm 节点ID
1 | docker node rm r7cv7prw1h2to9h1cpwxs9jhl |
管理集群服务
管理集群服必须在manager角色的主机上
创建overlay网络
我们需要载多个服务器中运行Docker容器集群,需要使用overlay网络,overlay网络用于连接不同机器上的docker容器,允许不同机器上的容器相互通信,同时支持对消息进行加密
1 | docker network create --driver overlay learn-docker-overlay-network |
创建服务
使用
docker service create
命令来创建服务
创建MySQL服务
1 | docker service create \ |
–replicas 1 表示在集群中创建1个服务
node.labels.role == data
表示节点需要创建在标签是data
的节点上
可以查看swarm的进程
1 | docker service ls |
创建nacos服务
nacos也是需要创建一个,但是节点是可以漂移的,不需要固定在某一台机器
1 | docker service create \ |
可以查看swarm的进程
1 | docker service ls |
我们发现nacos运行在了 node3节点上
创建learn-docker-storage服务
我们创建learn-docker-storage服务,我们将该服务部署两个节点
1 | docker service create \ |
可以查看swarm的进程
1 | docker service ls |
我们发现我们的存储服务运行在两个节点上
创建learn-docker-web服务
我们创建learn-docker-web服务,我们将该服务同样部署两个节点
1 | docker service create \ |
可以查看swarm的进程
1 | docker service ls |
创建learn-docker-gateway服务
我们创建learn-docker-gateway服务,因为是网关服务,我们只创建一个节点,因为需要对外暴漏端口,需要开放8888端口
1 | docker service create \ |
可以查看swarm的进程
1 | docker service ls |
测试访问微服务
因为在
node2
节点上,node2
节点IP是192.168.64.154
我们可以请求URL访问
1 | curl http://192.168.64.154:8888/employeapi/find/10001| python -m json.tool |
查看某个服务日志
通过
docker service logs 服务命
可以看到当前服务的日志,但是这个服务有两个容器在运行,所有能同时看到两个容器的日志
1 | docker service learn-docker-storage |
扩缩容服务
可以通过集群操作对集群进行扩缩容
扩容操作
我们将
learn-docker-storage
由两个容器变为三个容器
1 | docker service scale learn-docker-storage=3 |
这样我们就把存储服务变成了三台服务
扩容操作
同样,使用该命令对
learn-docker-storage
进行缩容
1 | docker service scale learn-docker-storage=2 |
删除服务
我们可以尝试把
learn-docker-gateway
删除掉,删除操作将会把整个服务的所有容器删除
1 | docker service rm learn-docker-gateway |
Docker Stack管理服务
我们上面使用
swarm
部署服务,单个服务还好,如果很多个服务怎么来解决呢,这里就用到了Docker Stack
管理服务。
在上面我们学会了如何配置一个swarm集群,并且知道如何在swarm集群上部署应用,现在,我们开始了解Docker层级关系中的最高一个层级——stack。一个stack就是一组有关联的服务的组合,可以编排在一起,一起管理。
单机模式下,我们可以使用 Docker-Compose来编排多个服务,而 Docker Swarm 只能实现对单个服务的简单部署。于是就引出了本文的主角 Docker Stack ,通过 Docker Stack 我们只需对已有的 docker-compose.yml 配置文件稍加改造就可以完成 Docker 集群环境下的多服务编排。
集群搭建案例
应用部署情况
服务名称 | 数量 |
---|---|
mysql | 1 |
nacos | 1 |
learn-docker-gateway | 1 |
learn-docker-web | 2 |
learn-docker-storage | 2 |
创建docker-compose.yml
首先创建一个 docker-compose.yml 文件,使用 Docker Compose v3 语法
我们把我们原来单机版的
docker-compose.yml
改造以下
1 | version: '3.9' |
配置介绍
Stack文件就是Docker Compose文件。唯一的要求就是version:一项需要是3.0或者更高的值。在Docker根据某个Stack文件部署应用的时候,首先会检查并创建networks:关键字对应网络。如果网络不存在,Docker会进行创建。下面我们详细看下这几个模块。
overlay网络
这里定义了1个网络,默认情况下网络都是使用overlay驱动,新建对应的覆盖类型的网络。
1 | networks: |
部署节点副本数
接下来我们进一步了解deploy关键字新增的内容
1 | deploy: |
- replicas: 2 设置了期望服务的副本数量为2,默认为1.如果服务正在运行,需要调整副本数。可以调整stack文件中的 replicas 的数值,然后重新部署stack。重新部署stack并不会影响那些没有改动的服务。
- restart_policy: 定义了Swarm针对容器异常退出的重启策略。当前服务的重启策略是:如果某个副本以非0返回值退出,会立即重启当前副本。重启最多尝试3次,每次都是等待之多120s来检测是否成功。每次重启的间隔是5s。
节点约束
因为我们的数据库节点只能部署在数据节点,因为需要挂载本地的数据文件以及数据库文件,所有需要使用标签进行节点约束
1 | mysql: |
这里的
'node.labels.role == data
含义就是将当前mysql节点约束在标签名字是role,并且值是data的数据节点,更多操作请参考下文
部署服务
部署应用
使用docker stack deploy 命令部署
1 | docker stack deploy -c docker-compose.yml learn-docker-test |
这里我们指定了docker-compose文件,并把stack命名为 learn-docker-test。
查看部署情况
可以通过
docker stack ls
命令查看集群部署情况,会列出 Swarm 集群中的全部 Stack,包括每个 Stack 拥有多少服务
服务部署情况
查看nacos节点信息
访问nacos服务,发现我们的服务都已经注册
测试访问服务
访问服务接口测试
1 | curl http://192.168.64.153:8888/employeapi/find/10001| python -m json.tool |
集群管理
更新服务
docker service upadte
可以对swarm服务进行升级
参数详解
–force 强制更新重启服务,无论是否配置或镜像改变都更新
–image <image:tag> 制定更新的镜像
–with-registry-auth 向 Swarm 代理发送 Registry 认证详细信息,私有仓库需要携带该参数
更新镜像
1 | 查看服务详情 |
删除应用
查看部署集群
docker stack ls
可以查看部署的服务列表
执行删除
docker stack rm stack名称
命令会删除整个stack集群,注意移除操作执行前并不会进行二次确认。
1 | docker stack rm learn-docker-test |
相关命令
docker stack 常用命令
命令 | 说明 |
---|---|
docker stack deploy | 部署新的堆栈或更新现有堆栈 |
docker stack ls | 列出现有堆栈 |
docker stack ps | 列出堆栈中的任务 |
docker stack rm | 删除堆栈 |
docker stack services | 列出堆栈中的服务 |
docker stack down | 移除某个堆栈(不会删除数据) |
docker service 常用命令
命令 | 说明 |
---|---|
docker service create | 部署服务 |
docker service inspect | 查看服务详情 |
docker service logs | 产看某个服务日志 |
docker service ls | 查看所有服务详情 |
docker service rm | 删除某个服务(-f 强制删除) |
docker service scale | 设置某个服务个数 |
docker service update | 更新某个服务 |
docker node 常用命令
命令 | 说明 |
---|---|
docker node ls | 查看所有集群节点 |
docker node rm | 删除某个节点(-f 强制删除) |
docker node inspect | 查看节点详情 |
docker node demote | 节点降级,由管理节点降级为工作节点 |
docker node promote | 节点升级,由工作节点升级为管理节点 |
docker node update | 更新节点 |
docker node ps | 查看节点中的 Task 任务 |
docker swarm 常用命令
命令 | 说明 |
---|---|
docker swarm init | 初始化集群 |
docker swarm join-token worker | 查看工作节点的 token |
docker swarm join-token manager | 查看管理节点的 token |
docker swarm join | 加入集群中 |
portainer集群管理
Portainer介绍
Portainer是一个可视化的容器镜像的图形管理工具,利用Portainer可以轻松构建,管理和维护Docker环境。 而且完全免费,基于容器化的安装方式,方便高效部署。
Portainer 的目的是部署和使用一样简单。它由一个可以在任何 Docker 引擎上运行的单一容器组成(可以部署为Linux容器或Windows本地容器,也支持其他平台)。Portainer允许你管理所有的Docker资源(容器、镜像、卷、网络等等)。它与独立的Docker引擎和Docker Swarm模式兼容。
swarm集群安装Portainer
使用swarm集群安装Portainer,用Portainer来管理swarm集群
1 | 下载部署配置文件 |
注意:此方法将自动部署Portainer服务器的单个实例,并将Portainer代理作为全局服务部署到集群中的每个节点上。
portainer使用
注册用户
默认访问接口是9000端口,可以通过浏览器进行访问,首次登陆需要注册用户,给admin用户设置密码
查看管理服务
点击home节点,当前这个节点就是我们的swarm集群
点进去就可以看到我们能操作的菜单了
查看swarm节点
点击swarm菜单就可以看到swarm节点了
管理微服务
服务部署情况
我们要将我们的服务交给portainer管理
服务名称 | 数量 |
---|---|
mysql | 1 |
nacos | 1 |
learn-docker-gateway | 1 |
learn-docker-web | 2 |
learn-docker-storage | 2 |
准备工作
管理节点标签
我们MySQL需要部署在数据节点,我们添加节点标签
在swarm管理节点,点击节点信息进入下面详情页面进行配置标签
添加网络信息
因为我们的节点需要一个共有的
overlay
网络,我们需要配置下,在network节点点击添加
在添加页面选择
overlay
网络类型,名字叫做learn-docker-network
然后点击创建就可以
创建仓库配置
因为我们的微服务需要从我们自己的harbor镜像仓库拉取,需要将我们的仓库配置
在仓库节点填写我们的镜像地址就可以
https://manager-hongbaoyu-java.itheima.net:8443
创建stack任务
在stack界面点击stack菜单进行添加stck任务
在stack管理界面将我们的
docker-compose.yml
复制进我们的stack界面
点击创建节点信息就可以,等待部署就可以
稍等下节点就部署完成了
点击进去就可以单到节点详情了
查看节点部署情况
进入swarm管理界面
点击
Go to cluster visualizer
查看服务部署情况