case-kの備忘録

日々の備忘録です。データ分析とクラウドに興味があります。

Docker Swarmの概要と実践

コンテナオーケストレーションシステムのDocker Swarmを触ってみました。「Docker/Kubernetesコンテナ実践入門」を読み進めておりDocker Swarmは飛ばしてKubernetesから入ろうかとも思ったのですが、Kubernetesを理解する上で、Docker Swarmの知識も役立ちそうだったので備忘録として残しておきます。
gihyo.jp

Code

github.com

Docker Swarmとは

Docker ホストを束ねてクラスタ化するコンテナオーケストレーションシステムの1つ。クラスタ内のノードのコンテナ配置方法やコンテナ同士の通信制御、スケーラビリティの制御を行います、Swarmを扱う上で次の役割のサービスを使います。

  • Compose:複数のコンテナを使うアプリケーションの管理(主にシングルホスト)
  • Swarm:クラスタの構築や管理を担う(主にマルチホスト)
  • Service:クラスタ内の1つ以上のコンテナの集まりを管理する
  • Stack:複数のServiceをまとめたアプリケーション全体の管理

Swarmクラスタの構築

Swarmクラスタを構築するため、まず下記のコンテナを用意します。

  • registry * 1:Dockerイメージのレジストリとなるコンテナ。managerとworkerから参照
  • manager * 1:Swarmクラスタ全体を制御する役割
  • worker * 3:managerのワーカー
$ docker-compose up -d
$ docker ps -a
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS              PORTS                                                              NAMES
425f9e302130        docker:18.05.0-ce-dind   "dockerd-entrypoint.…"   40 seconds ago      Up 38 seconds       2375/tcp, 4786/udp, 7946/tcp, 7946/udp                             worker03
9b49fbcd90ef        docker:18.05.0-ce-dind   "dockerd-entrypoint.…"   40 seconds ago      Up 38 seconds       2375/tcp, 4786/udp, 7946/tcp, 7946/udp                             worker01
68393f9a2309        docker:18.05.0-ce-dind   "dockerd-entrypoint.…"   40 seconds ago      Up 38 seconds       2375/tcp, 4786/udp, 7946/tcp, 7946/udp                             worker02
b01f251189c7        docker:18.05.0-ce-dind   "dockerd-entrypoint.…"   41 seconds ago      Up 40 seconds       2375/tcp, 3375/tcp, 0.0.0.0:9000->9000/tcp, 0.0.0.0:8000->80/tcp   manager
d7b24d89c6c5        registry:2.6             "/entrypoint.sh /etc…"   43 seconds ago      Up 41 seconds       0.0.0.0:5000->5000/tcp

実行したコンテナを協調クラスタとして動作させます。ホストからmanagerに対して「docker swarm init」を実行してSwarmのmanagerに設定します。

$ docker container exec -it manager docker swarm init

実行すると対象のコンテナ全体を管理するmanagerとして、Swarmモードが有効になります。ここから先ほど立ち上げたworkerコンテナを追加しクラスタを形成します。worker01~03を追加して行きます。

$ docker container exec -it worker01 docker swarm join --token SWMTKN-1-4j56rxglt7v1wih7qla3mn3nanrg43xt6l2v6dg1n9c2aqkfik-62ixkhr3obx36ppylqw4fvc81 172.18.0.3:2377
This node joined a swarm as a worker.

managerを確認すると、managerに加えてworkerも追加されていることが確認できます。

$ docker container exec -it manager docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
qkcdh7a24e2abg4ujqbik0s2e     9b49fbcd90ef        Ready               Active                                  18.05.0-ce
7r8cy38zsizyxk9jfdpfex111     425f9e302130        Ready               Active                                  18.05.0-ce
l8s5by2muej3ab1ntcp08gjwj     68393f9a2309        Ready               Active                                  18.05.0-ce
ckzn9h99a65l75qfnjey3i8z5 *   b01f251189c7        Ready               Active              Leader              18.05.0-ce

レジストリに登録

registryコンテナにイメージをpushし、クラスタ内のmanagerやworkerコンテナから参照できるようにします。

# docker image push [push先のレジストリのホスト/]リポジトリ名[:タグ]
$ docker image tag example/echo:latest localhost:5000/example/echo:latest
$ docker image push localhost:5000/example/echo:latest

試しにworker01からPULLし、取得できることを確認します。

$ docker container exec -it worker01 docker image pull registry:5000/example/echo:latest
$ docker container exec -it worker01 docker image ls
REPOSITORY                   TAG                 IMAGE ID            CREATED             SIZE
registry:5000/example/echo   latest              cc921756bbc3        2 days ago          750MB

Service

Serviceはアプリケーションを構成する一部を制御するための単位です。実行されている複数のコンテナをまとめて管理しています。位置付けとしては、Serviceの上位にStackがあり、StackはSwarmで制御される形になります。試しにServiceを一つ作ってみます。

