docker swarm介绍
Docker Swarm是Docker官方提供的一款集群管理工具,其主要作用是把若干台Docker主机抽象为一个整体,并且通过一个入口统一管理这些Docker主机上的各种Docker资源。Swarm和Kubernetes比较类似,但是更加轻,具有的功能也较kubernetes更少一些。
- 是docker host集群管理工具
- docker官方提供的
- docker 1.12版本以后
- 用来统一集群管理的,把整个集群资源做统一调度
- 比kubernetes要轻量化
- 实现scaling 规模扩大或缩小
- 实现rolling update 滚动更新或版本回退
- 实现service discovery 服务发现
- 实现load balance 负载均衡
- 实现route mesh 路由网格,服务治理
docker swarm概念与架构
架构

2.1 概念
节点 (node): 就是一台docker host上面运行了docker engine.节点分为两类:
- 管理节点(manager node) 负责管理集群中的节点并向工作节点分配任务
- 工作节点(worker node) 接收管理节点分配的任务,运行任务
服务(services): 在工作节点运行的,由多个任务共同组成docker node ls
任务(task): 运行在工作节点上容器或容器中包含应用,是集群中调度最小管理单元docker service ls
docker swarm集群部署
docker swarm 部署3主2从节点集群容器镜像仓库 Harbor准备
见harbor 服务器安装主机准备
| ip | 主机名 | 说明 | | —- | —- | —- | | 10.0.0.30 | sm1 | 管理节点1 | | 10.0.0.31 | sm2 | 管理节点2 | | 10.0.0.32 | sm2 | 管理节点3 | | 10.0.0.33 | sw1 | 工作节点 | | 10.0.0.34 | sw2 | 工作节点 |
配置ip地址解析
编辑主机/etc/hosts文件,添加主机名解析# vim /etc/hosts# cat /etc/hosts127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4::1 localhost localhost.localdomain localhost6 localhost6.localdomain610.0.0.30 sm110.0.0.31 sm210.0.0.32 sm310.0.0.33 sw110.0.0.34 sw2
主机时间同步
添加计划任务,实现时间同步,同步服务器为time1.aliyun.com# crontab -eno crontab for root - using an empty onecrontab: installing new crontab查看添加后计划任务# crontab -l0 */1 * * * ntpdate time1.aliyun.com
机安全设置
#关闭防火墙并查看其运行状态systemctl stop firewalld;systemctl disable firewalldfirewall-cmd --state#使用非交互式修改selinux配置文件sed -ri 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config#重启所有的主机系统reboot#重启后验证selinux是否关闭sestatus
docker安装
wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repoyum -y install docker-cesystemctl enable docker;systemctl start docker
配置docker daemon使用harbor
# vim /etc/docker/daemon.json# cat /etc/docker/daemon.json{"insecure-registries": ["http://harbor.iclpy.top"]}
#登录harbordocker login harbor.iclpy.topUsername: adminPassword:WARNING! Your password will be stored unencrypted in /root/.docker/config.json.Configure a credential helper to remove this warning. Seehttps://docs.docker.com/engine/reference/commandline/login/#credentials-storeLogin Succeeded
docker swarm集群初始化
获取docker swarm命令使用帮助#docker swarm --help##> 本次在sm1上初始化docker swarm init --advertise-addr 10.0.0.30 --listen-addr 10.0.0.30:2377Swarm initialized: current node (zj8lmzpy1o6c611bugablmt9w) is now a manager.To add a worker to this swarm, run the following command:docker swarm join --token SWMTKN-1-3vs2fij4jwfbhd0ntlqxy9fslr3m931wyhsb8ku2p6i5mptnyq-87hvt1z70sfgkjwgbsn138lix 10.0.0.30:2377To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.[root@sm1 ~]### --advertise-addr 当主机有多块网卡时使用其选择其中一块用于广播,用于其它节点连接管理节点使用## --listen-addr 监听地址,用于承载集群流量使用
添加工作节点到集群
sw1 sw2 上添加 工作几点
## 根据初始化的提示 在工作节点上执行如下命令docker swarm join --token SWMTKN-1-3vs2fij4jwfbhd0ntlqxy9fslr3m931wyhsb8ku2p6i5mptnyq-87hvt1z70sfgkjwgbsn138lix 10.0.0.30:2377## 查看节点信息docker node lsID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSIONzj8lmzpy1o6c611bugablmt9w * sm1 Ready Active Leader 20.10.17b876i5euumgphxlu025htvwzp sw1 Ready Active 20.10.17slxyyilk41wfzgr52qptsf3eb sw2 Ready Active 20.10.17
如果使用的token已过期,可以再次生成新的加入集群的方法,如下命令所示。
docker swarm join-token worker
添加管理节点到集群
##生成用于添加管理节点加入集群所使用的token sm1 上执行docker swarm join-token managerTo add a manager to this swarm, run the following command:docker swarm join --token SWMTKN-1-3vs2fij4jwfbhd0ntlqxy9fslr3m931wyhsb8ku2p6i5mptnyq-63qpc6ux4w28mdfbg374sa2ah 10.0.0.30:2377##加入集群 sm2 sm3 执行[root@sm2 ~]# docker swarm join --token SWMTKN-1-3vs2fij4jwfbhd0ntlqxy9fslr3m931wyhsb8ku2p6i5mptnyq-63qpc6ux4w28mdfbg374sa2ah 10.0.0.30:2377This node joined a swarm as a manager.[root@sm3 ~]# docker swarm join --token SWMTKN-1-3vs2fij4jwfbhd0ntlqxy9fslr3m931wyhsb8ku2p6i5mptnyq-63qpc6ux4w28mdfbg374sa2ah 10.0.0.30:2377This node joined a swarm as a manager.#查看节点状态docker node lsID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSIONzj8lmzpy1o6c611bugablmt9w * sm1 Ready Active Leader 20.10.17sh3pf17yiz89uhzsnj8slie72 sm2 Ready Active Reachable 20.10.17ugt01f9h3697i6fck0ochvexm sm3 Ready Active Reachable 20.10.17b876i5euumgphxlu025htvwzp sw1 Ready Active 20.10.17slxyyilk41wfzgr52qptsf3eb sw2 Ready Active 20.10.17
docker swarm集群应用
容器镜像准备
准备多个版本的容器镜像,以便于后期使用测试
# harbor 服务器上创建mkdir /opt/nginxcd /opt/nginxecho "v1 nginx success" >index.html#编写Dockerfile文件,用于构建容器镜像vim DockerFileFROM nginx:latestMAINTAINER 'icl<776172520@qq.com>'ADD index.html /usr/share/nginx/htmlRUN echo "daemon off;" >> /etc/nginx/nginx.confEXPOSE 80CMD /usr/sbin/nginx## 创建镜像docker build -t harbor.iclpy.top/library/nginx:v1 .## 推送镜像到 harbor中docker push harbor.iclpy.top/library/nginx:v1
# harbor 服务器上创建mkdir /opt/nginxcd /opt/nginxecho "v2 nginx success" >index.html#编写Dockerfile文件,用于构建容器镜像vim DockerFileFROM nginx:latestMAINTAINER 'icl<776172520@qq.com>'ADD index.html /usr/share/nginx/htmlRUN echo "daemon off;" >> /etc/nginx/nginx.confEXPOSE 80CMD /usr/sbin/nginx## 创建镜像docker build -t harbor.iclpy.top/library/nginx:v2 .## 推送镜像到 harbor中docker push harbor.iclpy.top/library/nginx:v2
发布服务
在docker swarm中,对外暴露的是服务(service),而不是容器。
为了保持高可用架构,它准许同时启动多个容器共同支撑一个服务,如果一个容器挂了,它会自动使用另一个容器
## 查看 服务docker service ls## 发布服务docker service create --name nginx-svc-1 --replicas 1 --publish 80:80 harbor.iclpy.top/library/nginx:v1##* 创建一个服务,名为nginx_svc-1* replicas 1指定1个副本* --publish 80:80 将服务内部的80端口发布到外部网络的80端口* 使用的镜像为`harbor.iclpy.top/library/nginx:v1`#查看已发布服务docker service ls## 查看已发布服务容器docker service ps nginx-svc-1docker ps# 访问已经发布的服务curl http://10.0.0.30##使用scale指定副本数来扩展docker service scale nginx-svc-1=2## 查看服务docker service ls[root@sm1 opt]# docker service lsID NAME MODE REPLICAS IMAGE PORTSmkrjanpb476p nginx-svc-1 replicated 2/2 harbor.iclpy.top/library/nginx:v1 *:80->80/tcp[root@sm1 opt]###服务裁减docker service scale nginx-svc-1=1[root@sm1 opt]# docker service lsID NAME MODE REPLICAS IMAGE PORTSmkrjanpb476p nginx-svc-1 replicated 1/1 harbor.iclpy.top/library/nginx:v1 *:80->80/tcp#删除服务docker service rm nginx-svc-1## 服务版本更新docker service update nginx-svc --image harbor.iclpy.top/library/nginx:v2##服务版本回退docker service update nginx-svc --image harbor.iclpy.top/library/nginx:v1#服务版本滚动间隔更新docker service create --name nginx-svc --replicas 60 --publish 80:80 harbor.iclpy.top/library/nginx:v1docker service update --replicas 60 --image harbor.iclpy.top/library/nginx:v2 --update-parallelism 5 --update-delay 30s nginx-svc说明* --update-parallelism 5 指定并行更新数量* --update-delay 30s 指定更新间隔时间##在指定网络中发布服务docker network create -d overlay tomcat-net# docker service create --name tomcat \--network tomcat-net \-p 8080:8080 \--replicas 2 \tomcat:7.0.96-jdk8-openjdk说明:创建名为tomcat的服务,使用了刚才创建的覆盖网络curl 127.0.0.1:8080
服务网络模式
服务模式一共有两种:Ingress和Host,如果不指定,则默认的是Ingress;
Ingress模式下,到达Swarm任何节点的8080端口的流量,都会映射到任何服务副本的内部80端口,就算该节点上没有tomcat服务副本也会映射;
docker service create --name tomcat \--network tomcat-net \-p 8080:8080 \--replicas 2 \tomcat:7.0.96-jdk8-openjdk
Host模式下,仅在运行有容器副本的机器上开放端口,使用Host模式的命令如下:
docker service create --name tomcat \--network tomcat-net \--publish published=8080,target=8080,mode=host \--replicas 3 \tomcat:7.0.96-jdk8-openjdkz5cmxxuph2jcsu4y3vcgiyr3qoverall progress: 3 out of 3 tasks1/3: running [==================================================>]2/3: running [==================================================>]3/3: running [==================================================>]verify: Service converged
服务数据持久化存储
本地存储
在集群所有主机上创建本地目录
```shell mkdir -p /data/nginxdata docker service create —name nginx-svc —replicas 3 —mount “type=bind,source=/data/nginxdata,target=/usr/share/nginx/html” —publish 80:80 harbor.iclpy.top/library/nginx:v1 xn3leldzle9kv98rceyk74q1s overall progress: 3 out of 3 tasks 1/3: running [==================================================>] 2/3: running [==================================================>] 3/3: running [==================================================>] verify: Service converged
docker service ls [root@sm1 ~]# docker service ls ID NAME MODE REPLICAS IMAGE PORTS xn3leldzle9k nginx-svc replicated 3/3 harbor.iclpy.top/library/nginx:v1 *:80->80/tcp z5cmxxuph2jc tomcat replicated 3/3 tomcat:7.0.96-jdk8-openjdk
docker service ps nginx-svc [root@sm1 ~]# docker service ps nginx-svc ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS t70a7gre2trt nginx-svc.1 harbor.iclpy.top/library/nginx:v1 sw2 Running Running 55 seconds ago
4by6dhzyndbh nginx-svc.2 harbor.iclpy.top/library/nginx:v1 sm3 Running Running 55 seconds ago
cy25q40ot7qg nginx-svc.3 harbor.iclpy.top/library/nginx:v1 sm1 Running Running 55 seconds ago
[root@sw2 nginxdata]# echo “sw2 web” > /data/nginxdata/index.html [root@sm3 nginxdata]# echo “sm3 web” > /data/nginxdata/index.html [root@sm1 nginxdata]# echo “sw1 web” > /data/nginxdata/index.html
访问 会出现数据不至于的问题
[root@sm1 nginxdata]# curl sm1 sw2 web [root@sm1 nginxdata]# curl sm1 sm3 web [root@sm1 nginxdata]# curl sm1 sw1 web [root@sm1 nginxdata]# curl sm1 sw2 web [root@sm1 nginxdata]# curl sm1 sm3 web [root@sm1 nginxdata]# curl sm1 sw1 web [root@sm1 nginxdata]# curl sm1 sw2 web [root@sm1 nginxdata]# curl sm1 sm3 web [root@sm1 nginxdata]# curl sm1 sw1 web [root@sm1 nginxdata]# curl sm1 sw2 web
<a name="x8EaP"></a>### 网络存储- 网络存储卷可以实现跨docker宿主机的数据共享,数据持久保存到网络存储卷中- 在创建service时添加卷的挂载参数,网络存储卷可以帮助自动挂载(**但需要集群节点都创建该网络存储卷**)<a name="To4Jb"></a>#### 部署NFS存储10.0.0.35 作为nfs存储服务器 共享目录为docker swarm集群主机使用。```shell## 创建共享目录mkdir /opt/dockervolume## 创建nfs工具yum -y install nfs-utilscat >/etc/exports <<EOF/opt/dockervolume *(rw,sync,no_root_squash)EOF
systemctl enable nfs-serversystemctl start nfs-servershowmount -e
为集群所有主机安装nfs-utils软件
yum -y install nfs-utilsshowmount -e 10.0.0.35Export list for 10.0.0.35:/opt/dockervolume *
创建存储卷
集群中所有节点创建
docker volume create --driver local --opt type=nfs --opt o=addr=10.0.0.35,rw --opt device=:/opt/dockervolume nginx_volume[root@sw1 nginxdata]# docker volume lsDRIVER VOLUME NAMElocal nginx_volume[root@sw1 nginxdata]# docker volume inspect nginx_volume[{"CreatedAt": "2022-06-26T11:37:23-04:00","Driver": "local","Labels": {},"Mountpoint": "/var/lib/docker/volumes/nginx_volume/_data","Name": "nginx_volume","Options": {"device": ":/opt/dockervolume","o": "addr=10.0.0.35,rw","type": "nfs"},"Scope": "local"}]
发布服务
docker service create --name nginx-svc --replicas 3 --publish 80:80 --mount "type=volume,source=nginx_volume,target=/usr/share/nginx/html" harbor.iclpy.top/library/nginx:v1rek50djy99llcjhbpw7pisxtsoverall progress: 3 out of 3 tasks1/3: running [==================================================>]2/3: running [==================================================>]3/3: running [==================================================>]verify: Service converged[root@sm1 nginxdata]# df -Th | grep nfs:/opt/dockervolume nfs 17G 1.9G 16G 11% /var/lib/docker/volumes/nginx_volume/_data[root@sm1 nginxdata]# df -Th | grep nfs:/opt/dockervolume nfs 17G 1.9G 16G 11% /var/lib/docker/volumes/nginx_volume/_data## nfs 创建echo "nfs test" > /opt/dockervolume/index.html[root@sm1 nginxdata]# curl sm1nfs test
服务互联与服务发现
如果一个nginx服务与一个mysql服务之间需要连接,在docker swarm如何实现呢?
方法1:
把mysql服务也使用 —publish参数发布到外网,但这样做的缺点是:mysql这种服务发布到外网不安全
方法2:
将mysql服务等运行在内部网络,只需要nginx服务能够连接mysql就可以了,在docker swarm中可以使用==overlay==网络来实现。
但现在还有个问题,服务副本数发生变化时,容器内部的IP发生变化时,我们希望仍然能够访问到这个服务, 这就是==服务发现(service discovery)==.
通过服务发现, service的使用者都不需要知道service运行在哪里,IP是多少,有多少个副本,就能让service通信
使用docker network ls查看到的ingress网络就是一个overlay类型的网络,但它不支持服务发现
[root@sm1 ~]# docker network lsNETWORK ID NAME DRIVER SCOPEdbd896f36018 bridge bridge local0e6e4e2c8d9e docker_gwbridge bridge locald4a9d1a1da0a host host localh5od7dcwj6u1 ingress overlay swarm3db66967c369 none null locald7f6o8mgivwr swarm_network overlay swarmzrmr0lxs8of3 tomcat-net overlay swarm
我们需要自建一个overlay网络来实现服务发现, 需要相互通信的service也必须属于同一个overlay网络
[root@sm1 ~]# docker network create --driver overlay --subnet 192.168.100.0/24 self-networkg4cq6y2ds6lxwfytaoqvcic70[root@sm1 ~]# docker network lsNETWORK ID NAME DRIVER SCOPEdbd896f36018 bridge bridge local0e6e4e2c8d9e docker_gwbridge bridge locald4a9d1a1da0a host host localh5od7dcwj6u1 ingress overlay swarm3db66967c369 none null localg4cq6y2ds6lx self-network overlay swarmd7f6o8mgivwr swarm_network overlay swarmzrmr0lxs8of3 tomcat-net overlay swarm
说明:
- —driver overlay指定为overlay类型
- —subnet 分配网段
- self-network 为自定义的网络名称
验证自动发现
1, 发布nignx-svc服务,指定在自建的overlay网络
[root@sm1 ~]# docker service create --name nginx-svc --replicas 3 --network self-network --publish 80:80 harbor.iclpy.top/library/nginx:v1dz34lyjwjg79wz9yvcb0hne8loverall progress: 3 out of 3 tasks1/3: running [==================================================>]2/3: running [==================================================>]3/3: running [==================================================>]verify: Service converged
2, 发布一个busybox服务,也指定在自建的overlay网络
[root@sm1 ~]# docker service create --name test --network self-network busybox sleep 100000djs31bcsrca4u09dkifj5cg21overall progress: 1 out of 1 tasks1/1: running [==================================================>]verify: Service converged
说明:
- 服务名为test
- busybox是一个集成了linux常用命令的软件,这里使用它可以比较方便的测试与nginx_service的连通性
- 没有指定副本,默认1个副本
- 因为它并不是长时间运行的daemon守护进程,所以运行一下就会退出.sleep 100000是指定一个长的运行时间,让它有足够的时间给我们测试
查出test服务在哪个节点运行的容器
[root@sm1 ~]# docker service ps testID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTSjq8hv0qkuhxa test.1 busybox:latest sm2 Running Running 13 minutes ago[root@sm1 ~]#
去运行test服务的容器节点查找容器的名称
[root@sm2 ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESa825468341d9 busybox:latest "sleep 100000" 13 minutes ago Up 13 minutes test.1.jq8hv0qkuhxa11xaep1a8r7wc5b9e6458471c tomcat:7.0.96-jdk8-openjdk "catalina.sh run" 22 minutes ago Up 22 minutes 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp tomcat.3.anigvi702bcymtvfocsk5rc2e[root@sm2 ~]#
使用查找出来的容器名称,执行命令测试
docker exec -it test.1.jq8hv0qkuhxa11xaep1a8r7wc ping -c 2 nginx-svcPING nginx-svc (192.168.100.2): 56 data bytes64 bytes from 192.168.100.2: seq=0 ttl=64 time=0.111 ms64 bytes from 192.168.100.2: seq=1 ttl=64 time=0.107 ms--- nginx-svc ping statistics ---2 packets transmitted, 2 packets received, 0% packet lossround-trip min/avg/max = 0.107/0.109/0.111 ms
4.15 docker swarm网络
在 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挂在上面。

docker stack
5.1 docker stack介绍
早期使用service发布,每次只能发布一个service。
yaml可以发布多个服务,但是使用docker-compose只能在一台主机发布。
一个stack就是一组有关联的服务的组合,可以一起编排,一起发布, 一起管理
5.2 docker stack与docker compose区别
- Docker stack会忽略了“构建”指令,无法使用stack命令构建新镜像,它是需要镜像是预先已经构建好的。 所以docker-compose更适合于开发场景;
- Docker Compose是一个Python项目,在内部,它使用Docker API规范来操作容器。所以需要安装Docker -compose,以便与Docker一起在您的计算机上使用;
- Docker Stack功能包含在Docker引擎中。你不需要安装额外的包来使用它,docker stacks 只是swarm mode的一部分。
- Docker stack不支持基于第2版写的docker-compose.yml ,也就是version版本至少为3。然而Docker Compose对版本为2和3的 文件仍然可以处理;
- docker stack把docker compose的所有工作都做完了,因此docker stack将占主导地位。同时,对于大多数用户来说,切换到使用docker stack既不困难,也不需要太多的开销。如果您是Docker新手,或正在选择用于新项目的技术,请使用docker stack。
docker stack常用命令
| 命令 | 描述 | | —- | —- | | docker stack deploy | 部署新的堆栈或更新现有堆栈 | | docker stack ls | 列出现有堆栈 | | docker stack ps | 列出堆栈中的任务 | | docker stack rm | 删除一个或多个堆栈 | | docker stack services | 列出堆栈中的服务 |
部署nginx与web管理服务案例
1, 编写YAML文件
