Swarm 是使用Docker 引擎内置的集群管理和编排工具。Swarm集群的框架与Hadoop集群或其他分布式系统类似,它也是由节点构成,每一个节点就是一台主机或者虚拟机。工作的机制也是主从模式(master/slaver),节点分为两种,一种是负责管理的Manager另一种是具体干活的Worker。
多个 Docker 主机就被抽象为单个大型的虚拟 Docker 主机,在管理节点上,用户可以像在单机一样在集群上操作容器或服务
Swarm集群中管理的对象主要由三个,Task、Service与Node,其中Node上面已经介绍过,这里解释下Task与Service的概念
Swarm 中的最小的调度单位,目前一个Task就是一个容器
Service一般是由一组相同的Task组成,Service是这组Task要完成的任务的一个抽象。按照其包含的Task的布署方式分为两种:
这两种模式是在服务创建时通过创建命令docker service create的 –mode 参数指定的
Service与Task以及容器的关系如下:
总结成一句话就是,swarm集群(cluster)是由节点(node)组成;服务(service)一般包含若干个任务(Task),一个Task就是运行一个容器,所有这些Task都是在节点上执行的,具体在那个个节点上执行是由管理节点调度的。
curl -sL https://gitee.com/YunFeiGuoJi/Cnblog/raw/master/shell/Scripts/docker_install.sh|sh -x -
# 修改 /etc/docker/damean.json 添加配置
"live-restore": false
# 重启
systemctl restart dockerd
docker swarm init --advertise-addr 192.168.56.101
--advertise-addr 指定与其他 node 通信的地址
docker swarm init 输出告诉我们:
① swarm 创建成功,swarm-manager 成为 manager node。
② 添加 worker node 需要执行的命令。
③ 添加 manager node 需要执行的命令。
如果当时没有记录下 docker swarm init 提示的添加 worker 的完整命令,可以通过 docker swarm join-token worker 查看
[root@master ~]# docker node --help
Usage: docker node COMMAND
Manage Swarm nodes
Commands:
demote Demote one or more nodes from manager in the swarm
inspect Display detailed information on one or more nodes
ls List nodes in the swarm
promote Promote one or more nodes to manager in the swarm
ps List tasks running on one or more nodes, defaults to current node
rm Remove one or more nodes from the swarm
update Update a node
Run 'docker node COMMAND --help' for more information on a command.
# 查看节点
docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
8x5iogo0c2d7cl9edjvbacxio * master Ready Active Leader 19.03.12
shihkplhlozcttq3m8va4129c node01 Ready Active 19.03.12
# 删除节点
docker node rm shihkplhlozcttq3m8va4129c
docker service create --name app1 --network yfgj --replicas 2 --entrypoint "sleep 1d" busybox
docker service create --name app2 --network yfgj --replicas 2 nginx
# 查看生成的vip
docker service inspect --format='{{json .Endpoint.VirtualIPs}}' app1
[{"NetworkID":"9ttgtpwyvnssbfnw33wchbgwi","Addr":"10.0.15.5/24"}]
docker service inspect --format='{{json .Endpoint.VirtualIPs}}' app2
docker service scale web1=2
docker service rm service_name
# docker-compose yml文件
version: "3.8"
services:
portainer:
image: portainer/portainer-ce:latest
ports:
- "9000:9000"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
networks:
- "tarfik-public"
deploy:
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik-public"
- "traefik.http.routers.portainer.rule=Host(`portainer.local.cluster`)"
- "traefik.http.routers.portainer.entrypoints=websecure"
- "traefik.http.routers.portainer.tls=true"
- "traefik.http.routers.portainer.tls.certresolver=foo"
- "traefik.http.routers.portainer.tls.domains[0].main=local.cluster"
- "traefik.http.routers.portainer.tls.domains[0].sans=*.local.cluster"
- "traefik.http.services.portainer.loadbalancer.server.port=9000"
replicas: 1
placement:
constraints: [node.role == manager]
networks:
traefik-public:
external: true
# 执行命令
docker stack deploy -c docker-compose.yaml docker-swarm-manager
# 访问
## 本地访问
http://localhost:9000
实现功能:
从使用者角度看,一个Service相当于它的所有Task的一个反向代理,它主要使用了 Linux 内核 iptables 和 IPVS 的功能来实现服务发现和负载均衡
Swarm支持三种模式的负载均衡,它们的使用方式如下:
docker service create --endpoint-mode dnsrr --network overlay1 --replicas 3 --name nginx nginx
docker service create --network overlay1 --replicas 3 --name nginx nginx
docker service create --network overlay1 --replicas 3 -p 80:80 --name nginx nginx
docker network create \
--driver overlay \
--gateway 10.0.4.1 \
--subnet 10.0.4.0/22 \
--ip-range 10.0.4.0/24 \
--attachable yfgj_net
version: "3.8"
secrets:
aliyun_region_id:
#external: true
file: "/root/.ssl/aliyun_region_id"
aliyun_access_key:
#external: true
file: "/root/.ssl/aliyun_access_key"
aliyun_secret_key:
#external: true
file: "/root/.ssl/aliyun_secret_key"
services:
traefik:
image: traefik:v2.4.8
command:
- "--log.level=DEBUG"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.swarmMode=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
#- "--entrypoints.webnossl.address=:8443"
- "--api=true"
- "--api.dashboard=true"
- "--api.debug=true"
- "--accesslog=true"
- "--log=true"
- "--log.filepath=/tmp/traefik.err.log"
- "--accesslog.filepath=/tmp/traefik.access.log"
- "--providers.docker.network=yfgj_net"
- "--certificatesresolvers.foo.acme.dnschallenge=true"
- "--certificatesresolvers.foo.acme.dnschallenge.provider=alidns"
- "--certificatesresolvers.foo.acme.dnschallenge.resolvers=114.114.114.114:53,8.8.8.8:53"
- "--certificatesresolvers.foo.acme.keytype=EC256" #RSA4096
#- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
- "--certificatesresolvers.foo.acme.email=xxxx"
- "--certificatesresolvers.foo.acme.storage=/letsencrypt/acme.json"
- "--metrics.prometheus=true"
- "--metrics.prometheus.buckets=0.100000, 0.300000, 1.200000, 5.000000"
- "--metrics.prometheus.addEntryPointsLabels=true"
- "--metrics.prometheus.addServicesLabels=true"
- "--entryPoints.metrics.address=:8082"
- "--metrics.prometheus.entryPoint=metrics"
ports:
- "80:80"
- "443:443"
- "8080:8080"
- "8020:8020"
secrets:
- "aliyun_region_id"
- "aliyun_access_key"
- "aliyun_secret_key"
environment:
- "ALICLOUD_REGION_ID_FILE=/run/secrets/aliyun_region_id"
- "ALICLOUD_ACCESS_KEY_FILE=/run/secrets/aliyun_access_key"
- "ALICLOUD_SECRET_KEY_FILE=/run/secrets/aliyun_secret_key"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
- "/root/letsencrypt:/letsencrypt"
networks:
- "yfgj_net"
deploy:
mode: replicated
replicas: 1
labels:
- "traefik.enable=true"
- "traefik.docker.network=yfgj_net"
- "traefik.http.services.traefik_traefik.loadbalancer.server.port=8080"
# http 80
- "traefik.http.routers.traefik-ui-80.rule=Host(`traefik.ctq6.cn`)"
- "traefik.http.routers.traefik-ui-80.entrypoints=web"
# http 8443
- "traefik.http.routers.traefik-ui-8443.rule=Host(`traefik-8443.ctq6.cn`)"
- "traefik.http.routers.traefik-ui-8443.entrypoints=webnossl"
- "traefik.http.routers.traefik-ui-8443.tls=true"
- "traefik.http.routers.traefik-ui-8443.tls.certresolver=foo"
- "traefik.http.routers.traefik-ui-8443.tls.domains[0].main=ctq6.cn"
- "traefik.http.routers.traefik-ui-8443.tls.domains[0].sans=*.ctq6.cn"
- "traefik.http.routers.traefik-ui-8443.middlewares=redirect-https"
# https 443
- "traefik.http.middlewares.redirect-https.redirectScheme.scheme=https"
- "traefik.http.routers.traefik-ui-443.rule=Host(`traefik-443.ctq6.cn`)"
- "traefik.http.routers.traefik-ui-443.tls=true"
- "traefik.http.routers.traefik-ui-443.tls.certresolver=foo"
- "traefik.http.routers.traefik-ui-443.tls.domains[0].main=ctq6.cn"
- "traefik.http.routers.traefik-ui-443.tls.domains[0].sans=*.ctq6.cn"
- "traefik.http.routers.traefik-ui-443.middlewares=redirect-https"
- "traefik.http.routers.traefik-ui-443.entrypoints=websecure"
placement:
constraints: [node.role == manager]
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
networks:
yfgj_net:
external: true
name: yfgj_net
# 配置域名
阿里云或者腾讯云上配置域名指向安装traefik所在节点,并将443,80,8443防火强配置为允许公网访问,配置需要访问的服务域名
# 部署traefik 服务
docker stack deploy -c docker-compose-traefik.yml traefik
# 测试traefik 域名是否生成
curl -v localhost:8080/api/http/routers|jq .
# 测试是否能访问对应的服务
curl -v -H "Host:traefik.ctq6.cn" localhost
curl -v -H "Host:traefik-443.ctq6.cn" localhost:443
curl -v -H "Host:traefik-8443.ctq6.cn" localhost:8443
# 浏览器访问
http://traefik.ctq6.cn
https://traefik-443.ctq6.cn
http://traefik-8443.ctq6.cn:8443
version: "3.8"
services:
nginx:
image: nginx:latest
logging:
driver: "json-file"
options:
max-size: "200k"
max-file: "10"
ports:
- 8088:80
networks:
- yfgj_net
volumes:
- /root/yunfeiguoji:/usr/share/nginx/html/blog/yunfeiguoji:rw
- ./default.conf:/etc/nginx/conf.d/default.conf:rw
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
deploy:
mode: replicated
replicas: 1
labels:
- "traefik.enable=true"
- "traefik.docker.network=yfgj_net"
- "traefik.http.services.nginx_nginx.loadbalancer.server.port=80"
# https 443
- "traefik.http.middlewares.redirect-https.redirectScheme.scheme=https"
- "traefik.http.routers.nginx-ui-443.rule=Host(`www.ctq6.cn`)"
- "traefik.http.routers.nginx-ui-443.tls=true"
- "traefik.http.routers.nginx-ui-443.tls.certresolver=foo"
- "traefik.http.routers.nginx-ui-443.tls.domains[0].main=ctq6.cn"
- "traefik.http.routers.nginx-ui-443.tls.domains[0].sans=*.ctq6.cn"
- "traefik.http.routers.nginx-ui-443.middlewares=redirect-https"
- "traefik.http.routers.nginx-ui-443.entrypoints=websecure"
placement:
constraints: [node.role == manager]
resources:
limits:
cpus: '0.50'
memory: 50M
reservations:
cpus: '0.25'
memory: 20M
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
networks:
yfgj_net:
external: true
name: yfgj_net
docker stack deploy nginx -c docker-conpose-nginx.yml