Help us understand the problem. What is going on with this article?

Dockerのoverlayネットワークでコンテナを分散実行

More than 3 years have passed since last update.

概要

Docker 1.9 からマルチホスト・ネットワーク機能が利用可能となった。動作検証として、DigitalOcean の環境上に、Docker Machine で Swarm クラスタを作り、オーバレイ・ネットワーク上を作成。最終的に、複数ホスト上にウェブとデータベースを分散した WordPress の環境を作成する。ここでは Docker Compose を使用し、オーバレイ・ネットワークの自動構築も試みる。

docker-overlay network.png

Docker 1.9 のネットワーク機能については、以下 URL を参照のこと。

前提条件と環境について

  • Docker 1.9~
  • Linux Kernel 3.16~
  • DigitalOcean

DockerのドキュメントはVirtualBox上だったが、実際に近い環境で試したかったので、DigitalOcean上に先の図のような環境構築を試みる。検証として、WordPressのwebdbコンテナを、複数のホスト上でありながら、同一のネットワーク上に配置する。

※偶然にも眼前の環境が DigitalOcean だっただけで、他の環境でも、同様に動くはず。

環境構築手順

3台のサーバ(KVS、Swarmマスタ、Swarmノード)を準備する。

KVS ( Consul ) 用マシンの作成

クラスタ全体の制御は Docker Swarm を通して行う。そのため、Docker Swarm クラスタが使用する KVS として Consul 用の環境を Docker Machine で作成する。

事前に DigitalOcean の API トークンを取得し、環境変数として定義する。

$ DO_TOKEN=3f0f0xxxxf65f

次に Docker Machine でマシン swarm-kvs を作成する。

$ docker-machine create \
    --driver digitalocean \
    --digitalocean-access-token $DO_TOKEN \
    --digitalocean-region sgp1 \
   swarm-kvs

正常に作成できると、docker-machine ls コマンドで次のように表示されている。

$ docker-machine ls
NAME        ACTIVE   DRIVER         STATE     URL                         SWARM
swarm-kvs   -        digitalocean   Running   tcp://188.166.225.62:2376

それから、作成したマシン内に consul をサーバ・モードで実行する。

$ docker $(docker-machine config swarm-kvs) run -d \
    -p "8500:8500" \
    -h "consul" \
    progrium/consul -server -bootstrap

Swarm マスタ用マシンの作成

Docker Machine を使い、swarm-node0マシンの作成と、Swarm マスタ用(クラスタ管理)の自動構築も行う。

docker-machine create \
    --driver digitalocean \
    --digitalocean-access-token $DO_TOKEN \
    --digitalocean-region sgp1 \
    --swarm \
    --swarm-image="swarm:1.0.0" \
    --swarm-master \
    --swarm-discovery="consul://$(docker-machine ip swarm-kvs):8500" \
    --engine-opt="cluster-store=consul://$(docker-machine ip swarm-kvs):8500" \
    --engine-opt="cluster-advertise=eth0:2376" \
    swarm-node0

正常に実行されると、docker-machine lsでは次のように2台のマシンが表示される。

$ docker-machine ls
NAME          ACTIVE   DRIVER         STATE     URL                         SWARM
swarm-kvs     -        digitalocean   Running   tcp://188.166.225.62:2376
swarm-node0   -        digitalocean   Running   tcp://188.166.225.83:2376   swarm-node0 (master)

次に、DigitalOcean の Ubuntu 14.04 LTS3 は Kernel バージョンが古く、オーバレイ・ネットワーク機能が利用出来ない。そのため、サーバにログインし、手動で Kernel のバージョンアップを行う。

  1. DigitalOcean の GUI にアクセス
  2. Dropets から対象のドロップレット(サーバ) をクリック
  3. Settings -> Kernel -> Ubuntu 14.10 x64 vmlinuz-3.16.0-41-generic を選択し、Change をクリック
  4. docker-machine ssh swarm-node0 でこの環境に SSH ログイン
  5. /sbin/poweroff コマンドでインスタンスを停止(rebootでは反映されない)
  6. GUI からドロップレットの情報を開き、Power On
  7. 再度 docker-machine ssh swarm-node0 でこの環境に SSH ログイン
  8. kernel が更新された事を確認
root@swarm-node0:~# uname -a
Linux swarm-node0 3.16.0-41-generic #57-Ubuntu SMP Thu Jun 18 08:44:16 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

 9. apt-get install -y -q linux-image-extra-3.16.0-41-generic を実行
 10. /sbin/reboot で再起動

動作確認は、docker クライアントの環境変数を切り替えて行う。環境変数を指定すると、docker コマンドはローカルではなく、ここで指定したリモート環境に対する操作を行う。単なる Docker デーモンのポートだけでなく、Swarm のポートを指定すると、クラスタ全体を操作できる。

$ eval $(docker-machine env --swarm swarm-node0)

