コンテナオーケストレーション入門🐳#1（Swarmを使ってみる）

# はじめに

Swarmを使用しながら、コンテナオーケストレーションの概要を体験したいと思います。

# 環境

- macOS Mojave 10.14.6
- Docker engine 19.03.5

# 内容

-  Swarm機能を有効化する
-  サービスを作成する
-  タスクを確認する
-  レプリカを作成する
-  コンテナをダウンさせ、復旧させる


# Swarm機能をOnにする

SwarmはDockerに付属しているAPIではあるものの、デフォルトでは使用できない状態になっています。
使用するためには、設定を変更する必要があります。

## 現在の設定を確認する

以下のコマンドを使用することで、現在のDockerの設定を確認することができます。

```docker
docker info
...
#  Swarm: inactive （Swarmが使用できない状態）
```


## Swarm機能をOnにする

以下のコマンドを使用することで、Swarm機能を有効化します。


```docker
docker swarm init

# Swarm initialized: current node (lo0dewyehl9qi1fd1thnza9bx) is now a manager.

# To add a worker to this swarm, run the following command:

#     docker swarm join --token SWMTKN-1-3y9vcbhfi1ppllmqj1971ua0brhx7k52gjmhlu0264oxjpsrqm-7rbc4fnt7llsze1ou22uszkbh 192.168.65.3:2377

# To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
```

このノードは新しいマネジャーです。

と表示されています。
どういうことでしょうか。


# `docker swarm init`で起こること

`docker swarm init`を行うと、今後Swarmを使用していくに当たって必要な設定が自動で行われます。
例えば...

- 公開鍵基盤（PKI）の自動設定
- ルート証明書の設定
- Join Tokenの生成


Swarmを使用することで、コンテナやそのネットワークはどんどん拡張されていきます。
ネットワークの通信を暗号化したりなど、ネットワークセキュリティに必要な内容を自動で設定しています。


また、**RAFTデータベース**がバックグラウンドで作成されています。
ここにはSwarmの構成や最初のマネジャーが格納され、暗号化されています。

このDBが自動で生成されているおかげで、これまで必要とされてきたコンフィグ用のDBは必要ありません。


## `docker node ls`

以下のコマンドを使用することで、ノードの一覧を確認することができます。

```bash
docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
lo0dewyehl9qi1fd1thnza9bx *   docker-desktop      Ready               Active              Leader              19.03.8
```


`docker swarm init`を実行したことで、マネジャーノードが1つ作成されています。
また、Statusが`Leader`となっています。


# Pets vs Cattles

オンプレミスとクラウドは、しばしばペットと家畜に例えられます。
これはコンテナオーケストレーションを扱う際にも当てはまります。


クラウド以前は、サーバー1台をオンプレミスで運用し、不調があれば修正するなどペットのように可愛がる必要がありました。

クラウドの時代では、サーバー1台だけを運用する事はありません。複数台のサーバー群を運用し、不調の際は手間をかける事なく落とし、代わりを立ち上げます。



コンテナオーケストレーションは、まさにコンテナやノードを「群れ」という単位で扱います。
群れに対して操作を行い、新しい群れを作成したり、群ごと削除したりできます。


# `docker service create`

以下のコマンド実行することで、新しいサービスを作成することができます。
GoogleのDNSサーバー`8.8.8.8`にpingを送り続けるaplineイメージからサービスを作成します。

```bash
docker service create alpine ping 8.8.8.8
# zn0631k8t6067p9gb517m6p87
```

`docker run`した時と同じように、IDが出力されています。
これはサービスIDです。


# `docker service ls`

以下のコマンドを実行することでサービスの一覧を確認することができます。


```bash
docker service ls
# ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
# zn0631k8t606        kind_perlman        replicated          1/1                 alpine:latest       
```

'REPLICAS'の値を確認することで、サービスの実行数が確認できます。
今は`1/1`となっています。


# `docker service ps`

