フリートユニットファイルを使用してCoreOSクラスターの柔軟なサービスを作成する方法

前書き

CoreOSのインストールでは、多数のツールを活用して、クラスタリングとDockerに含まれるサービスの管理を容易にします。 `+ etcd `は個別のノードをリンクし、グローバルデータ用の領域を提供することに関与していますが、実際のサービス管理および管理タスクのほとんどは ` fleet +`デーモンと連携する必要があります。

https://www.digitalocean.com/community/tutorials/how-to-use-fleet-and-fleetctl-to-manage-your-coreos-cluster [前のガイド]で、サービスとクラスタメンバーを操作するための `+ fleetctl `コマンド。 そのガイドでは、フリートがサービスを定義するために使用するユニットファイルについて簡単に触れましたが、これらは ` fleetctl +`を学習するための実用的なサービスを提供するために使用される単純化された例です。

このガイドでは、 `+ fleet +`ユニットファイルを詳細に調査して、それらを作成する方法と、本番環境でサービスをより堅牢にするためのテクニックについて学習します。

前提条件

このチュートリアルを完了するために、https://www.digitalocean.com/community/tutorials/how-to-set-up-a-coreos-cluster-onで説明されているようにCoreOSクラスターが設定されていると仮定します-digitalocean [クラスタリングガイド]。 これにより、次のような名前の3つのサーバーが残ります。

  • coreos-1

  • coreos-2

  • coreos-3

このチュートリアルの大部分はユニットファイルの作成に焦点を当てていますが、これらのマシンは、特定のディレクティブのスケジューリングの影響を示すために後で使用されます。

また、https://www.digitalocean.com/community/tutorials/how-to-use-fleet-and-fleetctl-to-manage-your-coreos-cluster [使用方法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]



[Service]




[X-Fleet]

ユニットファイル内のセクションヘッダーおよびその他すべてでは、大文字と小文字が区別されます。 `+ [Unit] +`セクションは、ユニットに関する一般的な情報を定義するために使用されます。 すべてのユニットタイプに共通のオプションは、通常ここに配置されます。

`+ [Service] +`セクションは、サービスユニットに固有のディレクティブを設定するために使用されます。 上記のユニットタイプのほとんど(すべてではない)には、ユニットタイプ固有の情報のセクションが関連付けられています。 詳細については、http://www.freedesktop.org/software/systemd/man/systemd.unit.html [generic systemd unit file man page]でさまざまなユニットタイプへのリンクを確認してください。

「+ [X-Fleet] 」セクションは、「 fleet +」で使用するユニットのスケジューリング要件を設定するために使用されます。 このセクションを使用すると、ホストでユニットをスケジュールするために特定の条件が満たされていることを要求できます。

メインサービスの構築

