CoreOSクラスターでサービスを作成して実行する方法
ステータス:期限切れ
この記事は最新ではありません。 この記事の更新を書くことに興味がある場合は、DigitalOceanが技術チュートリアルを公開したいのをご覧ください。
理由: 2016年12月22日、CoreOSはフリートを維持しなくなったことを発表しました。 CoreOSは、すべてのクラスタリングのニーズにKubernetesを使用することをお勧めします。
代わりに参照してください:フリートなしでCoreOSでKubernetesを使用するガイダンスについては、CoreOSドキュメントのKubernetesを参照してください。
序章
CoreOSの主な利点の1つは、クラスター全体のサービスを単一のポイントから管理できることです。 CoreOSプラットフォームは、このプロセスを簡単にする統合ツールを提供します。
このガイドでは、CoreOSクラスターでサービスを実行するための一般的なワークフローを示します。 このプロセスでは、アプリケーションをセットアップするためにCoreOSの最も興味深いユーティリティのいくつかと対話するいくつかの簡単で実用的な方法を示します。
前提条件と目標
このガイドを開始するには、少なくとも3台のマシンが構成されたCoreOSクラスターが必要です。 ここで、ガイドに従ってCoreOSクラスターをブートストラップできます。
このガイドのために、3つのノードは次のようになります。
- coreos-1
- coreos-2
- coreos-3
これらの3つのノードは、etcdクライアントアドレスとピアアドレス、およびフリートアドレスのプライベートネットワークインターフェイスを使用して構成する必要があります。 これらは、上記のガイドに示されているように、cloud-configファイルを使用して構成する必要があります。
このガイドでは、CoreOSクラスターでサービスを実行するための基本的なワークフローについて説明します。 デモンストレーションの目的で、単純なApacheWebサーバーをセットアップします。 Dockerを使用したコンテナー化されたサービス環境のセットアップについて説明し、次に、サービスとその操作パラメーターを記述するsystemdスタイルのユニットファイルを作成します。
コンパニオンユニットファイル内で、etcdに登録するようにサービスに指示します。これにより、他のサービスがその詳細を追跡できるようになります。 両方のサービスをフリートに送信します。フリートでは、クラスター全体のマシンでサービスを開始および管理できます。
ノードに接続してSSHエージェントを渡す
サービスの構成を開始するために最初に行う必要があるのは、SSHを使用してノードの1つに接続することです。
のために fleetctl
隣接ノードとの通信に使用するツールを使用するには、接続中にSSHエージェント情報を渡す必要があります。
SSH経由で接続する前に、SSHエージェントを起動する必要があります。 これにより、接続しているサーバーに資格情報を転送できるようになり、そのマシンから他のノードにログインできるようになります。 マシンでユーザーエージェントを起動するには、次のように入力する必要があります。
eval $(ssh-agent)
次に、次のように入力して、メモリストレージ内のエージェントに秘密鍵を追加できます。
ssh-add
この時点で、SSHエージェントが実行されており、SSHエージェントが秘密のSSHキーを認識している必要があります。 次のステップは、クラスター内のノードの1つに接続し、SSHエージェント情報を転送することです。 これを行うには、 -A
国旗:
ssh -A core@coreos_node_public_IP
ノードの1つに接続すると、サービスの構築を開始できます。
Dockerコンテナの作成
最初に行う必要があるのは、サービスを実行するDockerコンテナーを作成することです。 これは、2つの方法のいずれかで実行できます。 Dockerコンテナーを起動して手動で構成することも、必要なイメージをビルドするために必要な手順を記述したDockerfileを作成することもできます。
このガイドでは、Dockerを初めて使用する人にとってはより簡単なため、最初の方法を使用してイメージを作成します。 Dockerfile からDockerイメージをビルドする方法について詳しく知りたい場合は、このリンクをたどってください。 私たちの目標は、Docker内のUbuntu14.04ベースイメージにApacheをインストールすることです。
始める前に、DockerHubレジストリにログインまたはサインアップする必要があります。 これを行うには、次のように入力します。
docker login
ユーザー名、パスワード、および電子メールアドレスを提供するように求められます。 これを行うのが初めての場合は、指定した詳細を使用してアカウントが作成され、指定されたアドレスに確認メールが送信されます。 過去にすでにアカウントを作成している場合は、指定された資格情報でログインします。
イメージを作成するための最初のステップは、使用するベースイメージを使用してDockerコンテナーを起動することです。 必要なコマンドは次のとおりです。
docker run -i -t ubuntu:14.04 /bin/bash
上記で使用した引数は次のとおりです。
- run :これは、次のパラメーターを使用してコンテナーを起動することをDockerに通知します。
- -i :Dockerコンテナをインタラクティブモードで起動します。 これにより、コンテナ環境にSTDINが接続されていなくても、確実に使用できるようになります。
- -t :これにより疑似TTYが作成され、コンテナー環境への端末アクセスが可能になります。
- ubuntu:14.04 :これは実行したいリポジトリとイメージの組み合わせです。 この場合、Ubuntu14.04を実行しています。 イメージは、DockerHubのUbuntuDockerリポジトリ内に保持されます。
- / bin / bash :これはコンテナーで実行するコマンドです。 ターミナルアクセスが必要なので、シェルセッションを生成する必要があります。
ベースイメージレイヤーがDockerHubオンラインDockerレジストリからプルダウンされ、bashセッションが開始されます。 結果のシェルセッションにドロップされます。
ここから、サービス環境の構築を進めることができます。 Apache Webサーバーをインストールしたいので、ローカルパッケージインデックスを更新して、 apt
:
apt-get update
apt-get install apache2
インストールが完了したら、デフォルトを編集できます index.html
ファイル:
echo "<h1>Running from Docker on CoreOS</h1>" > /var/www/html/index.html
終了したら、従来の方法でbashセッションを終了できます。
exit
ホストマシンに戻り、残ったDockerコンテナのコンテナIDを取得する必要があります。 これを行うには、Dockerに最新のプロセス情報を表示するように依頼できます。
docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cb58a2ea1f8f ubuntu:14.04 "/bin/bash" 8 minutes ago Exited (0) 55 seconds ago jovial_perlman
必要な列は「CONTAINERID」です。 上記の例では、これは次のようになります cb58a2ea1f8f
. 後で行ったすべての変更で同じコンテナを起動できるようにするには、変更をユーザー名のリポジトリにコミットする必要があります。 画像の名前も選択する必要があります。
私たちの目的のために、ユーザー名は user_name
ただし、これを少し前にログインしたDockerHubアカウント名に置き換える必要があります。 私たちのイメージを呼びます apache
. イメージの変更をコミットするコマンドは次のとおりです。
docker commit container_ID user_name/apache
これにより画像が保存され、コンテナの現在の状態を思い出すことができます。 次のように入力して、これを確認できます。
docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
user_name/apache latest 42a71fb973da 4 seconds ago 247.4 MB
ubuntu 14.04 c4ff7513909d 3 weeks ago 213 MB
次に、ノードがイメージを自由にプルダウンして実行できるように、イメージをDockerHubに公開する必要があります。 これを行うには、次のコマンド形式を使用します。
docker push user_name/apache
これで、Apacheインスタンスで構成されたコンテナーイメージができました。
Apacheサービスユニットファイルの作成
Dockerコンテナーが利用可能になったので、サービスファイルの構築を開始できます。
フリートは、CoreOSクラスター全体のサービススケジューリングを管理します。 各ホストのsystemdinitシステムをローカルで操作して適切なアクションを実行しながら、ユーザーに一元化されたインターフェイスを提供します。
各サービスのプロパティを定義するファイルは、わずかに変更されたsystemdユニットファイルです。 過去にsystemdを使用したことがある場合は、構文に非常に精通しているはずです。
まず、というファイルを作成します [email protected]
ホームディレクトリにあります。 The @
これがテンプレートサービスファイルであることを示します。 それが何を意味するのかを少し説明します。 CoreOSイメージには vim
テキストエディタ:
vim [email protected]
サービス定義を開始するには、 [Unit]
セクションヘッダーを作成し、このユニットに関するメタデータを設定します。 説明を含め、依存関係情報を指定します。 etcdとDockerの両方が使用可能になった後でユニットを実行する必要があるため、その要件を定義する必要があります。
また、要件として作成する他のサービスファイルを追加する必要があります。 この2番目のサービスファイルは、etcdを当社のサービスに関する情報で更新する責任があります。 ここで要求すると、このサービスの開始時に強制的に開始されます。 説明します %i
後でサービス名に:
[Unit]
Description=Apache web server service
After=etcd.service
After=docker.service
Requires=apache-discovery@%i.service
次に、このユニットを起動または停止するときに何が必要かをシステムに通知する必要があります。 私たちはこれを [Service]
セクション、サービスを構成しているため。
最初に実行したいのは、サービスの起動がタイムアウトしないようにすることです。 私たちのサービスはDockerコンテナであるため、各ホストで初めて起動するときは、イメージをDocker Hubサーバーからプルダウンする必要があり、初回実行時に通常よりも長い起動時間が発生する可能性があります。
設定したい KillMode
systemdが「stop」コマンドでDockerプロセスを強制終了できるように、「none」に変更します。 これを省略すると、systemdはstopコマンドを呼び出したときにDockerプロセスが失敗したと見なします。
また、サービスを開始する前に、環境がクリーンであることを確認する必要があります。 これは、サービスを名前で参照するため、特に重要です。Dockerでは、一意の名前ごとに1つのコンテナーしか実行できません。
使用したい名前の残りのコンテナをすべて削除してから削除する必要があります。 この時点で、DockerHubからも実際にイメージをプルダウンします。 調達したい /etc/environment
ファイルも。 これには、サービスを実行しているホストのパブリックIPアドレスやプライベートIPアドレスなどの変数が含まれます。
[Unit]
Description=Apache web server service
After=etcd.service
After=docker.service
Requires=apache-discovery@%i.service
[Service]
TimeoutStartSec=0
KillMode=none
EnvironmentFile=/etc/environment
ExecStartPre=-/usr/bin/docker kill apache%i
ExecStartPre=-/usr/bin/docker rm apache%i
ExecStartPre=/usr/bin/docker pull user_name/apache
The =-
最初の2つの構文 ExecStartPre
行は、それらの準備行が失敗する可能性があり、ユニットファイルが引き続き続行されることを示します。 これらのコマンドは、その名前のコンテナーが存在する場合にのみ成功するため、コンテナーが見つからない場合は失敗します。
あなたは気づいたかもしれません %i
上記のディレクティブのapacheコンテナ名の最後にあるサフィックス。 作成しているサービスファイルは、実際にはテンプレートユニットファイルです。 これは、ファイルを実行すると、フリートがいくつかの情報を適切な値に自動的に置き換えることを意味します。 詳細については、提供されているリンクの情報をお読みください。
私たちの場合、 %i
ファイル内に存在するすべての場所で、サービスファイルの名前の右側の部分に置き換えられます。 @
の前に .service
サフィックス。 私たちのファイルは単に名前が付けられています [email protected]
けれど。
ファイルをに送信しますが fleetctl
と [email protected]
、ファイルをロードするとき、次のようにロードします apache@PORT_NUM.service
、ここで、「PORT_NUM」は、このサーバーを起動するポートになります。 サービスを簡単に区別できるように、実行するポートに基づいてサービスにラベルを付けます。
次に、実際のDockerコンテナを実際に起動する必要があります。
[Unit]
Description=Apache web server service
After=etcd.service
After=docker.service
Requires=apache-discovery@%i.service
[Service]
TimeoutStartSec=0
KillMode=none
EnvironmentFile=/etc/environment
ExecStartPre=-/usr/bin/docker kill apache%i
ExecStartPre=-/usr/bin/docker rm apache%i
ExecStartPre=/usr/bin/docker pull user_name/apache
ExecStart=/usr/bin/docker run --name apache%i -p ${COREOS_PUBLIC_IPV4}:%i:80 user_name/apache /usr/sbin/apache2ctl -D FOREGROUND
従来型と呼びます docker run
コマンドを実行し、いくつかのパラメータを渡しました。 上記で使用したのと同じ形式で名前を渡します。 また、Dockerコンテナからホストマシンのパブリックインターフェイスへのポートを公開します。 ホストマシンのポート番号は、 %i
変数。これにより、実際にポートを指定できます。
を使用します COREOS_PUBLIC_IPV4
バインドするホストインターフェイスに明示する変数(ソースした環境ファイルから取得)。 これを省略してもかまいませんが、これをプライベートインターフェイスに変更する場合(たとえば、負荷分散の場合)、後で簡単に変更できるように設定されています。
以前にDockerHubにアップロードしたDockerコンテナを参照します。 最後に、コンテナ環境でApacheサービスを開始するコマンドを呼び出します。 Dockerコンテナーは、指定されたコマンドが終了するとすぐにシャットダウンするため、デーモンとしてではなく、フォアグラウンドでサービスを実行する必要があります。 これにより、子プロセスが正常に生成されるとすぐにコンテナが終了するのではなく、実行を継続できるようになります。
次に、サービスを停止する必要があるときに呼び出すコマンドを指定する必要があります。 コンテナを停止するだけです。 コンテナのクリーンアップは、毎回再起動するときに実行されます。
また、というセクションを追加したいと思います [X-Fleet]
. このセクションは、サービスのスケジュール方法についてフリートに指示を与えるように特別に設計されています。 ここで、制限を追加して、サービスを他のサービスまたはマシンの状態に関連する特定の配置で実行する必要があるかどうかを指定できます。
Apache Webサーバーをまだ実行していないホストでのみサービスを実行する必要があります。これにより、可用性の高いサービスを簡単に作成できるようになります。 ワイルドカードを使用して、実行している可能性のあるapacheサービスファイルをキャッチします。
[Unit]
Description=Apache web server service
After=etcd.service
After=docker.service
Requires=apache-discovery@%i.service
[Service]
TimeoutStartSec=0
KillMode=none
EnvironmentFile=/etc/environment
ExecStartPre=-/usr/bin/docker kill apache%i
ExecStartPre=-/usr/bin/docker rm apache%i
ExecStartPre=/usr/bin/docker pull user_name/apache
ExecStart=/usr/bin/docker run --name apache%i -p ${COREOS_PUBLIC_IPV4}:%i:80 user_name/apache /usr/sbin/apache2ctl -D FOREGROUND
ExecStop=/usr/bin/docker stop apache%i
[X-Fleet]
X-Conflicts=apache@*.service
これで、Apacheサーバーユニットファイルが完成しました。 次に、etcdにサービスを登録するためのコンパニオンサービスファイルを作成します。
Etcdへのサービス状態の登録
クラスタで開始されたサービスの現在の状態を記録するために、etcdにいくつかのエントリを書き込みます。 これは、etcdへの登録として知られています。
これを行うために、サーバーがいつトラフィックに利用できるかについてetcdを更新できる最小限のコンパニオンサービスを開始します。
新しいサービスファイルが呼び出されます [email protected]
. 今すぐ開く:
vim [email protected]
まずは [Unit]
前と同じように、セクション。 サービスの目的を説明してから、というディレクティブを設定します BindsTo
.
The BindsTo
ディレクティブは、このサービスが状態情報を探す依存関係を識別します。 記載されているサービスが停止すると、現在書き込み中のユニットも停止します。 これを使用して、Webサーバーユニットに予期しない障害が発生した場合に、このサービスがetcdを更新してその情報を反映するようにします。 これにより、他のサービスによって誤って使用される可能性のある古い情報がetcdにあるという潜在的な問題が解決されます。
[Unit]
Description=Announce Apache@%i service
BindsTo=apache@%i.service
のために [Service]
セクションでは、ホストのIPアドレス情報を使用して環境ファイルを再度ソースします。
実際の開始コマンドでは、単純な無限のbashループを実行します。 ループ内では、 etcdctl
etcd値を変更するために使用されるコマンドで、etcdストアにキーを設定します。 /announce/services/apache%i
. The %i
の間にロードするサービス名のセクションに置き換えられます @
そしてその .service
接尾辞。これもApacheサービスのポート番号になります。
このキーの値は、ノードのパブリックIPアドレスとポート番号に設定されます。 また、値に60秒の有効期限を設定して、サービスが何らかの理由で停止した場合にキーが削除されるようにします。 その後、45秒間スリープします。 これにより、有効期限とのオーバーラップが提供されるため、タイムアウトに達する前にTTL(存続時間)値を常に更新します。
停止アクションについては、同じキーを削除するだけです。 etcdctl
ユーティリティ、サービスを利用不可としてマーク:
[Unit]
Description=Announce Apache@%i service
BindsTo=apache@%i.service
[Service]
EnvironmentFile=/etc/environment
ExecStart=/bin/sh -c "while true; do etcdctl set /announce/services/apache%i ${COREOS_PUBLIC_IPV4}:%i --ttl 60; sleep 45; done"
ExecStop=/usr/bin/etcdctl rm /announce/services/apache%i
最後に行う必要があるのは、このサービスがレポート対象のWebサーバーと同じホストで開始されるようにするための条件を追加することです。 これにより、ホストがダウンした場合に、etcd情報が適切に変更されるようになります。
[Unit]
Description=Announce Apache@%i service
BindsTo=apache@%i.service
[Service]
EnvironmentFile=/etc/environment
ExecStart=/bin/sh -c "while true; do etcdctl set /announce/services/apache%i ${COREOS_PUBLIC_IPV4}:%i --ttl 60; sleep 45; done"
ExecStop=/usr/bin/etcdctl rm /announce/services/apache%i
[X-Fleet]
X-ConditionMachineOf=apache@%i.service
これで、Apacheサーバーの現在のヘルスステータスをetcdに記録できるサイドキックサービスができました。
ユニットファイルとフリートの操作
これで、2つのサービステンプレートができました。 これらを直接に提出することができます fleetctl
私たちのクラスターがそれらについて知っているように:
fleetctl submit [email protected] [email protected]
次のように入力すると、新しいサービスファイルが表示されるはずです。
fleetctl list-unit-files
UNIT HASH DSTATE STATE TMACHINE
[email protected] 26a893f inactive inactive -
[email protected] 72bcc95 inactive inactive -
テンプレートは、クラスター全体のinitシステムに存在します。
特定のホストでのスケジュールに依存するテンプレートを使用しているため、次にファイルをロードする必要があります。 これにより、これらのファイルの新しい名前をポート番号で指定できるようになります。 これはいつ fleetctl
を見て [X-Fleet]
スケジューリング要件が何であるかを確認するセクション。
負荷分散を行っていないため、ポート80でWebサーバーを実行するだけです。 各サービスをロードするには、 @
そしてその .service
サフィックス:
fleetctl load [email protected]
fleetctl load [email protected]
クラスタ内のどのホストにサービスがロードされているかに関する情報を取得する必要があります。
Unit [email protected] loaded on 41f4cb9a.../10.132.248.119
Unit [email protected] loaded on 41f4cb9a.../10.132.248.119
ご覧のとおり、これらのサービスは両方とも同じマシンにロードされています。これは、指定したものです。 私たちの apache-discovery
サービスファイルはApacheサービスにバインドされているので、後で開始して両方のサービスを開始できます。
fleetctl start [email protected]
ここで、クラスターで実行されているユニットを尋ねると、次のように表示されます。
fleetctl list-units
UNIT MACHINE ACTIVE SUB
[email protected] 41f4cb9a.../10.132.248.119 active running
[email protected] 41f4cb9a.../10.132.248.119 active running
Webサーバーが稼働しているようです。 サービスファイルでは、DockerにホストサーバーのパブリックIPアドレスにバインドするように指示しましたが、IPは fleetctl
はプライベートアドレスです(私たちが渡したため $private_ipv4
このサンプルクラスターを作成するときのcloud-configで)。
ただし、パブリックIPアドレスとポート番号はetcdに登録しています。 値を取得するには、 etcdctl
設定した値を照会するユーティリティ。 思い出してください、私たちが設定したキーは /announce/services/apachePORT_NUM
. したがって、サーバーの詳細を取得するには、次のように入力します。
etcdctl get /announce/services/apache80
104.131.15.192:80
Webブラウザーでこのページにアクセスすると、作成した非常に単純なページが表示されます。
私たちのサービスは正常に展開されました。 別のポートを使用して別のインスタンスをロードしてみましょう。 Webサーバーと関連するサイドキックコンテナが同じホストでスケジュールされることを期待する必要があります。 ただし、Apacheサービスファイルの制約により、このホストはポート80サービスを提供するホストと異なるであると予想する必要があります。
ポート9999で実行されているサービスをロードしてみましょう。
fleetctl load [email protected] [email protected]
Unit [email protected] loaded on 855f79e4.../10.132.248.120
Unit [email protected] loaded on 855f79e4.../10.132.248.120
両方の新しいサービスが同じ新しいホストでスケジュールされていることがわかります。 Webサーバーを起動します。
fleetctl start [email protected]
これで、この新しいホストのパブリックIPアドレスを取得できます。
etcdctl get /announce/services/apache9999
104.131.15.193:9999
指定されたアドレスとポート番号にアクセスすると、別のWebサーバーが表示されます。
これで、クラスター内に2つのWebサーバーがデプロイされました。
Webサーバーを停止すると、サイドキックコンテナも停止するはずです。
fleetctl stop [email protected]
fleetctl list-units
UNIT MACHINE ACTIVE SUB
[email protected] 41f4cb9a.../10.132.248.119 inactive dead
[email protected] 855f79e4.../10.132.248.120 active running
[email protected] 41f4cb9a.../10.132.248.119 inactive dead
[email protected] 855f79e4.../10.132.248.120 active running
etcdキーも削除されたことを確認できます。
etcdctl get /announce/services/apache80
Error: 100: Key not found (/announce/services/apache80) [26693]
これは期待どおりに機能しているようです。
結論
このガイドに従うことで、CoreOSコンポーネントを操作する一般的な方法のいくつかに精通しているはずです。
実行したいサービスを内部にインストールして独自のDockerコンテナーを作成し、CoreOSにコンテナーの管理方法を指示するフリートユニットファイルを作成しました。 etcdデータストアをWebサーバーに関する状態情報で最新の状態に保つために、サイドキックサービスを実装しました。 fleetctlを使用してサービスを管理し、さまざまなホストでサービスをスケジュールしました。
後のガイドでは、この記事で簡単に触れたいくつかの領域を引き続き調査します。