Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

正式リリースされたDocker 1.12のクラスタ周りを触ってみた

More than 3 years have passed since last update.

はじめに

Docker 1.12が2016年7月28日に正式リリースされました。
今回リリースは非常に大規模なもので、特にdocker engineにクラスタ管理機能がビルトインされたことが大きな話題になっています。

今回の記事では、このクラスタ管理機能に絞って触った結果をまとめました。
さらに、experimentalな機能ですが、ビルトインSwarmクラスタ上にDocker Composeのように複数サービスをデプロイする方法についても触れたので、おまけ的に記事に載せてみました。

Docker 1.12で追加された機能

Docker1.12 で追加された細かい機能は、以下のリリース情報を参照してください。
https://github.com/docker/docker/releases/tag/v1.12.0

この記事で関係ある部分としては、見出しで「Swarm Mode」となっている部分です。

Standalone Docker Swarm と Docker Engine 内蔵 Swarmの違い

Docker1.12でビルトインされたswarmと、今まで使用されていたスタンドアロンSwarmの違いを(穴だらけですが)表で簡単にまとめてみました。
KVSを使用しなくてもよくなった点や、サービス単位でクラスタにデプロイが可能になった点が、違いとして大きいと思います。

スタンドアロン Swarm ビルトイン Swarm
クラスタの構築 Swarmコンテナの起動 docker swarmコマンドの実行
Key Value Storeの有無
コンテナをクラスタ上に起動するコマンド docker run docker service
クラスタ上で実行する単位 コンテナ単位 サービス単位
Docker Machineとの連携 無?
コンテナのリスケジューリング コンテナ起動時にオプションを付ける 特に指定しなくても実行される

Docker 1.12 で実際にクラスタを構成

導入環境

  • OS: Ubuntu 16.04 (64bit) * 3台
    • kernel: 4.4.0-28-generic
  • Docker Engine : 1.12.0
  • Docker Compose : 1.8.0

構築するクラスタ

  • 今回はクラスタを以下のように構成します。
    • manager + node: 2台
    • node: 1台

Dockerのインストール

まずは、Docker1.12のexperimental版を全てのマシンにインストールします。

# curl -fsSL https://experimental.docker.com/ | sh 

インストールが完了したら、Dockerのバージョンが1.12であることを確認します。

# docker version
Client:
 Version:      1.12.0
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   8eab29e
 Built:        Thu Jul 28 22:20:10 2016
 OS/Arch:      linux/amd64
 Experimental: true

Server:
 Version:      1.12.0
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   8eab29e
 Built:        Thu Jul 28 22:20:10 2016
 OS/Arch:      linux/amd64
 Experimental: true

Docker Swarmクラスタの構築

Docker 1.12のSwarmモードでの、クラスタの構築手順を説明します。
Docker 1.12から、Swarmクラスタは非常に簡単に作成できるようになりました。
具体的には、Swarmクラスタの初期化と、ノードのSwarmクラスタへの参加を行うだけでクラスタを作成できます。

Docker Swarm クラスタの初期化

まず、docker-masterでSwarmクラスタを初期化します。
初期化を行うコマンドはdocker swarm initです。
クラスタの初期化を行うと、クラスタへnodeとして参加するコマンドと、managerとして参加するコマンドが表示されます。

docker-master:~# docker swarm init --listen-addr 10.255.19.1:2377 --advertise-addr 10.255.19.1
Swarm initialized: current node (f16o8xd50nrlcjasiswk9zxjv) is now a manager.

To add a worker to this swarm, run the following command:
    docker swarm join \
    --token SWMTKN-1-0t9g8kk9u7976lk30737ykjswtmgb3wfqqbnkoy4nyp98immyg-a6i7vo6az2jhp7h5kaik5h901 \
    10.255.19.1:2377

To add a manager to this swarm, run the following command:
    docker swarm join \
    --token SWMTKN-1-0t9g8kk9u7976lk30737ykjswtmgb3wfqqbnkoy4nyp98immyg-8itaveatjiykl20fq9e8jrasy \
    10.255.19.1:2377
