目录
一。Docker Swarm简介
Swarm是Docker公司推出的用来管理docker集群,它将一群Docker宿主机变成一个单一的,虚拟的主机。Swarm使用标准的Docker API接口作为其前端访问入口,换言之,各种形式的Docker Client(docker client in Go, docker_py, docker等)均可以直接与Swarm通信。Swarm几乎全部用go语言来完成开发,Swarm0.2发布,相比0.1版本,0.2版本增加了一个新的策略来调度集群中的容器,使得在可用的节点上传播它们,以及支持更多的Docker命令以及集群驱动。
Swarm deamon只是一个调度器(Scheduler)加路由器(router),Swarm自己不运行容器,它只是接受docker客户端发送过来的请求,调度适合的节点来运行容器,这意味着,即使Swarm由于某些原因挂掉了,集群中的节点也会照常运行,当Swarm重新恢复运行之后,它会收集重建集群信息.
Swarm架构:
Swarm 集群中每台 Docker 主机称为一个节点。其中主动初始化一个 Swarm 集群的节点称为管理节点(Manager),加入一个Swarm 集群的节点称为工作节点(Worker Node)。工作节点是任务执行节点,管理节点将任务下发至工作节点执行。管理节点默认也作为工作节点。一个 Swarm 集群可以有多个管理节点,但只有一个管理节点可以成为 leader。
结构图
Docker Swarm 和 Docker Compose 一样,都是 Docker 官方容器编排项目,但不同的是,Docker Compose 是一个在单个服务器或主机上创建多个容器的工具,而 Docker Swarm 则可以在多个服务器或主机上创建容器集群服务,对于微服务的部署,显然 Docker Swarm 会更加适合。
从 Docker 1.12.0 版本开始,Docker Swarm 已经包含在 Docker 引擎中(docker swarm
),并且已经内置了服务发现工具
Docker Swarm操作集群步骤
- Docker Machine 创建 Docker 主机(开放远程2375端口 安装docker),也可以使用物理主机安装docker
修改 /lib/systemd/system/docker.service 在ExecStart添加-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock \ 执行sytemctl daemon-reload重启 - Docker Swarm 配置集群节点
- Docker Service 部署单个集群服务
- Docker Stack 部署多个集群服务,以及 GUI 管理页面
内部组件详细结构图:
二。Docker Swarm部署集群
规划主机
2.1.Swarm配置集群节点
2.1.1 Swarm组织集群
创建集群(docker swarm init)
docker swarm init命令详解参考官网 docker swarm init | Docker Documentation
[root@swarm01 ~]# docker swarm init --advertise-addr 192.168.58.144
Swarm initialized: current node (94y1aq5dfazm5bpppc5t0zi06) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-5c8fhbllao1tw97wn1ob7vytxnlw0b1kezcqqquo6k0qe5m1lu-3h1xt77env6excdy78q1qnlvo \
192.168.58.144:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
新增成功后 日志中就有添加到集群的命令,同时查看节点
主键编号 - 主机名 - 状态 - 是否激活(Active激活)-目前角色(leader就是管理者)
[root@swarm01 ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
94y1aq5dfazm5bpppc5t0zi06 * swarm01 Ready Active Leader
其他两台主机使用新建集群中日志的docker swarm join 语句加入集群
docker swarm join 详细参考docker swarm join | Docker Documentation
退出集群 docker swarm leave(worker) master退出 docker swarm leave --force
[root@swarm03 ~]# docker swarm join \
> --token SWMTKN-1-5c8fhbllao1tw97wn1ob7vytxnlw0b1kezcqqquo6k0qe5m1lu-3h1xt77env6excdy78q1qnlvo \
> 192.168.58.144:2377
This node joined a swarm as a worker.
如果推出了join界面可以通过以下命令查看
docker swarm join-token worker
管理机器继续查看节点(一个leader)
[root@swarm01 ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
74zhsvy6te3xbn4zmmct5dgno swarm02 Ready Active
7lg833q1b8ur3iayuvpp50umy swarm03 Ready Active
94y1aq5dfazm5bpppc5t0zi06 * swarm01 Ready Active Leader
145机器提升为leader(注意只有一个leader处于激活状态,其他leader高可用standby)
docker node详细命令参考docker node | Docker Documentation
[root@swarm01 ~]# docker node promote swarm02
Node swarm02 promoted to a manager in the swarm.
[root@swarm01 ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
74zhsvy6te3xbn4zmmct5dgno swarm02 Ready Active Reachable
7lg833q1b8ur3iayuvpp50umy swarm03 Ready Active
94y1aq5dfazm5bpppc5t0zi06 * swarm01 Ready Active Leader
2.1.2 docker swarm 过滤
docker swarm有两种角色 manager和worker,使用 promote节点自动从worker角色升级为manager 通过ls过滤
角色属于过滤机制的一种
[root@swarm01 ~]# docker node ls --filter role=worker
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
7lg833q1b8ur3iayuvpp50umy swarm03 Ready Active
[root@swarm01 ~]# docker node ls --filter role=manager
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
74zhsvy6te3xbn4zmmct5dgno swarm02 Ready Active Reachable
94y1aq5dfazm5bpppc5t0zi06 * swarm01 Ready Active Leader
将swarm02节点降级为worker节点
[root@swarm01 ~]# docker node update swarm02 --role=worker
swarm02
[root@swarm01 ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
74zhsvy6te3xbn4zmmct5dgno swarm02 Ready Active
7lg833q1b8ur3iayuvpp50umy swarm03 Ready Active
94y1aq5dfazm5bpppc5t0zi06 * swarm01 Ready Active Leader
当前swarm支持的 filters 有: (docker node ls | Docker Documentation)
- id 通过主机id过滤
[root@swarm01 ~]# docker node ls --filter id=74 ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 74zhsvy6te3xbn4zmmct5dgno swarm02 Ready Active
- label node -ls --filter通过label过滤目前暂时无法过滤
给节点添加label(lable一般是键值对的 --label-add name=db_1) 下面这个值是nulldocker node update --label-add foo swarm02
过滤
docker node ls -f "label=foo"
虽然无法过滤但是通过docker node inspect可以看到已经添加label了
[root@swarm01 ~]# docker node inspect swarm02 [ { "ID": "74zhsvy6te3xbn4zmmct5dgno", "Spec": { "Labels": { "hello": "", "myname": "node_145" }, "Role": "worker", "Availability": "active" },
删除label
[root@swarm01 ~]# docker node update swarm02 --label-rm hello swarm02 [root@swarm01 ~]# docker node update swarm02 --label-rm myname swarm02
- membership 成员资格筛选器根据成员关系的存在和接受或挂起的值匹配节点
[root@swarm01 ~]# docker node ls -f "membership=pending" ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 74zhsvy6te3xbn4zmmct5dgno swarm02 Ready Active [root@swarm01 ~]# docker node ls -f "membership=accepted" ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 7lg833q1b8ur3iayuvpp50umy swarm03 Ready Active 94y1aq5dfazm5bpppc5t0zi06 * swarm01 Ready Active Leader
- name通过主机名过滤
[root@swarm01 ~]# docker node ls --filter name=swarm02 ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 74zhsvy6te3xbn4zmmct5dgno swarm02 Ready Active
- role 通过角色过滤 参考前面的描述
2.1.3 Swarm常见运维问题
1. 如果某个worker节点处于down状态一直无法连接,无论怎么重启worker节点的docker或者主机,都无法时节点处于up状态,可能需要leave然后重新join,出现
如果在worker节点无法leave
Docker Swarm 报 Error response from daemon: rpc error: code = 4 desc = context deadline exceeded
前往down状态的worker节点所在node,找到swarm的安装目录
[root@swarm-worker07-fat worker]# find / -name swarm
/run/docker/swarm
/var/lib/docker.bak/swarm
/usr/src/kernels/3.10.0-1160.2.2.el7.x86_64.debug/arch/mips/sibyte/swarm
/data/docker/docker/swarm
/data/docker/swarm
进入目录找到tasks.db
[root@swarm-worker07-fat worker]# cd /data/docker/swarm
[root@swarm-worker07-fat swarm]# ls
certificates docker-state.json state.json worker
[root@swarm-worker07-fat swarm]# cd worker
[root@swarm-worker07-fat worker]# ls
tasks.db
删除tasks.db: rm -rf tasks.db
重启docker:systemctl restart docker
执行leave命令,docker swarm leave。
主节点上
docker node ls
docker node rm 节点id 删除之前旧的之后
docker swarm join-token worker 查看主节点秘钥和命令
在worker节点重新加入即可
2.1.4 Swarm日志
查看docker进程日志
journalctl --follow -u docker
查看服务日志
docker service logs 服务名称
2.2.Docker Swarm部署集群服务
2.2.1 docker serivce 部署单个集群
docker将启动在swarm集群中的容器叫做service 使用docker service命令提交服务
docker service具体详细参考:docker service create | Docker Documentation
[root@swarm01 ~]# docker service create --replicas 3 -p 8888:80 --name mynginx nginx
4obe48vuzsk68lea7zdhfh2pl
[root@swarm01 ~]# docker service ls
ID NAME REPLICAS IMAGE COMMAND
4obe48vuzsk6 mynginx 2/3 nginx
[root@swarm01 ~]# docker service ls
ID NAME REPLICAS IMAGE COMMAND
4obe48vuzsk6 mynginx 2/3 nginx
[root@swarm01 ~]# docker service ls
ID NAME REPLICAS IMAGE COMMAND
4obe48vuzsk6 mynginx 3/3 nginx
其中 --replicas表示启动该镜像的几个实例
docker service ls查看目前已经启动的实例 2/3表示需要启动3个目前启动了两个
查看所有的nginx在worker节点的信息(docker service ps 名称)
[root@swarm01 ~]# docker service ps mynginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
emxraij4vu4f4hnl4him6hjpw mynginx.1 nginx swarm01 Running Running 3 minutes ago
0qo34jw9hhs2ysvm8g0xav4ez mynginx.2 nginx swarm03 Running Running 3 minutes ago
6q0mluc2nce7isp65qc01o8t0 mynginx.3 nginx swarm02 Running Running 2 minutes ago
分别访问 http://192.168.58.144:8888/ http://192.168.58.145:8888/ http://192.168.58.147:8888/ 发现均可以访问ngingx
移除掉nginx的service
[root@swarm01 ~]# docker service rm mynginx
mynginx
新建两个副本
docker service create --replicas 2 -p 8888:80 --name mynginx nginx
分别访问 http://192.168.58.144:8888/ http://192.168.58.145:8888/ http://192.168.58.147:8888/ 发现均可以访问ngingx
命名只部署了两个为什么却能三台机器都能访问了
因为swarm使用了名字为ingress的overlay网络
[root@swarm01 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
be53c597d43f bridge bridge local
60c34082957b docker_gwbridge bridge local
76a93f7787fe host host local
5y2vupi4vqq5 ingress overlay swarm
74a25bcf3d4d none null local
介绍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 允许自定义。
swarm默认使用ingress网络查看mynginx服务
[root@swarm01 ~]# docker service inspect mynginx
其中有一段 说明ingress网络使用了vip模式并且vip是 10.255.0.6/16
"Endpoint": {
"Spec": {
"Mode": "vip",
"Ports": [
{
"Protocol": "tcp",
"TargetPort": 80,
"PublishedPort": 8888
}
]
},
"Ports": [
{
"Protocol": "tcp",
"TargetPort": 80,
"PublishedPort": 8888
}
],
"VirtualIPs": [
{
"NetworkID": "5y2vupi4vqq5e5papr26n661d",
"Addr": "10.255.0.6/16"
}
]
},
直接到节点上查看nginx 发现屋里地址是 10.255.0.7和10.255.0.8
[root@swarm03 ~]# docker inspect 8a | grep IPA
"SecondaryIPAddresses": null,
"IPAddress": "",
"IPAMConfig": {
"IPAddress": "10.255.0.8",
ingress网络 只能使用 -p 提供对外的端口映射 然后访问任意一台主机负载均衡来访问容器
比如在启动一个service
docker service create --name eureka -p 8760:8761 springcloud/eureka
如果需要在nginx服务中连接eureka就无法做到
需要在容器中互相访问可以自定义overlay网络
docker network create --driver overlay mynetwork
[root@swarm01 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
be53c597d43f bridge bridge local
60c34082957b docker_gwbridge bridge local
76a93f7787fe host host local
5y2vupi4vqq5 ingress overlay swarm
d27qf5ethd5j mynetwork overlay swarm
创建两个容器时可以指定使用自定义的mynetwork
docker service create --name eureka -p 8760:8761 --network=mynetwork springcloud/eureka
docker service create --replicas 2 -p 8888:80 --network=mynetwork --name mynginx nginx
找到eureka的容器 docker exec -it 容器id bash进入,发现可以使用服务名来ping访问对方ip地址
root@54c0ae2b74a8:/# ping mynginx
PING mynginx (10.0.0.2): 56 data bytes
64 bytes from 10.0.0.2: icmp_seq=0 ttl=64 time=0.088 ms
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.145 ms
介绍swarm filter:
2.1.2介绍过swarm的filter 可以给node节点设置label 比如
docker node update --label-add first=w1 swarm01
docker node update --label-add first=w3 swarm03
现在如果我想在lable是first==w3的机器上安装
docker service create --name eureka -p 8760:8761 --network=mynetwork --constraint=node.labels.first==w3 springcloud/eureka
如果我想在manager那台机器安装
[root@swarm01 ~]# docker service create --name eureka -p 8760:8761 --network=mynetwork --constraint=node.role==manager springcloud/eureka
80tcd3ty9uh1p9m67n2jf0aym
[root@swarm01 ~]# docker service ps eureka
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
125pnqml54txpavygvmw9t2pb eureka.1 springcloud/eureka swarm01 Running Running 4 seconds ago
同理也可以使用node.id或者node.name等过滤器,完全可以自主定制
2.2.2 docker stack部署多个集群
docker service
部署的是单个服务,我们可以使用docker stack
进行多服务编排部署,使用的同样是docker-compose.yml
配置文件,示例(部署mysql,同时部署phpadmin):
version: "2"
services:
mysql:
image: mariadb:5
environment:
MYSQL_ROOT_PASSWORD: 123456
restart: always
ports:
- 3306:3306
deploy:
mode: replicated
replicas: 1
phpMyAdmin:
image: phpmyadmin/phpmyadmin
environment:
PMA_HOST: 192.168.58.144
PMA_PORT: 3306
PMA_USER: root
PMA_PASSWORD: 123456
ports:
- 8888:80
deploy:
mode: replicated
replicas: 1
placement:
constraints: [node.role == manager]
部分老旧linux中可能docker版本比较低 没有docker stack命令,可以使用 yum -y update docker
使用命令部署(可以看到服务的名称就是 stack名字_服务名字,默认安装network 所以可以使用服务名访问
可以使用服务名称mysql访问也可以使用 真实服务名字phpadmin_mysql访问
)
[root@swarm01 ~]# docker stack deploy -c docker-compose1.yml phpadmin
Ignoring unsupported options: restart
Creating network phpadmin_default
Creating service phpadmin_phpMyAdmin
Creating service phpadmin_mysql
查看stack名字为phpadmin的所有服务
[root@swarm01 ~]# docker stack ls
NAME SERVICES
phpadmin 2
[root@swarm01 ~]# docker stack ps phpadmin
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
rxyc34diyjwx phpadmin_mysql.1 mariadb:5 swarm03 Running Running 28 seconds ago
gdu3hetdii6j phpadmin_phpMyAdmin.1 phpmyadmin/phpmyadmin:latest swarm01 Running Starting less than a second ago
访问phpadmin
2.3.Docker Swarm可视化工具
2.3.1 可视化工具visualizer
官方网站:https://github.com/dockersamples/docker-swarm-visualizer
docker镜像:Docker Hub
docker swarm安装
docker service create \
--name=viz \
--publish=8080:8080/tcp \
--constraint=node.role==manager \
--mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
dockersamples/visualizer
访问 http://192.168.58.144:8080/ 界面
2.3.2 可视化管理工具portainer
官网 Container Management | Kubernetes GUI | Docker Swarm GUI | Portainer
安装文档:Deployment — Portainer 1.23.2 documentation
github:https://github.com/portainer/portainer
docker swarm安装
docker service create \
--name portainer \
--publish 9000:9000 \
--replicas=1 \
--constraint 'node.role == manager' \
portainer/portainer
开启swarm集群每一台的远程服务 2375端口
参考 docker纪录篇4-docker使用maven远程构建_liaomin416100569的专栏-CSDN博客_maven 远程docker
访问 http://192.168.58.144:9000访问 界面1注册用户amdin,输入admin默认的密码两次, 8位以上
接下来选择remote的docker,点击connect
选择home节点列表 58.144进入
左侧菜单就可以看到58.144所有的services ,swarm集群管理等 具体自己发现
注意:
如果使用swarm部署微服务可以使用docker stack使用overlay网络部署,因为所有容器的服务都在同一个网络中
一般程序需要使用dockerfile打包,上传到类似harbor私服中,然后再使用docker stack部署