開発者ドキュメント

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

ステータス:非推奨

理由: 2016年12月22日、CoreOSはフリートを維持しないことを発表しました。 フリートは、CoreOSから削除される2017年2月まで、セキュリティアップデートとバグ修正を受け取ります。 プロジェクトでは、すべてのクラスタリングのニーズにKubernetesを使用することを推奨しています。

代わりに参照してください:フリートなしでCoreOSでKubernetesを使用するガイダンスについては、CoreOSドキュメントのKubernetesを参照してください。

序章

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

前のガイドでは、 fleetctl サービスとクラスターメンバーを操作するためのコマンド。 そのガイドでは、フリートがサービスを定義するために使用するユニットファイルについて簡単に触れましたが、これらは、学習するための実用的なサービスを提供するために使用される簡略化された例です。 fleetctl.

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

前提条件

このチュートリアルを完了するために、クラスタリングガイドで説明されているようにCoreOSクラスターが構成されていることを前提としています。 これにより、次のような名前の3つのサーバーが残ります。

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

また、fleetctlの使用方法に関するガイドを読んだことを前提としています。 あなたはの実用的な知識を持っている必要があります fleetctl これらのユニットファイルをクラスターで送信して使用できるようにします。

これらの要件を完了したら、ガイドの残りの部分に進みます。

ユニットファイルのセクションとタイプ

のサービス管理の側面のため fleet 主に各ローカルシステムに依存します systemd initシステム、 systemd ユニットファイルは、サービスを定義するために使用されます。

サービスはCoreOSで構成された最も一般的なユニットタイプですが、実際には定義できる他のユニットタイプがあります。 これらは、従来の方法で利用できるもののサブセットです。 systemd ユニットファイル。 これらの各タイプは、ファイル拡張子として使用されているタイプによって識別されます。 example.service:

これらのオプションはすべて利用可能ですが、サービスユニットが最も頻繁に使用されます。 このガイドでは、サービスユニットの構成についてのみ説明します。

ユニットファイルは、ドットと上記のサフィックスのいずれかで終わる単純なテキストファイルです。 内部では、セクションごとに編成されています。 為に 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

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

The [Service] セクションは、サービスユニットに固有のディレクティブを設定するために使用されます。 上記のユニットタイプのほとんど(すべてではありません)には、ユニットタイプ固有の情報に関連するセクションがあります。 詳細については、 generic systemd unit fileのマニュアルページで、さまざまなユニットタイプへのリンクを確認してください。

The [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コンテナーを構成する場合に非常に役立ちます。

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

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

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

メインサービスを構築するための基本的なポイント

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

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

サイドキックアナウンスサービスの構築

メインサービスを構築する際に留意すべき点についての良いアイデアが得られたので、従来の「サイドキック」サービスの検討を開始できます。 これらのサイドキックサービスはメインサービスに関連付けられており、サービスを登録するための外部ポイントとして使用されます。 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 保持する変数が必要なため、ファイル。 The ExecStart= この場合のディレクティブは基本的に短いです bash 脚本。 公開されたインターフェイスとポートを使用して、メインサービスに接続しようとします。

接続が成功した場合、 etcdctl コマンドは、内のホストマシンのパブリックIPアドレスにキーを設定するために使用されます /services/apache 内部 etcd. この値は、サービスに関する情報を含むJSONオブジェクトです。 キーは30秒で期限切れになるように設定されているため、このユニットが予期せずダウンした場合でも、古いサービス情報が残されることはありません etcd. 接続に失敗した場合、サービスが利用可能かどうかを確認できないため、キーはすぐに削除されます。

このループには、20秒のスリープコマンドが含まれます。 これは、20秒ごと(30秒前)を意味します etcd キータイムアウト)、本機は本体が使用可能かどうかを再確認し、キーをリセットします。 これにより、基本的にキーのTTLが更新され、さらに30秒間有効であると見なされます。

この場合のstopコマンドは、キーを手動で削除するだけです。 これにより、本体の停止コマンドが本機にミラーリングされた場合、サービス登録が削除されます。 BindsTo= 指令。

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

サイドキックサービスを構築するための基本的なポイント

このサイドキックを構築する際に、これらのタイプのユニットの一般的なルールとして覚えておくべきいくつかのことを見ることができます。

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

フリート固有の考慮事項

その間 fleet ユニットファイルは、ほとんどの場合、従来のものと同じです。 systemd ユニットファイルには、いくつかの追加機能と落とし穴があります。

最も明らかな違いは、 [X-Fleet] 指示するために使用することができます fleet スケジューリングの決定を行う方法について。 使用可能なオプションは次のとおりです。

