序章

CoreOSを可能にするテクノロジーの1つは、グローバルに分散されたKey-Valueストアであるetcdです。 このサービスは、個々のCoreOSマシンがクラスターを形成するため、およびグローバルにアクセス可能なデータを格納するためのプラットフォームとして使用されます。

このガイドでは、etcdデーモン、etcdctlユーティリティ、およびそれを制御するために使用できるHTTP /JSONAPIについて説明します。

前提条件

このガイドに従うために、DigitalOceanでCoreOSクラスターをセットアップするためのガイドとしてCoreOSマシンのクラスターがあることを前提としています。 これにより、1つのクラスターに3台のサーバーが残ります。

  • coreos-1
  • coreos-2
  • coreos-3

これらのマシンを稼働させたら、このガイドを続けることができます。

Etcdクラスター検出モデル

etcdが担当する最も基本的なタスクの1つは、個々のマシンをクラスターに編成することです。 これは、CoreOSが起動時に、作成時に渡されるcloud-configファイルで提供される検出アドレスにチェックインすることによって実行されます。

CoreOSによって実行される検出サービスには、https://discovery.etcd.ioからアクセスできます。 /newページにアクセスすると、新しいトークンを取得できます。 そこで、マシンがコンパニオンノードを検出するために使用できるトークンを取得します。 次のようになります。

https://discovery.etcd.io/dcadc5d4d42328488ecdcd7afae5f57c

新しいクラスターごとにmust新しいトークンを提供する必要があります。 これには、同じIPアドレスを持つ可能性のあるノードを使用してクラスターを再構築する必要がある場合も含まれます。 etcdインスタンスはこれによって混乱し、検出アドレスを再利用すると、クラスターを構築するために正しく機能しなくなります。

Webブラウザーで検出アドレスにアクセスすると、既知のマシンを説明するJSONオブジェクトが返されます。 最初に開始したとき、これにはノードがありません。

{"action":"get","node":{"key":"/_etcd/registry/dcadc5d4d42328488ecdcd7afae5f57c","dir":true,"modifiedIndex":102511104,"createdIndex":102511104}}

クラスタをブートストラップした後、ここで詳細情報を確認できます。

{"action":"get","node":{"key":"/_etcd/registry/1edee33e6b03e75d9428eacf0ff94fda","dir":true,"nodes":[{"key":"/_etcd/registry/1edee33e6b03e75d9428eacf0ff94fda/2ddbdb7c872b4bc59dd1969ac166501e","value":"http://10.132.252.38:7001","expiration":"2014-09-19T13:41:26.912303668Z","ttl":598881,"modifiedIndex":102453704,"createdIndex":102453704},{"key":"/_etcd/registry/1edee33e6b03e75d9428eacf0ff94fda/921a7241c31a499a97d43f785108b17c","value":"http://10.132.248.118:7001","expiration":"2014-09-19T13:41:29.602508981Z","ttl":598884,"modifiedIndex":102453736,"createdIndex":102453736},{"key":"/_etcd/registry/1edee33e6b03e75d9428eacf0ff94fda/27987f5eaac243f88ca6823b47012c5b","value":"http://10.132.248.121:7001","expiration":"2014-09-19T13:41:41.817958205Z","ttl":598896,"modifiedIndex":102453860,"createdIndex":102453860}],"modifiedIndex":101632353,"createdIndex":101632353}}

クラスタの検出URLを見つける必要がある場合は、メンバーである任意のマシンから見つけることができます。 この情報は、/run階層内から取得できます。

cat /run/systemd/system/etcd.service.d/20-cloudinit.conf
[Service]
Environment="ETCD_ADDR=10.132.248.118:4001"
Environment="ETCD_DISCOVERY=https://discovery.etcd.io/dcadc5d4d42328488ecdcd7afae5f57c"
Environment="ETCD_NAME=921a7241c31a499a97d43f785108b17c"
Environment="ETCD_PEER_ADDR=10.132.248.118:7001"

