Consul関連ドキュメント(参考訳)Part3

Consul関連ドキュメント(参考訳)Part3 はてなブックマーク - Consul関連ドキュメント(参考訳)Part3


Consul v.0.3.0 のリリースにより、いくつか新機能に関するドキュメントが追加されていました。主に、セッションの管理と、DNS の TTL 、そしてリーダー選出に関するドキュメントです。

例によって、手許に簡単に翻訳したものがあるのですが、このまま眠らせておくのも勿体ないかと思い、公開します。なお、あくまで自分のメモの共有であり、内容は参考程度、未保証ということでお願いします。

■Sessions – Consul
http://www.consul.io/docs/internals/sessions.html

Consul は分散ロックを構築するために、セッション機構を提供します。セッションは、ノード、ヘルスチェック、key/value データそれぞれのレイヤ間を結びつける働きをします。セッションは granular(グラニュラー)ロッキングを行えるよう設計されており、The Chubby Lock Service for Lossely-Coupled Distributed System(緩やかに結合した分散システム向けの、Chubby ロックサービス;Google 社の論文)の影響を強く受けています。

高度な内容です! ページ内では Consul 内部の技術詳細を扱います。Consul の使用や、効率的な運用のためだけであれば、以下を読む必要はありません。これら詳細なドキュメントは、ソースコードという洞窟を探検するような方にとって必要となるものです。

* セッションの設計

Consul のセッションには、とても明確な役割があります。セッションを新しく作成するために、ノード名と、ヘルスチェックの一覧、そして ‘lock-delay’ (ロック遅延) を指定します。新しいセッションには、ID という自分自身を参照するための情報が提供されます。以下の図 ( リンク先 ) は、構成要素の関係を表した図です。

Consul が提供するセッション機能は、次のような時に無効化されます。

– ノードの情報が削除された時
– ヘルスチェックの情報が削除された時
– ヘルスチェックの状況が critical になった時
– セッションを明確に破棄した時

セッションが無効になると、セッションに関連づけて保持されていたロックは解放され、’modifyIndex’ キーの値が増加します。また、セッションが破棄された後は、セッションが無効なので、再度ロックをかけようとしても利用できません。

これは単純な設計でありながら、いくつもの利用パターンが出てきます。標準では、ゴシップ・プロトコルを基盤とした障害検出機能 ( failure detector ) は、ヘルスチェックに関連して使用されます。障害検知機能により、もしも Consul がノードのロック維持ができない場合に、自動的にロックを解放する事を可能としています。この機能は Consul ロックの「生存性」を高めるものであり、障害下においてもシステムを継続し続けられる事を意味します。しかしながら、完全なる障害検知機能というのは存在しません。そのため、(検出対象となるキーの)ロックの所有者が正常な状態でも、ロックが解放されてしまう誤検出 ( false positive ) の可能性はあります。つまり、ロック機能のために、「安全性」を犠牲にしているのです。

これとは逆に、ヘルスチェックとは関係のないセッションを作成する事もできます。これは誤検出の可能性を無くすという安全性のかわりに、生存性を引き替えとするものです。つまり、もし既存のロック対象に障害が発生したとしても、正常にロック機能が動作しない場合が有り得ます。Consul API がセッションの強制破棄 ( force destroyed ) を有効にした時は、障害時にオペレータが割り込めるシステムを構築できるので、スプリットブレインの可能性を妨げます。

もう1つ、セッションには ‘lock-delay’(ロック遅延)を指定する事ができます。時間間隔は 0 ~ 60 秒です。セッションの無効化が発生すると、’lock-delay’ 間隔で指定した間は、再度ロックされる事を妨げる機能です。これは、セーフガード機能であり、Google 社の Chubby 論文に影響を受けました。ロックを遅延させるのは、生存している可能性のあるリーダーを無効とみなしてしまうと、システムが矛盾した状態となり、誤った命令を出すのを防ぐためです。bulletprool メソッドを使わなくとも、アプリケーションのロジック部分にスリープ状態を実装しなくても良いので、多くの問題を回避する助けになるでしょう。標準の遅延は 15 秒ですが、クライアント側は値に 0 を指定する事で、この機能を無効にする事ができます。