このセクションでは、https://www.digitalocean.com/community/tutorials/how-to-create-and-run-a-service-on-a-coreosで説明されているユニットファイルのバリアントから始めます。 -cluster [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 /apache
ExecStart=/usr/bin/docker run --name apache -p ${COREOS_PUBLIC_IPV4}:80:80 \
/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 +`ディレクティブを使用できます。

その後、要件の順序を明示的にリストします。 これは、必要なときに必要なサービスを利用できるようにするために重要です。 また、構築するサイドキックetcdアナウンスサービスを自動的に開始する方法でもあります。

`+ [Service] +`セクションでは、サービスの起動タイムアウトをオフにします。 ホストでサービスを初めて実行する場合、コンテナはDockerレジストリから取得する必要があります。Dockerレジストリは起動タイムアウトにカウントされます。 これはデフォルトで90秒に設定されており、通常は十分な時間になりますが、より複雑なコンテナーの場合は、さらに時間がかかる場合があります。

次に、killmodeをnoneに設定します。 これは、通常の強制終了モード(control-group)でコンテナー削除コマンドが失敗することがあるため(特にDockerの「+-rm +」オプションで試行された場合)に使用されます。 これは、次回の再起動時に問題を引き起こす可能性があります。

環境ファイルをプルして、 `+ COREOS_PUBLIC_IPV4 `と、作成中にプライベートネットワークが有効になっている場合は、 ` COREOS_PRIVATE_IPV4 +`環境変数にアクセスできるようにします。 これらは、特定のホストの情報を使用するようにDockerコンテナーを構成するのに非常に便利です。

`+ ExecStartPre`行は、実行環境がクリーンであることを確認するために、以前の実行で残った不要なデータを破棄するために使用されます。 これらの最初の2つで「+ =-」を使用して、これらのコマンドが失敗した場合に「 systemd +」が無視して続行することを示します。 このため、Dockerは以前のコンテナーを削除および削除しようとしますが、コンテナーが見つからなくても心配することはありません。 最後の事前開始は、コンテナの最新バージョンが実行されていることを確認するために使用されます。

実際の開始コマンドはDockerコンテナーを起動し、ホストマシンのパブリックIPv4インターフェースにバインドします。 これは環境ファイルの情報を使用し、インターフェースとポートの切り替えを簡単にします。 実行中のプロセスが終了するとコンテナが終了するため、プロセスはフォアグラウンドで実行されます。 停止コマンドは、コンテナを正常に停止しようとします。

`+ [X-Fleet] `セクションには、別のApacheサービスをまだ実行していないマシンで ` fleet +`にサービスのスケジュールを強制する単純な条件が含まれています。 これは、重複するサービスを別のマシンで強制的に開始することにより、サービスの可用性を高める簡単な方法です。

主なサービスを構築するための基本的な注意

上記の例では、かなり基本的な構成を検討しました。 ただし、一般的なサービスの構築を支援するために、これからできることはたくさんあります。

メインサービスを構築する際に留意すべきいくつかの動作:

  • 依存関係と順序の分離ロジック:依存関係を満たせない場合、構築中のユニットが失敗するかどうかに応じて、 `+ Requires = `または ` Wants = `ディレクティブで依存関係をレイアウトします。 要件が変更された場合に簡単に調整できるように、個別の ` After = `と ` Before = +`の行で順序を分けます。 依存関係リストを順序付けから分離すると、依存関係の問題が発生した場合のデバッグに役立ちます。

  • 別のプロセスでサービス登録を処理する:サービスの検出とこれが許可する動的構成機能を利用するには、サービスを「+ etcd +」に登録する必要があります。 ただし、ロジックを分離するために、これは別の「サイドキック」コンテナで処理する必要があります。 これにより、他のコンポーネントが必要とする外部の観点から見たサービスの状態をより正確にレポートできます。

  • サービスがタイムアウトする可能性に注意してください:開始時間が長くなるように、 `+ TimeoutStartSec +`ディレクティブの調整を検討してください。 これを「0」に設定すると、起動タイムアウトが無効になります。 これは、Dockerがイメージをプルする必要がある場合があるため(最初の実行時または更新が見つかった場合)、サービスの初期化にかなりの時間を追加する可能性があるためです。

  • サービスが正常に停止しない場合はKillModeを調整します:サービスまたはコンテナが正常に停止していないように思われる場合は、 `+ KillMode +`オプションに注意してください。 これを「なし」に設定すると、停止後にコンテナが削除されないという問題を解決できる場合があります。 これは、同じ名前のコンテナーが前回の実行で残された場合にDockerが失敗するため、コンテナーに名前を付けるときに特に重要です。 http://www.freedesktop.org/software/systemd/man/systemd.kill.html [詳細についてはKillModeのドキュメント]をご覧ください。

  • 起動前に環境をクリーンアップ:上記の項目に関連して、起動するたびに以前のDockerコンテナを必ずクリーンアップしてください。 サービスの前回の実行が期待どおりに終了したと想定しないでください。 これらのクリーンアップ行では、クリーンアップが不要な場合にサイレントで失敗するように、「+ =-」指定子を使用する必要があります。 通常はコンテナを ` docker stop `で停止する必要がありますが、おそらくクリーンアップ中に ` docker kill +`を使用する必要があります。

  • サービスの移植性のためにホスト固有の情報を引き出して使用する:サービスを特定のネットワークインターフェイスにバインドする必要がある場合は、 + / etc / environment +`ファイルをプルして `+ COREOS_PUBLIC_IPV4 +`にアクセスし、構成されている場合、 `+ COREOS_PRIVATE_IPV4 +。 サービスを実行しているマシンのホスト名を知る必要がある場合は、 +%H + systemd指定子を使用します。 指定可能な指定子の詳細については、http://www.freedesktop.org/software/systemd/man/systemd.unit.html#Specifiers [systemd specifiers docs]をご覧ください。 + [X-Fleet] +`セクションでは、 `+%n ++%N ++%i +、および `+%p +`指定子のみが機能します。

Sidekick Announce Serviceの構築

メインサービスを構築する際に留意すべき事項についてのアイデアが得られたので、従来の「サイドキック」サービスの検討を開始できます。 これらのサイドキックサービスはメインサービスに関連付けられ、サービスを `+ 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秒間有効と見なされます。