URLはETCD_DISCOVERYエントリ内に保存されます。

etcdを実行しているマシンが起動すると、このURLの情報を確認します。 それはそれ自身の情報を提出し、他のメンバーについて質問します。 クラスターの最初のノードは明らかに他のノードに関する情報を見つけられないため、クラスターリーダーとして自分自身を指定します。

後続のマシンも、その情報を検出URLに接続します。 彼らはすでにチェックインしたマシンに関する情報を受け取ります。 次に、これらのマシンの1つを選択して直接接続し、正常なクラスターメンバーの完全なリストを取得します。 データの複製と配布は、Raftコンセンサスアルゴリズムを介して実行されます。

各マシンに関するデータは、etcd内の隠しディレクトリ構造内に保存されます。 etcdが認識しているマシンに関する情報は、次のように入力すると表示されます。

etcdctl ls /_etcd/machines --recursive
/_etcd/machines/2ddbdb7c872b4bc59dd1969ac166501e
/_etcd/machines/921a7241c31a499a97d43f785108b17c
/_etcd/machines/27987f5eaac243f88ca6823b47012c5b

etcdが新しいクラスターメンバーに渡す詳細は、これらのキーに含まれています。 etcdctlでリクエストすると、個々の値を確認できます。

etcdctl get /_etcd/machines/2ddbdb7c872b4bc59dd1969ac166501e
etcd=http%3A%2F%2F10.132.252.38%3A4001&raft=http%3A%2F%2F10.132.252.38%3A7001

etcdctlコマンドについては、後で詳しく説明します。

Etcdctlの使用法

etcdと対話する基本的な方法は2つあります。 HTTP / JSON APIを介して、および付属のetcdctlユーティリティなどのクライアントを介して。 最初にetcdctlについて説明します。

キーとディレクトリの表示

まず、etcdctlが現在保存しているものを見てみましょう。 次のように入力すると、最上位のキーが表示されます。

etcdctl ls /
/coreos.com

ご覧のとおり、1つの結果があります。 現時点では、これがディレクトリなのかキーなのかは不明です。 ノードをgetして、キーの値を確認するか、それがディレクトリであることを確認することができます。

etcdctl get /coreos.com
/coreos.com: is a directory

この手動の再帰プロセスを回避するために、etcdctlに、次のように入力して、表示されている情報の階層全体を一覧表示するように指示できます。

etcdctl ls / --recursive
/coreos.com
/coreos.com/updateengine
/coreos.com/updateengine/rebootlock
/coreos.com/updateengine/rebootlock/semaphore

ご覧のとおり、最初の/coreos.comノードの下にはかなりの数のディレクトリがありました。 最終エンドポイントで情報を要求することにより、ノードから実際のデータを取得することがどのように見えるかを確認できます。

etcdctl get /coreos.com/updateengine/rebootlock/semaphore
{"semaphore":1,"max":1,"holders":null}

これには、私たちにとって非常に役立つ情報は含まれていません。 -o extendedオプションを渡すことで、このエントリに関する追加のメタデータを取得できます。 これはグローバルオプションであるため、getコマンドの前に配置する必要があります。

etcdctl -o extended get /coreos.com/updateengine/rebootlock/semaphore
Key: /coreos.com/updateengine/rebootlock/semaphore
Created-Index: 6
Modified-Index: 6
TTL: 0
Etcd-Index: 170387
Raft-Index: 444099
Raft-Term: 8

{"semaphore":1,"max":1,"holders":null}

キーの設定とノードの作成

新しいディレクトリを作成するには、次のようにmkdirコマンドを使用できます。

etcdctl mkdir /example

キーを作成するには、mkコマンドを使用できます。

etcdctl mk /example/key data
data

これは、キーがまだ存在しない場合にのみ機能します。 作成したキーの値を尋ねると、設定したデータを取得できます。

