Docker Swarm で sticky session の LBを立てる

検証のため sticky sessionのLBが欲しかったのです。

nginx とか Apache でLB作ってもいいんですが、コンパイルが必要だったりモジュール入れたりめんどくさそう・・・
いろいろ調べてたら なんか Docker Swarm で traefik を使えばできそうだったのでやってみました。

環境

OS version

$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.1 LTS"

docker version

# docker version
Client:
 Version:           18.09.0
 API version:       1.39
 Go version:        go1.10.4
 Git commit:        4d60db4
 Built:             Wed Nov  7 00:49:01 2018
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.0
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.4
  Git commit:       4d60db4
  Built:            Wed Nov  7 00:16:44 2018
  OS/Arch:          linux/amd64
  Experimental:     false

手順

swarm mode

swame mode にします。

# docker swarm init
Swarm initialized: current node (y66s0tr38tdfobqklee89d5i7) is now a manager.

# docker node ls
ID                            HOSTNAME              STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
y66s0tr38tdfobqklee89d5i7 *   ****   Ready               Active              Leader              18.09.0

docker compose ファイルを作成します

version: "3"

services:

  whoami:
    image: tutum/hello-world
    networks:
      - net
    ports:
      - "80"
    deploy:
      restart_policy:
        condition: any
      mode: replicated
      replicas: 5
      update_config:
        delay: 2s
      labels:
        - "traefik.docker.network=test_net"
        - "traefik.port=80"
        - "traefik.frontend.rule=PathPrefix:/hello;"
        - "traefik.backend.loadbalancer.sticky=true"

  loadbalancer:
    image: traefik
    command: --docker \
      --docker.swarmmode \
      --docker.watch \
      --web \
      --loglevel=DEBUG
    ports:
      - 80:80
      - 9090:8080
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    deploy:
      restart_policy:
        condition: any
      mode: replicated
      replicas: 1
      update_config:
        delay: 2s
      placement:
         constraints: [node.role == manager]
    networks:
      - net

networks:
  net:

docker stack deploy

docker swarm に 先程作ったcomposeファイルを使用してコンテナのデプロイを行います

# docker stack deploy -c docker-compose.swarm.yml test
Creating network test_net
Creating service test_whoami
Creating service test_loadbalancer

# docker stack ls
NAME                SERVICES            ORCHESTRATOR
test                2                   Swarm

# docker ps 
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS              PORTS               NAMES
93f4aedc3e2c        traefik:latest             "/traefik --docker '…"   23 seconds ago      Up 9 seconds        80/tcp              test_loadbalancer.1.g29b0pvnvna3dznnx2itt7gbr
fa9b6f64e7d3        tutum/hello-world:latest   "/bin/sh -c 'php-fpm…"   29 seconds ago      Up 6 seconds        80/tcp              test_whoami.4.qn4wph6t3vqtjq5o7uc2r12zs
b25c164b5658        tutum/hello-world:latest   "/bin/sh -c 'php-fpm…"   29 seconds ago      Up 9 seconds        80/tcp              test_whoami.1.lbh83j9ruenjv8vsrzj0mk17g
93842a9fffd5        tutum/hello-world:latest   "/bin/sh -c 'php-fpm…"   29 seconds ago      Up 9 seconds        80/tcp              test_whoami.5.aezv9xt4fda4y72tb5a3v72d7
74b06ecaa0b9        tutum/hello-world:latest   "/bin/sh -c 'php-fpm…"   29 seconds ago      Up 10 seconds       80/tcp              test_whoami.3.50uxml9u0xco2ulqjj3ujtbsg
10cb355434a8        tutum/hello-world:latest   "/bin/sh -c 'php-fpm…"   29 seconds ago      Up 11 seconds       80/tcp              test_whoami.2.dxik1yuou7pf3y6zkmptbcgkq

起動確認

http://127.0.0.1:9090 にアクセスしてみます

f:id:moremagic:20190108223323p:plain こんな感じに コンテナが5個見えれば無事起動できてます

sticky session の確認

# curl -vs -c cookie.txt -b cookie.txt http://127.0.0.1/hello -o /dev/null
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> GET /hello HTTP/1.1
> Host: 127.0.0.1
> User-Agent: curl/7.58.0
> Accept: */*
> Cookie: _TRAEFIK_BACKEND=http://10.0.0.6:80
> 
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=UTF-8
< Date: Tue, 08 Jan 2019 13:34:56 GMT
< Server: nginx/1.8.0
< X-Powered-By: PHP/5.6.14
< Content-Length: 478
< 
{ [478 bytes data]
* Connection #0 to host 127.0.0.1 left intact

何回試しても Cookie: _TRAEFIK_BACKEND のIPが同じになります
また cookie.txt を一回消すと変わることが確認できます

止め方

# docker stack rm test
Removing service test_loadbalancer
Removing service test_whoami
Removing network test_net

資料

以下の資料を参考にしてます

www.littlebigextra.com