この場合の停止コマンドは、キーを手動で削除するだけです。 これにより、メインユニットの停止コマンドが `+ BindsTo = +`ディレクティブによりこのユニットにミラーリングされると、サービス登録が削除されます。

`+ [X-Fleet] `セクションでは、このユニットがメインユニットと同じサーバー上で起動することを確認する必要があります。 これにより、ユニットがリモートマシンへのサービスの可用性についてレポートすることはできませんが、 ` BindsTo = +`ディレクティブが正しく機能することが重要です。

Sidekickサービスを構築するための基本的な準備

この相棒を構築する際に、これらのタイプのユニットの一般的なルールとして留意すべきことがいくつかあります。

  • メインユニットの実際の可用性を確認する:メインユニットの状態を実際に確認することが重要です。 サイドキックが初期化されたという理由だけでメインユニットが使用可能であると想定しないでください。 これは、メインユニットの設計と機能に依存しますが、チェックの堅牢性が高いほど、登録状態の信頼性が高まります。 チェックは、ユニットで意味のあるものであれば何でもかまいません。「+ / health」エンドポイントのチェックから、クライアントを使用したデータベースへの接続の試行までです。

  • 登録ロジックをループして定期的に再確認する:開始時にサービスの可用性を確認することは重要ですが、定期的に再確認することも不可欠です。 これにより、特に何らかの理由でコンテナが停止しない場合に、予期しないサービス障害のインスタンスをキャッチできます。 サイクル間の休止は、メインユニットの追加の負荷に対する迅速な検出の重要性を考慮して、ニーズに応じて調整する必要があります。

  • 失敗時の自動登録解除のためにetcdに登録するときはTTLフラグを使用します:サイドキックユニットの予期しない失敗により、 `+ etcd +`の失効した検出情報が生じる可能性があります。 サービスの登録状態と実際の状態の競合を避けるために、キーをタイムアウトさせる必要があります。 上記のループ構造を使用すると、タイムアウト間隔の前に各キーを更新して、サイドキックの実行中にキーが実際に期限切れにならないようにすることができます。 この機能を正しく機能させるには、ループのスリープ間隔をタイムアウト間隔よりわずかに短く設定する必要があります。

  • 確認だけでなく、etcdに有用な情報を登録します:サイドキックの最初のイテレーションでは、ユニットの起動時に `+ etcd `で正確に登録することにのみ関心があるかもしれません。 ただし、これは他のサービスが利用するための多くの有用な情報を提供する機会を逃しています。 現時点ではこの情報は必要ないかもしれませんが、独自の設定のために ` etcd `から値を読み取る機能を備えた他のコンポーネントを構築すると、より便利になります。 ` etcd +`サービスはグローバルなキーと値のストアなので、キー情報を提供することでこれを活用することを忘れないでください。 JSONオブジェクトに詳細を保存すると、複数の情報を渡すことができます。

