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

Docker 1.12 ハンズオン資料 (JAWS-UGコンテナ支部)

More than 3 years have passed since last update.

Docker 1.12 ハンズオン資料 (JAWS-UGコンテナ支部)

by zembutsu
1 / 66

誰?


Topics

  • ハンズオン概要
  • swarm モードの基本的概念
  • 手順

概要と目的

Docker 1.12 から組み込まれた swarm モードを試します。

  • 3台のノードでクラスタを構築します
  • クラスタ上で、Nginx サービス(コンテナ)を起動
  • スケールアップ・ダウンや、ルーティング・メッシュ、ローリング・アップデート、自動復旧までの流れをコマンドを実行しながら理解

swarm mode


swarm-mode-1.png


swarm-mode-2.png


swarm-mode-3.png


swarm-mode-4.png


swarm-mode-5.png


ハンズオン


注意事項

Docker Engine 1.12 (GA) 現在の情報に基づいています。バージョンが変わった場合、コマンド体系や挙動が変わる場合がありますので、ご注意願います。


1. 環境構築編


1.1 概要

1.1.1 準備する環境と役割

3台のノード(インスタンス/仮想サーバ)を準備します。それぞれ異なる役割があります。

manager (マネージャ)はクラスタのサービスの受け入れと、タスクの割り振りを行います。 worker (ワーカ)はマネージャからの命令を受け取り、タスク(としてのコンテナ)を実行します。


名前 役割
node1 manager, worker
node2 worker
node3 worker

便宜上、それぞれ node1 node2 node3 と呼びます。

今回は manager が 1 台です。また、 3 台ともコンテナを実行する worker の役割です。設定により、3 台とも manager と worker を兼ねられますし、どれかをmanager 専用にすることも可能です。


1.1.2 ハンズオン環境


セキュリティグループで、次の接続を許可する必要があります。

  • SSH 22(TCP) SSH ログイン用
  • HTTP80(TCP) 動作確認用
  • 2377(TCP) クラスタ管理の通信用
  • 7496(TCP,UDP) ノード間の通信用
  • 4789(TCP,UDP) オーバレイ・ネットワークの通信

1.2. 環境の準備


1.2.1. インスタンスの準備


  • ステップ6:セキュリティグループの設定
    • セキュリティグループの割り当て: 新しいセキュリティグループを作成する docker-swarm
    • SSH TCP 22 マイIP
    • HTTP TCP 80 任意の場所
    • カスタム TCP ルール 2377
    • カスタム TCP/UDP ルール 4789
    • カスタム TCP/UDP ルール 7946
  • 作成

1.2.3. ログイン

各サーバに ubuntu ユーザでログインします。

ssh ubuntu@<ip>

or

ssh -l ubuntu <ip>

1.3. Docker 1.12 のインストール

以下のコマンドを実行すると、ディストリビューションに対応したリポジトリとパッケージをセットアップします。

curl -sSL https://get.docker.com/ | sh
sudo usermod -aG docker ubuntu

sudo docker を実行しなくても、 docker コマンドを有効にする設定をしました。ログアウト再ログインすると有効になります。


1.4 動作確認

docker psdocker version コマンドを実行し、どちらもエラーが出ないことを確認します。

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

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

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

正常であれば、サーバの情報も表示します。


2. クラスタ構築編

Docker の swarm (クラスタ)を構築し、nginx サービスを起動します。ここでは zembutsu/docker-sample-nginx イメージを使います(Dockerfile, source repo)。

  • nginx:latest イメージがベース
  • コンテナ ID を表示する index.html
  • SSI を有効化する Nginx 設定ファイル(default.conf)

準備

これまでクラスタ構築用の環境を準備してきました。コンソール画面(ターミナル)を4つ開き、各サーバにログインします。node1(manager) は2つログインしておきます。


2.1. swarm クラスタの構築

node1(manager) で、次のコマンドを実行します。ハンズオン中は起動したままにします。

watch -n 1 'echo "$ docker node ls"; docker node ls; echo; echo "$ docker service ls"; docker service ls; echo ; echo "$ docker service ps mynginx"; docker service ps mynginx'

これは watch コマンドで、以下のコマンドを毎秒実行します。

  • docker node ls … swarm クラスタ上のノード一覧と、状態を表示
  • docker service ls … クラスタ上のサービス一覧を表示
  • docker service ps mynginxmynginx サービスのタスク(コンテナ)一覧を表示

実行時はまだ swarm を構成していないため、次のようにエラーメッセージが画面に表示されます。