これらの追加のディレクティブにより、管理者は、使用可能なマシンでサービスを実行する方法を定義する際の柔軟性と能力が向上します。 これらは、特定のマシンに渡す前に評価されます systemd 中のインスタンス fleetctl load ステージ。

これにより、関連するユニットを操作するときに注意すべき次のことがわかります。 fleet. The fleetctl ユーティリティは、外部の依存関係要件を評価しません [X-Fleet] ユニットファイルのセクション。 これは、コンパニオンユニットを操作するときにいくつかの興味深い問題につながります fleet.

これは、 fleetctl ツールは、ターゲットユニットを目的の状態にするために必要な手順を実行し、指定されたコマンドに基づいて必要に応じて送信、ロード、および開始プロセスを実行します。ユニットの依存関係に対してはこれを実行しません。

したがって、メインユニットとサイドキックユニットの両方を送信したが、ロードしていない場合は、 fleet、入力 fleetctl start main.service ロードしてから開始を試みます main.service 単位。 ただし、 sidekick.service ユニットはまだロードされていません。 fleetctl 依存関係情報を評価して、依存関係ユニットをロードおよび開始プロセスに持ち込むことはありません。 main.service ユニットは故障します。 これは、かつてのマシンが systemd インスタンスは main.service ユニット、それは見つけることができなくなります sidekick.service itが依存関係を評価するとき。 The sidekick.service ユニットがマシンにロードされたことはありません。

コンパニオンユニットを扱うときにこの状況を回避するために、サービスを同時に開始することができます。 BindsTo= サイドキックを実行状態にするディレクティブ:

fleetctl start main.service sidekick.service

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

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

あなたの関連するユニットがあなたに正しく反応しない場合には、これを覚えておいてください fleetctl コマンド。

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

で作業するときの最も強力な概念の1つ fleet 単位テンプレートです。

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

テンプレートファイルは、 @ それらのファイル名で。 従来のサービスはこの形式を取りますが:

unit.service

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

unit@.service

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

unit@instance_id.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 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. これは、このユニットファイルのインスタンスが apache@8888.service、これにはと呼ばれる相棒が必要になります apache-discovery@8888.service. The %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コマンド内でポート公開マッピングを変更したために必要です。

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

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

テンプレートからのユニットのインスタンス化

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

両方 fleetsystemd シンボリックリンクを処理できます。これにより、次のように、完全なインスタンスIDを使用してテンプレートファイルへのリンクを作成するオプションが提供されます。

ln -s apache@.service apache@8888.service
ln -s apache-discovery@.service apache-discovery@8888.service

これにより、2つのリンクが作成されます。 apache@8888.serviceapache-discovery@8888.service. これらのそれぞれには、に必要なすべての情報があります fleetsystemd これらのユニットを今すぐ実行します。 ただし、必要な変更を1か所で行えるように、テンプレートに戻されています。

その後、これらのサービスを送信、ロード、または開始できます。 fleetctl このような:

fleetctl start apache@8888.service apache-discovery@8888.service

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

fleetctl submit apache@.service apache-discovery@.service

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

fleetctl start apache@8888.service apache-discovery@8888.service

これにより、シンボリックリンクが不要になります。 一部の管理者は、いつでもインスタンスファイルを利用できることを意味するため、リンクメカニズムを好みます。 また、ディレクトリをに渡すこともできます fleetctl すべてが一度に開始されるようにします。

たとえば、作業ディレクトリには、というサブディレクトリがあります。 templates テンプレートファイルとサブディレクトリ instances インスタンス化されたリンクバージョンの場合。 あなたも static テンプレート化されていないユニットの場合。 あなたはそのようにこれを行うことができます:

mkdir templates instances static

次に、静的ファイルをに移動できます static とテンプレートファイルを templates:

mv apache.1.service apache-discovery.1.service static
mv apache@.service apache-discovery@.service templates

ここから、必要なインスタンスリンクを作成できます。 ポートでサービスを実行してみましょう 5555, 6666、 と 7777:

cd instances
ln -s ../templates/apache@.service apache@5555.service
ln -s ../templates/apache@.service apache@6666.service
ln -s ../templates/apache@.service apache@7777.service
ln -s ../templates/apache-discovery@.service apache-discovery@5555.service
ln -s ../templates/apache-discovery@.service apache-discovery@6666.service
ln -s ../templates/apache-discovery@.service apache-discovery@7777.service

次に、次のように入力して、すべてのインスタンスを一度に開始できます。

cd ..
fleetctl start instances/*

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

結論

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

後のガイドでは、登録している情報を使用するようにコンテナーを構成する方法について説明します。 etcd. これは、バックエンド内の適切なコンテナーに要求を渡すために、サービスが実際のデプロイメント環境の実用的な知識を構築するのに役立ちます。

モバイルバージョンを終了