これらの考慮事項を念頭に置くことで、 `+ etcd +`に正しい情報があることをインテリジェントに保証できる堅牢な登録ユニットの構築を開始できます。

フリート固有の考慮事項

`+ fleet `ユニットファイルの大部分は従来の ` systemd +`ユニットファイルと変わりませんが、いくつかの追加機能と落とし穴があります。

最も明らかな違いは、スケジューリングの決定方法を「フリート」に指示するために使用できる「+ [X-Fleet] +」というセクションが追加されていることです。 利用可能なオプションは次のとおりです。

  • * X-ConditionMachineID *:これは、ユニットをロードする正確なマシンを指定するために使用できます。 指定された値は完全なマシンIDです。 この値は、 `+ / etc / machine-id `ファイルを調べることでクラスターの個々のメンバーから取得するか、 ` list-machines -l `コマンドを発行して ` fleetctl +`から取得できます。 ID文字列全体が必要です。 これは、特定のマシンにデータディレクトリを保持してデータベースを実行している場合に必要になることがあります。 これを使用する特別な理由がない限り、ユニットの柔軟性を低下させるため、それを避けるようにしてください。

  • * X-ConditionMachineOf *:このディレクティブは、指定されたユニットがロードされている同じマシンでこのユニットをスケジュールするために使用できます。 これは、サイドキックユニットまたは関連するユニットをまとめてまとめるのに役立ちます。

  • * X-Conflicts *:これは上記の宣言の反対です。このユニットは、このユニットが一緒にスケジュールできないユニットファイルを指定するという点で。 これは、それぞれが異なるマシンで同じサービスの複数のバージョンを開始することにより、高可用性を簡単に構成するのに役立ちます。

  • * X-ConditionMachineMetadata *:これは、使用可能なマシンのメタデータに基づいてスケジューリング要件を指定するために使用されます。 `+ fleetctl list-machines `出力の「METADATA」列で、各ホストに設定されたメタデータを確認できます。 メタデータを設定するには、サーバーインスタンスの初期化時にそれを ` cloud-config +`ファイルに渡します。

  • グローバル:これは、クラスター内のすべてのマシンでこれをスケジュールするかどうかを示すブール引数を取る特別なディレクティブです。 このディレクティブと一緒に使用できるのはメタデータ条件のみです。

