本节将测试通过 docker-machine 创建 Docker Swarm 集群,并部署 Traefik
环境介绍
- 宿主机: MacOS 10.14.6
    - VirtualBox: 5.2.18 r124319 (Qt5.6.3)
- docker-machine: 0.16.1, build cce350d7
- boot2docker: v19.03.2-rc1
- Docker: 18.09.6, build 481bc77
- traefik: v1.7.14
 
通过 docker-machine 创建 3 台服务器
| 主机名 | IP | Swarm 集群角色 | 备注 | 
|---|---|---|---|
| manager | 192.168.99.100 | manager | - | 
| worker1 | 192.168.99.101 | worker1 | - | 
| worker2 | 192.168.99.102 | worker2 | - | 
前期准备
- 需安装 docker-machine
- 需安装 VirtualBox
为加快 docker-machine 创建 vm 速度,建议:
- 手动下载 boot2docker.iso
- 放到 ~/.docker/machine/cache/boot2docker.iso 目录
- 创建 alias
sudo bash -c 'cat >>~/.profile <<EOF
alias docker-machinec='docker-machine create -d virtualbox   --virtualbox-boot2docker-url ~/.docker/machine/cache/boot2docker.iso'
EOF
source  ~/.profile
一、具体操作
1.1 创建并初始化 Docker Swarm 集群
# create docker-machine manager,work1,work2
$ for host in manager worker1 worker2; do docker-machinec $host; done
# init cluster
##manager
$ docker-machine ssh manager "docker swarm init \
    --listen-addr $(docker-machine ip manager) \
    --advertise-addr $(docker-machine ip manager)"
$ export worker_token=$(docker-machine ssh manager "docker swarm join-token worker -q")
##worker1
$ docker-machine ssh worker1 "docker swarm join \
    --token=${worker_token} \
    --listen-addr $(docker-machine ip worker1) \
    --advertise-addr $(docker-machine ip worker1) \
    $(docker-machine ip manager)"
##worker2
$ docker-machine ssh worker2 "docker swarm join \
    --token=${worker_token} \
    --listen-addr $(docker-machine ip worker2) \
    --advertise-addr $(docker-machine ip worker2) \
    $(docker-machine ip manager)"
##check
$ docker-machine ssh manager docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
tnc7tqgwjp5eqba0i1zji0mnj *   manager             Ready               Active              Leader              18.09.6
lwvomgs80i85zzkh4ptwewpij     worker1             Ready               Active                                  18.09.6
w2cgm0zib6dxs9d6mn07ladsf     worker2             Ready               Active                                  18.09.6
1.2 部署 Traefik
#创建 traefik 使用的网络
docker-machine ssh manager "docker network create --driver=overlay traefik-net"
# manager 节点部署 traefik 服务
$ docker-machine ssh manager "docker service create \
    --name traefik \
    --constraint=node.role==manager \
    --publish 80:80 --publish 8080:8080 \
    --mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
    --network traefik-net \
    traefik \
    --docker \
    --docker.swarmMode \
    --docker.domain=traefik \
    --docker.watch \
    --api"v
启动参数说明:
| 选项 | 说明 | 
|---|---|
| –publish 80:80 –publish 8080:8080 | 80 端口为集群监听端口,8080 为 webUI 访问端口 | 
| –constraint=node.role==manager | 指定在集群 manager 角色节点部署 | 
| –mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock | 监听 Docker socket API 事件(容器创建、删除等) | 
| –network traefik-net | 指定容器使用的网络名称 | 
| –docker | 指定为 docker 引擎 | 
| –api | 开启 WebUI 访问 | 
1.3 部署应用
#app1
$ docker-machine ssh manager "docker service create \
    --name whoami0 \
    --label traefik.port=80 \
    --network traefik-net \
    containous/whoami"
#app2
$ docker-machine ssh manager "docker service create \
    --name whoami1 \
    --label traefik.port=80 \
    --network traefik-net \
    --label traefik.backend.loadbalancer.sticky=true \
    containous/whoami"