$ docker container exec -it manager docker service \
create --replicas 1 --publish 8000:8080 --name echo registry:5000/example/echo:latest

Serviceが作られたことを確認してみます。

$ docker container exec -it manager docker service  ls 
ID                  NAME                MODE                REPLICAS            IMAGE                               PORTS
bd5wgpbdl1w7        echo                replicated          1/1                 registry:5000/example/echo:latest   *:8000->8080/tcp

Serviceが制御するレプリカを増やしてみる。Swarmクラスタ上で実行されているコンテナを確認。6つのechoコンテナが分散されて配置されていることがわかる。

$ docker container exec -it manager docker service scale echo=6
$ docker container exec -it manager docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                               PORTS
bd5wgpbdl1w7        echo                replicated          6/6                 registry:5000/example/echo:latest   *:8000->8080/tcp
$ docker container exec -it manager docker service ps echo
ID                  NAME                IMAGE                               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
nqwi4tu8rram        echo.1              registry:5000/example/echo:latest   9b49fbcd90ef        Running             Running 20 minutes ago
ipb2o6lzuurr        echo.2              registry:5000/example/echo:latest   425f9e302130        Running             Running 9 minutes ago
j9tqjwvcvek2        echo.3              registry:5000/example/echo:latest   425f9e302130        Running             Running 9 minutes ago
7ep1m82eg57x        echo.4              registry:5000/example/echo:latest   9b49fbcd90ef        Running             Running 11 minutes ago
m3qaesn6rnw9        echo.5              registry:5000/example/echo:latest   b01f251189c7        Running             Running 9 minutes ago
m0md7lsjqgil        echo.6              registry:5000/example/echo:latest   68393f9a2309        Running             Running 9 minutes ago

デプロイしたサービスを削除する

$ docker container exec -it manager docker service rm echo

Stack

Stackは複数のServiceをグルーピングした単位のことです。Serviceは1つのアプリケーションイメージしか使うことができない。複数のServiceが協調するアプリケーションを動かす場合は、Serviceの上位概念である Stackを活用します。StackはSwarm上でスケールイン・スケールアウトが可能になったComposeという位置付けです。Stackの制御にはdocker stackサブコマンドが利用されます。

overlayネットワーク

overlayネットワークとはStackによってデプロイされるService群が所属するネットワークです。同じネットワークに所属しているコンテナ間では通信が可能となる。特にoverlayネットワークを設定しなければ、Stackの数だけoverlayネットワークが作られ、異なるStackで作られたコンテナ群同士は通信もできなくなります。この問題を解決するためには、同一のoverlayネットワークに所属させる必要があります。overlayネットワークを作りStackから作成されるServiceを所属させます。

$ docker container exec -it manager docker network create --driver=overlay --attachable ch03
# webapi.yml
version: "3"
services:
  nginx:
    image: gihyodocker/nginx-proxy:latest
    deploy:
      replicas: 3
      placement:
        constraints: [node.role != manager]
    environment:
      BACKEND_HOST: echo_api:8080
    depends_on:
      - api
    networks:
      - ch03
  api:
    image: registry:5000/example/echo:latest
    deploy:
      replicas: 3
      placement: 
        constraints: [node.role != manager]
    networks:
      - ch03
networks:
  ch03:
    external: true
  • deploy:新規にStackをデプロイ、または更新する
  • external= true :Stack の外にネットワークを作成します(訳者注:Compose が管理していない Docker ネットワークを利用します
  • placement:コンテナ配置戦略の設定
  • constraints:manager以外のノードにコンテナを配置

Stackをデプロイ

StackをSwarmクラスタにデプロイします。

$ docker container exec -it manager docker stack deploy -c /stack/ch03-webapi.yml echo
Creating service echo_nginx
Creating service echo_api
  • C:Stack定義ファイルのパス

デプロイされたStackを確認します。

$ docker container exec -it manager docker stack services echo
ID                  NAME                MODE                REPLICAS            IMAGE                               PORTS
iqerba71n0mh        echo_nginx          replicated          3/3                 gihyodocker/nginx-proxy:latest
z03j17trpp4o        echo_api            replicated          3/3                 registry:5000/example/echo:latest

配置されているコンテナを可視化

コンテナ群がSwarmクラスタ上のノードにどのように配置されているか可視化できるアプリケーションがあります。

# visualizer.yml
version: "3"

services:
  app:
    image: dockersamples/visualizer
    ports: 
      - "9000:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    deploy:
      mode: global
      placement:
        constraints: [node.role == manager]
$ docker container exec -it manager docker stack deploy -c /stack/visualizer.yml visualizer
Creating network visualizer_default
Creating service visualizer_app

f:id:casekblog:20200219192406p:plain

Stackの削除

$ docker container exec -it manager docker stack rm echo
Removing service echo_api
Removing service echo_nginx

以上となります。