etcdctl get /example/key
data

既存のキーを更新するには、updateコマンドを使用します。

etcdctl update /example/key turtles
turtles

ディレクトリ用のコンパニオンupdatedirコマンドは、TTL、つまりディレクトリの存続時間を設定した場合にのみ役立つ可能性があります。 これにより、TTL時間が渡されたもので更新されます。 --ttl #引数を渡すことにより、ディレクトリまたはキーのTTLを設定できます。ここで、「#」は保持する秒数です。

etcdctl mkdir /here/you/go --ttl 120

次に、updatedirを使用してTTLを更新できます。

etcdctl updatedir /here/you/go --ttl 500

既存のキーの値を変更したり、存在しない場合はキーを作成したりするには、setコマンドを使用します。 これは、mkコマンドとupdateコマンドの組み合わせと考えてください。

etcdctl set /example/key new
new

これには、存在しないパスが含まれる場合があります。 パスコンポーネントは動的に作成されます。

etcdctl set /a/b/c here
here

ディレクトリに対してこれと同じcreate-if-does-not-exist機能を取得するには、setdirコマンドを使用できます。

etcdctl setdir /x/y/z

setdirコマンドは、現在、記載されているとおりに機能しません。 現在のビルドでは、その使用法はupdatedirコマンドを反映しており、ディレクトリがすでに存在する場合は失敗します。 これに対処するために、GitHubリポジトリに未解決の問題があります。

エントリの削除

既存のキーを削除するには、rmまたはrmdirコマンドを使用できます。

rmコマンドを使用して、キーを削除できます。

etcdctl rm /a/b/c

また、ディレクトリとすべてのサブディレクトリを削除するために再帰的に使用することもできます。

etcdctl rm /a --recursive

空のディレクトリまたはキーのみを削除するには、rmdirコマンドを使用します。

etcdctl rmdir /x/y/z

これを使用して、階層のエンドポイントのみを削除していることを確認できます。

変化を監視する

特定のキーまたはディレクトリ全体のいずれかで変更を監視できます。 etcdctlでこれらを監視すると、監視対象に何らかのイベントが発生するまで操作がハングします。

キーを監視するには、フラグなしで使用します。

etcdctl watch /example/hello

視聴を停止するには、CTRL-Cを押します。 監視中に変更が検出された場合は、新しい値が返されます。

ディレクトリ構造全体を監視するには、--recursiveフラグを使用します。

etcdctl watch --recursive /example

値の状態を常に監視するために単純なループ構造に配置することで、これがどのように役立つかを確認できます。

while true; do etcdctl watch --recursive /example; done

変更が検出されるたびにコマンドを実行する場合は、exec-watchコマンドを使用します。

etcdctl exec-watch --recursive  /example -- echo "hello"

これにより、そのディレクトリの値が変更されるたびに、画面に「hello」がエコーされます。

隠された値

すぐにはわからないことの1つは、etcd内に隠しディレクトリ構造があることです。 これらは、アンダースコアで始まるディレクトリまたはキーです。

これらは、従来のetcdctlツールにはリストされていないため、それらを見つけるには、探しているものを知っている必要があります。

たとえば、/_coreos.comという隠しディレクトリがあります。このディレクトリにはfleetに関する内部情報が含まれています。 明示的に要求することで、階層を確認できます。

etcdctl ls --recursive /_coreos.com 
/_coreos.com/fleet
/_coreos.com/fleet/states
/_coreos.com/fleet/states/[email protected]
/_coreos.com/fleet/states/[email protected]/2ddbdb7c872b4bc59dd1969ac166501e
/_coreos.com/fleet/states/[email protected]
/_coreos.com/fleet/states/[email protected]/921a7241c31a499a97d43f785108b17c
. . .

別のそのようなディレクトリ構造は、/_etcd内にあります。

