Docker Swarm
1、基础环境说明
第一步:启动4个服务器(保证在一个网段内)
192.168.0.111
192.168.0.112
192.168.0.113
192.168.0.114
第二步:命名服务器(方便查看)
第三步:每一个服务器都安装Docker
2、DockerSwarm架构
官网:https://docs.docker.com/engine/swarm/how-swarm-mode-works/nodes/
3、搭建集群环境
shell
[root@node111 ~]# docker swarm --help
Usage: docker swarm COMMAND
Manage Swarm
Commands:
# 初始化节点
init Initialize a swarm
# 加入节点
join Join a swarm as a node and/or manager
初始化第一个节点
shell
# 暴露第一个节点
[root@node111 ~]# docker swarm init --advertise-addr 192.168.0.111
Swarm initialized: current node (h6cjybqx8m7fqc9vih7z1qcdy) is now a manager.
# 添加工作节点的命令
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-019i2ettz5yuv6j62eqpwk4ensnmc50fauda6ohd6p0bgkn27b-dzbzn9jzsz9q3zrf6zvdena70 192.168.0.111:2377
# 添加管理节点的命令 docker swarm join-token manager
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
[root@node111 ~]# docker swarm join-token manager
To add a manager to this swarm, run the following command:
docker swarm join --token SWMTKN-1-019i2ettz5yuv6j62eqpwk4ensnmc50fauda6ohd6p0bgkn27b-bprv9pj27xgt5hq1m1b4xhguu 192.168.0.111:2377
如果你当前电脑上的docker已经加入了一个swarm集群,先要离开节点
shell
docker swarm leave
docker swarm leave --force
将第二台机器加入节点,Work
shell
[root@node112 ~]# docker swarm join --token SWMTKN-1-019i2ettz5yuv6j62eqpwk4ensnmc50fauda6ohd6p0bgkn27b-dzbzn9jzsz9q3zrf6zvdena70 192.168.0.111:2377
This node joined a swarm as a worker.
第三台机器加入节点,管理节点
shell
[root@node113 ~]# docker swarm join --token SWMTKN-1-019i2ettz5yuv6j62eqpwk4ensnmc50fauda6ohd6p0bgkn27b-bprv9pj27xgt5hq1m1b4xhguu 192.168.0.111:2377
This node joined a swarm as a manager.
第四台同上
Shell
[root@node114 ~]# docker swarm join --token SWMTKN-1-019i2ettz5yuv6j62eqpwk4ensnmc50fauda6ohd6p0bgkn27b-bprv9pj27xgt5hq1m1b4xhguu 192.168.0.111:2377
This node joined a swarm as a manager.
查看集群是否搭建成功!
4、Raft协议
双主双从搭建完毕,但是现在我们只有两个管理节点,如果一个节点挂了,另外一个节点也不能用,Raft一致性算法,确保大多数节点存活才可以用,至少大于 1 台!生产环境最少3 manager;
1、先保证有两个管理节点,挂掉其中一台。node ls 命名不可用。
2、如果有work节点离开了,状态会更新为down,不可用了。
3、可以没有Work节点,全是管理节点。
4、leader挂了,就全部都挂掉了。
结论:
Raft保证:至少要保证有两个及两个以上的管理者节点,集群才可以使用,否则直接挂掉。
全部移除,重新初始化才可以再次使用了。
这就是 Raft协议,确保大多数节点存活才可以用!高可用!
5、使用Swarm
docker service
集群、不是单机了 ,告别Docker run
以后告别 docker run!之前docker compose up 使用compose启动一个服务。docker compose是单机下的玩具
现在是集群,要使用:**docker service (使用docker管理服务。)容器升级为服务。**其实和容器一一样,只是集群下变成了服务!
容器:单个容器运行,docker run 流量太大扛不住
服务:多个容器运行,负载均衡。
企业中真实使用的,docker service
demo: nginx
shell
# 单机下docker run # 集群下 docker service create
[root@node111 ~]# docker service create -p 8888:80 --name my-nginx nginx
# 通过docker service启动服务,在任何服务器都可以访问到该服务,不需要在启动容器的节点中访问。
shell
# 查看服务的详细信息
[root@node111 ~]# docker service inspect --pretty my-nginx
ID: v3dzdnv1hokey3174ytg7ydbs
Name: my-nginx
# 副本数量Replicated
Service Mode: Replicated
Replicas: 1
Placement:
UpdateConfig:
Parallelism: 1
On failure: pause
Monitoring Period: 5s
Max failure ratio: 0
Update order: stop-first
RollbackConfig:
Parallelism: 1
On failure: pause
Monitoring Period: 5s
Max failure ratio: 0
Rollback order: stop-first
ContainerSpec:
Image: nginx:latest@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Init: false
Resources:
Endpoint Mode: vip
Ports:
PublishedPort = 8888
Protocol = tcp
TargetPort = 80
PublishMode = ingress
[root@node111 ~]# docker service ps my-nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
v0ukz27ag5tg my-nginx.1 nginx:latest kuangshenlinux Running Running 3 minutes ago
一台服务器不够用了,动态扩容。
所有和服务相关的命令 docker service
shell
docker service create --replicas 3 my-nginx
[root@node111 ~]# docker service update --replicas 3 my-nginx
my-nginx
overall progress: 3 out of 3 tasks
1/3: running
2/3: running
3/3: running
verify: Service converged
回滚!
shell
# 回滚到之前的状态!(当前和上一个来回回滚)
docker service rollback my-nginx
# 灰度发布
# --image nginx:1.18.0-alpine 新的容器镜像
# --update-parallelism 1 同时更新的数量
# --update-delay 10s
[root@node111 ~]# docker service update --image nginx:1.18.0-alpine --update-parallelism 1 --update-delay 10s my-nginx
Tomcat
shell
# 给服务创建一个专属网络
docker network create -d overlay tomcat-net
# 启动服务
[root@node111 ~]# docker service create --name tomcat \
> --network tomcat-net \
> -p 8080:8080 \
> --replicas 3 \
> tomcat
yscxmfw6uchsivqrsald8tj11
overall progress: 3 out of 3 tasks
1/3: running
2/3: running
3/3: running
verify: Service converged
# 扩缩容
# docker service scale tomcat=5
# 服务删除
#[root@node111 ~]# docker service rm tomcat
tomcat
# 服务一旦移除,所有节点上的容器就自动停止
wordpress
1、创建网络
2、创建 mysql 服务
shell
[root@node111 ~]# docker service create --name mysql --env MYSQL_ROOT_PASSWROD=root --env MYSQL_DATABASE=wordpress --network demo --mount type=volume,source=mysql-data,destination=/var/lib/mysql mysql:5.7.24
# 如果做了数据共享,那么启动多份的话,是可以保证数据不同的。
3、创建 wordpress 服务
shell
[root@node111 ~]# docker service create --name wordpress -p 80:80 --env WORDPRESS_DB_USER=root --env WORDPRESS_DB_PASSWORD=root --env WORDPRESS_DB_HOST=mysql:3306 --env WORDPRESS_DB_NAME=wordpress --network demo wordpress
4、访问测试
说明:服务模式
服务模式一共有两种:Ingress和Host,如果不指定,则默认的是Ingress;
-
Ingress模式(overlay网络)下,到达Swarm任何节点的8080端口的流量,都会映射到任何服务副本的内部80端口,就算该节点上没有tomcat服务副本也会映射;
-
Host模式下,仅在运行有容器副本的机器上开放端口,使用Host模式的命令如下:
shelldocker service create --name tomcat \ --network host \ --publish published=8080,target=8080,mode=host \ --replicas 2 \ tomcat:7.0.96-jdk8-openjdk
docker service ps tomcat
6、Swarm的一些概念
shell
1.Swarm
集群的管理和编排是使用嵌入docker引擎的SwarmKit,可以在docker初始化时启动swarm模式或者加入已存在的swarm
init
join
shell
2.Node
一个节点是docker引擎集群的一个实例。您还可以将其视为Docker节点。您可以在单个物理计算机或云服务器上运行一个或多个节点,但生产群集部署通常包括分布在多个物理和云计算机上的Docker节点。
要将应用程序部署到swarm,请将服务定义提交给 管理器节点。管理器节点将称为任务的工作单元分派 给工作节点。
Manager节点还执行维护所需群集状态所需的编排和集群管理功能。Manager节点选择单个领导者来执行编排任务。
工作节点接收并执行从管理器节点分派的任务(Task)。默认情况下,管理器节点还将服务作为工作节点运行,但您可以将它们配置为仅运行管理器任务并且是仅管理器节点。代理程序在每个工作程序节点上运行,并报告分配给它的任务。工作节点向管理器节点通知其分配的任务的当前状态,以便管理器可以维持每个工作者的期望状态。
shell
3.Service
一个服务是任务的定义,管理机或工作节点上执行。它是群体系统的中心结构,是用户与群体交互的主要根源。创建服务时,你需要指定要使用的容器镜像。
说明:Docker service 不管镜像的构建的。必须要自己去构建镜像。通过dockerservice启动
shell
4.Task
docker run xxx
任务是在docekr容器中执行的命令,Manager节点根据指定数量的任务副本分配任务给worker节点
Swarm特点
1. Docker Engine集成集群管理
使用Docker Engine CLI 创建一个Docker Engine的Swarm模式,在集群中部署应用程序服务。链接数以万计的docker节点。
2. 去中心化设计
Swarm角色分为Manager和Worker节点,Manager节点故障不影响应用使用,raft协议原则。
3. 扩容缩容
可以声明每个服务运行的容器数量,通过添加或删除容器数自动调整期望的状态。
4. 期望状态协调
Swarm Manager节点不断监视集群状态,并调整当前状态与期望状态之间的差异。例如,设置一个服务运行10个副本容器,如果两个副本的服务器节点崩溃,Manager将创建两个新的副本替代崩溃的副本。并将新的副本分配到可用的worker节点。
- 一个节点上在运行3个容器,节点停止,运行,它会在其他节点上拉起这三个容器。
5. 多主机网络
可以为服务指定overlay网络。当初始化或更新应用程序时,Swarm manager会自动为overlay网络上的容器分配IP地址。
6. 服务发现
Swarm manager节点为集群中的每个服务分配唯一的DNS记录和负载均衡VIP。可以通过Swarm内置的DNS服务器查询集群中每个运行的容器。
7. 负载均衡
实现服务副本负载均衡,提供入口访问。也可以将服务入口暴露给外部负载均衡器再次负载均衡。
- 多个服务,随机访问其中的服务
- 读取容器的id信息,打印到日志
8. 安全传输
Swarm中的每个节点使用TLS相互验证和加密,确保安全的其他节点通信。
9. 滚动更新
升级时,逐步将应用服务更新到节点,如果出现问题,可以将任务回滚到先前版本。
7、工作模式
Node
Service
任务与调度
swarm manager:
-- 1、API:这个请求直接由Swarm manager的API进行接收,接收命令并创建服务对象。
-- 2、orchestrator:为服务创建一个任务。
-- 3、allocater:为这个任务分配IP地址。
-- 4、dispatcher:将任务分配到指定的节点。
-- 5、scheduler:在该节点中下发指定命令。
worker node:接收manager任务后去运行这个任务。
-- 1、container:创建相应的容器。
-- 2、worker:连接到调度程序以检查分配的任务
-- 3、executor:执行分配给工作节点的任务
服务副本与全局服务
在docker swarm中部署的service,有几种类型?
这个问题的答案,非常的简单,2种:
- replicated(副本)
- global(全局) ,启动一个服务,会在所有的节点,自动拉起,保证每个节点上都有该容器运行,日志、监控
下面的图表显示了一个有3个副本的service(黄色)和一个global的service(灰色):
调整service以什么方式运行
shell
--mode string
Service mode (replicated or global) (default "replicated")
docker service create --mode replicated --name mytom tomcat:7 默认的
# 副本类型的service,就是你需要部署几个副本,指定一下就可以有几个task在swarm集群中运行
docker service create --mode global --name test alpine ping baidu.com
# 全局类型的service,类似于k8s的daemonset对象,就是在每个节点上都运行一个task,不需要预先指定副本的数量,如果有新的节点加入到集群中,也会自动的在这个节点上运行一个新的task.
补充Label的说明
我们讨论了 Service 部署的两种模式:global mode 和 replicated mode。无论采用 global mode 还是 replicated mode,副本运行在哪些节点都是由 Swarm 决定的,作为用户我们有没有可能精细控制 Service 的运行位置呢?
答:能,使用 label
逻辑分两步:
1、为每个 node 定义 label。
2、设置 service 运行在指定 label 的 node 上。
```shell
docker node update --label-add env=test 节点1
docker node update --label-add env=prod swarm-worker2
# 指定在那个机器上来拉起这个服务。很少用
docker service create \
--constraint node.labels.env==test \
--replicas 3 \
--name my_web \
--publish 8080:80 \
httpd
#更新 service,将其迁移到生产环境:
docker service update --constraint-rm node.labels.env==test my_web
docker service update --constraint-add node.labels.env==prod my_web
8、网络概念说明
在 Swarm Service 中有三个重要的网络概念:
- Overlay networks 管理 Swarm 中 Docker 守护进程间的通信。你可以将服务附加到一个或多个已存在的
overlay
网络上,使得服务与服务之间能够通信。 - ingress network 是一个特殊的
overlay
网络,用于服务节点间的负载均衡:启动多个服务,访问的时候随机分配到一个服务上 。当任何 Swarm 节点在发布的端口上接收到请求时,它将该请求交给一个名为IPVS
的模块。IPVS
跟踪参与该服务的所有IP地址,选择其中的一个,并通过ingress
网络将请求路由到它。
初始化或加入 Swarm 集群时会自动创建ingress
网络,大多数情况下,用户不需要自定义配置,但是 docker 17.05 和更高版本允许你自定义。 - docker_gwbridge 是一种桥接网络,将
overlay
网络(包括ingress
网络)连接到一个单独的 Docker 守护进程的物理网络。默认情况下,服务正在运行的每个容器都连接到本地 Docker 守护进程主机的docker_gwbridge
网络。
docker_gwbridge
网络在初始化或加入 Swarm 时自动创建。大多数情况下,用户不需要自定义配置,但是 Docker 允许自定义。
名称 | 类型 | 注释 |
---|---|---|
docker_gwbridge | bridge | none |
ingress | overlay | none |
custom-network | overlay | none |
- docker_gwbridge和ingress是swarm自动创建的,当用户执行了docker swarm init/connect之后。
- docker_gwbridge是bridge类型的负责本机container和主机直接的连接。
- ingress负责service在多个主机container之间的路由。
- custom-network是用户自己创建的overlay网络,通常我们都需要创建自己的network并把service挂在上面。
ingress网络。vip(虚拟ip模式)
https://docs.docker.com/engine/swarm/ingress/
到这里 Docker 多机通信逻辑及实战就结束了,但 Docker Swarm 只是匆匆过客,最终还是要回到 Kubernetes 上。