docker-master:~#
docker-master:~# docker node ls
ID                           HOSTNAME       STATUS  AVAILABILITY  MANAGER STATUS
csmk41357kk8y53loldgpsm7h *  docker-master  Ready   Active        Leader

Docker Swarm クラスタに参加

dicker swarm init時に表示されたコマンドをクラスタに参加させたいノード上で実行します。
docker-node01はnodeとしてクラスタに参加し、docker-node02はmanager兼nodeとしてクラスタに参加します。

docker-node01:~# docker swarm join \
 --token SWMTKN-1-5z5tkorsbo07neq446j07e1kpyjt3h1a43bjkaez5veyakv72x-aius9gmwk5lg8ydyiccj0sw5x \
 10.255.19.1:2377
This node joined a swarm as a worker.
docker-node02:~# docker swarm join \
 --token SWMTKN-1-5z5tkorsbo07neq446j07e1kpyjt3h1a43bjkaez5veyakv72x-4azspb12qwb8edyxbyfuhnk95 \
This node joined a swarm as a manager.

これでmanger + node:2台、node:1台の計3台構成のDockerクラスタの構築ができました。

docker node ls
ID                           HOSTNAME       STATUS  AVAILABILITY  MANAGER STATUS
c1h1zgz0f62ttimde2cm2fyb5    docker-node02  Ready   Active        Reachable
csmk41357kk8y53loldgpsm7h *  docker-master  Ready   Active        Leader
d2ia3um0iyink4fs2xszvy2c0    docker-node01  Ready   Active

クラスタ構成の編集

各ノードのmanager/nodeのroleを変更できるので試してみます。

nodeからmanagerに昇格

唯一のnode roleであるdocker-node01をmanagerroleに昇格してみます。

  • docker-node01をmanagerに昇格させるにはdocker node promoteコマンドをmanagerroleのマシンで実行します。
  • Leader以外のmanagerノードはReachableというステータスを持ちます。
docker-master:~# docker node promote docker-node01
Node docker-node01 promoted to a manager in the swarm.
docker-master:~# docker node ls
ID                           HOSTNAME       STATUS  AVAILABILITY  MANAGER STATUS
c1h1zgz0f62ttimde2cm2fyb5    docker-node02  Ready   Active        Reachable
csmk41357kk8y53loldgpsm7h *  docker-master  Ready   Active        Leader
d2ia3um0iyink4fs2xszvy2c0    docker-node01  Ready   Active        Reachable

managerからnodeに降格

では、今度はdocker-node02をmanagerからnodeに降格してみます。

  • docker-node02をmanagerからnodeに降格させるにはdocker node demoteコマンドををmanager roleのマシン上で実行します。
  • managerから降格したdocker-masterでは、クラスタの情報を取得することができなくなります。
docker-master:~# docker node demote docker-node02
Manager docker-node02 demoted in the swarm.
docker-master:~# docker node ls
ID                           HOSTNAME       STATUS  AVAILABILITY  MANAGER STATUS
c1h1zgz0f62ttimde2cm2fyb5    docker-node02  Ready   Active
csmk41357kk8y53loldgpsm7h *  docker-master  Ready   Active        Leader
d2ia3um0iyink4fs2xszvy2c0    docker-node01  Ready   Active        Reachable

クラスタ上にサービスを作成

構築したクラスタ上にnginx imageから、nginという名前のサービス(コンテナ)を作成します。

docker-master:~# docker service create --name ngin -p 8080:80 nginx
docker-master:~# docker service ls
ID            NAME  REPLICAS  IMAGE  COMMAND
b0h4m6jf9tf9  ngin  1/1       nginx
docker-master:~# docker service ps ngin
ID                         NAME    IMAGE  NODE           DESIRED STATE  CURRENT STATE           ERROR
eyybcfh9wtfrmlohyrod457jp  ngin.1  nginx  docker-master  Running        Running 31 seconds ago

作成したサービスはdocker service rmで削除可能です。

