プロダクション用の Swarm クラスタ構築

高い可用性を持つ Docker Swarm クラスタのデプロイ方法を紹介します。この例では Amazon Web Services (AWS) をプラットフォームとして使いますが、他のプラットフォーム上でも Docker Swarm クラスタを同じようにデプロイできます。

Swarm クラスタは3種類のノードで構成されます。

  • Swarm マネージャ
  • Swarm ノード(別名 Swarm エージェント)
  • consul が動くディスカバリ・バックエンド・ノード

この例では次の手順で進めます。セキュリティ・グループを作成し、基本的なネットワークセキュリティを確立するために、ポート番号、タイプ、通信元に応じたインバウンドのトラフィックを制限します。それから、ネットワーク上にエラスティック・クラウド(EC2)インスタンスを4ホスト起動します。それぞれ適切なセキュリティ・グループを割り当て、それぞれに Docker Engine をインストールします。ホストの1つはディスカバリ・バックエンドとして consul コンテナを実行します。そして2つの Swarm マネージャを実行し、高い可用性を持つクラスタの設定を行います。Swarm マネージャの1つは consul とホストを共有します。それから2つの Swarm ノードを起動し、アプリケーションがノード上で動作するか確認するため、簡単な hello world アプリケーションを動かします。最後に高可用性を確認するため Swarm マネージャの1つを落とし、マネージャの状態がどうなるかを確認します。

一般的な Swarm の導入方法については Swarm を検証環境で試すには をご覧ください。

動作条件

  • Amazon Web Services (AWS) アカウント
  • 以下の AWS 機能やツールに慣れている:
    • エラスティック・クラウド(EC2)ダッシュボード
    • バーチャル・プライベート・クラウド(VPC)ダッシュボード
    • VPC セキュリティ・グループ
    • EC2 インスタンスに SSH で接続

ネットワークのセキュリティ・ルールを変更

AWS は VPC ネットワークに対して許可するネットワーク通信を「セキュリティ・グループ」で指定します。初期状態の default セキュリティ・グループは、インバウンドの通信を全て拒否し、アウトバンドの通信を全て許可し、インスタンス間の通信を許可するルール群です。ここに SSH 接続とコンテナのイメージを取得(インバウンド)する2つのルールを追加します。このルール設定は Engine 、Swarm 、 Consul のポートを少々は守ります。プロダクション環境においては、セキュリティ度合いによって更に制限するでしょう。Docker Engine のポートを無防備にしないでください。

AWs ホーム・コンソール画面から、 VPC - 独立したクラウドリソース をクリックします。VPC ダッシュボードが開いたら、 セキュリティグループ をクリックします。 default セキュリティ・グループを選び、 default VPC にセキュリティ・グループを関連付け、以下の2つのルールを追加します( 説明 の列は自分の確認用です )。

タイプ プロトコル ポート範囲 送信元 説明
SSH TCP 22 0.0.0.0/0 SSH接続
HTTP TCP 80 0.0.0.0/0 コンテナのイメージ

ホストの作成

ここでは4つの Linux ホストを作成します。それぞれ「Docker Swarm Example」セキュリティ・グループに属します。

EC2 ダッシュボードを開き、EC2 インスタンスを1つずつ起動します。

  • ステップ1 では : Amazon マシン・イメージ (AMI)を選択 します。 Amazon Linux AMI を探します。
  • ステップ5 では: インスタンスにタグ を付けます。各インスタンスの Value に名前を付けます。
    • manager0 & consul0
    • manager1
    • node0
    • node1
  • ステップ6 では: セキュリティ・グループを設定 します。 既存のセキュリティグループ から「default」を探します。

インスタンスの起動を確認します。

各インスタンスに Docker Engine をインストール

各インスタンスに SSH で接続し、Docker エンジンをインストールします。

yum パッケージを更新し、「y/n/abort」プロンプトに注意します。

$ sudo yum update

インストール用スクリプトを実行します。

$ curl -sSL https://get.docker.com/ | sh

Docker エンジンが Swarm ノードのポート 2375 をリッスンできる指定をして起動します。

$ sudo docker daemon -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock

Docker Engine が正常にインストールされたことを確認します。

$ sudo docker run hello-world

「Hello World」メッセージが画面に表示され、エラーではない文字列が表示されます。

ec2-user に root 権限を与えます。

$ sudo usermod -aG docker ec2-user

それから logout を実行します。

注釈

トラブルシューティング: docker コマンドを実行してもホスト上で docker が動作しているかどうか訊ねる表示が出るのは、ユーザが root 権限を持っていない可能性があります。そうであれば、 sudo を使うか、ユーザに対して root 権限を付与します。この例では、Docker Engine を実行するインスタンスのために AMI イメージを使っておらず、既存のインスタンスを再利用する方法ではありません。そのため、エラーが起こった場合は確認してください。

注釈

トラブルシューティング: ホスト上で docker run コマンドを実行しても Docker Hub に接続できない場合は、コンテナ・イメージの取得に失敗するでしょう。そのような場合、VPC に関連付けられているセキュリティ・グループのルールを参照し、インバウンドの通信(例: HTTP/TCP/80/0.0.0.0.0/0)が許可されているか確認します。また、 Docker Hub ステータス・ページ でサービスが利用可能かどうか確認します。

consul ディスカバリ・バックエンドのセットアップ

