Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Quorum on AWS

ryo0301
January 24, 2020

Quorum on AWS

ryo0301

January 24, 2020
Tweet

More Decks by ryo0301

Other Decks in Technology

Transcript

  1. Quorum+Raftの欠点 • BFTでなくCFT ◦ ビザンティン障害耐性はない • Leader盲信 ◦ 全ブロック作り直せる ◦

    extraDataに署名があるので検証はできるっぽい • Leaderが高負荷 ◦ 全てのブロックはLeaderからレプリケーションされる • プライベートチェーンにしか向かなそう ◦ コンソーシアムチェーンの規模や信頼に依る?
  2. Quorum小話 • 現状、Quorum 2.2.5を使っている • 2.2.6〜2.4.0で色々機能が追加されてる • RaftのLearnerノード ◦ ノード追加時はLearnerとして追加

    ◦ 同期完了後Verifierに昇格、という方法が推奨されてる • RBACコントラクトによるパーミッション管理(β版) ◦ スマートコントラクトで Role Base Access Control ◦ Network、Org.、Sub-Org.、Node、Account を管理 • DNSサポート ◦ enodeにIPでなくホスト名を使える ◦ 実装するなら先に言って欲しかった
  3. クラスターメンバー全員のenodeを列挙しておく 同じ内容のstatic-nodes.jsonを全員が持っておく 起動方法の違い(初期ノード) • 初期クラスターの構築時 a. 各ノードのローカルに static-nodes.json を用意する必要がある b.

    各ノードのenodeが必要=公開鍵とIPが必要 c. static-nodes.json に enode をJSON配列で記述 d. 配列順に上から RaftID が振られる e. 各ノードの static-nodes.json には enode が同じ順序で記述されている必要がある
  4. 起動方法の違い(追加ノード) • 既存クラスターに新規ノードを追加する場合 a. static-nodes.jsonには自分のenodeだけ記述すればよい b. geth の起動前に raft.addPeer(enode) しておく必要がある

    c. raft.addPeer することで RaftID が発番される d. RaftIDを指定して geth を起動する(--raftjoinexisting) geth 起動前にノード情報をクラスターに事前通知しておく RaftIDを指定して起動すると既存メンバーからの接続待受けモードになる static-nodes.json はもうどうでもいい
  5. 無限ループして起動できない問題 起動には RaftID が必要 ↓ RaftID を取得するには raft.addPeer を実行する必要 ↓

    raft.addPeer を実行するには引数として enode が必要 ↓ enode を作るには IP が必要 ↓ Fargateはタスクの IP を指定できない (ElasticIPは指定できた気がする ) ↓ IP は起動時に決まる ↓ 起動には RaftID が必要 (振り出しに戻る)
  6. 起動イベント 停止イベント Event Bridge default イベントバス Fargate Quorumクラスター Step Functions

    Expressワークフロー Cloud Map ノード情報参照 ノード情報 登録・削除 その他、 ・ALBへのIP登録・削除 ・raft.removePeer ・CloudMap更新の進捗確認 なども行っている
  7. Fargate Quorumクラスター Event Bridge default イベントバス Step Functions Expressワークフロー 起動イベント

    StartExecution Cloud Map RegisterInstance WaitOperation ALB TargetGroup RegisterTargets ヘルスチェック ノード情報参照
  8. Fargate Quorumクラスター Event Bridge default イベントバス Step Functions Expressワークフロー 停止イベント

    StartExecution Cloud Map DeregisterInstance WaitOperation ALB TargetGroup DeregisterTargets raft.removePeer
  9. CloudMapでのノード管理 • フルマネージドなサービスディスカバリ • DNSかAPIかその両方で情報を取得(今回はAPIのみ利用) ◦ QuorumのDNSサポートが実装されたので DNSを使ってもいいかも • ノード管理のためのプロセスを運用したくなかったので使っ

    てみた • consul-templateのような構成の変化をイベントで検知する 機能はなかった ◦ Event BridgeにはCloudMap関連のイベントはなさそうだった ◦ 定期的にプルしてくる処理を実装した
  10. 起動イベント • カスタムイベント • Dockerの起動スクリプト内で送信している cat << EOJ | aws

    events put-events --entries file:///dev/stdin [ { "Source": "lifull-coin.quorum", "Detail": "$json", "Resources": [ "$task_arn" ], "DetailType": "Quorum Node State Change" } ] EOJ
  11. 初期クラスターの構築 • 各Fargateタスクでクラスターサイズを指定して起動 ◦ Consulの-bootstrap-expectオプションのような感じ ◦ 指定台数に達したらクラスターの起動処理を開始するオプション • Dockerの起動スクリプトで諸々初期化 •

    必要な情報を用意してEventBridgeに起動イベントを送信 ◦ order (=nodeID) ◦ raftId ◦ env ◦ publicKey ◦ IP ◦ p2pPort ◦ raftPort • 起動スクリプトはCloudMapのノード情報を参照して指定台数が起動するまで待機 • CloudMap上に指定台数のノード情報が集まったら各ノードでstatic-nodes.jsonを 生成→geth起動 2/5 4/5 Waiting Waiting 5/5
  12. ノードの追加 • Dockerの起動スクリプトで諸々初期化 • 同じenvの既存ノード一覧をCloudMapから取得 • 必要な情報を用意してJSON-RPCで raft.addPeer(enode)を実行→RaftIDゲット ◦ どれかのノードで成功すればあとはクラスター内で新参者情報

    は共有される • 必要な情報を用意してEventBridgeに起動イベントを送 信 • RaftIDを付けてgethを起動 ◦ CloudMapへの登録は待たない ◦ static-nodes.jsonには自身のenodeだけ記述 5 5 raft.addPeer 6