これはセクションの複数ページ印刷用ビューです。 .
内部実装
- 1: ディスカバリーサービスのプロトコル
- 2: ログの規約
- 3: Goモジュール
1 - ディスカバリーサービスのプロトコル
ディスカバリーサービスのプロトコルは、共有のディスカバリートークンとエンドポイントリストを使用して、クラスターのブートストラップ時に新しいetcdメンバーが他のすべてのメンバーを検出できるようにします。
ディスカバリーサービスのプロトコルは、クラスターのブートストラップ時にのみ使用します。実行時の再構成やクラスターの監視には使用できません。
このプロトコルでは、新しいディスカバリートークンを使って一意のetcdクラスターをブートストラップします。1つのディスカバリートークンが表せるetcdクラスターは1つだけであることに注意してください。そのトークンを使ったディスカバリープロトコルが開始されたら、途中で失敗した場合でも、別のetcdクラスターのブートストラップに再利用してはなりません。
以降では、自前で運用するディスカバリークラスターに対応した例を使い、検出処理を順に説明します。
このドキュメントはv3ディスカバリーのみを対象とします。v2ディスカバリー の詳細は、以前のドキュメントを参照してください。
プロトコルの流れ
ディスカバリープロトコルは、内部のetcdクラスターを使って新しいクラスターのブートストラップを調整する仕組みです。まず、新しいメンバーすべてがディスカバリーサービスとやり取りし、想定するメンバーリストを生成します。次に、新しい各メンバーはこのリストを使ってサーバーをブートストラップします。これは-initial-clusterフラグと同じ役割を果たします。
以下の手順例では、理解しやすいようにetcdctlコマンドで各ステップを示します。http://example.com:2379でディスカバリーサービス用のetcdクラスターが稼働しているものとします。
etcdのディスカバリープロトコルでは、慣例としてキープレフィックス/_etcd/registryを使用します。
新しいディスカバリートークンの作成
新しいクラスターを識別する一意のトークンを生成します。以降の手順では、ディスカバリー用のキー空間で一意のプレフィックスとして使用します。uuidgenを使うと簡単に生成できます。
想定するクラスターサイズの指定
ディスカバリートークンには、想定するクラスターサイズを必ず指定する必要があります。ディスカバリーサービスはこのサイズを使い、初期クラスターを構成するすべてのメンバーが見つかったかどうかを判断します。
通常のクラスターサイズは3、5、7です。詳細は最適なクラスターサイズ を参照してください。
etcdプロセスの起動
--discovery-tokenフラグにディスカバリートークン${UUID}を設定し、--discovery-endpointsフラグにディスカバリーサービスを支えるetcdクラスターのエンドポイントを設定します。これにより、v3ディスカバリーを使ってetcdクラスターをブートストラップできます。
--discovery-tokenと--discovery-endpointsフラグを指定すると、各etcdプロセスは内部で以下の手順を実行します。
ディスカバリーサービスでクライアント証明書認証を有効にしている場合は、次のフラグを設定します。使い方は、etcdctlでetcdクラスターと通信する場合とまったく同じです。
ディスカバリーサービスでロールベースの認証を有効にしている場合は、次のフラグを設定します。使い方は、etcdctlでetcdクラスターと通信する場合とまったく同じです。
時間やタイムアウトのデフォルト値も、次のフラグで変更できます。使い方は、etcdctlでetcdクラスターと通信する場合とまったく同じです。
自身の登録
各etcdプロセスはまず、指定した新しいクラスターに自分自身をメンバーとして登録します。これは、レジストリーの完全なキーパス内に、メンバーIDをキーとして作成することで行います。
状態の確認
想定するクラスターサイズと登録状況を確認し、次の操作を決定します。
登録済みのメンバーがまだ足りない場合は、他のメンバーが現れるまで待機します。
登録済みメンバー数が想定サイズNを超えている場合は、最初に登録したN個のメンバーをクラスターのメンバーリストとします。自身がこのリストに含まれていれば、検出手順は成功し、メンバーリストを通じてすべてのピアを取得します。含まれていなければ、クラスターが満員であるため、検出手順は失敗して終了します。
メンバーは自身を登録する前にクラスターの状態を確認することもできます。そのため、クラスターが満員の場合はすぐに失敗できます。
全メンバーの待機
待機処理では、すべてのメンバーが見つかるまでキープレフィックス/_etcd/registry/${UUID}/membersを監視し続けます。
2 - ログの規約
etcdはzap ライブラリーを使用し、アプリケーションの出力をレベル別に分類してログに記録します。ログメッセージのレベルは、次の規約に従って決まります。
-
DebugLevelのログは通常、大量に出力されるため、本番環境では一般に無効にします。
- 例:
- リモートピアへの通常のメッセージの送信
- ディスクへのログエントリーの書き込み
- 例:
-
InfoLevelは、デフォルトのログ優先度です。
- 例:
- 起動時の構成
- スナップショット作成の開始
- クラスターへの新しいノードの追加
- 認証サブシステムへの新しいユーザーの追加
- 例:
-
WarnLevelのログはInfoより重要ですが、人が個別に確認する必要はありません。
- 例:
- リモートピアへのRaftメッセージの送信失敗
- 設定された選出タイムアウト内でのハートビートメッセージの受信失敗
- 例:
-
ErrorLevelのログは優先度が高いログです。アプリケーションが正常に動作している場合、エラーレベルのログは出力されないはずです。
- 例:
- WAL用のディスク領域の割り当て失敗
- 例:
-
PanicLevelはメッセージをログに記録した後、パニックを発生させます。
- 例:
- Raftメッセージのエンコード失敗
- 例:
-
FatalLevelはメッセージをログに記録した後、os.Exit(1)を呼び出します。
- 例:
- Raftスナップショットの保存失敗
- 例:
3 - Goモジュール
etcdプロジェクトはバージョン3.5以降、単一のリポジトリ に置かれた複数のGoモジュール で構成されています。
次のモジュールがあります。
-
go.etcd.io/etcd/api/v3 - etcdクライアントとサーバー間の通信プロトコルを定義する API定義(protoやprotoから生成されたライブラリーなど)を含みます。
-
go.etcd.io/etcd/pkg/v3 - etcdで使用する、etcd固有ではないユーティリティーパッケージ群です。 将来独立したリポジトリに移せる可能性のあるパッケージだけをここに置きます。 多くの依存関係を持つコードの追加は避けてください。 それらは自動的にクライアントライブラリーの依存関係にもなり、 軽量に保つという方針に反するためです。
-
go.etcd.io/etcd/client/v3 - ネットワーク(grpc)経由でetcdに接続するクライアントライブラリーです。 etcdの新規利用すべてに推奨します。
-
go.etcd.io/etcd/client/v2 - HTTPプロトコル経由でetcdに接続する旧クライアントライブラリーです。 非推奨です。新規利用ではすべて/v3ライブラリーへの依存を推奨します。
-
go.etcd.io/etcd/raft/v3 - 分散コンセンサスプロトコルの実装です。 etcd固有のコードを含めないようにしてください。
-
go.etcd.io/etcd/server/v3 - etcdの実装です。 このパッケージのコードはetcdの内部実装であり、外部プロジェクトからの利用は推奨しません。 パッケージ構成やAPIは同じマイナーバージョン内でも変更される場合があります。
-
go.etcd.io/etcd/etcdctl/v3 - etcdへのアクセスと管理を行うコマンドラインツールです。
-
go.etcd.io/etcd/tests/v3 - etcdのすべての結合テストを含むモジュールです。 注意:単体テスト(高速でモジュール間の依存関係を必要としないもの)はすべて、 テスト対象のコードと同じモジュールに置くことを推奨します。
-
go.etcd.io/bbolt - 永続的なB木の実装です。 独立したリポジトリ https://github.com/etcd-io/bbolt に置かれています。
運用
-
etcdのすべてのモジュールは、同じバージョンでリリースすることを推奨します。たとえば、
go.etcd.io/etcd/client/v3@v3.5.10はgo.etcd.io/etcd/api/v3@v3.5.10に依存しなければなりません。バージョンを一貫して更新するには、次のコマンドを使用できます。
-
リリースするモジュールは https://golang.org/ref/mod#vcs-version の規則に従ってタグ付けすることを推奨します。 つまり、モジュールごとに固有のタグを付けます。 タグ付けには次のコマンドを使用できます。
-
etcdのすべてのモジュールは、共通の依存先に対して同じバージョンに依存することを推奨します。 次のコマンドで確認できます。
-
go.modファイルには未使用の依存関係を含めてはならず、
go mod tidyの形式に従わなければなりません。 次のコマンドで確認します。 -
全ファイルの自動整形など、すべてのモジュールに対する操作を行うには、 次のスクリプトを使用または拡張してください。
今後の方向性
長期的な目標として、etcdのモジュール構成を次のモデルに近づけたいと考えています。
このモデルは次を前提とします。
- etcdmigrate/etcdadmをetcdctlバイナリーから分離します。 これにより、etcdctlはネットワーククライアントAPIを扱う コマンドラインのラッパーとして明確に位置付けられ、 etcdmigrate/etcdadmはetcdのストレージファイルに対する 直接的な物理操作を担うようになります。
- etcd-proxyを./etcdバイナリーから分離します。実験的なコードが多く、 追加のリスクと依存関係を伴うためです。
- v2プロトコルのサポートを非推奨にします。