etcdctl ls --recursive /_etcd
/_etcd/machines
/_etcd/machines/27987f5eaac243f88ca6823b47012c5b
/_etcd/machines/2ddbdb7c872b4bc59dd1969ac166501e
/_etcd/machines/921a7241c31a499a97d43f785108b17c
/_etcd/config

これらは他のエントリとまったく同じように機能しますが、唯一の違いは、一般的なリストに表示されないことです。 キーまたはディレクトリ名をアンダースコアで始めるだけで作成できます。

Etcd HTTP /JSONAPIの使用法

etcdと対話するもう1つの方法は、単純なHTTP /JSONAPIを使用することです。

APIにアクセスするには、curlのような単純なHTTPプログラムを使用できます。 返されるリダイレクトを追跡するには、-Lフラグを指定する必要があります。 クラスタ内から、ほとんどのクエリにローカル127.0.0.1インターフェイスとポート4001を使用できます。

:Dockerコンテナ内からetcdに接続するには、アドレスhttp://172.17.42.1:4001を使用できます。 これは、アプリケーションが登録された情報に基づいて構成を更新する場合に役立ちます。

通常のキースペースに到達するには、任意のホストマシンでhttp://127.0.0.1:4001/v2/keys/に移動します。 たとえば、最上位のキー/ディレクトリのリストを取得するには、次のように入力します。

curl -L http://127.0.0.1:4001/v2/keys/
{"action":"get","node":{"key":"/","dir":true,"nodes":[{"key":"/coreos.com","dir":true,"modifiedIndex":6,"createdIndex":6},{"key":"/services","dir":true,"modifiedIndex":333,"createdIndex":333}]}}

リクエストの末尾のスラッシュは必須です。 それがないと正しく解決されません。

通常のHTTP動詞を使用して値を設定または取得できます。

これらの操作の動作を変更するには、?flag=value構文を使用して、リクエストの最後にフラグを渡すことができます。 複数のフラグは&文字で区切ることができます。

たとえば、すべてのキーを再帰的に一覧表示するには、次のように入力します。