* キーバリュー・ストア ( KVS ) との統合

KVS とセッション機能の統合作業により、KVS はセッションを主に使う場所となりました。セッションは使用前に作成しなくてはいけませんし、セッションは ID を用いて参照されます。

KVS の API は、’acquire’ と ‘release’ 操作をサポートするために拡張されました。’acquire’ は、Check-And-Set、チェックした後にセットするという動作のため、既存のロックがかかっていない場合のみ成功します。成功した場合、通常はキーの更新を実施し、’LockIndex’ の値が増え、’Session’ 値は、セッションのロックを保持するために更新されます。

一度ロックをかけた後は、対象となる同じセッションに対して ‘release’ 操作を行い、ロックを解除できます。また、Check-And-Set 操作時に、無効なセッションに対してリクエストを行っても、処理は失敗します。重要な注意事項として、ロックはセッションの作成者でなくとも、解除(リリース)する事ができます。このような設計なので、必要があればオペレータの手作業によって、セッションを強制停止する事ができます。以上のように、セッションを無効にすると、対象となるロックを解放する事を意味します。ロックが解放されても ‘LockIndex’ は変わりませんが、’Session’ はクリアされ、’modifyIndex’ の値が増えます。

このような概念( Chubby 論文の影響を強く受けています )のため、Key、LockIndex、Session のセットは、’sequencer’ ( シーケンサ ) というユニークな働きをします。’sequencer’ は、処理を順番に廻す事ができ、リクエストが現在のロック所有者と同一かどうか確認する事ができます。これは、’acquire’ を行う度に、’LockIndex’ の値を増します。もし、同じセッションで再度ロックが必要になった時は、値が増えているため、sequencer は古くなった( stale ) リクエストを見つける事が可能です。同様に、セッションが無効になった場合は、対象セッションの LockIndex は空白になります。

1つ明確にしておくと、ロックシステムは単なる補助的な機能です。クライアントが何か作業をする度に、都度ロックが必要になる訳ではありません。クライアント側は、ロックの有無にかかわらず、読み込み・書き込み・削除ができます(訳者注;ロックはConsul サーバ側の処理のための仕組み)。Consul サーバは、不適切なクライアントからのアクセスを防止するために、ロック機能を提供している訳ではありません。

* リーダー選出

セッションと KVS をロックする両機能を、クライアント側のリーダー選出のためのアルゴリズムに用いる事ができます。詳細については Leader Election Guide を参照してください。

■Leader Election – Consul
http://www.consul.io/docs/guides/leader-election.html

このガイドでは、Consul を使用して、クライアント側のリーダー選出を行う方法を扱います。Consul サーバが内部で行っているリーダー選出について知りたい場合は、このガイドよりも ‘consensus protocol‘ をご覧ください。

リーダー選出を行う手法はいくつかありますが、ここでは全ての手法を扱いません。そのかわり、Consul に対してセッション機能をサポートさせ、どのように gracefully (優雅)に障害を取り扱うシステムを構築するかに焦点をあてます。

* ノード競合

最初に私たちが行うフローは、対象サービスのリーダーが誰かであるかを確認する事です。簡単に知る方法は、次のようにします:

service/<サービス名>/leader

単純にリーダーを取得するには、純粋に(leader という名前の ?) ‘key’ を取得します。

そのために、まずはセッションを作成します。セッションの標準の役目は、ゴシップ障害検知としてのみ使用します。これは /v1/session/create エンドポイントで使用します。必要があれば、他にもチェックを追加する事ができます。また、セッション ID は ‘session’ で参照できます。

次は、ローカルなノードを指し示す(実際には KVS の値になるもので、API アクセス時に PUT する) ‘body’ の内容を考えます。これは単純な JSON オブジェクトであり、body にはノード名称や、アプリケーション固有の情報を埋め込む事ができます。

key を取得するには PUT を次のように実行します。

curl -X PUT -d body http://localhost:8500/v1/kv/key?acquire=session

戻り値は ‘true’ か ‘false’ です。戻り値が ‘true’ であれば、ロックが有効になった状態であり、対象となるローカルのノードがリーダーに設定されます。’false’ が戻ってくる場合は、他のノードがロックして(リーダーになって)います。