docker-master:~# docker service rm ngin
ngin

クラスタ上で使える便利な機能

Docker クラスタ上でオプション指定を行うことで便利な機能が使用できます。
今回の記事では、以下の3つの機能を紹介したいと思います。

  • コンテナのスケール
  • コンテナの自動リスケジュール
  • コンテナのローリングアップデート

コンテナのスケール

クラスタ内でコンテナのスケールを簡単に行うことができます。

  • サービスのレプリカ数を変える方法は2パターンあります。
    • 1. docker service update : サービスの状態を色々変更可能
    • 2. docker service scale : 複数サービスのレプリケーション数を一度に変更可能
docker-master:~# docker service ps ngin
ID                         NAME    IMAGE  NODE           DESIRED STATE  CURRENT STATE           ERROR
bblpwo69rn1m6wdwc7449rll7  ngin.1  nginx  docker-node02  Running        Running 35 seconds ago
docker-master:~#
docker-master:~# docker service update --replicas 3 ngin
docker-master:~# docker service ps ngin
ID                         NAME    IMAGE  NODE           DESIRED STATE  CURRENT STATE              ERROR
bblpwo69rn1m6wdwc7449rll7  ngin.1  nginx  docker-node02  Running        Running about an hour ago
7wwcvo8r19ceoksotjm23wf45  ngin.2  nginx  docker-master  Running        Running 11 seconds ago
e3f3ubpyppppzbxwcf53eszb4  ngin.3  nginx  docker-node01  Running        Running 12 seconds ago
docker-master:~#
docker-master:~# docker service scale ngin=6
ngin scaled to 6
docker-master:~# docker service ps ngin
ID                         NAME    IMAGE  NODE           DESIRED STATE  CURRENT STATE                 ERROR
bblpwo69rn1m6wdwc7449rll7  ngin.1  nginx  docker-node02  Running        Running about an hour ago
7wwcvo8r19ceoksotjm23wf45  ngin.2  nginx  docker-master  Running        Running 2 minutes ago
e3f3ubpyppppzbxwcf53eszb4  ngin.3  nginx  docker-node01  Running        Running 2 minutes ago
4ggj14auikb1plytdc6nqa8db  ngin.4  nginx  docker-master  Running        Preparing 2 seconds ago
2laq1kxpdb4rff8xr72m3lr07  ngin.5  nginx  docker-node02  Running        Ready less than a second ago
dji94wy1tdo2nkb9x0fqv6r32  ngin.6  nginx  docker-node01  Running        Preparing 2 seconds ago

コンテナの自動リスケジュール

障害がクラスタ内で発生した時、特に何も設定しなくても、コンテナは自動リスケジュールされます。

今回は、クラスタ内の1ノードがシャットダウンしてしまった場合と、NICがダウンした時を想定して、コンテナのリスケジュールの様子を見てみます。

ノードがシャットダウンしてしまった時

各ノードで2コンテナずつ動作している環境が動作しています。

#  docker service ps ngin
ID                         NAME    IMAGE  NODE           DESIRED STATE  CURRENT STATE            ERROR
37739ros8fhwut1o6bv6bm0pb  ngin.1  nginx  docker-node02  Running        Preparing 2 seconds ago
3egtwo22yl0gwowm55vkkdczy  ngin.2  nginx  docker-master  Running        Preparing 2 seconds ago
0whuiqad3o9g8r5vj545ym3gx  ngin.3  nginx  docker-node02  Running        Preparing 2 seconds ago
7kphzzw5y24hapvwrq8t49t7d  ngin.4  nginx  docker-master  Running        Preparing 2 seconds ago
c8o89xnnc14hd1lvulm38xi9s  ngin.5  nginx  docker-node01  Running        Preparing 2 seconds ago
15vuulew16u4qqdprtyvmybgg  ngin.6  nginx  docker-node01  Running        Preparing 2 seconds ago

  • docker-node02の電源を落とします
docker-node02~# shutdown -h now
  • すると、docker-node02にいたコンテナが生き残っているクラスタ内に再スケジュールされます。