docker psdocker info の情報が、Docker デーモンの情報ではなく、クラスタに関する情報に切り替わっていることを確認する。

Swarm ノード用マシンの作成

swarm-node1という名称のマシンを作成する。

docker-machine create \
    --driver digitalocean \
    --digitalocean-access-token $DO_TOKEN \
    --digitalocean-region sgp1 \
    --swarm \
    --swarm-image="swarm:1.0.0" \
    --swarm-discovery="consul://$(docker-machine ip swarm-kvs):8500" \
    --engine-opt="cluster-store=consul://$(docker-machine ip swarm-kvs):8500" \
    --engine-opt="cluster-advertise=eth0:2376" \
    swarm-node1

作成後は先ほど同様、kernel のバージョンアップ作業を行う。

この時点で3台の環境が準備できた。

$ docker-machine ls
NAME          ACTIVE   DRIVER         STATE     URL                          SWARM
swarm-kvs     -        digitalocean   Running   tcp://188.166.225.62:2376
swarm-node0   *        digitalocean   Running   tcp://188.166.225.83:2376    swarm-node0 (master)
swarm-node1   -        digitalocean   Running   tcp://128.199.242.128:2376   swarm-node0

動作確認は docker info コマンド実行時、リソース情報で2台分(Swarm マスタとノード)表示されていることを確認。

$ eval $(docker-machine env --swarm swarm-node0)
$ docker info
Containers: 3
Images: 2
Role: primary
Strategy: spread
Filters: health, port, dependency, affinity, constraint
Nodes: 2
 swarm-node0: 188.166.225.83:2376
  m Containers: 2
  m Reserved CPUs: 0 / 1
  m Reserved Memory: 0 B / 514 MiB
  m Labels: executiondriver=native-0.2, kernelversion=3.16.0-41-generic, operatingsystem=Ubuntu 14.04.3 LTS, provider=digitalocean, storagedriver=aufs
 swarm-node1: 128.199.242.128:2376
  m Containers: 1
  m Reserved CPUs: 0 / 1
  m Reserved Memory: 0 B / 514.5 MiB
  m Labels: executiondriver=native-0.2, kernelversion=3.13.0-57-generic, operatingsystem=Ubuntu 14.04.3 LTS, provider=digitalocean, storagedriver=aufs
CPUs: 2
Total Memory: 1.004 GiB
Name: 6bbe5d40c009

オーバレイ・ネットワークの作成

以降の作業では、Swarm クラスタに対する操作を行う。常に、次の環境変数の定義されているものとする。

$ eval $(docker-machine env --swarm swarm-node0)

ネットワーク情報を見るには、docker network ls コマンドを実行する。次のように swarm-node1swam-node0 の各ホスト上に hostbridge という Docker 標準ネットワーク情報を確認できる。これは各ホスト毎に存在している。そして、別々のネットワーク ID を持つ。

$ docker network ls
NETWORK ID          NAME                 DRIVER
392db5e3bd70        swarm-node1/host     host
9d23b56deb9f        swarm-node0/bridge   bridge
5ab9066e5c50        swarm-node0/none     null
bb18b404a6c6        swarm-node0/host     host
dd8fc71c6bbc        swarm-node1/bridge   bridge
a747d9e4ef62        swarm-node1/none     null

オーバレイ・ネットワークは、ホスト毎にまたがるネットワークであり、ネットワーク ID も共通している。手動で internal という名称のネットワークを作成するには、次のように実行する。

$ docker network create internal
1b2b66f54a72b83d5151bad8af84ac7244a3cc74a18151fbaeaf4bf4ff92b8de

再び docker network ls を実行すると、所属するホスト名がない DRIVERoverlay のネットワークが作成できる。

$ docker network ls
NETWORK ID          NAME                 DRIVER
bb18b404a6c6        swarm-node0/host     host
1b2b66f54a72        internal             overlay
9d23b56deb9f        swarm-node0/bridge   bridge
dd8fc71c6bbc        swarm-node1/bridge   bridge
a747d9e4ef62        swarm-node1/none     null
392db5e3bd70        swarm-node1/host     host
5ab9066e5c50        swarm-node0/none     null

nginx コンテナを手動で作成して、挙動の確認

この時点で docker ps を実行しても、Swarm クラスタ上にはコンテナが作成していないため、次のように実行中のコンテナはなにも表示されない(実際には各ホスト上で swarm 用のコンテナが実行中だが、Swarm を通すと表示されない)

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

Swarm クラスタで、web という名称の nginx コンテナを起動する。constraintフィルタを指定し、起動するホストをswarm-node0と指定している(指定しない場合は、ノードのいずれかがランダムに選択される。あるいは Swarm のステラテジに依存する。フィルタやストラテジの詳細は Docker Swarm 入門を参照のこと)。