これで、(ロックが成功し)全てのノードが稼働中の場合を考えます。稼働中は、対象となるサービスの ‘key’ 値の変更のみに注目します。確認するのは、ロックが解除されないかどうかと、ノードで障害が起こらないかどうかです。これをクライアントのリーダーが観察し、ロックが手作業で行われるかや、あるいは、障害検出によって自動的にロックが解除されるかを見ます。

このような key に対する変化を確認するには、ブロッキング・クエリ機能を用いた問い合わせを行います。もし、私たちが ‘key’ の ‘Session’ が空白になって見える場合は、リーダーが存在していません。ロックは成功していないので、再度、ロック試みてリーダーを選出する事になります。ただ、その場合は、少々の待ち時間が発生するかもしれません。それは、’lock-delay’ (ロック遅延) を強制する場合です。

curl -X PUT http://localhost:8500/v1/kv/key?release=session

* リーダーを発見する

特定サービスに対するリーダーを登録したら、次はノード側がリーダーを確認できるようにします。全てのノード(リーダーとして競合する相手も含む)が(リーダー選出時の)合意に関わるべきです。ここでの key は、単純に ‘key’ として考えます。

そして、クライアントは非常に簡単な役割があります。現在のリーダーが誰かを確認するためには、単純に (~/leader の)’key’ を読み込みます。もし、問い合わせた key に対応する ‘Sessoin’ が存在しない場合は、リーダーが存在していません(選出されていません)。一方で、リーダーが確認できた場合は、value には、アプリケーションに関連した様々な情報が提供されるでしょう。

また、クライアント側からは、kqy の何らかの変更を確認するためには、ブロッキング・クエリを用います。リーダーが引退するか、あるいは障害が起こると、対象サービスの key に関する ‘Session’ はクリアされます。その後、新しいリーダーが選出されると、key に対する value が更新されます。

■DNS Caching – Consul
http://www.consul.io/docs/guides/dns-cache.html

* DNS キャッシング

DNS は Consul の主要なインターフェースの1つです。既存のインフラ環境に対し、特別な何かを入れる事なく Consul を導入するには、DNS を使うのが簡単です。

Consul は、標準では TTL ( Time To Live ) の値が 0 であり、値をキャッシュする事はありません。この方法の良いところは、DNS 問い合わせ時、常に最新情報を確認するため、今まさに起こってる状況を確認する事ができます。しかしながら、都度問い合わせを行うと遅延が発生するだけでなく、クラスタへの問い合わせに、無駄にネットワーク帯域を使ってしまうかもしれません。

そのため、Consul は DNS に対する問い合わせに対し、どのように振る舞うかを調整するための、パラメータを提供します。

* ステール読み込み ( Stale Read; Stale = 古い、新鮮ではない )

 

ステール読み込みによって、遅延の減少や、DNS クエリのスループットを向上する事ができます。デフォルトでは、データを読み込む事ができる(問い合わせる事ができる)のは、単一のリーダーノード ( Consul の、リーダー状態のサーバ1台 ) のみです。この状態では、読み込みに対する強い一貫性がありますが、スループットは1台のノード分という限界があります。そこで、ステール読み込みを設定する事で、あらゆる Consul サーバに対してサービス状況の問い合わせを行う事ができます。ただ、この状態では、リーダー以外のノードは、古い情報を返すかもしれません。とはいえ、データをステールする事で、並列読み込みによってスケーラビリティが向上します。これにより、全ての Consul サーバは、サービスに対するリクエストがあれば、クラスタ内にあるサーバの数だけスループットを向上できます。

ステール読み込みを制御するための設定は、2つあります。’dns_config.allow_stale’ は、ステール読み込みを有効にするものです。’dns_config.max-stale’ は、どれだけの期間、情報を保持するかを決めます。標準では ‘allow_stale’ は無効になっており、ステールされた結果は表示されません(常に最新の情報が戻ります)。また、’max_stale’ は 5 秒です。つまり、’allow_stale’ が有効であれば、どの Consul サーバに問い合わせもデータを返しますが、(デフォルトでは)リーダーが 5 秒以内に保持しているデータとなります。