docker-master:~#  docker node ls
ID                           HOSTNAME       STATUS  AVAILABILITY  MANAGER STATUS
c1h1zgz0f62ttimde2cm2fyb5    docker-node02  Down    Active
csmk41357kk8y53loldgpsm7h *  docker-master  Ready   Active        Leader
d2ia3um0iyink4fs2xszvy2c0    docker-node01  Ready   Active        Reachable
docker-master:~# docker service ps ngin
ID                         NAME        IMAGE  NODE           DESIRED STATE  CURRENT STATE                     ERROR
99dj47rlphkbyv7hh8r1jy1yn  ngin.1      nginx  docker-node01  Ready          Preparing less than a second ago
37739ros8fhwut1o6bv6bm0pb   \_ ngin.1  nginx  docker-node02  Shutdown       Running 33 seconds ago
3egtwo22yl0gwowm55vkkdczy  ngin.2      nginx  docker-master  Running        Running 34 seconds ago
e1ks7kcpscb5zaiqffsaljk1b  ngin.3      nginx  docker-master  Ready          Preparing less than a second ago
0whuiqad3o9g8r5vj545ym3gx   \_ ngin.3  nginx  docker-node02  Shutdown       Running 33 seconds ago
7kphzzw5y24hapvwrq8t49t7d  ngin.4      nginx  docker-master  Running        Running 34 seconds ago
c8o89xnnc14hd1lvulm38xi9s  ngin.5      nginx  docker-node01  Running        Running 34 seconds ago
15vuulew16u4qqdprtyvmybgg  ngin.6      nginx  docker-node01  Running        Running 34 seconds ago
  • docker-node02を再起動すると、自動的にDockerクラスタへ復帰します。
    • この時、別ノードに再スケジュールされたコンテナはdocker-node02には戻りません

NICダウン

NICダウンした時のコンテナ再スケジュールの様子を見ていきます。

各ノードで2コンテナずつ動作しているクラスタ内の、docker-node02のNICを落とします。

docker-node02~# ifdown ens160

すると、docker-node02にいたコンテナの数と同じ2コンテナ分が、クラスタ内に再スケジュールされます。

docker-master:~# docker node ls
ID                           HOSTNAME       STATUS  AVAILABILITY  MANAGER STATUS
c1h1zgz0f62ttimde2cm2fyb5    docker-node02  Down    Active
csmk41357kk8y53loldgpsm7h *  docker-master  Ready   Active        Leader
d2ia3um0iyink4fs2xszvy2c0    docker-node01  Ready   Active        Reachable
docker-master:~# docker service ps ngin
ID                         NAME        IMAGE  NODE           DESIRED STATE  CURRENT STATE                     ERROR
0cmw5u3ltdhef88ft5nydsy39  ngin.1      nginx  docker-master  Ready          Preparing less than a second ago
b2p4o6f086q4wxunjst2clzgj   \_ ngin.1  nginx  docker-node02  Shutdown       Running 45 seconds ago
9xm8mkwe9456nq2g1xun3lazq  ngin.2      nginx  docker-master  Running        Running 44 seconds ago
3y26d6xl0g4qtiwi7x7bmvz8i  ngin.3      nginx  docker-node01  Running        Running 45 seconds ago
12hveh2vcmmqcnkg3trgbidz0  ngin.4      nginx  docker-node01  Running        Running 44 seconds ago
bw0n128l5pg6h2phhl4r01cxm  ngin.5      nginx  docker-node01  Ready          Preparing less than a second ago
0gf5hlm0shhlc37y8hpcw52y8   \_ ngin.5  nginx  docker-node02  Shutdown       Running 45 seconds ago
b4wf19a1ya7wsob54khdfqpdb  ngin.6      nginx  docker-master  Running        Running 44 seconds ago
  • docker-node02はdocker自体は止まっていないので、NIC停止前に起動したコンテナはまだ動いています。

  • docker-node02のNICを起動します。

