>   >  痴山紘史の日本CG見聞録:第13回:クラウド環境構築[複数コンテナの連携]
第13回:クラウド環境構築[複数コンテナの連携]

第13回:クラウド環境構築[複数コンテナの連携]

みなさんこんにちは。五月下旬にCOMPUTEX TAIPEI 2019が開催され、新しいハードウェアが続々と発表されました。今年の話題No.1は何といってもAMDのRyzenシリーズの発表でしょう。ほんの数年前までは12コア/24スレッドのCPUが$500なんて価格で手に入るとはとても考えられなかったですし、基本性能も今の時代になってそんなに上がる!?という数字が出てきて驚きの連続です。AMDの最近の躍進はすさまじく、新製品発表のたびにワクワクさせてくれるこの感覚はとても久しぶりです。7/7発売ということなので今から楽しみです。

TEXT_痴山紘史 / Hiroshi Chiyama(日本CGサービス
EDIT_尾形美幸 / Miyuki Ogata(CGWORLD)

クラウド環境構築の前準備

前回の予告の通り、今回からはクラウド環境を活用するためのお話に進んでいきます。クラウドだからといって何か特別なことをするわけではなく、これまで行なってきたことの延長線上の内容として話を進めていきます。そのため、いきなりクラウドの世界に飛び出してしまうのではなく、今回から数回に渡って社内サーバ運用からクラウド運用に移行するためのトピックをご紹介していきます。


・Dockerのおさらい

Dockerは本連載でずっと活用してきました。もちろんクラウド環境でもフルに活用していく予定ですが、そのためには、これまできちんと扱ってこなかったいくつかのトピックを確認する必要があるので、まずはそこから進めていきます。

本連載中では最初にDockerのコンテナを単体で起動し、単独のアプリケーションを起動することから始め、続いて複数のコンテナを起動し、それぞれを連携させる方法を見てきました。

これまで話のながれ上、あえてあまり詳しく触れず、「とりあえず、そういうふうにやるものだ」と割り切って進めた内容がいくつかあります。今後の話を進める上で必要になってきそうなので、ここでまとめてご紹介します。


・データの永続化

Dockerは、コンテナを実行してイメージの内容を更新しても、コンテナを終了すると更新内容は消えてしまい、再度コンテナを実行すると、初期の状態から実行されるという特徴があります。最初は「エエッ!?」と思うかもしれませんが、一度つくったイメージを元に複数のコンテナを起動したときに、起動した順番によって異なる環境ができてしまうと大きなトラブルの要因になってしまいます。そのため、毎回同じ状態に戻るのは正しい仕様といえます。

変更内容を保存したい場合、2つの対応方法があります。

ひとつは、元のイメージから新しいイメージを作成し、それを使用する方法です。この場合はDockerfileを書いて専用のイメージをビルドします。もうひとつは、アプリケーションが使用するデータを保存する場合です。この場合は、コンテナが停止してもデータが残る場所を保存先として指定します。

前者はわれわれもずっと活用していました。例えば第3回:USD環境の構築で使用したAnimalLogic/docker-usdでも、CY2018環境を構築するためにDockerfileを用意しています。このDockerfile内ではcentos/devtoolset-7-toolchain-centos7というイメージをベースに追加で環境構築を行なっています。

後者はlogstashで行なっていて、-vオプションで指定していました。logstashを起動するためのコマンドは以下の通りでした。

$ sudo docker run -d --name logstash --rm -it -v /root/pipeline/:/usr/share/logstash/pipeline/ docker.elastic.co/logstash/logstash:6.6.0

この場合、ホストの/root/pipelineをコンテナの/usr/share/logstash/pipelineとしてアクセスできるようになります。データは/root/pipelineに置かれているので、コンテナが終了しても存在し続けます。

後者のように、コンテナが終了しても残しておきたいデータが消えないようにすることをデータの永続化といいます。永続化をきちんとしておかないと、メトリクスを一生懸命取得して蓄積しても、ある日コンテナを再起動する必要が出たときに全てがなかったことになってしまいます。


・Dockerコンテナの管理

これまで、Dockerコンテナを立ち上げる際には以下のような感じでコマンドを入力していました。

$ sudo docker run -d --name graphite --restart=always -p 9080:80 -p 2003-2004:2003-2004 -p 2023-2024:2023-2024 -p 8125:8125/udp -p 8126:8126 graphiteapp/graphite-statsd

コンテナの数が少なく、動作確認のために実行するだけならひとつひとつコンテナを立ち上げてもいいですが、Fifemonのように複数のコンテナが連携して処理を行うようになると、とてもじゃないですが管理しきれなくなってしまいます。また、時間が経ってから改めて同じ手順でコンテナを起動しなければいけなくなった場合、オプションを正確に覚えておくのは難しいです。

このような複数のコンテナをまとめて管理するためのツールがあります。今回はDocker Composeを使用して、Fifemon環境を構築してみます。


・Docker Composeを使用したコンテナの管理

Docker Composeを使用したコンテナの管理は、大きく2つの部分に分かれます。ひとつめが各コンテナ(イメージ)を管理する部分、ふたつめが複数のコンテナをまとめてひとつのシステムを構築するための部分です。

イメージはdocker hubにあるものなど、既存のものを使用する方法と、Dockerfileを定義して自分で作成する方法があります。

Fifemonでは、Elasticsearchとgrafana、graphiteでオリジナルイメージのまま使用することができます。Elasticsearchで日本語に対応する必要がある場合は、kuromojiプラグインのインストールなどが必要ですが、Fifemonでは使用しないのでオリジナルのイメージを使用します。logstashはちょっと複雑で、基本は公式イメージを使用するのですが、probeを使用するための環境を構築する必要があります。また、probeはlogstash以外にもsupervisordを使用してメトリクスの取得を行うので、そのための環境も必要です。

まとめると

-Elasticsearch、grafana、graphite → オリジナルイメージを使用しつつ、永続化が必要なデータは永続化する
- logstash → オリジナルイメージをベースに独自のイメージを作成
- probe → supervisordを使用するようにイチから環境構築

ということになります。


・Docker Composeのインストール

DockerとDocker Composeは別のプロダクトなので、インストールをする必要があります。

$ sudo yum -y install docker-compose

・Elasticsearch、graphiteの設定

Docker Composeを使用する際には、docker-compose.xmlファイルを作成します。ディレクトリ構成は以下のようになります。

$ tree .
.
├── docker-compose.yml
└── Elasticsearch
    ├── config
    │   └── elasticsearch.yml
    ├── data
    └── logs

4 directories, 2 files
$

docker-compose.ymlは、servicesで起動するコンテナの定義、networksでネットワークを定義しています。

$ cat docker-compose.yml
version: '3.3'

services:
  elasticsearch:
    container_name: es01
    image: docker.elastic.co/elasticsearch/elasticsearch:6.6.0
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
      nofile:
        soft: 65536
        hard: 65536
    volumes:
      - ./Elasticsearch/data:/usr/share/elasticsearch/data
      - ./Elasticsearch/logs:/usr/share/elasticsearch/logs
      - ./Elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
    networks:
      - default

  graphite:
    container_name: graphite
    image: graphiteapp/graphite-statsd
    links:
      - elasticsearch
    networks:
      - default

networks:
    default:

$

services中ではelasticsearchとgraphiteの2つのサービスが定義されています。最も単純なgraphiteの中身を見てみます。

  graphite:
    container_name: graphite
    image: graphiteapp/graphite-statsd
    links:
      - elasticsearch
    networks:
      - default

container_nameでコンテナ名を指定し、imageでコンテナを実行する際に使用するイメージ名を指定します。実行環境にイメージがなければ自動的にダウンロードして環境を構築します。

linksは、このコンテナを実行する際に必要なほかのサービスを指定することができます。graphiteを実行するためには、elasticsearchが実行されている必要があることがわかります。

networksはこのコンテナが接続するネットワークを指定します。Dockerがデフォルトで用意しているネットワーク(bridge)ではDNSが有効になっていないため、別のコンテナにアクセスするためにはIPアドレスで指定する必要がありましたが、新たに定義したネットワークではDNSが有効になっているため、コンテナ名でアクセスすることができます。

続いて、Elasticsearchの中身を見てみます。

  elasticsearch:
    container_name: es01
    image: docker.elastic.co/elasticsearch/elasticsearch:6.6.0
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
      nofile:
        soft: 65536
        hard: 65536
    volumes:
      - ./Elasticsearch/data:/usr/share/elasticsearch/data
      - ./Elasticsearch/logs:/usr/share/elasticsearch/logs
      - ./Elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
    networks:
      - default

environmentは、コンテナにセットする環境変数になります。docker runコマンドで-eオプションで指定していた内容です。

ulimitsは、Elasticsearchを動かすために必要な設定です。

volumes が、永続化したいデータ置き場を用意するための項目です。例えば、

      - ./Elasticsearch/data:/usr/share/elasticsearch/data

は、Elasticsearch/dataディレクトリをコンテナの/usr/share/elasticsearch/dataディレクトリにマウントしています。docker runコマンドの-vオプションで指定していた内容です。

これで一度コンテナを起動してみます。docker-compose.ymlのあるディレクトリで、docker-compose upを実行します。

$ sudo docker-compose up -d
Creating es01 ... done
Creating graphite ... done
Creating graphite ...

コンテナの状態は docker-compose psで確認できます。

$ sudo docker-compose ps
  Name                Command               State                         Ports
-----------------------------------------------------------------------------------------------------
es01       /usr/local/bin/docker-entr ...   Up      9200/tcp, 9300/tcp
graphite   /entrypoint                      Up      2003/tcp, 2004/tcp, 2013/tcp, 2014/tcp, 2023/tcp,
                                                    2024/tcp, 80/tcp, 8080/tcp, 8125/tcp, 8125/udp,
                                                    8126/tcp
$

ご覧の通り、コマンドひとつで必要な設定が行われたコンテナが全て立ち上がりました。設定を変更してコンテナを立ち上げ直したいときはdocker-compose restartが使用できます。

$ sudo docker-compose restart
Restarting graphite ... done
Restarting es01     ... done
$

ひとつひとつのコンテナを管理するよりもとても楽ですね。

次ページ:
・grafanaの設定

その他の連載