# Configuring and operating a Raft ordering service **対象読者**: *Raftオーダリングノード管理者* ## Conceptual overview オーダリングの概念と、サポートされているオーダリングサービスの実装(Raftを含む)の仕組みについては、 [Ordering Service](./orderer/ordering_service.html)のコンセプトドキュメントを参照してください。 オーダリングノードの設定方法(ローカルMSPの作成、ジェネシスブロックの作成など)については、 [Setting up an ordering node](orderer_deploy.html)のドキュメントを参照してください。 ## Configuration すべてのRaftノードはシステムチャネルに追加されなければなりませんが、ノードはすべてのアプリケーションチャネルに追加される必要はありません。 さらに、他のノードに影響を与えることなく、チャネルからノードを動的に削除および追加することができます。 このプロセスについては、以下のReconfigurationセクションで説明します。 RaftノードはTLSピンニングを使用してお互いを識別するため、Raftノードになりすますには、攻撃者はそのTLS証明書の**秘密鍵**を取得する必要があります。 そのため、有効なTLS設定がないRaftノードを実行することはできません。 Raftクラスタは2つのプレーンで構成されます。 * **Local configuration**: TLS通信、レプリケーション動作、ファイルストレージなど、ノード固有の側面を管理します。 * **Channel configuration**: 対応するチャネルのRaftクラスタのメンバーシップ、および、ハートビート頻度、リーダーのタイムアウトなどのプロトコル固有のパラメータを定義します。 各チャネルには、それぞれRaftプロトコルのインスタンスが実行されていることを思い出してください。 そのため、Raftノードは所属する各チャネルの設定に、そのサーバーとクライアントのTLS証明書( `PEM` 形式) を追加して参照する必要があります。 これにより、他のノードがそのノードからのメッセージを受信したときに、メッセージを送信したノードのアイデンティティを安全に確認することができます。 次の `configtx.yaml` のセクションは、チャネルに3つのRaftノード("同意者"とも呼ばれる)が存在することを示します。 ``` Consenters: - Host: raft0.example.com Port: 7050 ClientTLSCert: path/to/ClientTLSCert0 ServerTLSCert: path/to/ServerTLSCert0 - Host: raft1.example.com Port: 7050 ClientTLSCert: path/to/ClientTLSCert1 ServerTLSCert: path/to/ServerTLSCert1 - Host: raft2.example.com Port: 7050 ClientTLSCert: path/to/ClientTLSCert2 ServerTLSCert: path/to/ServerTLSCert2 ``` 注: Ordererは、システムチャネルと、参加するすべてのアプリケーションチャネルに同意者としてリストアップされます。 チャネルコンフィギュレーションブロックが作成される時、 `configtxgen` ツールがTLS証明書のパスを読み取り、そのパスに対応する証明書のバイトに置き換えます。 ### Local configuration `orderer.yaml` には、Raft Ordererに関連する2つの設定セクションがあります。 **Cluster** は、TLS通信の設定を決めます。また、 **consensus** は、ログ先行書き込みとスナップショットの保存場所を決めます。 **Cluster parameters:** デフォルトでは、トランザクションの送信やブロックのプルに使用されるクライアント向けのサーバーと同じgRPCサーバー上で、Raftサービスは実行されていますが、別のポートを持つ別のgRPCサーバーを持つように設定することもできます。 これは、組織のCAによって発行されたTLS証明書を、クラスタノードが相互に通信するためにのみ使用し、クライアント向けAPIにはパブリックTLS CAによって発行されたTLS証明書を使用したい場合に便利です。 * `ClientCertificate`, `ClientPrivateKey`: クライアントTLS証明書とそれに対応する秘密鍵のファイルパス。 * `ListenPort`: クラスタがリッスンするポート。 チャネル設定の `consenters[i].Port` と同じにする必要があります。 空白の場合、Ordererの一般ポート( `general.listenPort` )と同じポートが使用されます。 * `ListenAddress`: クラスタサービスがリッスンしているアドレス。 * `ServerCertificate`, `ServerPrivateKey`: クラスタサービスが別のgRPCサーバー(別ポート)で動作している場合に使用するTLSサーバー証明書のキーペアです。 注: `ListenPort`, `ListenAddress`, `ServerCertificate`, `ServerPrivateKey` は一緒に設定するか、設定しないかを合わせる必要があります。 設定されていない場合は、一般的なTLSのセクション、例えば `general.tls.{privateKey, certificate}` から設定が継承されます。 一般的なTLSが無効の場合: - Ordererの一般的なポートとは異なる `ListenPort` を使用します。 - チャネル設定でTLSルートCAを適切に設定します。 また、`general.cluster` には隠された設定パラメータがあり、これを使用してクラスタ通信やレプリケーション機構をさらに細かく調整できます。 * `SendBufferSize`: Egressバッファに格納されるメッセージの数を調節します。 * `DialTimeout`, `RPCTimeout`: コネクション生成やストリーム確立のタイムアウトを指定します。 * `ReplicationBufferSize`: 他のクラスタノードからのブロックレプリケーションに使用するインメモリバッファに割り当て可能な最大バイト数です。 各チャネルがメモリバッファを持ちます。デフォルトは `20971520` で、これは `20MB` に相当します。 * `PullTimeout`: オーダリングノードがブロックの受信を待って中断するまでの最大時間です。デフォルトは5秒です。 * `ReplicationRetryTimeout`: オーダリングノードが2回連続で試行するまでの最大時間です。デフォルトは5秒です。 * `ReplicationBackgroundRefreshInterval`: このノードが追加された既存のチャネル、または、このノードが過去にレプリケーションに失敗したチャネルに対して、レプリケーションを2回連続で試行する間の時間です。デフォルトは5分です。 * `TLSHandshakeTimeShift`: オーダリングノードのTLS証明書が期限切れで交換が間に合わない場合(下記のTLS証明書のローテーションを参照)、オーダリングノード間の通信が確立できず、オーダリングサービスに新しいトランザクションを送信できなくなります。 このようなシナリオから回復するために、オーダリングノード間のTLSハンドシェイクを `TLSHandshakeTimeShift` に設定された所定の時間だけ後ろにシフトすることができます。 この設定は、個別のクラスタリスナーが使用されている場合にのみ適用されます。 もし、クラスタサービスがOrdererのメインgRPCサーバーを共有している場合は、代わりに `General.TLS` セクションで `TLSHandshakeTimeShift` を指定してください。 **Consensus parameters:** * `WALDir`: `etcd/raft` のログ先行書き込みが保存される場所です。 各チャネルはチャネルIDにちなんだサブディレクトリを持つことになります。 * `SnapDir`: `etcd/raft` のスナップショットを保存する場所を指定します。 各チャンルはチャネルIDにちなんだサブディレクトリを持つことになります。 また、2つの隠し設定パラメータがあり、それぞれ `orderer.yaml` のconsensusセクションに追加して設定できます。 * `EvictionSuspicion`: チャネル退去疑惑の累積期間。ノードがチャネルから追い出された疑惑を確認するために、他のノードからブロックを取得するトリガとなります。 疑惑が確認された場合(検査したブロックにノードのTLS証明書が含まれていない)、ノードはそのチャネルでの動作を停止します。 ノードは、そのチャネルで選出されたリーダーを知らない、または、リーダーとして選出されない場合、そのチャネルの退去を疑います。 デフォルトは10分です。 * `TickIntervalOverride`: この値が設定されている場合、このオーダリングノードが同意者となっている全チャネルで設定されているtick間隔よりも優先されます。 Orderer間のtick間隔の不一致により、1つまたは複数のチャネルで定足数が失われる可能性があります。 この値を設定する際は、十分に注意してください。 ### Channel configuration (既に説明した)コンセンサスとは別に、Raft チャネル設定にはプロトコル固有のツマミに関連する `Options` セクションがあります。 現在のところ、ノードの実行中にこれらの値を動的に変更することはできません。 ノードを再設定して再起動する必要があります。 唯一の例外は `SnapshotIntervalSize` で、これは実行中に調整できます。 注: 設定を誤ると、リーダーが全く選出されない状態になる可能性がある( `TickInterval` と `ElectionTick` が極端に低い場合など)ため、以下の値の変更は避けることを推奨します。 リーダーが選出されない状況を解消することは不可能です。これは、変更にはリーダーが必要なためです。 このような危険性があるため、ほとんどのユースケースにおいて、これらのパラメータをチューニングしないことを推奨します。 * `TickInterval`: 2つの `Node.Tick` を呼び出す間の時間間隔。 * `ElectionTick`: 選出の間に必要な `Node.Tick` を呼び出す回数。つまり、 `ElectionTick` が経過するまでにフォロワーが現在のリーダーから何もメッセージを受け取らなかった場合、そのフォロワーが候補者となり選出が開始されます。 * `ElectionTick` は `HeartbeatTick` よりも大きい必要があります。 * `HeartbeatTick`: ハートビートの間に必要な `Node.Tick` を呼び出す回数。つまり、リーダーはリーダーの地位を維持するために、 `HeartbeatTick` ごとにハートビートメッセージを送信します。 * `MaxInflightBlocks`: 楽観的なレプリケーションフェーズにおいて、インフライトアペンドブロックの最大数を制限します。 * `SnapshotIntervalSize`: スナップショットを取得するバイト数を定義します。 ## Reconfiguration Raft Ordererは、一度に1つのノードのみを追加・削除する場合に限り、動的な(つまり、チャネルがサービスとして起動中に)ノードの追加と削除をサポートしています。 クラスタを再設定する前に、クラスタが運用可能であり、コンセンサスを得られることを確認してください。 たとえば、3つのノードを使用していて、2つのノードが障害を起こした場合、それらのノードを削除するためにクラスタを再設定することはできません。 同様に、3つのノードがあるチャネルで1つのノードが障害を起こした場合、証明書をローテーションすることを試みてはいけません。 これは、2番目の障害を誘発します。 原則として、すべての同意者がオンラインかつ健全でない限り、同意者の追加や削除、同意者の証明書のローテーションなど、Raft同意者への設定変更は決して試みてはいけません。 これらのパラメータを変更する場合、メンテナンス期間中にのみ変更を試みることをお勧めします。 ノードがダウンしているときに、数ノードしかないクラスタで設定を試みた場合に、問題が発生する可能性が最も高くなります。 たとえば、同意者セットに3つのノードがあり、そのうちの1つがダウンしている場合、3つのノードのうち2つが生きていることを意味します。 この状態でクラスタを4ノードに拡張すると、4ノードのうち2ノードしか生きていないことになり、定足数ではありません。 ノードは機能しているクラスタにしかオンボードできない(クラスタの合計サイズが1か2でない限り)ので、4番目のノードはオンボードできません。 そのため、(2つのノードしか生きていない状態で)クラスタを3ノードから4ノードに拡張すると、元のオフラインのノードが復活するまで動けなくなります。 Raftクラスタに新しいノードを追加するには、次のようにします。 1. **TLS証明書の追加** チャネルコンフィギュレーション更新トランザクションを通じて、新しいノードのTLS証明書をチャネルに追加します。 注:新しいノードは、1つまたは複数のアプリケーションチャネルに追加する前に、システムチャネルに追加する必要があります。 2. **最新のコンフィグブロックを取得** システムチャネルに参加しているオーダリングノードから、システムチャネル最新のコンフィグブロックを取得します。 3. **追加されるノードがシステムチャネルに参加していることを確認** 取得されたコンフィグブロックに(もうすぐ追加される)ノードの証明書が含まれていることを確認します。 4. **新しいRaftノードを起動** 設定パラメータ `General.BootstrapFile` に記述されたコンフィグブロックへのパスでノードを起動します。 5. **Raftノードがブロックをレプリケーションするまで待機** 証明書が追加された全てのチャネルについて、既存のノードからブロックをレプリケーションするのを待ちます。 このステップが完了すると、ノードはチャネルへのサービスを開始します。 6. **エンドポイントを追加** 新しく追加されたRaftノードのエンドポイントを、全てのチャネルのチャネル設定に追加します。 既に動作している(いくつかのチャネルに参加している)ノードを、そのノード自身が動作している間にチャネルに追加することは可能です。 これを行うには、単にノードの証明書をチャネルの設定に追加します。 ノードは新しいチャネルへの追加を自律的に検出し(ここでのデフォルト値は5分ですが、もっと早くチャネルを検出したい場合はノードを再起動します)、チャネル内のOrdererからチャネルブロックを取得し、そのチェーン用のRaftインスタンスを起動します。 これが成功したら、新しいRaft Ordererのエンドポイントを含むようにチャネル設定を更新することができます。 Raftクラスタからのノードの削除は、以下の方法で行います。 1. Orderer管理者が制御するシステムチャネルを含めて、全チャネルのチャネル設定から、そのエンドポイントを削除します。 2. 全チャネルのチャネル設定から、(証明書によって識別される)エントリを削除します。ここでも、システムチャネルが含まれます。 3. ノードをシャットダウンします。 特定のチャネルからノードを削除し、他のチャネルへのサービスを継続するには、以下の方法で行います。 1. チャネルのチャネル設定から、そのエンドポイントを削除します。 2. チャネル設定から、(証明書によって識別される)エントリを削除します。 3. 第2フェーズは以下を引き起こします。 * チャネル内の残りのオーダリングノードは、削除が行われたチャネルで、削除されたオーダリングノードとの通信を停止します。 これらのノードは、他のチャネルではまだ通信している可能性があります。 * チャネルから削除されたノードは、すぐに、または `EvictionSuspicion` の時間が経過した後(デフォルトでは10分)、自律的にその削除を検出し、Raftインスタンスをシャットダウンします。 ### TLS certificate rotation for an orderer node すべてのTLS証明書には、発行者が定める有効期限があります。 これらの有効期限は、発行日から10年のものから数ヶ月のものまであるので、発行元に確認してください。 有効期限前に、ノード自身と、そのノードが参加しているすべてのチャネル(システムチャネルを含む)で、これらの証明書をローテーションする必要があります。 ノードが参加する各チャネルについて。 1. 新しい証明書でチャネル設定を更新します。 2. ノードのファイルシステム内の証明書を交換します。 3. ノードを再起動します。 ノードが持つことのできるTLS証明書のキーペアは1つだけなので、更新処理の間は新しい証明書が追加されていないチャネルでサービスを提供できず、フォールトトレランスの能力が低下します。 このため、**一度開始した証明書のローテーションは、できるだけ早く完了させる必要があります**。 TLS証明書のローテーションを開始後、何らかの理由で全チャネルで完了できない場合、TLS証明書を元の状態に戻して、後でローテーションを試みることを推奨します。 ### Certificate expiration related authentication 有効期限があるアイデンティティ(x509証明書に基づくアイデンティティなど)を持つクライアントがOrdererにトランザクションを送信する場合、 Ordererはアイデンティティの有効期限が切れていないかどうかをチェックし、切れている場合はトランザクションの送信を拒否します。 しかし、 `orderer.yaml` の `General.Authentication.NoExpirationChecks` 設定オプションを有効にすることで、アイデンティティの有効期限を無視するようにOrdererを設定することが可能です。 これは、管理者の証明書が期限切れで、管理者の証明書を更新したものに置き換えるためのコンフィギュレーショントランザクションを送信できないような極端な状況でのみ行うべきです。 なぜなら、既存の管理者が署名したコンフィギュレーショントランザクションが期限切れで拒否されてしまうからです。 チャネルを更新した後は、アイデンティティの有効期限チェックを行うデフォルトの設定に戻すことを推奨します。 ## Metrics Operations Serviceの説明と設定方法については、[our documentation on the Operations Service](operations_service.html) を参照してください。 Operations Serviceが収集するメトリクスの一覧は、 [reference material on metrics](metrics_reference.html) を参照してください。 優先するメトリクスは、特定のユースケースと設定に大きく関係しますが、特に監視したいメトリクスが2つあります。 * `consensus_etcdraft_is_leader`: クラスタ内のどのノードが現在リーダーであるかを特定します。 このセットが設定されているノードがない場合、定足数を失ったことになります。 * `consensus_etcdraft_data_persist_duration`: Raftクラスタの永続的なログ先行書き込みにかかる時間を示します。 プロトコルの安全性のために、メッセージは、同意者セットと共有される前に、必要に応じて `fsync` を呼び出し、永続的に保持されなければなりません。 この値が上昇し始めると、このノードはコンセンサスに参加できなくなる可能性があります (このノードやネットワークのサービス停止につながる可能性もあります)。 * `consensus_etcdraft_cluster_size` と `consensus_etcdraft_active_nodes`: これらのチャネルメトリクスは "active" ノード(クラスタの総ノード数に対して現在貢献しているノードのことです)を追跡するのに役立ちます。 アクティブなノード数がクラスタの過半数を下回ると、定足数が失われ、オーダリングサービスはそのチャネル上のブロックの処理を停止します。 ## Troubleshooting * ノードに負荷がかかると、特定のパラメータを変更する必要があるかもしれません。 どのようなシステム、コンピュータ、機械にもあるように、負荷はパフォーマンスの低下を招くことがあります。 コンセプトドキュメントで述べたように、Raftのリーダー選出は、フォロワーノードがリーダーからのデータを運ぶ "heartbeat"メッセージ、または、"append"メッセージのいずれかを一定時間受信しなかった場合に発生します。 Raftノードはチャネル間で同じ通信レイヤーを共有しているため(これはデータの共有を意味していません)、Raftノードが多くのチャネルで同意者セットの一部である場合、不用意なリーダー選出を避けるために、選出のトリガーにかかる時間を長くすることができます。