$ docker node ls
Error response from daemon: This node is not a swarm manager. Use "docker swarm init" or "docker swa
rm join" to connect this node to swarm and try again.

$ docker service ls
Error response from daemon: This node is not a swarm manager. Use "docker swarm init" or "docker swa
rm join" to connect this node to swarm and try again.

$ docker service ps mynginx
Error response from daemon: This node is not a swarm manager. Use "docker swarm init" or "docker swa
rm join" to connect this node to swarm and try again.

2.1.1. クラスタの初期化

node1(manager) でコマンド docker swarm init --listen-addr <プライベートIP>:2377 を実行します。しばらく待つと、次のような画面が表示されますので、 To add a worker to ....docker swarm join コマンドをエディタ等にコピーします。

実行例
 docker swarm init --listen-addr 10.0.0.11:2377
Swarm initialized: current node (931rg7ls3uqvj4kzzp7tdjmp9) is now a manager.

To add a worker to this swarm, run the following command:
    docker swarm join \
    --token SWMTKN-1-5rhptp943t9khjc4mvuez2pq7n3q39fny5r7ambgxgnzr36v4o-7pl78zmpe7uue8fnyt3sqdywo \
    10.0.0.11:2377

To add a manager to this swarm, run the following command:
    docker swarm join \
    --token SWMTKN-1-5rhptp943t9khjc4mvuez2pq7n3q39fny5r7ambgxgnzr36v4o-3hcqutifxpnv5wr15p0ychv5g \
    10.0.0.11:2377

正常に認識されると、ノード一覧は次のような画面になります。1台のノードが MANAGER として Active (有効)になっているのが分かります。

watch
$ docker node ls
ID                           HOSTNAME      STATUS  AVAILABILITY  MANAGER STATUS
931rg7ls3uqvj4kzzp7tdjmp9 *  ip-10-0-0-11  Ready   Active        Leader

$ docker service ls
ID  NAME  REPLICAS  IMAGE  COMMAND

$ docker service ps mynginx
Error: No such service: mynginx

docker info コマンドでもクラスタの情報を確認できます。

$ docker info
(省略)
Swarm: active
 NodeID: 931rg7ls3uqvj4kzzp7tdjmp9
 IsManager: Yes
 Managers: 1
 Nodes: 1

ここでは node1 自身がマネージャ( IsManager: Yes )であり、現時点ではマネージャが1つ、ノードが1つと分かります。特に指定しなければ、

次に、 node2 node3 をクラスタに追加します。


2.1.2. ノードの追加①

node2(worker) をクラスタに追加します。 node2 上で直前に控えた swarm join コマンドを実行します。※皆さんの環境によってトークンが異なるため、このまま貼り付けても実行できません。

実行例
docker swarm join \
    --token SWMTKN-1-5rhptp943t9khjc4mvuez2pq7n3q39fny5r7ambgxgnzr36v4o-7pl78zmpe7uue8fnyt3sqdywo \
    10.0.0.11:2377

正常に認識されると、ノード一覧は次のような画面になります。

watch
$ docker node ls
ID                           HOSTNAME      STATUS  AVAILABILITY  MANAGER STATUS
931rg7ls3uqvj4kzzp7tdjmp9 *  ip-10-0-0-11  Ready   Active        Leader
cjofpj3ga0n32elf99gxs16ha    ip-10-0-0-13  Ready   Active

$ docker service ls
ID  NAME  REPLICAS  IMAGE  COMMAND

$ docker service ps mynginx
Error: No such service: mynginx

2.1.3. ノードの追加②

node3(worker) をクラスタに追加します。 node3 で控えておいた swarm join コマンドを実行します。

実行例
docker swarm join \
    --token SWMTKN-1-5rhptp943t9khjc4mvuez2pq7n3q39fny5r7ambgxgnzr36v4o-7pl78zmpe7uue8fnyt3sqdywo \
    10.0.0.11:2377

正常に認識されると、ノード一覧に3つのノードが表示されます。


これで今回の環境が整いました。

watch
$ docker node ls
ID                           HOSTNAME      STATUS  AVAILABILITY  MANAGER STATUS
39h0ngc66hwydtviaietjmapc    ip-10-0-0-12  Ready   Active
931rg7ls3uqvj4kzzp7tdjmp9 *  ip-10-0-0-11  Ready   Active        Leader
cjofpj3ga0n32elf99gxs16ha    ip-10-0-0-13  Ready   Active

$ docker service ls
ID  NAME  REPLICAS  IMAGE  COMMAND

$ docker service ps mynginx
Error: No such service: mynginx

2.2. サービスの作成と変更

2.2.1. サービスの作成

swarm モード上でコンテナを実行するには docker service create コマンドを使います。このコマンドを実行できるのはマネージャ・ノードの node1 上のみです。

$ docker service create --replicas <タスク数> \
    --name <サービス名> \
    -p <公開ポート>:<コンテナのポート> \
    <イメージ名>:<タグ>

ここでは Nginx コンテナでコンテナ ID を表示する zembutsu/docker-sample-nginx:1.0 イメージを使います。

Nginx イメージを起動するため node1(manager) で次の docker service create コマンドを実行します。

node1(manager)
docker service create --replicas 1 --name mynginx -p 80:80 zembutsu/docker-sample-nginx:1.0

  • サービスを作成する docker service create はマネージャ上でのみ実行可能
  • --replicas 1 は、起動するタスクの期待状態(desired state)を 1 に指定
  • --name mynginx はサービス名の定義
  • -p 80:80 はパブリック・ネットワークのポート 80 をコンテナの 80 にマッピング
  • zembutsu/docker-sample-nginx:1.0 は起動するイメージとタグ

次のようにサービスが追加され、タスクとしてのコンテナが実行されるのが分かります。

watch
ID            NAME     REPLICAS  IMAGE                             COMMAND
d4832nzhk6ht  mynginx  1/1       zembutsu/docker-sample-nginx:1.0

$ docker service ps mynginx
ID                         NAME       IMAGE                             NODE          DESIRED STATE
 CURRENT STATE          ERROR
eo0nxwwje5nx5jynfv9vssv1f  mynginx.1  zembutsu/docker-sample-nginx:1.0  ip-10-0-0-11  Running
 Running 2 minutes ago

タスクはコンテナの実行単位であり、注目すべきは CURRENT STATE (現在の状態)と DESIRED STATE (期待状態)です。コマンド時刻時、 --replicas 1 を指定したのは、このサービスは指定したイメージを常時1つ実行するという意味があります。しかし、実際にはイメージのダウンロードや起動に時間がかかるため、今どのような状況にあるかが CURRENT STATE に表示されます( Preparing -> Starting --> Running と遷移)。


また、 docker servie lsREPLICAS も同様です。タスク数が 0/1 (現在の数/期待数)から 1/1 に変わります。


2.2.2. コンテナの確認

この例ではホスト ip-10-0-0-11node1) でタスク(コンテナ)を実行しています。node1docker ps を実行すると、コンテナが実行中なのが分かります。

ubuntu@ip-10-0-0-11:~$ docker ps
CONTAINER ID        IMAGE                              COMMAND                  CREATED             STATUS              PORTS               NAMES
e9c2ab0f4782        zembutsu/docker-sample-nginx:1.0   "nginx -g 'daemon off"   8 minutes ago       Up 8 minutes        80/tcp, 443/tcp     mynginx.1.eo0nxwwje5nx5jynfv9vssv1f

2.2.3. ルーティング・メッシュの確認

この状態で、ブラウザあるいはから node1 (manager) の *パブリック IP * にアクセスします。正常に応答があれば、次のようにコンテナ ID の情報が確認できます。

ubuntu@ip-10-0-0-11:~$ curl http://54.199.232.181
<html>
<body>
        <h1>Host: e9c2ab0f4782</h1>
</body>
</html>

同様に

  • node2 (worker) のパブリック IP
  • node3 (worker) のパブリック IP

でもアクセスを試み、同じコンテナ ID の情報が表示されることを確認します。
sawrm クラスタ上のどのパブリック IP にアクセスしても、ルーティング・メッシュにより、自動的にタスク(コンテナ)を実行しているノード(この例では node1 )に通信が経路付けされます。


2.2.4. サービスの変更

サービスの状態を変更するには docker service update コマンドを使います。

実行中の nginx コンテナの数を 3 に増やし、サービスを分散します。 サービスの状態を更新するには docker service update --replicas 3 mynginx を実行します。

$ docker service update --replicas 3 mynginx
mynginx

コマンドを実行してしばらくすると、タスクが3つに増えるのが確認できます。

$ docker service ls
ID            NAME     REPLICAS  IMAGE                             COMMAND
d4832nzhk6ht  mynginx  3/3       zembutsu/docker-sample-nginx:1.0

$ docker service ps mynginx
ID                         NAME       IMAGE                             NODE          DESIRED STATE
 CURRENT STATE           ERROR
eo0nxwwje5nx5jynfv9vssv1f  mynginx.1  zembutsu/docker-sample-nginx:1.0  ip-10-0-0-11  Running
 Running 16 minutes ago
2v1scy4uojwnn3qd6tmtdkpp1  mynginx.2  zembutsu/docker-sample-nginx:1.0  ip-10-0-0-12  Running
 Running 22 seconds ago
8kxqhzytt54pn2c3uktt6jmrx  mynginx.3  zembutsu/docker-sample-nginx:1.0  ip-10-0-0-13  Running
 Running 2 seconds ago

この例では Preparing (準備中)に時間がかかりますが、各ノード上に Docker イメージをダウンロードしているからです。イメージのダウンロード後は迅速にコンテナを開始できるようになるため、開始までのタイムラグを短縮したい場合は、あらかじめ各ノード上にイメージをダウンロード( docker pull )しておくのがおすすめです。

また、swarm モードはデフォルトで spread(スプレッド;拡散の意味)ストラテジが適用されるため、各コンテナは全てのノードで均等に起動しようと(実行中コンテナの数が釣り合うように)します。


2.2.5. 負荷分散(ingress loadbalancing)の再確認

この状態で、再びサーバ側のホストに curl またはブラウザでアクセスすると、コンテナIDが毎回切り替わります。各ノード上のコンテナは ingress という名前のオーバレイ・ネットワークでつながっています。そして、サービスに対するアクセスは、各タスク(コンテナ)に対して自動的に負荷分散します。

curl やブラウザの接続先を node1 だけでなく、 node2node-03 で実行しても、負荷分散されるのを確認します。


$ curl http://54.238.132.234
<html>
<body>
        <h1>Host: 76998bac246c</h1>
</body>
</html>
$ curl http://54.238.132.234
<html>
<body>
        <h1>Host: bba7788e2a0e</h1>
</body>
</html>
$ curl http://54.238.132.234
<html>
<body>
        <h1>Host: e9c2ab0f4782</h1>
</body>
</html>

2.3. ローリング・アップデート

docker service update はタスク数の変更だけでなく、実行中のイメージの差し替えも可能です。具体的には起動中のコンテナを停止し、新しいイメージのダウンロードと起動を自動的に行います。

先ほどの mynginx サービスが使うイメージのタグを 1.0 から latest に切り替えます。


$ docker service update \
    --update-delay 5s \
    --update-parallelism 1 \
    --image zembutsu/docker-sample-nginx:latest \
    mynginx
  • --update-delay ノードごとの更新タイミングの遅延指定
  • --update-arallelism 並列に処理するノード数

暫く待つと、順番にタグ 1.0 のコンテナが停止し、自動的にタグ latest のイメージに切り替わります。

$ docker service ls
ID            NAME     REPLICAS  IMAGE                                COMMAND
d4832nzhk6ht  mynginx  3/3       zembutsu/docker-sample-nginx:latest

$ docker service ps mynginx
ID                         NAME           IMAGE                                NODE          DESIRED
 STATE  CURRENT STATE            ERROR
6x7my3c1q7w3msgq7u67bv6kx  mynginx.1      zembutsu/docker-sample-nginx:latest  ip-10-0-0-12  Running
        Running 27 seconds ago
eo0nxwwje5nx5jynfv9vssv1f   \_ mynginx.1  zembutsu/docker-sample-nginx:1.0     ip-10-0-0-11  Shutdow
n       Shutdown 29 seconds ago
29sccuc76n5lxos9wek8vqcpj  mynginx.2      zembutsu/docker-sample-nginx:latest  ip-10-0-0-13  Running
        Running 44 seconds ago
2v1scy4uojwnn3qd6tmtdkpp1   \_ mynginx.2  zembutsu/docker-sample-nginx:1.0     ip-10-0-0-12  Shutdow
n       Shutdown 47 seconds ago
0avnz6ghafe34uae2zwwoesgo  mynginx.3      zembutsu/docker-sample-nginx:latest  ip-10-0-0-12  Running
        Running 36 seconds ago
8kxqhzytt54pn2c3uktt6jmrx   \_ mynginx.3  zembutsu/docker-sample-nginx:1.0     ip-10-0-0-13  Shutdow
n       Shutdown 38 seconds ago

curl やブラウザで確認すると、表示結果には新しく Version: 1.1 の文字列が入っているのが分かります。


2.4. 障害自動復旧

swarm モードのサービスは、常に期待状態(desire state)を維持し続けます。そのため、あるノードで障害が起これば、自動的に別ノードで追加タスクを実行しなおす仕組みが働きます。

ここでは node3 上の Docker Engine を停止します。

ubuntu@ip-10-0-0-13:~$ sudo systemctl stop docker

しばらく待つと、自動的に node3 の状態が停止 Down となります。

$ docker node ls
ID                           HOSTNAME      STATUS  AVAILABILITY  MANAGER STATUS
39h0ngc66hwydtviaietjmapc    ip-10-0-0-12  Ready   Active
931rg7ls3uqvj4kzzp7tdjmp9 *  ip-10-0-0-11  Ready   Active        Leader
cjofpj3ga0n32elf99gxs16ha    ip-10-0-0-13  Down    Active

REPLICAS が一時的に 2/3 になりますが、自動的に別ノードでタスク(コンテナ)が実行されるため、最終的には 3/3 に戻ります。

$ docker service ls
ID            NAME     REPLICAS  IMAGE                                COMMAND
d4832nzhk6ht  mynginx  3/3       zembutsu/docker-sample-nginx:latest

$ docker service ps mynginx
ID                         NAME           IMAGE                                NODE          DESIRED
 STATE  CURRENT STATE               ERROR
6x7my3c1q7w3msgq7u67bv6kx  mynginx.1      zembutsu/docker-sample-nginx:latest  ip-10-0-0-12  Running
        Running 3 minutes ago
eo0nxwwje5nx5jynfv9vssv1f   \_ mynginx.1  zembutsu/docker-sample-nginx:1.0     ip-10-0-0-11  Shutdow
n       Shutdown 3 minutes ago
9rs1pjqmeru0s84f0nsdy1ha1  mynginx.2      zembutsu/docker-sample-nginx:latest  ip-10-0-0-11  Running
        Running about a minute ago
29sccuc76n5lxos9wek8vqcpj   \_ mynginx.2  zembutsu/docker-sample-nginx:latest  ip-10-0-0-13  Shutdow
n       Running 3 minutes ago
2v1scy4uojwnn3qd6tmtdkpp1   \_ mynginx.2  zembutsu/docker-sample-nginx:1.0     ip-10-0-0-12  Shutdow
n       Shutdown 3 minutes ago
0avnz6ghafe34uae2zwwoesgo  mynginx.3      zembutsu/docker-sample-nginx:latest  ip-10-0-0-12  Running
        Running 3 minutes ago
8kxqhzytt54pn2c3uktt6jmrx   \_ mynginx.3  zembutsu/docker-sample-nginx:1.0     ip-10-0-0-13  Shutdow
n       Shutdown 3 minutes ago

ノードに復旧させるには sudo systemctl start docker を実行します。


2.5. サービスの削除

サービスを削除するには docker service rm <サービス名> を実行します。ここでは mynginx サービスを削除します。

ubuntu@ip-10-0-0-11:~$ docker service rm mynginx
mynginx

サービス一覧からも、消えているのが分かります。

$ docker service ls
ID  NAME  REPLICAS  IMAGE  COMMAND

$ docker service ps mynginx
Error: No such service: mynginx

3. クラスタの離脱と削除

3.1. クラスタから離脱

クラスタからノードを自動削除するには、ノード上で docker swarm leave コマンドを実行します。 ワーカの node2node3 上でコマンドを実行します。

$ docker swarm leave
Node left the swarm.

これで node2node3 上の Docker エンジンは swarm モードではなくなりました


マネージャの node1 には次のノード情報が残っています。

$ docker node ls
ID                           HOSTNAME      STATUS  AVAILABILITY  MANAGER STATUS
39h0ngc66hwydtviaietjmapc    ip-10-0-0-12  Down    Active
931rg7ls3uqvj4kzzp7tdjmp9 *  ip-10-0-0-11  Ready   Active        Leader
cjofpj3ga0n32elf99gxs16ha    ip-10-0-0-13  Down    Active

この状態では管理情報が manager 上に残っています。最終的に情報を削除するには、 manager 上で docker node rm <ノードID> コマンドを実行します。

ubuntu@ip-10-0-0-11:~$ docker node rm 39h0ngc66hwydtviaietjmapc
39h0ngc66hwydtviaietjmapc
ubuntu@ip-10-0-0-11:~$ docker node rm cjofpj3ga0n32elf99gxs16ha
cjofpj3ga0n32elf99gxs16ha

3.2. クラスタの削除

最後に残った node1 のマネージャ情報を削除するには docker swarm leave --force コマンドを実行します。

$ docker swarm leave --force
Node left the swarm.

これですべてのクラスタが解放されました。

$ docker node ls
Error response from daemon: This node is not a swarm manager. Use "docker swarm init" or "docker swa
rm join" to connect this node to swarm and try again.

4. 最後に

  • インスタンス環境の削除をお願いいたします。

おつかれさまでした^^


さらに詳しく

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