* TTL 値

TTL 値は、上位の Consul に対して DNS 結果に対するキャッシュを有効にするもので、(サービスに対する)問い合わせ(lookups)の数を減らし、DNS 問い合わせ実行時の待ち時間(レイテンシ)を減少できます。デフォルトでは TTL 値は 0 であり、何もキャッシュしません。

ノードに対する問い合わせ(例:”foo.node.consul”) のキャッシュを有効にするには、’dns_config.node_ttl’ の値をセットする事ができます。たとえば、”10s” とセットした場合は、サーバからの問い合わせ結果は 10 秒の TTL を提供します。

サービスに対する TTL は、より詳細に指定する事ができます。TTL をサービス単位といったレベルで指定する事ができるほか、ワイルドカートを指定する事で、特定のサービス毎に TTL を使用する必要はなくなります。

使うためには、’dns_config.service_ttl’ マップを使用します。”*” というサービスは、ワイルドカードのサービスです。例えば、次のように指定すると、

{
   "dns_config": {
     "service_ttl": {
        "*": "5s",
        "web": "30s"
     }
  }
}

“web.service.consul” は、30 秒の TTL を持ちますが、”db.service.consul” や “api.service.consul” は 5 秒の TTL になります。

■セッション ( HTTP API )
http://www.consul.io/docs/agent/http.html

session のエンドポイントは、セッションの作成、破棄、問い合わせのために使用します。サポートされているエンドポイントは以下の通りです。

– /v1/session/create: 新しいセッションの作成
– /v1/session/destroy/<session>: 指定したセッションの破棄
– /v1/session/info/<session>: 指定したセッションに問い合わせ
– /v1/session/node/<node>: 特定ノードに紐付くセッション一覧
– /v1/session/list:アクティブなセッションの一覧

session のエンドポイントの読み込みには、ブロッキングクエリがサポートされているので、全ての状態における一貫性をサポートします。

* /v1/session/create

create エンドポイントは、新しいセッションの初期化のために用います。より多くのドキュメントはこちらを参照ください。セッションは、ノードとヘルスチェック(オプション)とを関連づけなくてはいけません。デフォルトでは、エージェント自身のノード名称と、”serfHealth” チェック、そして 15 秒のロック遅延を提供します。

デフォルトでは、エージェントのローカルデータセンタが使用されます。他のデータセンタに問い合わせたい場合は “?dc=” クエリのパラメータを使用して指定できます。なお、リージョン(データセンタ)を跨がってセッションを利用する事は推奨されません。

create エンドポイントは、PUT によって JSON リクエストを body に送ります。リクエスト用の body は、以下の様な形式です。

{
    "LockDelay": "15s",
    "Name": "my-service-lock",
    "Node": "foobar",
    "Checks": ["a", "b", "c"]
}

各フィールドの項目は入力が必須ではありません。デフォルトの値を使うならば、body を PUT する必要はありません。’LockDelay’ フィールドには “s” を使い、秒数を指定する事ができます。また数値のみの指定もできます。小さな値は秒とみなされますが、別途、ナノ秒での設定も可能です。

‘Node’ フィールドは、既に登録されているノードを指し示さなくてはいけません。デフォルトでは、エージェントは自分自身の名前を使用します。’Name’ フィールドは、セッション情報を人間が読む事ができるようにする名前を指定します。最後に ‘Checks’ フィールドは、関連したヘルスチェックのリストを指定するために使います。デフォルトでは、”serfHealth” チェック夫w使用します。なお、このリストをかきかえるのであれば、チェック部分に、この serfHealth を含んでおく事を強く奨めます。

リターンコードが 200 の場合は、body が次のようになります。

{"ID":"adf4238a-882b-9ddc-4a9d-5b6758e4159e"}

ここで表示された ID の値が、新しく作成されたセッションの ID です。

—-

以上です。皆さんの参考になりましたら幸いです。

One thought on “Consul関連ドキュメント(参考訳)Part3

  1. Pingback: Consul の Python クライアントを試す | cloudpack技術情報サイト