docker-node02~# ifup ens160
  • NIC回復後docker-node02はクラスタへ復帰します。しかし、docker-node02上で動いていたnginのコンテナはクラスタ復帰後削除されることを確認しました。

コンテナのローリングアップデート

コンテナのローリングアップデートを行うことができます。

  • nginxコンテナが各ノードに1コンテナずつ起動している状態から、nginxコンテナをdockercon2016で使用されていた、投票アプリに1分間隔で1コンテナずつ入れ替えていきます。
docker-master:~# docker service ps ngin
ID                         NAME    IMAGE  NODE           DESIRED STATE  CURRENT STATE          ERROR
b5sl2ste8zvnum4wou5ax6ggd  ngin.1  nginx  docker-master  Running        Running 3 seconds ago
3ct7khgjefjnl0yg26mutg4zk  ngin.2  nginx  docker-node02  Running        Running 3 seconds ago
3zpssl78bcbrmav5yrfjbrhly  ngin.3  nginx  docker-node01  Running        Running 3 seconds ago

docker-master:~$ curl 10.255.19.1: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>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

docker-master:~# docker service update --image instavote/vote:latest --update-delay 60s --update-parallelism 1 ngin


docker-master:~# docker service tasks ngin
ID                         NAME        IMAGE                  NODE           DESIRED STATE  CURRENT STATE                ERROR
5tx5smm7tjc217ddw8xoh3tfq  ngin.1      instavote/vote:latest  docker-node01  Running        Running 49 seconds ago
b5sl2ste8zvnum4wou5ax6ggd   \_ ngin.1  nginx                  docker-master  Shutdown       Shutdown 50 seconds ago
1mi5moqfzu8x4g3szy9gp8v3e  ngin.2      instavote/vote:latest  docker-master  Running        Running 2 minutes ago
3ct7khgjefjnl0yg26mutg4zk   \_ ngin.2  nginx                  docker-node02  Shutdown       Shutdown 2 minutes ago
8ta3maek8n621p0ailhqidxsa  ngin.3      instavote/vote:latest  docker-node02  Running        Running about a minute ago
3zpssl78bcbrmav5yrfjbrhly   \_ ngin.3  nginx                  docker-node01  Shutdown       Shutdown about a minute ago

docker-master:~# curl 10.255.19.1:80
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Cats vs Dogs!</title>
    <base href="/index.html">
    <meta name = "viewport" content = "width=device-width, initial-scale = 1.0">
    <meta name="keywords" content="docker-compose, docker, stack">
    <meta name="author" content="Tutum dev team">
    <style type="text/css">
    ~省略~
</style>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
  </head>
  <body>
    <div id="content-container">
      <div id="content-container-center">
        <h3>Cats vs Dogs!</h3>
        <form id="choice" name='form' method="POST" action="/">
          <button id="a" type="submit" name="vote" class="a" value="a">Cats</button>
          <button id="b" type="submit" name="vote" class="b" value="b">Dogs</button>
        </form>
        <div id="tip">
          (Tip: you can change your vote)
        </div>
        <div id="hostname">
          Processed by container ID 35b4fb6615b9
        </div>
      </div>
    </div>
    <script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.js"></script>


  </body>

Experimental: Distributed Application Bundles(DAB)

まだExperimentalな機能ながら、今回のビルトインSwarmクラスタと絡んでくる機能として、Docker Composeのように、複数サービスを管理する機能があります。
その中で新しく出てくるファイル形式として、Distributed Application Bundles(DAB)があります。
このDABファイルは、docker-compose の1.8で実装されたdocker-compose bundleを実行することで作成できます。
DABファイルを使用することで、複数サービスのまとまりをswarmクラスタ上にまとめてデプロイできるようになります。

メモ:以下のdocker-compose.ymlファイルを作成して、docker-compose upを実行するとcomposeはserviceコマンドに対応してないというメッセージが出る。

version: '2'

