アンバサダーパターンを使用してCoreOSでサービスを動的に構成する方法
序章
Dockerリンク機能を使用すると、アンバサダーパターンと呼ばれる、コンテナー間のネットワーク接続を動的に構成する方法が可能になります。 アンバサダーパターンは、プロバイダーコンテナーとコンシューマーコンテナー間のサービスの移植性を促進します。 CoreOSでは、etcd
を利用して、クラスター内の複数のマシンに分散されたアンバサダーパターンを実装できます。
このチュートリアルでは、etcd
に登録されているApacheHTTPコンテナのデプロイについて説明します。 Apacheコンテナーはプロバイダーコンテナーを表し、HAProxyをコンシューマーコンテナーとして使用します。 このCoreOSアンバサダーデモのDockerイメージをアンバサダーコンテナーに使用し、独自のApacheおよびHAProxyDockerイメージを最初から作成します。
前提条件
DigitalOceanには、少なくとも3台のマシンで構成されるCoreOSクラスターが必要です。 これを設定する方法のチュートリアルは次のとおりです。CoreOSクラスターでサービスを作成して実行する方法
CoreOS、etcdctl、fleetctlの使用、サービスのセットアップ、およびDockerコンテナーの実行に関する基本的な知識が必要です。 これらのトピックは、CoreOSチュートリアルシリーズで説明されています。
DockerHubアカウントまたはプライベートDockerレジストリが必要です。 これについては、CoreOSクラスターでサービスを作成して実行する方法チュートリアルのDockerコンテナーの作成セクションで説明されています。
アンバサダーパターンの仕組みの詳細については、Dockerの Link via AmbassadorContainerの記事をご覧ください。 また、CoreOSブログに投稿された次の記事も確認してください。動的Dockerは、etcdを搭載したアンバサダーとリンクしています。
私たちの目標
このチュートリアルの最後に、2台のマシンで6つのコンテナーを実行します。 このセクションでは、それぞれについて簡単に説明し、それらをグループ化する方法について説明します。 この正確な設定はほとんどの人にとって有用ではありませんが、独自のサービスの動的なサービス検出を可能にするように適合させることができます。
マシンA
マシンAはプロバイダーコンテナを実行します。 Apache Webサーバー、およびそれをサポートする他のいくつかのコンテナー。
- Apache Webサーバー: CoreOSクラスターでサービスを作成して実行する方法チュートリアルで説明されているものと同様の、最初から作成する基本的なApacheコンテナー。 これが私たちのプロデューサーです
- polvi / docker-register :Docker APIを介してApacheのIPアドレスとポートを読み取り、
etcd
に書き込む登録コンテナー - polvi / simple-amb :トラフィックを指定された場所に転送するシンプルなアンバサダーコンテナ。 この場合、トラフィックを
etcd
に転送し、docker-register
コンテナにリンクして、そのコンテナがetcd
にアクセスできるようにします。 CoreOSでは、etcd
の場所は静的であるため、docker-register
がetcd
に直接アクセスするように変更された場合、これを削除できます。
マシンB
マシンBは、コンシューマーコンテナを実行するCoreOSマシンです。 HAProxy、およびメインのアンバサダーコンテナ。
- HAProxyリバースプロキシ:コンシューマーを表す、最初から作成する基本的なHAProxyコンテナー。 これは、アンバサダーのセットアップが機能することを示すために使用されます
- polvi / dynamic-etcd-amb :メインのアンバサダーコンテナ。 指定された
etcd
キーでプロバイダーコンテナのIPアドレスとポートを監視し、すべてのトラフィックをプロバイダーコンテナにルーティングする動的プロキシ。 キーの値は更新可能であり、プロキシはそれ自体を更新します - polvi / simple-amb :他のマシンで使用されているのと同じコンテナーですが、
dynamic-etcd-amb
をetcd
にリンクするために使用されます
ApacheDockerイメージを作成する
CoreOSマシンの1つにSSHで接続し、SSHエージェントを渡します(パブリックIPアドレスに置き換えます)。
ssh -A core@coreos-1_public_IP
次に、Dockerにログインします。
docker login
プロンプトが表示されたら、 user_name 、パスワード、および電子メールアドレスを入力します。
次に、ApacheDockerfileを書き込む新しいディレクトリを作成します。
mkdir -p ambassador/apache
次に、ディレクトリに移動し、Dockerfile
を開いて編集します。
cd ambassador/apache vi Dockerfile
CoreOSクラスターでサービスを作成して実行する方法のApacheコンテナーのセットアップに基づいて、次のDockerfileを作成できます(user_name
を独自のDockerユーザー名に置き換えてください)。
FROM ubuntu:14.04 MAINTAINER user_name RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get -y install apache2 && \ echo "<h1>Running from Docker on CoreOS</h1>" > /var/www/html/index.html EXPOSE 80 ENTRYPOINT ["/usr/sbin/apache2ctl"] CMD ["-D", "FOREGROUND"]
保存して終了します。
Apacheをインストールしてindex.htmlを基本的なメッセージに置き換えるDockerfileができたので、Dockerイメージを作成し、次のコマンドで「apache」という名前を付けます(独自のユーザー名に置き換えます)。
docker build --tag="user_name/apache" .
ここで、イメージを他のCoreOSマシンで使用できるようにするには、次のコマンドを使用して、イメージをDockerレジストリにpush
します。
docker push user_name/apache
これで、Apacheイメージを使用する準備が整いました。 HAProxyイメージの作成に移りましょう。
HAProxyDockerイメージを作成する
信頼できる自動Dockerビルド用のHAproxyDockerfileに基づいてHAProxyDockerイメージを作成します。 提供されているhaproxy.cfg
およびstart.bash
ファイルを少し変更します。
ambassador
ディレクトリで、git
を使用してHAProxyリポジトリのクローンを作成します。
cd ~/ambassador git clone https://github.com/dockerfile/haproxy.git
これにより、Dockerfile
、haproxy.cfg
、およびstart.bash
ファイルを含むhaproxy
ディレクトリが作成されます。
Dockerfileは基本的にHAProxyをインストールし、ポート80と443を公開するため、そのままにしておくことができます。
haproxy.cfg
ファイルを変更して、frontend
とbackend
を追加します。 haproxy.cfg
を開いて編集します。
cd haproxy vi haproxy.cfg
次に、次の行を見つけて削除します。
listen stats :80 stats enable stats uri /
次に、ファイルの最後に次の行を追加します。
frontend www-http bind :80 default_backend www-backend backend www-backend server apache private_ipv4:80 check
これにより、HAProxyがポート80でリッスンし、着信トラフィックを単一サーバーで構成されるwww-backend
に転送するように構成されます。 start.bash
スクリプトを使用して、private_ipv4
を、HAProxyコンテナーの起動時にこのコンテナーが実行されるCoreOSマシンのプライベートIPアドレスに置き換えます。 HAProxyがトラフィックをApacheコンテナに転送する動的アンバサダーコンテナは、同じマシンで実行されます。
start.bash
ファイルを開いて編集します。
vi start.bash
ファイルの下部に、このコンテナでHAProxyプロセスを開始する行があります。 次のようになります。
haproxy -f /etc/haproxy/haproxy.cfg -p "$PIDFILE"
この行のすぐ上に、次の行を挿入します。
# Set backend IP address to machine's private IP address PRIVATE_IPV4=$(curl -sw "\n" http://169.254.169.254/metadata/v1/interfaces/private/0/ipv4/address) sed -i -e "s/server apache private_ipv4:80 check/server apache ${PRIVATE_IPV4}:80 check/g" $HAPROXY/$CONFIG
保存して終了。 curl
コマンドは、DigitalOceanメタデータサービスを介してコンテナーが実行されるマシンのプライベートIPアドレスを取得します。 sed
コマンドは、haproxy.cfg
のprivate_ipv4
文字列をメタデータから取得した実際のIPアドレスに置き換えます。 このスクリプトはHAProxyコンテナ内から実行されるため、実行時にプライベートIPアドレスが構成されます。
これで、HAProxyDockerイメージを構築する準備が整いました。 Dockerイメージをビルドし、次のコマンドを使用して「haproxy」という名前を付けます(独自のユーザー名に置き換えます)。
docker build --tag="user_name/haproxy" .
ここで、イメージを他のCoreOSマシンで使用できるようにするには、次のコマンドを使用して、イメージをDockerレジストリにpush
します。
docker push user_name/haproxy
HAProxyイメージを使用する準備が整いました。 フリートサービスユニットファイルを作成する準備が整いました。
フリートサービスユニットファイル
必要なすべてのDockerイメージがCoreOSクラスターで利用できるようになったので、コンテナーのデプロイに必要なファイルの作業を始めましょう。 CoreOSクラスターを使用しているため、単一のCoreOSマシンからすべてのフリートサービスユニットファイルを作成およびスケジュールできます。
以前に作成した~/ambassador
ディレクトリにすべてのサービスファイルを作成するので、今すぐそのディレクトリに変更します。
cd ~/ambassador
apache.service
apache.service
ユニットはホストAで実行されます。
最初に作成するサービスファイルは、ApacheWebサーバーコンテナuser_name/apache
用です。 apache.service
というファイルを開いて、今すぐ編集します。
vi apache.service
次の行を追加します(両方の場所でDockerユーザー名に置き換えます)。
[Unit] Description=Apache web server service [Service] EnvironmentFile=/etc/environment ExecStartPre=-/usr/bin/docker kill %n ExecStartPre=-/usr/bin/docker rm %n ExecStartPre=/usr/bin/docker pull user_name/apache ExecStart=/usr/bin/docker run --rm --name %n -p ${COREOS_PRIVATE_IPV4}::80 user_name/apache ExecStop=/usr/bin/docker stop -t 3 %n
保存して終了。 これは、Apacheをフォアグラウンドモードで起動する非常に単純なサービスファイルです。 特に注目すべきは、コンテナ内のポート80をプライベートネットワークインターフェイス(-p ${COREOS_PRIVATE_IPV4}::80
)の動的ポートにバインドしていることです。
etcd-amb-apache.service
etcd-amb-apache.service
ユニットはホストAで実行されます。
次に、Apache登録コンテナーがetcd
にアクセスできるようにする単純なアンバサダーコンテナー(simple-amb
)のサービスファイルを作成します。 etcd-amb-apache.service
というファイルを今すぐ開きます。
vi etcd-amb-apache.service
次の行を追加します。
[Unit] Description=Simple Apache ambassador After=apache.service BindsTo=apache.service [Service] ExecStartPre=-/usr/bin/docker kill %n ExecStartPre=-/usr/bin/docker rm %n ExecStart=/usr/bin/docker run --rm --name %n polvi/simple-amb 172.17.42.1:4001 ExecStop=/usr/bin/docker stop -t 3 %n [X-Fleet] X-ConditionMachineOf=apache.service
保存して終了。
simple-amb
コンテナは、ポート10000で受信したすべてのトラフィックを、開始時に指定された引数に転送します。 172.17.42.1:4001
は、CoreOSでのetcd
の標準的な場所です。
X-ConditionMachineOf=apache.service
は、Apacheコンテナと同じマシンでこれをスケジュールするようにフリートに指示します。これはdocker-register
コンテナが、Apacheが使用しているIPアドレスとポートをetcd
。
apache-docker-reg.service
apache-docker-reg.service
ユニットはホストAで実行されます。
ApacheのIPアドレスとポートをetcd
、docker-register
に登録するコンテナのサービスファイルを作成しましょう。 apache-docker-reg.service
というファイルを今すぐ開きます。
vi apache-docker-reg.service
次の行を挿入します。
[Unit] Description=Register Apache After=etcd-amb-apache.service BindsTo=etcd-amb-apache.service [Service] ExecStartPre=-/usr/bin/docker kill %n ExecStartPre=-/usr/bin/docker rm %n ExecStart=/usr/bin/docker run --link etcd-amb-apache.service:etcd -v /var/run/docker.sock:/var/run/docker.sock --rm polvi/docker-register apache.service 80 apache-A [X-Fleet] X-ConditionMachineOf=etcd-amb-apache.service
保存して終了。 docker run
コマンドの注目すべき部分の内訳は次のとおりです。
--link etcd-amb-apache.service:etcd
は、このコンテナーを単純なアンバサダーにリンクします。このアンバサダーは、Apacheの接続情報をetcd
に渡すために使用されます。-v /var/run/docker.sock:/var/run/docker.sock
を使用すると、このコンテナーは、実行するマシンのDockerAPIを介してApacheがバインドしている動的ポートを判別できます。apache.service 80 apache-A
はこれらの引数をコンテナーに渡します。 最初の2つの引数は、検索するDockerコンテナーの名前とポートを指定し、3番目の引数は、書き込むetcd
キーの名前を指定します。 このコンテナが起動すると、apache.service
の動的ポートとIPアドレスが/services/apache-A/apache.service
キーに書き込まれます。
X-ConditionMachineOf=etcd-amb-apache.service
は、Dockerリンクにリンクされているため重要な単純なアンバサダーコンテナーと同じマシンでこれをスケジュールするようにフリートに指示し、登録コンテナーにetcd
を見つける方法を提供します。
etcd-amb-apache2.service
etcd-amb-apache2.service
ユニットはホストBで実行されます。
ダイナミックアンバサダーコンテナがetcd
にアクセスできるようにする、2番目のシンプルアンバサダーコンテナ(simple-amb
)のサービスファイルを作成します。 etcd-amb-apache2.service
というファイルを今すぐ開きます。
vi etcd-amb-apache2.service
次の行を追加します。
[Unit] Description=Simple Apache ambassador 2 [Service] ExecStartPre=-/usr/bin/docker kill %n ExecStartPre=-/usr/bin/docker rm %n ExecStart=/usr/bin/docker run --rm --name %n polvi/simple-amb 172.17.42.1:4001 ExecStop=/usr/bin/docker stop -t 3 %n [X-Fleet] X-Conflicts=apache.service
保存して終了。
これはetcd-amb-apache.service
とほぼ同じサービスファイルですが、X-Conflicts=apache.service
はフリートにApacheコンテナとは別のマシンでスケジュールするように指示し、ダイナミックアンバサダーをetcd
。
apache-dyn-amb.service
apache-dyn-amb.service
ユニットはホストBで実行されます。
ダイナミックアンバサダーコンテナがetcd
にアクセスできるようにする、ダイナミックアンバサダーコンテナ(dynamic-etd-amb
)のサービスファイルを作成します。 apache-dyn-amb.service
というファイルを今すぐ開きます。
vi apache-dyn-amb.service
次の行を追加します。
[Unit] Description=Dynamic ambassador for Apache After=etcd-amb-apache2.service BindsTo=etcd-amb-apache2.service [Service] EnvironmentFile=/etc/environment ExecStartPre=-/usr/bin/docker kill %n ExecStartPre=-/usr/bin/docker rm %n ExecStartPre=/usr/bin/docker pull polvi/dynamic-etcd-amb ExecStart=/usr/bin/docker run --link etcd-amb-apache2.service:etcd --rm --name %n -p ${COREOS_PRIVATE_IPV4}:80:80 polvi/dynamic-etcd-amb apache-A 80 ExecStop=/usr/bin/docker stop -t 3 %n [X-Fleet] X-ConditionMachineOf=etcd-amb-apache2.service
保存して終了。 docker run
コマンドの注目すべき部分の内訳は次のとおりです。
--link etcd-amb-apache2.service:etcd
は、このコンテナーを2番目の単純なアンバサダーにリンクします。このアンバサダーは、etcd
からApacheの接続情報を取得するために使用されます。-p ${COREOS_PRIVATE_IPV4}:80:80
は、コンテナのポート80とマシンのプライベートネットワークインターフェイスを公開しますapache-A 80
は、ポート80のトラフィックを指定する2つの引数です(つまり、 プライベートネットワークインターフェイスのポート80)は、etcd
でapache-A
として登録されているサービスにプロキシする必要があります。
X-ConditionMachineOf=etcd-amb-apache2.service
は、動的アンバサダーコンテナにetcd
を見つける方法を提供するために、Dockerリンクにリンクされているため重要な2番目のシンプルなアンバサダーコンテナと同じマシンでこれをスケジュールするようにフリートに指示します。
haproxy.service
haproxy.service
ユニットはホストBで実行されます。
動的アンバサダーコンテナを介してApacheコンテナに接続するために使用されるHAProxyコンテナ(haproxy
)のサービスファイルを作成します。 haproxy.service
というファイルを今すぐ開きます。
vi haproxy.service
次の行を追加します(両方の場所でDockerユーザー名に置き換えます)。
[Unit] Description=HAProxy consumer [Service] EnvironmentFile=/etc/environment ExecStartPre=-/usr/bin/docker kill %n ExecStartPre=-/usr/bin/docker rm %n ExecStartPre=/usr/bin/docker pull user_name/haproxy ExecStart=/usr/bin/docker run --name %n -p ${COREOS_PUBLIC_IPV4}:80:80 user_name/haproxy ExecStop=/usr/bin/docker stop -t 3 %n [X-Fleet] X-ConditionMachineOf=apache-dyn-amb.service
保存して終了。 これは単純なサービスファイルであり、HAProxyを起動し、ホストマシンのパブリックIPアドレスのポート80を公開します。 バックエンドサーバーは、ポート80のホストマシンのプライベートIPアドレスに構成されることに注意してください。これは、ダイナミックアンバサダーがApacheサービスにプロキシするトラフィックをリッスンしている場所です。
X-ConditionMachineOf=apache-dyn-amb.service
は、動的アンバサダーがHAProxyコンテナーにApacheコンテナーに到達するためのルートを提供するため、これを動的アンバサダーコンテナーと同じマシンでスケジュールするようにフリートに指示します。
フリートでデプロイ
必要なフリートサービスファイルがすべて揃ったので、最終的にアンバサダーセットアップをデプロイできます。 すべてのサービスファイルが含まれているディレクトリで、次のコマンドを実行します。
fleetctl start apache.service fleetctl start etcd-amb-apache.service fleetctl start apache-docker-reg.service fleetctl start etcd-amb-apache2.service fleetctl start apache-dyn-amb.service fleetctl start haproxy.service
各サービスがロードされたことを示すメッセージが表示されます。 フリートユニットのステータスを確認するには、次のコマンドを実行します。
fleetctl list-units
次のような出力が表示されます。
UNIT MACHINE ACTIVE SUB apache-docker-reg.service ceb3ead2.../10.132.233.107 active running apache-dyn-amb.service 3ce87ca7.../10.132.233.106 active running apache.service ceb3ead2.../10.132.233.107 active running etcd-amb-apache.service ceb3ead2.../10.132.233.107 active running etcd-amb-apache2.service 3ce87ca7.../10.132.233.106 active running haproxy.service 3ce87ca7.../10.132.233.106 active running
すべてのステータスはactive
およびrunning
である必要があります。 もう1つの注意点は、「マシンA」ユニットは同じマシン上にあり、「マシンB」ユニットは別のマシン上にある必要があるということです。これを確認するには、各ユニットのIPアドレスを確認してください。
セットアップのテスト
HAProxyがApacheに到達できることを確認する
HAProxyコンテナを特定のマシンで実行するように指定しなかったため、実行されている場所を見つける必要があります。 これを行う簡単な方法は、fleetctl ssh
コマンドを使用することです。
fleetctl ssh haproxy.service
これにより、haproxy.service
コンテナを実行しているマシンに接続されます。 これで、/etc/environment
ファイルを入手して、HAProxyを実行しているCoreOSマシンのパブリックIPアドレスを取得できます。
. /etc/environment echo $COREOS_PUBLIC_IPV4
結果のIPアドレスを取得し、Webブラウザを使用してアクセスします。 次の画像が表示されます。
HAProxyにアクセスしており、HAProxyは動的アンバサダープロキシを介してApacheにアクセスしていることに注意してください。
これで、現在のSSHセッションを終了して、元のSSHセッションに戻ることができます。
exit
フェイルオーバーのテスト
アンバサダーのセットアップが機能することを確認したので、プロバイダーサービス(apache.service
)がIPアドレスとポートを変更するとどうなるか見てみましょう。
fleetctl
を使用して、apache.service
を実行しているマシンに接続します。
fleetctl ssh apache.service
次に、Apacheが実行されているマシンを再起動します。
sudo reboot
注:SSH経由で最初に接続したマシンでapache.service
が実行されていた場合は、切断されます。 この場合は、同じCoreOSクラスター内の別のマシンにSSHで接続するだけです。
ここで、1分待って、実行中のユニットを確認します。
fleetctl list-units
待機時間によっては、「ホストA」に関連する3つのユニット(apache.service
、etcd-amb-apache.service
、およびapache-docker-reg.service
)が再起動またはアクティブになっていることがわかります。 最終的には、すべてアクティブ状態に戻るはずです。 実行したら、以前とは異なるマシンで実行されていることに注意してください。
次に、HAProxyに接続していたWebブラウザーに戻り、更新を押します。 以前と同じテストページが表示され、HAProxyがダイナミックアンバサダーを介してApacheに接続できることを示しています。
結論
独自のアンバサダーパターンを設定したので、このチュートリアルで提示された概念を独自のサービスに適合させることができるはずです。 これは、実行時にコンシューマーサービスを構成するための独自の方法であり、バックエンドプロバイダーサービスをマシン間で簡単に移動できます。 より現実的な設定では、おそらくApacheサービスを1つ以上のアプリケーションコンテナに置き換え、HAProxyを複数のバックエンドサーバーで構成する(またはまったく異なるコンシューマーサービスを使用する)可能性があります。