curl -L http://127.0.0.1:4001/v2/keys/?recursive=true
{"action":"get","node":{"key":"/","dir":true,"nodes":[{"key":"/coreos.com","dir":true,"nodes":[{"key":"/coreos.com/updateengine","dir":true,"nodes":[{"key":"/coreos.com/updateengine/rebootlock","dir":true,"nodes":[{"key":"/coreos.com/updateengine/rebootlock/semaphore","value":"{\"semaphore\":1,\"max\":1,\"holders\":null}","modifiedIndex":6,"createdIndex":6}],"modifiedIndex":6,"createdIndex":6}],"modifiedIndex":6,"createdIndex":6}],"modifiedIndex":6,"createdIndex":6}. . .

通常のキースペースの外でアクセスできるもう1つの便利な情報は、バージョン情報です。ここからアクセスできます。

curl -L http://127.0.0.1:4001/version
etcd 0.4.6

このエンドポイントにアクセスすると、クラスターリーダーと各フォロワーとの各関係に関する統計を表示できます。

curl -L http://127.0.0.1:4001/v2/stats/leader
{"leader":"921a7241c31a499a97d43f785108b17c","followers":{"27987f5eaac243f88ca6823b47012c5b":{"latency":{"current":1.607038,"average":1.3762888642395448,"standardDeviation":1.4404313533578545,"minimum":0.471432,"maximum":322.728852},"counts":{"fail":0,"success":98718}},"2ddbdb7c872b4bc59dd1969ac166501e":{"latency":{"current":1.584985,"average":1.1554367141497013,"standardDeviation":0.6872303198242179,"minimum":0.427485,"maximum":31.959235},"counts":{"fail":0,"success":98723}}}}

同様の操作を使用して、現在使用しているマシンに関する統計を検出できます。

curl -L http://127.0.0.1:4001/v2/stats/self
{"name":"921a7241c31a499a97d43f785108b17c","state":"leader","startTime":"2014-09-11T16:42:03.035382298Z","leaderInfo":{"leader":"921a7241c31a499a97d43f785108b17c","uptime":"1h19m11.469872568s","startTime":"2014-09-12T19:47:25.242151859Z"},"recvAppendRequestCnt":1944480,"sendAppendRequestCnt":201817,"sendPkgRate":40.403374523779064,"sendBandwidthRate":3315.096879676072}

実行された操作に関する統計を表示するには、次のように入力します。

curl -L http://127.0.0.1:4001/v2/stats/store
{"getsSuccess":78823,"getsFail":14,"setsSuccess":121370,"setsFail":4,"deleteSuccess":28,"deleteFail":32,"updateSuccess":20468,"updateFail":4,"createSuccess":39,"createFail":102340,"compareAndSwapSuccess":51169,"compareAndSwapFail":0,"compareAndDeleteSuccess":0,"compareAndDeleteFail":0,"expireCount":3,"watchers":6}

これらは、APIを介してetcdを制御するために使用できる操作のほんの一部です。

Etcd構成

etcdサービスは、いくつかの異なる方法で構成できます。

最初の方法は、ノードのブートストラップに使用するcloud-configファイルを使用してパラメーターを渡すことです。 ブートストラップガイドでは、これを行う方法について少し見ました。

#cloud-config

coreos:
  etcd:
    discovery: https://discovery.etcd.io/<token>
    addr: $private_ipv4:4001
    peer-addr: $private_ipv4:7001
. . .

使用可能なオプションを確認するには、-hフラグをetcdとともに使用します。

etcd -h

これらのオプションをcloud-configに含めるには、先頭のダッシュを外し、等号の代わりにコロンを使用してキーを値から区切ります。 したがって、-peer-addr=<host:port>peer-addr: <host:port>になります。

CoreOSは、cloud-configファイルを読み取ると、これらをスタブユニットファイルの環境変数に変換します。このファイルは、サービスの開始に使用されます。

etcdの設定を調整する別の方法は、APIを使用することです。 これは通常、キークエリに使用される標準の4001の代わりに、7001ポートを使用して行われます。

たとえば、次のように入力すると、現在の構成値の一部を取得できます。

curl -L http://127.0.0.1:7001/v2/admin/config
{"activeSize":9,"removeDelay":1800,"syncInterval":5}

これらの値を変更するには、PUT操作で新しいJSONをデータペイロードとして渡します。

curl -L http://127.0.0.1:7001/v2/admin/config -XPUT -d '{"activeSize":9,"removeDelay":1800,"syncInterval":5}'
{"activeSize":9,"removeDelay":1800,"syncInterval":5}

マシンのリストを取得するには、/v2/admin/machinesエンドポイントに移動します。

curl -L http://127.0.0.1:7001/v2/admin/machines
[{"name":"27987f5eaac243f88ca6823b47012c5b","state":"follower","clientURL":"http://10.132.248.121:4001","peerURL":"http://10.132.248.121:7001"},{"name":"2ddbdb7c872b4bc59dd1969ac166501e","state":"follower","clientURL":"http://10.132.252.38:4001","peerURL":"http://10.132.252.38:7001"},{"name":"921a7241c31a499a97d43f785108b17c","state":"leader","clientURL":"http://10.132.248.118:4001","peerURL":"http://10.132.248.118:7001"}]

これは、DELETEメソッドを使用してクラスターからマシンを強制的に削除するために使用できます。

結論

ご覧のとおり、etcdを使用して、クラスター内の任意のマシンから情報を保存または取得できます。 これにより、データを同期し、サービスが構成データと接続の詳細を探す場所を提供できます。

これは、クラスター内の任意の場所から有効になる単純なエンドポイントを提供できるため、分散システムを構築するときに特に役立ちます。 このリソースを利用することで、サービスは動的に構成できます。