以下のコマンドを使用することで、サービス内に含まれるタスク(コンテナ)の一覧を表示することができます。


```bash
docker service ps kind_perlman
# ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
# taaj0dalmte5        kind_perlman.1      alpine:latest       docker-desktop      Running             Running 10 minutes ago                       
```

デフォルトで作成されたノードに、タスク（コンテナ）が作成されています。


# `docker service update`

では、このサービスのレプリカを増やしてみます。
以下の`update`コマンドを実行することで、レプリカを増やし冗長化を図ることができます。

```docker
docker  service update zn06 --replicas 3
# zn06
# overall progress: 3 out of 3 tasks 
# 1/3: running   [==================================================>] 
# 2/3: running   [==================================================>] 
# 3/3: running   [==================================================>] 
# verify: Service converged 
```

`docker service ls`でサービスを確認すると、レプリカの数が増えていることが確認できます。


```docker
docker service ls
# ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
# zn0631k8t606        kind_perlman        replicated          3/3                 alpine:latest       
```

また、``docker service ps`を実行することで、コンテナも増えていることが確認できます。

```docker
docker service ps kind_perlman
# ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
# taaj0dalmte5        kind_perlman.1      alpine:latest       docker-desktop      Running             Running 18 minutes ago                       
# l5ply9585ptc        kind_perlman.2      alpine:latest       docker-desktop      Running             Running 2 minutes ago                        
# rhnb1bnfsic3        kind_perlman.3      alpine:latest       docker-desktop      Running             Running 2 minutes ago                        
```

コンテナの`NAME`に、番号が自動で添えられているのもすごいですね。自動で名前が一意になるようになっています。

**`update`コマンドを使用することでコンテナを停止したり新しく作り直すことなしに、変更を加えることができます。
これは稼働率を確保する上で重要な特徴です。**

これはSwarmを使用する目的の一つでもあります。コンテナやその集合でできた環境を停止することなく、レプリケーションしたり、変更を加えることができるようになります。


# もしコンテナの一部がダウンしたら

もしコンテナの一部がダウンしたらどうなるか、試してみます。

以下のコマンドを使用して、コンテナの一つを削除してみます。

```docker
docker container rm -f  kind_perlman.1.taaj0dalmte5iqmagqgy97tbt
```

サービスを確認してみると、

```docker
docker service ls
# ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
# zn0631k8t606        kind_perlman        replicated          3/3                 alpine:latest       
```

あれ？　特に変化ありませんね。

では、タスク一覧を確認してみます。

```docker
docker service ps kind_perlman
# ID                  NAME                 IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR                         PORTS
# ztbj2mfbzqzh        kind_perlman.1       alpine:latest       docker-desktop      Running             Running 18 seconds ago                                 
# taaj0dalmte5         \_ kind_perlman.1   alpine:latest       docker-desktop      Shutdown            Failed 23 seconds ago    "task: non-zero exit (137)"   
# l5ply9585ptc        kind_perlman.2       alpine:latest       docker-desktop      Running             Running 37 minutes ago                                 
# rhnb1bnfsic3        kind_perlman.3       alpine:latest       docker-desktop      Running             Running 37 minutes ago                                 
```

コンテナ`kind_perlman.1`は確かに削除されています。

でも、その数秒後には同名のコンテナが復活しています。


これがSwarmを初めとするコンテナオーケストレーションの強みです。
コンテナが落ちたとしても、即座に元の状態に自動て復旧します。


# `docker service rm`

以下のコマンドを使用することで、サービスを削除することができます。

```docker
docker service rm 
```

サービスだけでなく、サービスに紐づいているタスク（コンテナ）も削除されます。




# まとめ

-  Swarm機能を有効化する
-  サービスを作成する
-  タスクを確認する
-  レプリカを作成する
-  コンテナをダウンさせ、復旧させる

上記を確認しながら、コンテナオーケストレーションの強みがわかってきました。