アンバサダーパターンを使用してCoreOSでサービスを動的に構成する方法

提供:Dev Guides
移動先:案内検索

序章

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-registeretcdに直接アクセスするように変更された場合、これを削除できます。

マシンB

マシンBは、コンシューマーコンテナを実行するCoreOSマシンです。 HAProxy、およびメインのアンバサダーコンテナ。

  • HAProxyリバースプロキシコンシューマーを表す、最初から作成する基本的なHAProxyコンテナー。 これは、アンバサダーのセットアップが機能することを示すために使用されます
  • polvi / dynamic-etcd-amb :メインのアンバサダーコンテナ。 指定されたetcdキーでプロバイダーコンテナのIPアドレスとポートを監視し、すべてのトラフィックをプロバイダーコンテナにルーティングする動的プロキシ。 キーの値は更新可能であり、プロキシはそれ自体を更新します
  • polvi / simple-amb :他のマシンで使用されているのと同じコンテナーですが、dynamic-etcd-ambetcdにリンクするために使用されます

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

これにより、Dockerfilehaproxy.cfg、およびstart.bashファイルを含むhaproxyディレクトリが作成されます。

Dockerfileは基本的にHAProxyをインストールし、ポート80と443を公開するため、そのままにしておくことができます。

haproxy.cfgファイルを変更して、frontendbackendを追加します。 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.cfgprivate_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アドレスとポートをetcddocker-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)は、etcdapache-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.serviceetcd-amb-apache.service、およびapache-docker-reg.service)が再起動またはアクティブになっていることがわかります。 最終的には、すべてアクティブ状態に戻るはずです。 実行したら、以前とは異なるマシンで実行されていることに注意してください。

次に、HAProxyに接続していたWebブラウザーに戻り、更新を押します。 以前と同じテストページが表示され、HAProxyがダイナミックアンバサダーを介してApacheに接続できることを示しています。

結論

独自のアンバサダーパターンを設定したので、このチュートリアルで提示された概念を独自のサービスに適合させることができるはずです。 これは、実行時にコンシューマーサービスを構成するための独自の方法であり、バックエンドプロバイダーサービスをマシン間で簡単に移動できます。 より現実的な設定では、おそらくApacheサービスを1つ以上のアプリケーションコンテナに置き換え、HAProxyを複数のバックエンドサーバーで構成する(またはまったく異なるコンシューマーサービスを使用する)可能性があります。