ここでは最小のディスカバリ・バックエンドを作成します。Swarm マネージャとノードは、このバックエンドをクラスタ上のメンバを認識するために使います。また、Swarm マネージャはコンテナを実行可能なノードがどれかを識別するためにも使います。

簡単さを保つために、Swarm マネージャが動いているホストのうちどれか1つで consul デーモンを起動します。

実行するには、以下のコマンドをコピーして consul コンテナを起動します。

$ docker run -d -p 8500:8500 --name=consul progrium/consul -server -bootstrap

それから、「manager0 & consul0」インスタンスに SSH を使って接続します。コマンドラインで ifconfig を実行します。出力結果の inet addr から eth0 IP アドレスをコピーします。

consul ノードを立ち上げて実行すると、クラスタ用のディスカバリ・バックエンドを提供します。このバックエンドの信頼性を高めるには、3つの consul ノードを使った高可用性クラスタを作成する方法があります。詳細情報へリンクを、このページの一番下をご覧ください(consul ノードのクラスタを作成する前に、VPC セキュリティ・グループに対し、必要なポートに対するインバウンド通信を許可する必要があります)。

高可用性 Swarm クラスタを作成

ディスカバリ・バックエンドを作ったあとは、Swarm マネージャを作成できます。ここでは高い可用性を持つ設定のため、2つの Swarm マネージャを作成します。1つめのマネージャを Swarm の プライマリ・マネージャ (primary manager) * とします。ドキュメントのいくつかはプライマリを「マスタ」と表現していますが、置き換えてください。2つめのマネージャは *レプリカ(replica) を提供します。もしもプライマリ・マネージャが利用できなくなれば、クラスタはレプリカからプライマリ・マネージャを選出します。

高可用性 Swarm クラスタのプライマリ・マネージャを作成するには、次の構文を使います。

$ docker run -d -p 4000:4000 swarm manage -H :4000 --replication --advertise <manager0_ip>:4000  consul://<consul_ip>

特定のマネージャは「manager0 & consul0」インスタンスの consul ノードでもあるので、 <manager0_ip><consul_ip> と同じ IP アドレスに書き換えます。例:

$ docker run -d -p 4000:4000 swarm manage -H :4000 --replication --advertise 172.30.0.161:4000  consul://172.30.0.161:8500

docker ps を実行します。出力結果から swarm と consul コンテナが動いているのを確認します。それから「manager0 & consul0」インスタンスから切断します。

「manager1」インスタンスに接続し、 ifconfig で IP アドレスを取得します。それから次のコマンドを実行しますが <manager1_ip> の部分は書き換えてください。実行例:

$ docker run -d swarm manage -H :4000 --replication --advertise <manager1_ip>:4000  consul://172.30.0.161:8500

docker ps を実行し、出力結果から swarm コンテナの実行を確認します。

あとは「node0」「node1」インスタンスに接続し、それぞれの IP アドレスを取得し、次の構文を使って Swarm ノードを実行します。

$ docker run -d swarm join --advertise=<node_ip>:2375 consul://<consul_ip>:8500

実行例:

$ docker run -d swarm join –advertise=172.30.0.69:2375 consul://172.30.0.161:8500

あなたの小さな Swarm クラスタが起動し、複数のホスト上で実行中になりました。

Swarm との通信

Swarm API を使って Swarm と通信し、マネージャとノードに関する情報を取得できます。Swarm API はスタンダード Docker API とよく似ています。この例では SSL を使って「manager0 & consul0」ホストに再び接続します。そしてコマンドを Swarm マネージャに対して割り当てます。

クラスタ内のマスタとノードの情報を取得します。

$ docker -H :4000 info

出力結果から、マスターの役割がプライマリ( Role: primary )であることと、各ノードの情報が分かります。

次は Swarm 上でアプリケーションを実行します。

$ docker -H :4000 run hello-world

Swarm ノード上でアプリケーションが動いているのを確認します。

$ docker -H :4000 ps

Swarm マネージャの高可用性試験

レプリカ・インスタンスへの継承を確認するために、プライマリ・マネージャをシャットダウンします。これが選出のきっかけとなり、レプリカがプライマリ・マネージャになります。停止したマネジャを再び起動すると、今度はこちらがレプリカになります。

SSH を使って「manager0 & consul0」インスタンスに接続し、swarm コンテナのコンテナ ID かコンテナ名を取得します。

$ docker ps

プライマリ・マスタをシャットダウンするため、 <id_name> の部分をコンテナ ID あるいはコンテナ名に置き換えます(例: 「8862717fe6d3」または「trusting_lamarr」)。

$ docker rm -f <id_name>

swarm マスタを起動します。例:

$ docker run -d -p 4000:4000 swarm manage -H :4000 --replication --advertise 172.30.0.161:4000  consul://172.30.0.161:237

ログを確認します。 <id_name> は新しいコンテナ ID かコンテナ名に置き換えます。

$ sudo docker logs <id_name>

出力から次のような2つのエントリが確認できます。

time="2016-02-02T02:12:32Z" level=info msg="Leader Election: Cluster leadership lost"
time="2016-02-02T02:12:32Z" level=info msg="New leader elected: 172.30.0.160:4000"

クラスタのマスタとノードに関する情報を取得するには、次のように実行します。

$ docker -H :4000 info

「master1」ノードに接続し、 infologs コマンドを実行できます。そうすると、新しいリーダーが適切なエントリを返します。