services:
  web:
    image: wordpress
    environment:
          - "WORDPRESS_DB_HOST=wordpress_db"
          - "WORDPRESS_DB_USER=root"
          - "WORDPRESS_DB_PASSWORD=password"
    ports:
      - 8000:80
    container_name: "wordpress_web"

  db:
    image: mariadb
    environment:
          - "MYSQL_ROOT_PASSWORD=password"
    container_name: "wordpress_db"
docker-master:~# docker-compose up -d
WARNING: The Docker Engine you're using is running in swarm mode.

Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All containers will be scheduled on the current node.

To deploy your application across the swarm, use the bundle feature of the Docker experimental build.

More info:
https://docs.docker.com/compose/bundles

Creating network "wordpress_default" with the default driver
Creating wordpress_web
Creating wordpress_db

では先ほどのdocker-compose.ymlファイルを使用してDABファイルを作成します。

docker-master:~# docker-compose bundle
WARNING: Unsupported key 'container_name' in services.web - ignoring
WARNING: Unsupported key 'container_name' in services.db - ignoring
Wrote bundle to wordpress.dab
docker-master:~# ls
docker-compose.yml  wordpress.dab
docker-master:~# cat wordpress.dab
{
  "Services": {
    "db": {
      "Env": [
        "MYSQL_ROOT_PASSWORD=password"
      ],
      "Image": "mariadb@sha256:c5984a0db84a3eaef09bb25af32052686ffa976e15e59789bceb7b5d1678433d",
      "Networks": [
        "default"
      ]
    },
    "web": {
      "Env": [
        "WORDPRESS_DB_HOST=wordpress_db",
        "WORDPRESS_DB_USER=root",
        "WORDPRESS_DB_PASSWORD=password"
      ],
      "Image": "wordpress@sha256:0f73fa5e20b0194c6cffc78143e9b9b966c952b57118be12526edb058726cd92",
      "Networks": [
        "default"
      ],
      "Ports": [
        {
          "Port": 80,
          "Protocol": "tcp"
        }
      ]
    }
  },
  "Version": "0.1"
}

作成されたwordpress.dabをdocker swarm クラスタ上にデプロイします。
デプロイにはdocker service deployコマンドを使用します。

docker-master:~# ls
docker-compose.yml  wordpress.dab
docker-master:~# docker stack deploy wordpress
Loading bundle from wordpress.dab
Creating network wordpress_default
Creating service wordpress_db
Creating service wordpress_web
docker-master:~# docker stack ps wordpress
ID                         NAME             IMAGE                                                                              NODE           DESIRED STATE  CURRENT STATE          ERROR
9qtvjbi2uq7zj9vkt4hw2r8xr  wordpress_web.1  wordpress@sha256:0f73fa5e20b0194c6cffc78143e9b9b966c952b57118be12526edb058726cd92  docker-node01  Running        Running 2 minutes ago
5ztyx62uudemewue9zju3zkiu  wordpress_db.1   mariadb@sha256:c5984a0db84a3eaef09bb25af32052686ffa976e15e59789bceb7b5d1678433d    docker-master  Running        Running 2 minutes ago
docker-master:~# docker service ls
ID            NAME           REPLICAS  IMAGE                                                                              COMMAND
9yyxr3ial9qk  wordpress_db   1/1       mariadb@sha256:c5984a0db84a3eaef09bb25af32052686ffa976e15e59789bceb7b5d1678433d
bv2cdvgym33o  ngin           3/3       instavote/vote:latest
e3oo6tztgllq  wordpress_web  1/1       wordpress@sha256:0f73fa5e20b0194c6cffc78143e9b9b966c952b57118be12526edb058726cd92

これでDocker 1.12で追加された、クラスタ周りの機能について一通り触れることができました。

おわりに

いかかでしたでしょうか?
Docker 1.12のリリースによって、今までのDocker Swarmクラスタよりも、より早く・簡単に多機能なクラスタを作成できるようになりました。
今まで、「クラスタ組むのめんどくさそうだな」と思っていたそこのあなたも楽しいDockerクラスタライフをぜひエンジョイしてみてください。

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