$ docker run -d --name=web --net=internal --env="constraint:node==swarm-node0" nginx
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
6473ca45464d        nginx               "nginx -g 'daemon off"   25 seconds ago      Up 23 seconds       80/tcp, 443/tcp     swarm-node0/web

この状態で、もう1つのホスト swarm-node1 を指定して busybox コンテナを起動し、疎通を確認する。

$  docker run -it --net=internal --env="constraint:node==swarm-node1" busybox

シェルが表示され、コンテナ内で操作が可能になる。/etc/hostsを見ると、自動的に先ほど作成されたホスト名と IP アドレスが自動的に追加されているのが分かる。

/ # cat /etc/hosts
10.0.0.3        5656bd4c2072
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
10.0.0.2        web
10.0.0.2        web.internal

※ネットワークは docker network connect xxx で接続、docker network disconnect xxx で、任意のコンテナに対し、任意のネットワークの追加・削除が動的に可能。設定を適用した瞬間、コンテナ内のインターフェースと /etc/hosts エントリに追加・削除される。

この状態で web という名称で名前確認が可能なため、次のように ping の疎通確認や wget によるコンテンツ取得がオーバレイ・ネットワークを通して可能となる。この2つのコンテナは別々のホスト上に存在しているが、オーバレイ・ネットワーク機能のおかげで、同一のネットワーク上に存在しているように見えるため。

/ # ping web
PING web (10.0.0.2): 56 data bytes
64 bytes from 10.0.0.2: seq=0 ttl=64 time=0.680 ms
64 bytes from 10.0.0.2: seq=1 ttl=64 time=0.600 ms
64 bytes from 10.0.0.2: seq=2 ttl=64 time=0.731 ms
^C
--- web ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.600/0.670/0.731 ms
/ # wget -O - http://web
Connecting to web (10.0.0.2:80)
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
(省略)

Docker Compose で WordPress を分散実行

従来の Docker Compose は1つのホスト上でのみ複数コンテナの操作が可能だった。Docker Compose 1.5 と Docker Swarm 1.0, Docker Engine 1.9 の組み合わせにより、複数のホスト上で複数のコンテナを起動し、かつ名前解決が可能となる。

ここでは cms という Compose プロジェクトを使い、オーバレイ・ネットワークの自動起動と、コンテナの自動起動・ネットワークの割り当てを行う。

webdb という名称のコンテナを定義する。web コンテナは swarm-node0 上で実行する設定とするが、db は Swarm のストラテジに従う(デフォルトは Spread 方式なので、リソースが空いている別のサーバ上でコンテナは起動する)。

mkdir cms
cd cms
cat << EOF > docker-compose.yml
web:
  image: wordpress
  environment:
        - "WORDPRESS_DB_HOST=cms_db_1"
        - "WORDPRESS_DB_USER=root"
        - "WORDPRESS_DB_PASSWORD=example"
        - "constraint:node==swarm-node0"
  ports:
    - 8080:80

db:
  image: mariadb
  environment:
    MYSQL_ROOT_PASSWORD: example
EOF

オーバレイ・ネットワーク機能を有効にしてコンテナを起動するには --x-networking --x-network-driver を実行する。

$ docker-compose --x-networking --x-network-driver overlay up -d
Creating network "cms" with driver "overlay"
Pulling web (wordpress:latest)...
swarm-node1: Pulling wordpress:latest... : downloaded
swarm-node0: Pulling wordpress:latest... : downloaded
Creating cms_web_1
Pulling db (mariadb:latest)...
swarm-node0: Pulling mariadb:latest... : downloaded
swarm-node1: Pulling mariadb:latest... : downloaded
Creating cms_db_1

実行状態の確認は docker-compose ps を実行する。

$ docker-compose ps
  Name                 Command               State              Ports
--------------------------------------------------------------------------------
cms_db_1    /docker-entrypoint.sh mysqld     Up      3306/tcp
cms_web_1   /entrypoint.sh apache2-for ...   Up      188.166.225.83:8080->80/tcp

この例では、ブラウザから http://188.166.225.83:8080 にアクセスすると、WordPress の初期画面が表示される。あとは docker-compose stop での停止や docker-compose rm の環境削除は、通常の Compose コマンドと変わりない。

注意点としては、docker-compose up時に各マシン上でイメージのダウンロードが開始される。そのため、一見すると止まって見える場合も有る。また、今回の例でタイムアウトして自動起動に失敗して見える場合 stop start を繰り返すと正常に起動する。

どこのノード上にどのコンテナを実行するかは、基本的に Swarm のストラテジフィルタに依存する。

Swarm 全般については以下、

Compose 全般については以下参照。

sakura_internet
さくらレンタルサーバ、さくらのVPS、 さくらのクラウド、さくらの専用サーバなどのインターネットサービス・ITプラットフォームを提供しています。
https://www.sakura.ad.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした