Dockerを使用した超簡単ロードバランサー(Let’sEncrypt+セッション維持)の作り方

DockerのTraefikを使って簡単にロードバランサーを作ることができましたので、紹介したいと思います。

ネットワーク内でアプリ(wordpressやwebサービス)のコンテナを起動すれば、自動的にLet’s Encryptの設定が行われます。アプリのコンテナを複数起動すれば、ロードバランサーとして振り分けもしてくれます。セッション維持の有無についても簡単に指定できます。

前準備

外部に公開されたサーバを用意してください。最近は気軽にVPSサーバを借りられるようになりましたので、それらを利用するのもおすすめです。

サーバにはDockerとdocker-composeをインストールしておいてください。

ここでは「test-loadbalancer.com」というドメインがサーバに割り当てられているものとして、説明を進めていきますので、適宜置き換えて解釈してください。

ロードバランサーを作る

まずは、コンテナ同志の通信に使用するネットワークを作ります。

docker network create web

次にロードバランサーとして使用するTraefikを設定するディレクトリを用意します。

mkdir -p /opt/traefik

このディレクトリ内に、以下の3つのファイルを作ります。

touch /opt/traefik/docker-compose.yml
touch /opt/traefik/acme.json && chmod 600 /opt/traefik/acme.json
touch /opt/traefik/traefik.toml

docker-compose.yml を以下のように記述します。

version: '2'

services:
  traefik:
    image: traefik
    restart: always
    ports:
      - 80:80
      - 443:443
    networks:
      - web
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /opt/traefik/traefik.toml:/traefik.toml
      - /opt/traefik/acme.json:/acme.json
    container_name: traefik

networks:
  web:
    external: true

ports:
外部に公開するポートを指定します。ここではhttpとhttpsを指定しています。

network:
先程準備したdocker内のネットワーク名を指定します。

volumes:
コンテナの追加や削除を検知するための記述と、traefikの設定ファイル、Let’s Encrypt用の設定ファイルをマウントしています。

Traefik container を起動する前に、設定ファイルを用意します。

debug = false

logLevel = "ERROR"
defaultEntryPoints = ["https","http"]

[entryPoints]
  [entryPoints.http]
  address = ":80"
    [entryPoints.http.redirect]
    entryPoint = "https"
  [entryPoints.https]
  address = ":443"
  [entryPoints.https.tls]

[retry]

[docker]
endpoint = "unix:///var/run/docker.sock"
domain = "test-loadbalancer.com"
watch = true
exposedByDefault = false

[acme]
email = "your-email@test-loadbalancer.com"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
[acme.httpChallenge]
entryPoint = "http"

httpのアクセスはhttpsにリダイレクトするように設定しています。
尚、[acme]セクションのemailについては、あなたの本物のメールアドレスを指定する必要があります。架空のメールアドレスだとLet’s Encryptの設定に失敗します。
SSL証明書は、acme.jsonに保管されます。

ここまで準備できたら、Traefikを起動できます。

cd /opt/traefik
docker-compose up -d

あとは、同じネットワーク内にアプリケーションコンテナを立ち上げればOKです。

ここでは、「tutum/hello-world」イメージを使ってサンプルを作ります。

適当なディレクトリに以下の内容で docker-compose.yml を用意してください。

version: '2.1'

services:
  app:
    image: tutum/hello-world
    networks:
      - web
      - default
    expose:
      - "80"
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=web"
      - "traefik.frontend.rule=Host:test-loadbalancer.com"
      - "traefik.port=80"
      - "traefik.protocol=http"
networks:
  web:
    external: true

ポイントは、「labels」セクションです。traefikに対して、このコンテナへの接続する仕様を伝えます。

“traefik.enable=true”
このコンテナがtraefikを使用することを宣言します。

“traefik.docker.network=web”
このコンテナはwebネットワークを使用してtraefikと通信します。

“traefik.frontend.rule=Host:test-loadbalancer.com”
このコンテナでは、ここで指定したドメイン宛のリクエストを受け付けます。

“traefik.port=80”
80番ポートでリクエストを受け付けます。

“traefik.protocol=http”
通信のプロトコルは、httpであることを宣言します。

traefikでSSLの処理をすべて行ってくれるので、アプリケーションコンテナではSSLの処理が不要になります。

準備ができたら、アプリケーションコンテナを起動します。

docker-compose up -d

これで、サンプルサイトの公開が完了しました。
ブラウザから確認してみましょう!

こんなサイトが表示されていれば成功です。SSL証明書の設定も自動的に行われています。

では、再度コンソールに戻って、以下のコマンドでアプリケーションを3つに増やしてみましょう。

docker-compose scale app=3

ブラウザをリロードしてみてください。リロードの度に「My hostname is」の後の文字が変わるのが分かりますでしょうか?

ロードバランサーによって、3つのアプリケーションにラウンドロビンで順に振り分けが行われるようになりました。

なんということでしょう、アプリケーションのコンテナさえ用意しておけば、コマンドひとつでスケール出来てしまいます。

ただし、セッションを使うウェブアプリなどの場合は、これでは困ります。アクセスの度にセッションが切れてしまいます。traefik導入の前には、Nginxのリバースプロクシを使ったロードバランサーを検討していたのですが、ip_hushを使った振り分けになるため、wifi環境などでは不具合が出るのではという懸念がありました。traefikでは、cookieを使った振り分けに対応しているため、こうした心配は無用です。

では、先程のアプリケーションを、cookieを使用した振り分けに変更して行きましょう。
再度、アプリケーションコンテナの設定ファイルを開いて、labelsセクションに1行追加してください。

    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=web"
      - "traefik.frontend.rule=Host:test-loadbalancer.com"
      - "traefik.port=80"
      - "traefik.protocol=http"
      - "traefik.backend.loadbalancer.stickiness=true"

先程の設定ファイルに以下の一行を追加しただけです。
“traefik.backend.loadbalancer.stickiness=true”

保存したら、コンテナを再起動します。

docker-compose restart

ブラウザでサイトを表示してリロードしてみましょう。
いかがでしょうか?
リロードしてもHOSTNAMEが変わらず、同じコンテナにアクセスする状態になったと思います。

あっという間に、ロードバランサーが出来上がってしまいました。

今はひとつのホスト内で運用するテストを行いましたが、次はマルチホストでの運用に挑戦してみたいと思います。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする