docker v1.12のオーケストレーション機能をマルチホストで試すよ on さくらのクラウド

2016/6/20の[DockerCon16](http://2016.dockercon.com)でDocker v1.12の新機能たちが発表されました。

今回は新機能の中から目玉の一つ「オーケストレーション」機能を試してみました。
元ネタ：[Swarm Modeチュートリアル](https://docs.docker.com/engine/swarm/swarm-tutorial/)

=====追記
**今回は実験用であるため、セキュリティ面/パフォーマンス面など考慮していません。
実際に試す際は十分に注意ください。**
=====追記ここまで

=====追記その2
2016年7月29日 Docker v1.12.0がGAとなりました。
それに伴い、DockerMachineのオプションに`--engine-install-url`を指定する必要がなくなりました。
その他端々変更されている箇所がありますので、最新情報は[公式マニュアル](https://docs.docker.com)を参照してください。
=====追記ここまで


## オーケストレーション機能とは

今回も神速で紹介ブログが和訳されていました(さすが！)。

引用：[【参考訳】Docker 1.12: ついにオーケストレーションを組み込み！](https://pocketstudio.net/2016/06/21/docker-1-12-build-in-orchestration-translate/)


![swarm-mode.png](https://pocketstudio.net/images/docker-engine-112-swarm-mode.png "Swarmモード.png")

従来と比べると、etcdやconsulをインストールしなくても良いため
swarmクラスタの構築が楽になりましたね。

早速試してみます。

# 準備

以下ではMacで作業しています。
コマンド例などは各自の環境に応じて適宜読み替えてください。

## 手元のマシンにdocker v1.12をインストール

今回のDockerConに合わせ、Docker for Mac/Windowsがプライベートベータからパブリックベータとなりました。せっかくなので使ってみましょう。
Docker for Mac/Windowsは以下のサイトからダウンロードできます。

https://docs.docker.com

## swarmクラスタ用マシンの準備

#### DockerMachine + さくらのクラウド

今回はさくらのクラウド上に3台マシンを作ります。
docker-machineのさくらのクラウド用ドライバを使いますので[こちらの記事](http://qiita.com/yamamoto-febc/items/4aff7472fc1ea025db0a)などを参考に
インストールを行っておいてください。

#### マシン作成 + dockerインストール

以下コマンドでさくらのクラウド上にマシンを作ります。
`--engine-install-url`を指定することで、正式リリース前のedgeバージョンの
dockerをインストールすることができます。

```bash:マシン作成
# 1台目
$ docker-machine create -d sakuracloud \
    --sakuracloud-access-token=[ACCESS TOKEN] \
    --sakuracloud-access-token-secret=[ACCESS TOKEN SECRET] \
    --engine-install-url="https://experimental.docker.com" \
    sakura01

# 2台目
$ docker-machine create -d sakuracloud \
    --sakuracloud-access-token=[ACCESS TOKEN] \
    --sakuracloud-access-token-secret=[ACCESS TOKEN SECRET] \
    --engine-install-url="https://experimental.docker.com" \
    sakura02

# 3台目
$ docker-machine create -d sakuracloud \
    --sakuracloud-access-token=[ACCESS TOKEN] \
    --sakuracloud-access-token-secret=[ACCESS TOKEN SECRET] \
    --engine-install-url="https://experimental.docker.com" \
    sakura03
```

## クラスタ構築

### 1台目 init

早速クラスタ構築を行っていきましょう。

まずはクラスタの初期化を行います。初期化は`swarm init`コマンドとのことです。

```bash:swarm_init
$ docker swarm init --help

Usage:	docker swarm init [OPTIONS]

Initialize a Swarm

Options:
      --auto-accept value   Auto acceptance policy (worker, manager, or none)
      --force-new-cluster   Force create a new cluster from current state.
      --help                Print usage
      --listen-addr value   Listen address (default 0.0.0.0:2377)
      --secret string       Set secret value needed to accept nodes into cluster
```

ではまず1台目のマシンでinitを実行してみましょう。

```bash:_swarm_init実行
# 1台目のマシンに接続
$ eval $(docker-machine env sakura01)

# init実施
$ docker swarm init 
Swarm initialized: current node (bvotc0o2ukxbeud6jedhpyvsq) is now a manager.
```

本来は内部のネットワークでリッスンするように`--listen-addr`オプションをつけるべきですが、
今回は検証用ということでデフォルト値(`0.0.0.0:2377`)でリッスンしてます。

以下コマンドで確認できます。

```bash:swarm_init確認
$ docker node ls
ID                           NAME      MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS
bvotc0o2ukxbeud6jedhpyvsq *  sakura01  Accepted    Ready   Active        Leader

```

### 2,3台目 join

残り2台をクラスタに参加させましょう。
参加するには1台目のIPアドレス/ポートをオプションで指定します。
以下コマンドで1台目のIPアドレスを確認してから参加していきましょう。

```bash:IP確認
$ docker-machine ip sakura01
```

swarmクラスタへの参加は`join`コマンドを用います。

```bash:swarm_join
$ docker swarm join --help

Usage:	docker swarm join [OPTIONS] HOST:PORT

Join a Swarm as a node and/or manager

Options:
      --ca-hash string      Hash of the Root Certificate Authority certificate used for trusted join
      --help                Print usage
      --listen-addr value   Listen address (default 0.0.0.0:2377)
      --manager             Try joining as a manager.
      --secret string       Secret for node acceptance

```

早速実行しましょう。

```bash:swarm_join実施
# 2台目のマシンへ接続
$ eval $(docker-machine env sakura02)

# join
$ docker swarm join `docker-machine ip sakura01`:2377
This node joined a Swarm as a worker.

# 3台目のマシンへ接続
$ eval $(docker-machine env sakura03)

# join
$ docker swarm join `docker-machine ip sakura01`:2377
This node joined a Swarm as a worker.

# 1台目に接続して確認
$ eval $(docker-machine env sakura01)
$ docker node ls
ID                           NAME      MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS
03qup39ksvhcgvusqk7o9x50h    sakura03  Accepted    Ready   Active        
bvotc0o2ukxbeud6jedhpyvsq *  sakura01  Accepted    Ready   Active        Leader
ccup7i31v4dbzip15ej49wpzm    sakura02  Accepted    Ready   Active        

```

これでクラスタ構築ができました。

## クラスタ上でdockerコンテナ起動(serviceコマンド)

クラスタ上でのコンテナ起動には`service`コマンドを利用します。

```bash:serviceコマンド
$ docker service --help

Usage:	docker service COMMAND

Manage Docker services

Options:
      --help   Print usage

Commands:
  create      Create a new service
  inspect     Inspect a service
  tasks       List the tasks of a service
  ls          List services
  rm          Remove a service
  scale       Scale one or multiple services
  update      Update a service

Run 'docker service COMMAND --help' for more information on a command.

```

今回はNginxを起動してみます。サービス名として`hellosakura`と指定しています。
また、http用に80番ポートを指定しています。

```bash:service実行
$ docker service create --replicas 1 --name hellosakura -p 80:80 nginx:latest
```

確認は`service ls`と`service tasks [タスク名]`というコマンドで行います。

```bash:確認
# サービス起動状況の確認
$ docker service ls
ID            NAME         REPLICAS  IMAGE         COMMAND
2685cua3k8wm  hellosakura  1/1       nginx:latest  

# サービス内の各タスクの起動状況の確認(sakura03で起動しているのが見える)
$ docker service tasks hellosakura
ID                         NAME           SERVICE      IMAGE         LAST STATE          DESIRED STATE  NODE
4zh6ppxmxncfm6guswtoixmho  hellosakura.1  hellosakura  nginx:latest  Running 37 seconds  Running        sakura03
```

## 動作確認

それではブラウザなどで各マシンのIPにアクセスしてみましょう。

```bash:動作確認
$ open http://`docker-machine ip sakura01`
$ open http://`docker-machine ip sakura02`
$ open http://`docker-machine ip sakura03`
```

どのIPを指定してもNginxのページが表示されますよね？
Swarmクラスタ上では(クラスタ内の)どのIPであっても、公開ポートへのアクセスがあると、
Overlayネットワーク上で対象サービスポートへ到達できるようになっています。

## 残り

本日はとりあえずここまでです。
他にも

  - スケールアウト/スケールイン
  - クラスタ内コンテナのローリングアップデート
  - ノード除去時の再配置

など面白い機能が盛りだくさんです。
ぜひチュートリアルを実施してみてください。

以上です。