フリートユニットファイルを使用してCoreOSクラスター用の柔軟なサービスを作成する方法
ステータス:非推奨
理由: 2016年12月22日、CoreOSはフリートを維持しないことを発表しました。 フリートは、CoreOSから削除される2017年2月まで、セキュリティアップデートとバグ修正を受け取ります。 プロジェクトでは、すべてのクラスタリングのニーズにKubernetesを使用することを推奨しています。
代わりに参照してください:フリートなしでCoreOSでKubernetesを使用するガイダンスについては、CoreOSドキュメントのKubernetesを参照してください。
序章
CoreOSのインストールでは、多数のツールを活用して、クラスタリングとDockerに含まれるサービスを管理しやすくします。 etcd
は、個別のノードのリンクとグローバルデータ用の領域の提供に関与しますが、実際のサービス管理および管理タスクのほとんどは、fleet
デーモンの操作を伴います。
以前のガイドでは、サービスとクラスターメンバーを操作するためのfleetctl
コマンドの基本的な使用法について説明しました。 そのガイドでは、フリートがサービスを定義するために使用するユニットファイルについて簡単に触れましたが、これらはfleetctl
を学習するための実用的なサービスを提供するために使用される簡略化された例です。
このガイドでは、fleet
ユニットファイルを詳しく調べて、それらを作成する方法と、本番環境でサービスをより堅牢にするためのいくつかの手法について学習します。
前提条件
このチュートリアルを完了するために、クラスタリングガイドで説明されているようにCoreOSクラスターが構成されていることを前提としています。 これにより、次のような名前の3つのサーバーが残ります。
- coreos-1
- coreos-2
- coreos-3
このチュートリアルのほとんどはユニットファイルの作成に焦点を当てていますが、これらのマシンは、特定のディレクティブのスケジューリングへの影響を示すために後で使用されます。
また、fleetctlの使用方法に関するガイドを読んだことを前提としています。 これらのユニットファイルをクラスターで送信して使用できるように、fleetctl
の実用的な知識が必要です。
これらの要件を完了したら、ガイドの残りの部分に進みます。
ユニットファイルのセクションとタイプ
fleet
のサービス管理の側面は、主に各ローカルシステムのsystemd
initシステムに依存しているため、systemd
ユニットファイルを使用してサービスを定義します。
サービスはCoreOSで構成された最も一般的なユニットタイプですが、実際には定義できる他のユニットタイプがあります。 これらは、従来のsystemd
ユニットファイルで使用できるもののサブセットです。 これらの各タイプは、example.service
のように、ファイル拡張子として使用されているタイプによって識別されます。
- service :これは最も一般的なタイプのユニットファイルです。 これは、クラスター内のマシンの1つで実行できるサービスまたはアプリケーションを定義するために使用されます。
- socket :ソケットまたはソケットのようなファイルに関する詳細を定義します。 これらには、ネットワークソケット、IPCソケット、およびFIFOバッファが含まれます。 これらは、ファイルにトラフィックが見られたときに開始するサービスを呼び出すために使用されます。
- device :udevデバイスツリーで使用可能なデバイスに関する情報を定義します。 Systemdは、udevルールに基づいて、カーネルデバイスの個々のホストで必要に応じてこれらを作成します。 これらは通常、マウントを試みる前にデバイスが使用可能であることを確認するための注文の問題に使用されます。
- mount :デバイスのマウントポイントに関する情報を定義します。 これらは、参照するマウントポイントにちなんで名付けられ、スラッシュがダッシュに置き換えられています。
- automount :自動マウントポイントを定義します。 それらはマウントユニットと同じ命名規則に従い、関連するマウントユニットを伴う必要があります。 これらは、オンデマンドおよび並列マウントを説明するために使用されます。
- timer :別のユニットに関連付けられたタイマーを定義します。 このファイルで定義された時点に達すると、関連するユニットが開始されます。
- path :パスベースのアクティブ化を監視できるパスを定義します。 これは、特定のパスに変更が加えられたときに別のユニットを起動するために使用できます。
これらのオプションはすべて利用可能ですが、サービスユニットが最も頻繁に使用されます。 このガイドでは、サービスユニットの構成についてのみ説明します。
ユニットファイルは、ドットと上記のサフィックスのいずれかで終わる単純なテキストファイルです。 内部では、セクションごとに編成されています。 fleet
の場合、ほとんどのユニットファイルの一般的な形式は次のとおりです。
[Unit] generic_unit_directive_1 generic_unit_directive_2 [Service] service_specific_directive_1 service_specific_directive_2 service_specific_directive_3 [X-Fleet] fleet_specific_directive
ユニットファイル内のセクションヘッダーとその他すべては大文字と小文字が区別されます。 [Unit]
セクションは、ユニットに関する一般的な情報を定義するために使用されます。 すべてのユニットタイプに共通のオプションは、通常、ここに配置されます。
[Service]
セクションは、サービスユニットに固有のディレクティブを設定するために使用されます。 上記のユニットタイプのほとんど(すべてではありません)には、ユニットタイプ固有の情報に関連するセクションがあります。 詳細については、 generic systemd unit fileのマニュアルページで、さまざまなユニットタイプへのリンクを確認してください。
[X-Fleet]
セクションは、fleet
で使用するユニットのスケジューリング要件を設定するために使用されます。 このセクションを使用すると、ユニットをホストでスケジュールするために、特定の条件が真である必要があります。
メインサービスの構築
このセクションでは、CoreOSでのサービスの実行に関する基本ガイドで説明されているユニットファイルのバリアントから始めます。 このファイルはapache.1.service
と呼ばれ、次のようになります。
[Unit] Description=Apache web server service # Requirements Requires=etcd.service Requires=docker.service Requires=apache-discovery.1.service # Dependency ordering After=etcd.service After=docker.service Before=apache-discovery.1.service [Service] # Let processes take awhile to start up (for first run Docker containers) TimeoutStartSec=0 # Change killmode from "control-group" to "none" to let Docker remove # work correctly. KillMode=none # Get CoreOS environmental variables EnvironmentFile=/etc/environment # Pre-start and Start ## Directives with "=-" are allowed to fail without consequence ExecStartPre=-/usr/bin/docker kill apache ExecStartPre=-/usr/bin/docker rm apache ExecStartPre=/usr/bin/docker pull username/apache ExecStart=/usr/bin/docker run --name apache -p ${COREOS_PUBLIC_IPV4}:80:80 \ username/apache /usr/sbin/apache2ctl -D FOREGROUND # Stop ExecStop=/usr/bin/docker stop apache [X-Fleet] # Don't schedule on the same machine as other Apache instances X-Conflicts=apache.*.service
[Unit]
セクションから始めます。 ここでの基本的な考え方は、ユニットを記述し、依存関係情報を配置することです。 まず、一連の要件から始めます。 この例では、厳しい要件を使用しました。 fleet
で追加のサービスの開始を試みても、障害が発生しても停止しないようにする場合は、代わりにWants
ディレクティブを使用できます。
その後、要件の順序を明示的にリストします。 これは、必要なときに前提条件のサービスを利用できるようにするために重要です。 また、サイドキックなどを自動的に開始して、構築するサービスをアナウンスする方法でもあります。
[Service]
セクションでは、サービス起動タイムアウトをオフにします。 ホストでサービスを初めて実行するときは、コンテナをDockerレジストリからプルダウンする必要があります。これは、起動タイムアウトにカウントされます。 これはデフォルトで90秒に設定されており、通常は十分な時間ですが、より複雑なコンテナーでは、さらに時間がかかる場合があります。
次に、killmodeをnoneに設定します。 これが使用されるのは、通常のキルモード(control-group)により、コンテナー削除コマンドが失敗することがあるためです(特に、Dockerの--rm
オプションで試行された場合)。 これにより、次回の再起動時に問題が発生する可能性があります。
COREOS_PUBLIC_IPV4
にアクセスできるように環境ファイルを取得し、作成中にプライベートネットワークが有効になっている場合は、COREOS_PRIVATE_IPV4
環境変数にアクセスできるようにします。 これらは、特定のホストの情報を使用するようにDockerコンテナーを構成する場合に非常に役立ちます。
ExecStartPre
行は、実行環境がクリーンであることを確認するために、前の実行から残った残骸を破棄するために使用されます。 これらの最初の2つで=-
を使用して、これらのコマンドが失敗した場合にsystemd
を無視して続行する必要があることを示します。 このため、Dockerは以前のコンテナーを強制終了して削除しようとしますが、コンテナーが見つからなくても心配する必要はありません。 最後の事前開始は、コンテナーの最新バージョンが実行されていることを確認するために使用されます。
実際のstartコマンドは、Dockerコンテナーを起動し、それをホストマシンのパブリックIPv4インターフェイスにバインドします。 これにより、環境ファイルの情報が使用され、インターフェイスとポートを簡単に切り替えることができます。 実行中のプロセスが終了するとコンテナが終了するため、プロセスはフォアグラウンドで実行されます。 stopコマンドは、コンテナーを正常に停止しようとします。
[X-Fleet]
セクションには、fleet
に別のApacheサービスをまだ実行していないマシンでサービスをスケジュールするように強制する単純な条件が含まれています。 これは、重複するサービスを別々のマシンで強制的に開始することにより、サービスを高可用性にする簡単な方法です。
メインサービスを構築するための基本的なポイント
上記の例では、かなり基本的な構成を確認しました。 ただし、一般的なサービスの構築を支援するために、これからできることはたくさんあります。
メインサービスを構築する際に留意すべきいくつかの動作:
- 依存関係と順序付けの個別のロジック:依存関係を満たせない場合に、構築しているユニットが失敗するかどうかに応じて、
Requires=
またはWants=
ディレクティブを使用して依存関係をレイアウトします。 要件が変更された場合に簡単に調整できるように、注文をAfter=
とBefore=
の別々の行で区切ります。 依存関係リストを順序付けから分離すると、依存関係の問題が発生した場合のデバッグに役立ちます。 - 別のプロセスでサービス登録を処理する:サービス検出とこれが可能にする動的構成機能を利用するには、サービスを
etcd
に登録する必要があります。 ただし、ロジックを分離しておくために、これは別の「サイドキック」コンテナで処理する必要があります。 これにより、他のコンポーネントが必要とする外部の観点から見たサービスの状態をより正確にレポートできます。 - サービスがタイムアウトする可能性に注意してください:開始時間を長くできるように、
TimeoutStartSec
ディレクティブを調整することを検討してください。 これを「0」に設定すると、起動タイムアウトが無効になります。 Dockerがイメージをプルする必要がある場合があるため(初回実行時または更新が見つかった場合)、これが必要になることがよくあります。これにより、サービスの初期化にかなりの時間がかかる可能性があります。 - サービスが正常に停止しない場合はKillModeを調整します:サービスまたはコンテナーが正常に停止していないように見える場合は、
KillMode
オプションに注意してください。 これを「なし」に設定すると、停止後にコンテナが削除されないという問題を解決できる場合があります。 前回の実行で同じ名前のコンテナーが残されているとDockerが失敗するため、コンテナーに名前を付ける場合は特に重要です。 詳細については、KillModeのドキュメントを確認してください - 起動する前に環境をクリーンアップする:上記の項目に関連して、起動するたびに以前のDockerコンテナーを必ずクリーンアップしてください。 前回のサービスの実行が期待どおりに終了したと想定しないでください。 これらのクリーンアップラインは、
=-
指定子を使用して、クリーンアップが不要な場合にサイレントに失敗できるようにする必要があります。 通常はdocker stop
でコンテナを停止する必要がありますが、クリーンアップ中はおそらくdocker kill
を使用する必要があります。 - サービスの移植性のためにホスト固有の情報を取得して使用する:サービスを特定のネットワークインターフェイスにバインドする必要がある場合は、
/etc/environment
ファイルを取得してCOREOS_PUBLIC_IPV4
にアクセスします]および、構成されている場合はCOREOS_PRIVATE_IPV4
。 サービスを実行しているマシンのホスト名を知る必要がある場合は、%H
systemd指定子を使用してください。 可能な指定子の詳細については、systemd指定子のドキュメントをご覧ください。[X-Fleet]
セクションでは、%n
、%N
、%i
、および%p
指定子のみが機能します。
サイドキックアナウンスサービスの構築
メインサービスを構築する際に留意すべき点についての良いアイデアが得られたので、従来の「サイドキック」サービスの検討を開始できます。 これらのサイドキックサービスはメインサービスに関連付けられており、etcd
にサービスを登録するための外部ポイントとして使用されます。
このファイルは、本体ファイルで参照されているため、apache-discovery.1.service
と呼ばれ、次のようになります。
[Unit] Description=Apache web server etcd registration # Requirements Requires=etcd.service Requires=apache.1.service # Dependency ordering and binding After=etcd.service After=apache.1.service BindsTo=apache.1.service [Service] # Get CoreOS environmental variables EnvironmentFile=/etc/environment # Start ## Test whether service is accessible and then register useful information ExecStart=/bin/bash -c '\ while true; do \ curl -f ${COREOS_PUBLIC_IPV4}:80; \ if [ $? -eq 0 ]; then \ etcdctl set /services/apache/${COREOS_PUBLIC_IPV4} \'{"host": "%H", "ipv4_addr": ${COREOS_PUBLIC_IPV4}, "port": 80}\' --ttl 30; \ else \ etcdctl rm /services/apache/${COREOS_PUBLIC_IPV4}; \ fi; \ sleep 20; \ done' # Stop ExecStop=/usr/bin/etcdctl rm /services/apache/${COREOS_PUBLIC_IPV4} [X-Fleet] # Schedule on the same machine as the associated Apache service X-ConditionMachineOf=apache.1.service
メインサービスとほぼ同じ方法でサイドキックサービスを開始します。 依存関係情報と順序付けロジックに進む前に、ユニットの目的について説明します。
ここでの最初の新しいアイテムは、BindsTo=
ディレクティブです。 このディレクティブにより、このユニットは、リストされたユニットに送信された開始、停止、および再起動コマンドに従います。 基本的に、これは、両方がfleet
にロードされたら、メインユニットを操作することによって、これらのユニットの両方を管理できることを意味します。 これは一方向のメカニズムであるため、サイドキックを制御しても本体には影響しません。
[Service]
セクションでは、保持する変数が必要なため、/etc/environment
ファイルを再度ソースします。 この場合のExecStart=
ディレクティブは、基本的に短いbash
スクリプトです。 公開されたインターフェイスとポートを使用して、メインサービスに接続しようとします。
接続に成功した場合は、etcdctl
コマンドを使用して、etcd
内の/services/apache
内のホストマシンのパブリックIPアドレスにキーを設定します。 この値は、サービスに関する情報を含むJSONオブジェクトです。 キーは30秒で期限切れになるように設定されているため、このユニットが予期せずダウンした場合でも、etcd
に古いサービス情報が残ることはありません。 接続に失敗した場合、サービスが利用可能かどうかを確認できないため、キーはすぐに削除されます。
このループには、20秒のスリープコマンドが含まれます。 これは、20秒ごと(30秒etcd
キータイムアウトの前)に、このユニットが本体が使用可能かどうかを再チェックし、キーをリセットすることを意味します。 これにより、基本的にキーのTTLが更新され、さらに30秒間有効であると見なされます。
この場合のstopコマンドは、キーを手動で削除するだけです。 これにより、BindsTo=
ディレクティブにより、本体の停止コマンドが本機にミラーリングされると、サービス登録が削除されます。
[X-Fleet]
セクションでは、このユニットがメインユニットと同じサーバーで起動していることを確認する必要があります。 これにより、ユニットはリモートマシンへのサービスの可用性についてレポートできなくなりますが、BindsTo=
ディレクティブが正しく機能することが重要です。
サイドキックサービスを構築するための基本的なポイント
このサイドキックを構築する際に、これらのタイプのユニットの一般的なルールとして覚えておくべきいくつかのことを見ることができます。
- 本体の実際の可用性を確認する:本体の状態を実際に確認することが重要です。 サイドキックが初期化されたからといって、本体が使用可能であると思い込まないでください。 これは、本体の設計と機能に依存しますが、チェックが堅牢であるほど、登録状態の信頼性が高くなります。 チェックは、
/health
エンドポイントのチェックから、クライアントを使用したデータベースへの接続の試行まで、ユニットにとって意味のあるものであれば何でもかまいません。 - 登録ロジックをループして定期的に再確認します:開始時にサービスの可用性を確認することは重要ですが、定期的に再確認することも不可欠です。 これにより、予期しないサービス障害のインスタンスをキャッチできます。特に、コンテナが停止しない場合はなおさらです。 サイクル間の一時停止は、メインユニットの追加の負荷に対して迅速な検出の重要性を比較検討することにより、ニーズに応じて微調整する必要があります。
- 障害の自動登録解除のためにetcdに登録するときにTTLフラグを使用します:サイドキックユニットの予期しない障害により、
etcd
の検出情報が古くなる可能性があります。 サービスの登録状態と実際の状態の競合を回避するには、キーをタイムアウトさせる必要があります。 上記のループ構造を使用すると、タイムアウト間隔の前に各キーを更新して、サイドキックの実行中にキーが実際に期限切れにならないようにすることができます。 これが正しく機能するようにするには、ループ内のスリープ間隔をタイムアウト間隔よりわずかに短く設定する必要があります。 - 確認だけでなく、etcdに有用な情報を登録する:サイドキックの最初の反復では、ユニットの起動時に
etcd
に正確に登録することだけに関心がある場合があります。 しかし、これは他のサービスが利用するために多くの有用な情報を提供する機会を逃しました。 この情報は今は必要ないかもしれませんが、etcd
から独自の構成の値を読み取る機能を備えた他のコンポーネントを構築すると、より便利になります。etcd
サービスはグローバルなKey-Valueストアであるため、重要な情報を提供することでこれを活用することを忘れないでください。 JSONオブジェクトに詳細を保存することは、複数の情報を渡すための良い方法です。
これらの考慮事項を念頭に置くことで、etcd
が正しい情報を持っていることをインテリジェントに保証できる堅牢な登録ユニットの構築を開始できます。
フリート固有の考慮事項
fleet
ユニットファイルは、ほとんどの場合、従来のsystemd
ユニットファイルと同じですが、いくつかの追加機能と落とし穴があります。
最も明らかな違いは、[X-Fleet]
と呼ばれるセクションが追加されたことです。このセクションを使用して、fleet
にスケジューリングの決定方法を指示できます。 使用可能なオプションは次のとおりです。
- X-ConditionMachineID :これを使用して、ユニットをロードする正確なマシンを指定できます。 提供される値は完全なマシンIDです。 この値は、
/etc/machine-id
ファイルを調べることによってクラスターの個々のメンバーから取得するか、list-machines -l
コマンドを発行することによってfleetctl
を介して取得できます。 ID文字列全体が必要です。 これは、データディレクトリが特定のマシンに保持されているデータベースを実行している場合に必要になることがあります。 これを使用する特別な理由がない限り、ユニットの柔軟性が低下するため、使用しないようにしてください。 - X-ConditionMachineOf :このディレクティブを使用して、指定されたユニットがロードされているのと同じマシンでこのユニットをスケジュールできます。 これは、サイドキックユニットや関連するユニットをまとめる場合に役立ちます。
- X-Conflicts :これは、このユニットがと一緒にスケジュールできないユニットファイルを指定するという点で、上記の宣言の反対です。 これは、同じサービスの複数のバージョンをそれぞれ異なるマシンで開始することにより、高可用性を簡単に構成するのに役立ちます。
- X-ConditionMachineMetadata :これは、使用可能なマシンのメタデータに基づいてスケジューリング要件を指定するために使用されます。
fleetctl list-machines
出力の「METADATA」列には、各ホストに設定されているメタデータが表示されます。 メタデータを設定するには、サーバーインスタンスを初期化するときにcloud-config
ファイルにメタデータを渡します。 - Global :これは、クラスター内のすべてのマシンでスケジュールする必要があるかどうかを示すブール引数を取る特別なディレクティブです。 このディレクティブと一緒に使用できるのは、メタデータ条件付きのみです。
これらの追加のディレクティブにより、管理者は、使用可能なマシンでサービスを実行する方法を定義する際の柔軟性と能力が向上します。 これらは、fleetctl load
ステージで、特定のマシンのsystemd
インスタンスに渡す前に評価されます。
これにより、fleet
で関連するユニットを操作するときに注意すべき次のことがわかります。 fleetctl
ユーティリティは、ユニットファイルの[X-Fleet]
セクション以外の依存関係要件を評価しません。 これにより、fleet
のコンパニオンユニットを操作するときにいくつかの興味深い問題が発生します。
つまり、fleetctl
ツールは、ターゲットユニットを目的の状態にするために必要な手順を実行し、指定されたコマンドに基づいて必要に応じて送信、読み込み、開始のプロセスを実行しますが、実行しません。ユニットの依存関係のためにこれ。
したがって、メインユニットとサイドキックユニットの両方を送信したが、ロードしていない場合は、fleet
で、fleetctl start main.service
と入力するとロードされ、main.service
ユニットの起動が試行されます。 ただし、sidekick.service
ユニットはまだロードされておらず、fleetctl
は依存関係情報を評価して依存関係ユニットをロードおよび開始プロセスに通さないため、main.service
ユニットは失敗します。 これは、マシンのsystemd
インスタンスがmain.service
ユニットを処理すると、itが依存関係を評価するときにsidekick.service
を見つけることができないためです。 sidekick.service
ユニットがマシンにロードされたことはありません。
コンパニオンユニットを処理するときにこの状況を回避するには、サイドキックを実行状態にするBindsTo=
ディレクティブに依存せずに、同時に手動でサービスを開始できます。
fleetctl start main.service sidekick.service
もう1つのオプションは、メインユニットの実行時にサイドキックユニットが少なくともロードされていることを確認することです。 ロード段階では、マシンが選択され、ユニットファイルがローカルsystemd
インスタンスに送信されます。 これにより、依存関係が満たされ、BindsTo=
ディレクティブが正しく実行されて2番目のユニットが起動できるようになります。
fleetctl load main.service sidekick.service fleetctl start main.service
関連するユニットがfleetctl
コマンドに正しく応答しない場合は、このことに注意してください。
インスタンスとテンプレート
fleet
を使用する際の最も強力な概念の1つは、ユニットテンプレートです。
ユニットテンプレートは、「インスタンス」と呼ばれるsystemd
の機能に依存しています。 これらは、テンプレートユニットファイルを処理することによって実行時に作成されるインスタンス化されたユニットです。 テンプレートファイルは、ほとんどの場合、通常のユニットファイルと非常によく似ていますが、いくつかの小さな変更が加えられています。 ただし、これらは正しく使用すると非常に強力です。
テンプレートファイルは、ファイル名の@
で識別できます。 従来のサービスはこの形式を取りますが:
unit.service
テンプレートファイルは次のようになります。
[email protected]
ユニットがテンプレートからインスタンス化されると、そのインスタンス識別子は@
と.service
サフィックスの間に配置されます。 この識別子は、管理者が選択した一意の文字列です。
unit@instance_id.service
基本ユニット名は、%p
指定子によってユニットファイル内からアクセスできます。 同様に、指定されたインスタンス識別子には%i
でアクセスできます。
テンプレートとしてのメインユニットファイル
つまり、前に見た内容でapache.1.service
というメインユニットファイルを作成する代わりに、次のような[email protected]
というテンプレートを作成できます。
[Unit] Description=Apache web server service on port %i # Requirements Requires=etcd.service Requires=docker.service Requires=apache-discovery@%i.service # Dependency ordering After=etcd.service After=docker.service Before=apache-discovery@%i.service [Service] # Let processes take awhile to start up (for first run Docker containers) TimeoutStartSec=0 # Change killmode from "control-group" to "none" to let Docker remove # work correctly. KillMode=none # Get CoreOS environmental variables EnvironmentFile=/etc/environment # Pre-start and Start ## Directives with "=-" are allowed to fail without consequence ExecStartPre=-/usr/bin/docker kill apache.%i ExecStartPre=-/usr/bin/docker rm apache.%i ExecStartPre=/usr/bin/docker pull username/apache ExecStart=/usr/bin/docker run --name apache.%i -p ${COREOS_PUBLIC_IPV4}:%i:80 \ username/apache /usr/sbin/apache2ctl -D FOREGROUND # Stop ExecStop=/usr/bin/docker stop apache.%i [X-Fleet] # Don't schedule on the same machine as other Apache instances X-Conflicts=apache@*.service
ご覧のとおり、apache-discovery.1.service
の依存関係をapache-discovery@%i.service
に変更しました。 これは、[email protected]
というこのユニットファイルのインスタンスがある場合、[email protected]
というサイドキックが必要になることを意味します。 %i
はインスタンス識別子に置き換えられました。 この場合、識別子を使用して、サービスの実行方法、特にApacheサーバーが使用可能なポートに関する動的な情報を保持しています。
これを機能させるために、コンテナのポートをホスト上のポートに公開するdocker run
パラメータを変更しています。 静的ユニットファイルでは、使用したパラメーターは${COREOS_PUBLIC_IPV4}:80:80
で、コンテナーのポート80をパブリックIPv4インターフェイス上のホストのポート80にマップしました。 このテンプレートファイルでは、インスタンス識別子を使用して使用するポートを指定しているため、これを${COREOS_PUBLIC_IPV4}:%i:80
に置き換えました。 インスタンス識別子を賢く選択することは、テンプレートファイル内の柔軟性を高めることを意味します。
Docker名自体も変更され、インスタンスIDに基づく一意のコンテナー名も使用されるようになりました。 Dockerコンテナは@
シンボルを使用できないため、ユニットファイルから別の名前を選択したことに注意してください。 Dockerコンテナで動作するすべてのディレクティブを変更します。
[X-Fleet]
セクションでは、以前使用していた静的な種類ではなく、これらのインスタンス化されたユニットを認識するようにスケジューリング情報も変更しました。
テンプレートとしてのサイドキックユニット
同様の手順を実行して、サイドキックユニットをテンプレートに適合させることができます。
新しいサイドキックユニットは[email protected]
と呼ばれ、次のようになります。
[Unit] Description=Apache web server on port %i etcd registration # Requirements Requires=etcd.service Requires=apache@%i.service # Dependency ordering and binding After=etcd.service After=apache@%i.service BindsTo=apache@%i.service [Service] # Get CoreOS environmental variables EnvironmentFile=/etc/environment # Start ## Test whether service is accessible and then register useful information ExecStart=/bin/bash -c '\ while true; do \ curl -f ${COREOS_PUBLIC_IPV4}:%i; \ if [ $? -eq 0 ]; then \ etcdctl set /services/apache/${COREOS_PUBLIC_IPV4} \'{"host": "%H", "ipv4_addr": ${COREOS_PUBLIC_IPV4}, "port": %i}\' --ttl 30; \ else \ etcdctl rm /services/apache/${COREOS_PUBLIC_IPV4}; \ fi; \ sleep 20; \ done' # Stop ExecStop=/usr/bin/etcdctl rm /services/apache/${COREOS_PUBLIC_IPV4} [X-Fleet] # Schedule on the same machine as the associated Apache service X-ConditionMachineOf=apache@%i.service
静的バージョンではなく、インスタンス化されたバージョンのメインユニットプロセスを要求してバインドするのと同じ手順を実行しました。 これにより、インスタンス化されたサイドキックユニットが正しいインスタンス化されたメインユニットと一致します。
curl
コマンドで、サービスの実際の可用性を確認するときに、静的ポート80をインスタントIDに置き換えて、正しい場所に接続できるようにします。 これは、メインユニットのDockerコマンド内でポート公開マッピングを変更したために必要です。
また、etcd
に記録されている「ポート」を変更して、これと同じインスタンスIDを使用するようにします。 この変更により、etcd
に設定されているJSONデータは完全に動的になります。 ホスト名、IPアドレス、およびサービスが実行されているポートを取得します。
最後に、[X-Fleet]
セクションの条件を再度変更します。 このプロセスがメインユニットインスタンスと同じマシンで開始されていることを確認する必要があります。
テンプレートからのユニットのインスタンス化
テンプレートファイルからユニットを実際にインスタンス化するには、いくつかの異なるオプションがあります。
fleet
とsystemd
はどちらもシンボリックリンクを処理できます。これにより、次のように、テンプレートファイルへの完全なインスタンスIDを持つリンクを作成するオプションが提供されます。
ln -s [email protected] [email protected] ln -s [email protected] [email protected]
これにより、[email protected]
と[email protected]
という2つのリンクが作成されます。 これらのそれぞれには、fleet
およびsystemd
がこれらのユニットを実行するために必要なすべての情報が含まれています。 ただし、必要な変更を1か所で行えるように、テンプレートに戻されています。
次に、次のようにfleetctl
を使用して、これらのサービスを送信、ロード、または開始できます。
fleetctl start [email protected] [email protected]
インスタンスを定義するためのシンボリックリンクを作成したくない場合は、次のように、テンプレート自体をfleetctl
に送信することもできます。
fleetctl submit [email protected] [email protected]
実行時にインスタンス識別子を割り当てるだけで、fleetctl
内からこれらのテンプレートからユニットをインスタンス化できます。 たとえば、次のように入力すると、同じサービスを実行できます。
fleetctl start [email protected] [email protected]
これにより、シンボリックリンクが不要になります。 一部の管理者は、いつでもインスタンスファイルを利用できることを意味するため、リンクメカニズムを好みます。 また、ディレクトリをfleetctl
に渡して、すべてを一度に開始することもできます。
たとえば、作業ディレクトリには、テンプレートファイル用にtemplates
というサブディレクトリがあり、インスタンス化されたリンクバージョン用にinstances
というサブディレクトリがある場合があります。 テンプレート化されていないユニットには、static
という名前を付けることもできます。 あなたはそのようにこれを行うことができます:
mkdir templates instances static
次に、静的ファイルをstatic
に移動し、テンプレートファイルをtemplates
に移動できます。
mv apache.1.service apache-discovery.1.service static mv [email protected] [email protected] templates
ここから、必要なインスタンスリンクを作成できます。 ポート5555
、6666
、および7777
でサービスを実行してみましょう。
cd instances ln -s ../templates/[email protected] [email protected] ln -s ../templates/[email protected] [email protected] ln -s ../templates/[email protected] [email protected] ln -s ../templates/[email protected] [email protected] ln -s ../templates/[email protected] [email protected] ln -s ../templates/[email protected] [email protected]
次に、次のように入力して、すべてのインスタンスを一度に開始できます。
cd .. fleetctl start instances/*
これは、サービスをすばやく開始するのに非常に役立ちます。
結論
この時点で、fleet
のユニットファイルを作成する方法を十分に理解しているはずです。 ユニットファイル内で利用可能な動的機能のいくつかを利用することにより、サービスが均等に分散され、依存関係に近くなり、etcd
に有用な情報を登録できるようになります。
後のガイドでは、etcd
に登録している情報を使用するようにコンテナーを構成する方法について説明します。 これは、バックエンド内の適切なコンテナーに要求を渡すために、サービスが実際のデプロイメント環境の実用的な知識を構築するのに役立ちます。