これらの追加のディレクティブにより、管理者は、利用可能なマシン上でサービスを実行する方法を定義する際の柔軟性とパワーを高めることができます。 これらは、 `+ 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

別のオプションは、メインユニットの実行時にサイドキックユニットが少なくともロードされるようにすることです。 ロード段階では、マシンが選択され、ユニットファイルがローカルの「+ systemd 」インスタンスに送信されます。 これにより、依存関係が満たされ、 ` BindsTo = +`ディレクティブが2番目のユニットを起動するために正しく実行できるようになります。

fleetctl load main.service sidekick.service
fleetctl start main.service

関連するユニットが `+ fleetctl +`コマンドに正しく応答しない場合は、このことに留意してください。

インスタンスとテンプレート

`+ fleet +`を使用する際の最も強力な概念の1つは、ユニットテンプレートです。

ユニットテンプレートは、「インスタンス」と呼ばれる「+ systemd +」の機能に依存しています。 これらは、テンプレートユニットファイルを処理することにより実行時に作成されるインスタンス化されたユニットです。 テンプレートファイルの大部分は、いくつかの小さな変更を加えた通常のユニットファイルに非常に似ています。 ただし、これらは正しく使用すると非常に強力です。

テンプレートファイルは、ファイル名の「+ @ +」で識別できます。 従来のサービスはこの形式を取りますが:

.service

テンプレートファイルは次のようになります。

@.service

ユニットがテンプレートからインスタンス化されると、そのインスタンス識別子は「+ @ 」と「 .service +」サフィックスの間に配置されます。 この識別子は、管理者が選択した一意の文字列です。

@.service

ベースユニット名は、ユニットファイル内から `%p +`指定子によってアクセスできます。 同様に、与えられたインスタンス識別子は `%i +`でアクセスできます。

テンプレートとしてのメインユニットファイル

これは、先ほど見た内容で `+ apache.1.service `というメインユニットファイルを作成する代わりに、次のような ` apache @ .service +`というテンプレートを作成できることを意味します。

[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 /apache
ExecStart=/usr/bin/docker run --name apache.%i -p ${COREOS_PUBLIC_IPV4}:%i:80 \
/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] +」セクションでは、以前使用していた静的な種類ではなく、これらのインスタンス化されたユニットを認識するようにスケジューリング情報も変更しました。

テンプレートとしてのサイドキックユニット

同様の手順を実行して、サイドキックユニットをテンプレート化に適合させることができます。

新しいサイドキックユニットは「+ apache-discovery @ .service +」と呼ばれ、次のようになります。

[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コマンド内でポートエクスポージャーマッピングを変更したために必要です。

また、同じインスタンスIDを使用するように、「+ etcd 」に記録される「ポート」を変更します。 この変更により、 ` etcd +`に設定されるJSONデータは完全に動的になります。 ホスト名、IPアドレス、およびサービスが実行されているポートを取得します。

最後に、 `+ [X-Fleet] +`セクションの条件を再度変更します。 このプロセスは、メインユニットインスタンスと同じマシンで開始する必要があります。

テンプレートからユニットをインスタンス化する

テンプレートファイルからユニットを実際にインスタンス化するには、いくつかの異なるオプションがあります。

`+ fleet `と ` systemd +`はどちらもシンボリックリンクを処理できます。これにより、次のように、テンプレートファイルへの完全なインスタンスIDを持つリンクを作成するオプションが提供されます。

これにより、「+ [email protected]+」と「[email protected]」という2つのリンクが作成されます。 これらのそれぞれは、 `+ fleet `と ` systemd +`がこれらのユニットを実行するために必要なすべての情報を持っています。 ただし、必要な変更を1か所で行えるように、テンプレートを指すようになっています。

次に、次のように `+ fleetctl +`でこれらのサービスを送信、ロード、または開始できます。

インスタンスを定義するためのシンボリックリンクを作成したくない場合は、次のように、テンプレート自体を `+ fleetctl +`に送信することもできます。

実行時にインスタンス識別子を割り当てるだけで、これらのテンプレートからユニットを `+ fleetctl +`内から直接インスタンス化できます。 たとえば、次のように入力して同じサービスを実行できます。

これにより、シンボリックリンクが不要になります。 一部の管理者は、リンクメカニズムを好みますが、これは、インスタンスファイルをいつでも利用できることを意味するためです。 また、ディレクトリを `+ 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 ..
fleetctl start instances/*

これは、サービスをすばやく起動するのに非常に役立ちます。

結論

この時点までに、 `+ fleet `のユニットファイルを構築する方法を十分に理解している必要があります。 ユニットファイル内で利用可能ないくつかの動的な機能を利用することで、サービスが均等に分散され、依存関係に近くなり、 ` etcd +`で有用な情報を登録することができます。

https://www.digitalocean.com/community/tutorials/how-to-use-confd-and-etcd-to-dynamically-reconfigure-services-in-coreos [後のガイド]で、設定方法を説明します`+ etcd +`で登録している情報を使用するコンテナ。 これは、バックエンドの適切なコンテナにリクエストを渡すために、実際のデプロイメント環境の実用的な知識を構築するサービスを支援します。