#检查服务
$ docker-machine ssh manager "docker service ls"
ID            NAME     MODE        REPLICAS  IMAGE                     PORTS
moq3dq4xqv6t  traefik  replicated  1/1       traefik:latest            *:80->80/tcp,*:8080->8080/tcp
ysil6oto1wim  whoami0  replicated  1/1       containous/whoami:latest
z9re2mnl34k4  whoami1  replicated  1/1       containous/whoami:latest
说明:通过
--label traefik.backend.loadbalancer.sticky=true实现会话保持。
1.4. 通过 Traefik 访问应用
#app1: whoami0
$ curl -H Host:whoami0.traefik http://$(docker-machine ip manager)
Hostname: dfa25599e253
IP: 127.0.0.1
IP: 10.0.0.13
IP: 172.18.0.4
GET / HTTP/1.1
Host: whoami0.traefik
User-Agent: curl/7.54.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 10.255.0.2
X-Forwarded-Host: whoami0.traefik
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: 7403d79c27d0
X-Real-Ip: 10.255.0.2
#app2: whoami1
$ curl -H Host:whoami1.traefik http://$(docker-machine ip manager)
Hostname: 44e396b2b959
IP: 127.0.0.1
IP: 10.0.0.17
IP: 172.18.0.5
GET / HTTP/1.1
Host: whoami1.traefik
User-Agent: curl/7.54.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 10.255.0.2
X-Forwarded-Host: whoami1.traefik
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: 7403d79c27d0
X-Real-Ip: 10.255.0.2
如果是 Swarm 模式,访问集群任意节点都可得到相同结果
#cluster worker1
$ curl -H Host:whoami0.traefik http://$(docker-machine ip worker1)
Hostname: f1ecf18a1bd2
IP: 127.0.0.1
IP: 10.0.0.14
IP: 172.18.0.4
GET / HTTP/1.1
Host: whoami0.traefik
User-Agent: curl/7.54.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 10.255.0.3
X-Forwarded-Host: whoami0.traefik
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: 7403d79c27d0
X-Real-Ip: 10.255.0.3
#cluster worker2
$ curl -H Host:whoami1.traefik http://$(docker-machine ip worker2)
Hostname: a7f079a2ec71
IP: 127.0.0.1
IP: 10.0.0.18
IP: 172.18.0.6
GET / HTTP/1.1
Host: whoami1.traefik
User-Agent: curl/7.54.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 10.255.0.4
X-Forwarded-Host: whoami1.traefik
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: 7403d79c27d0
X-Real-Ip: 10.255.0.4
1.5 伸缩服务
$ docker-machine ssh manager "docker service scale whoami0=5"
$ docker-machine ssh manager "docker service scale whoami1=5"
#check
$ docker-machine ssh manager "docker service ls"
ID                  NAME                MODE                REPLICAS            IMAGE                      PORTS
k36uevddcmkc        traefik             replicated          1/1                 traefik:latest             *:80->80/tcp, *:8080->8080/tcp
tjby5a5gfrti        whoami0             replicated          5/5                 containous/whoami:latest
246bcqk4imw1        whoami1             replicated          5/5                 containous/whoami:latest
1.6 测试会话保持
因 whoami0 未设置会话保持,故每次访问返回容器节点 IP 不同
$ for n in `seq 5`
do
  echo "$n >>>"
  curl -c cookies.txt -sH Host:whoami0.traefik http://$(docker-machine ip manager) |grep -m 2 'IP'
done
#输出结果(第二行IP)
1 >>>
IP: 127.0.0.1
IP: 10.0.0.11
2 >>>
IP: 127.0.0.1
IP: 10.0.0.12
3 >>>
IP: 127.0.0.1
IP: 10.0.0.6
4 >>>
IP: 127.0.0.1
IP: 10.0.0.13
5 >>>
IP: 127.0.0.1
IP: 10.0.0.14
因 whoami1 已设置会话保持,故每次访问返回容器节点 IP 相同(会话保持)
#第一次访问,设置 cookie
$ curl -c cookies.txt -sH Host:whoami1.traefik http://$(docker-machine ip manager) |grep -m 2 'IP';
# 第二次访问
## 如果访问时指定 cookie 文件,则讲访问同一台服务器(容器)
$ for n in `seq 5`
do
    echo "$n >>>"
    curl -b cookies.txt -sH Host:whoami1.traefik http://$(docker-machine ip manager) |grep -m 2 'IP';
done
#输出结果
1 >>>
IP: 127.0.0.1
IP: 10.0.0.18
2 >>>
IP: 127.0.0.1
IP: 10.0.0.18
3 >>>
IP: 127.0.0.1
IP: 10.0.0.18
4 >>>
IP: 127.0.0.1
IP: 10.0.0.18
5 >>>
IP: 127.0.0.1
IP: 10.0.0.18
二、懒人版
在初始化 docker-machine 集群后,其中 1.2,1.3 步骤可通过 Docker-compse 编排文件部署 Traefik 及 app 服务 直接替代
2.1 manager 节点操作
docker-compose 单机模式
#登录manager,并安装 docker-compose 工具
$ docker-machine ssh manager
$ sudo curl -o /usr/local/bin/docker-compose https://mirrors.aliyun.com/docker-toolbox/linux/compose/1.21.2/docker-compose-Linux-x86_64 && \
sudo chmod +x /usr/local/bin/docker-compose && \
docker-compose -v
#生成编排文件
$ echo '
version: "3"
services:
  reverse-proxy:
    image: traefik
    restart: always
    command: --api --docker
    networks:
      - traefik-net
    ports:
      - "80:80"
      - "8080:8080"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /dev/null:/traefik.toml
    deploy:
      mode: global
      placement:
        constraints:
          - node.role == manager
  whoami0:
    image: containous/whoami
    restart: always
    networks:
      - traefik-net
    labels:
      - "traefik.backend=whoami0"
      - "traefik.frontend.rule=Host:whoami0.traefik"
  whoami1:
    image: containous/whoami
    restart: always
    networks:
      - traefik-net
    labels:
      - "traefik.backend=whoami1"
      - "traefik.backend.loadbalancer.sticky=true"
      - "traefik.frontend.rule=Host:whoami1.traefik"
networks:
  traefik-net:
    driver: overlay
' > docker-compose.yml
#语法检查
$ docker-compose config
#运行
$ docker-compose up -d
#检查
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                                                              NAMES
5451484ec7f9        traefik             "/traefik --api --do…"   About a minute ago   Up About a minute   0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:8080->8080/tcp   docker_reverse-proxy_1
3f782ace7aaf        containous/whoami   "/whoami"                About a minute ago   Up About a minute   80/tcp                                                             docker_whoami1_1
30e1b5c721b4        containous/whoami   "/whoami"                About a minute ago   Up About a minute   80/tcp
后面测试参考 1.4 及以后步骤
docker swarm 集群模式
待补充。。。