Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Quorum on AWS
Search
ryo0301
January 24, 2020
Technology
0
560
Quorum on AWS
ryo0301
January 24, 2020
Tweet
Share
More Decks by ryo0301
See All by ryo0301
Blockchain x Slack botでピアボーナス
ryo0301
0
240
国交省のデータをSolrで検索
ryo0301
3
1.2k
Other Decks in Technology
See All in Technology
10分で紹介するAmazon Bedrock利用時のセキュリティ対策 / 10-minutes introduction to security measures when using Amazon Bedrock
hideakiaoyagi
0
180
リアルタイム分析データベースで実現する SQLベースのオブザーバビリティ
mikimatsumoto
0
1.2k
現場の種を事業の芽にする - エンジニア主導のイノベーションを事業戦略に装着する方法 -
kzkmaeda
2
1.8k
Postman Flowsの基本 / Postman Flows Basics
yokawasa
1
100
あれは良かった、あれは苦労したB2B2C型SaaSの新規開発におけるCloud Spanner
hirohito1108
2
370
技術的負債解消の取り組みと専門チームのお話 #技術的負債_Findy
bengo4com
1
1.2k
トラシューアニマルになろう ~開発者だからこそできる、安定したサービス作りの秘訣~
jacopen
2
1.8k
技術負債の「予兆検知」と「状況異変」のススメ / Technology Dept
i35_267
1
1k
Building Products in the LLM Era
ymatsuwitter
10
5k
Developers Summit 2025 浅野卓也(13-B-7 LegalOn Technologies)
legalontechnologies
PRO
0
500
マルチモーダル理解と生成の統合 DeepSeek Janus, etc... / Multimodal Understanding and Generation Integration
hiroga
0
370
開発スピードは上がっている…品質はどうする? スピードと品質を両立させるためのプロダクト開発の進め方とは #DevSumi #DevSumiB / Agile And Quality
nihonbuson
2
2.4k
Featured
See All Featured
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
Building Better People: How to give real-time feedback that sticks.
wjessup
366
19k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5.2k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
132
33k
Raft: Consensus for Rubyists
vanstee
137
6.8k
A Modern Web Designer's Workflow
chriscoyier
693
190k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
49
2.3k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
10
1.3k
Fontdeck: Realign not Redesign
paulrobertlloyd
82
5.4k
Keith and Marios Guide to Fast Websites
keithpitt
411
22k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
366
25k
Building Applications with DynamoDB
mza
93
6.2k
Transcript
Quorum ----------› AWS blockchain.tokyo#24 LIFULL Co., Ltd. 秀野 亮@ryo0301
自己紹介 • 物件検索エンジン • AWS移行 • 不動産情報コンソーシアム ADRE • 社内通貨
LIFULL COIN
話すこと 1. 社内通貨の取組み 2. Quorumの仕様とシステム構成 3. AWSのマネージドサービスを使ったノード管 理
社内通貨の取組み
社内通貨の取組み • LIFULL COIN • ブロックチェーン上に御天道様を作 るプロジェクト • 「御天道様が見ている」という 日本古来のアレ
• ほぼ1人で開発 ◦ ボランティアで月1回参加が数人
社内通貨での構成(理想) Cognito AppSync ALB KMS LIFULL COIN Wallet Quorum
QuorumとRaftの特性
Quorum • コンセンサスアルゴリズムにはRaftを採用 ◦ リーダーがブロックを生成、リーダーのブロックをレプリケーション ◦ リーダーは選挙で決める ◦ 過半数のノードが生きてれば大丈夫 •
Raft Visualization ◦ https://raft.github.io/ ◦ 可視化されてて分かった気になれる
Quorum+Raftの利点 • トランザクション発生時にブロックが生成される ◦ 無駄なブロックが出ないので容量節約 /同期高速 • ブロックがほぼリアルタイムに生成される ◦ 初期値だと最低50ms間隔
• フォークがない ◦ Leaderが正義 • ブロックタイムスタンプに信憑性がある ◦ Raftの場合は block.timestamp がナノ秒単位
Quorum+Raftの欠点 • BFTでなくCFT ◦ ビザンティン障害耐性はない • Leader盲信 ◦ 全ブロック作り直せる ◦
extraDataに署名があるので検証はできるっぽい • Leaderが高負荷 ◦ 全てのブロックはLeaderからレプリケーションされる • プライベートチェーンにしか向かなそう ◦ コンソーシアムチェーンの規模や信頼に依る?
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でなくホスト名を使える ◦ 実装するなら先に言って欲しかった
ノード起動時の仕様
起動時の仕様 • Raftでは各ノードにRaftIDが振られる ◦ RaftIDは1から連番で振られる ◦ 1度使ったIDは再利用されない ◦ 新規ノード追加時は最大値 +1
• クラスターの初期ノードか追加ノードかで起動方法が違う
クラスターメンバー全員のenodeを列挙しておく 同じ内容のstatic-nodes.jsonを全員が持っておく 起動方法の違い(初期ノード) • 初期クラスターの構築時 a. 各ノードのローカルに static-nodes.json を用意する必要がある b.
各ノードのenodeが必要=公開鍵とIPが必要 c. static-nodes.json に enode をJSON配列で記述 d. 配列順に上から RaftID が振られる e. 各ノードの static-nodes.json には enode が同じ順序で記述されている必要がある
static-nodes.json [ "enode://
[email protected]
:30303?raftport=50400&discport=0", "enode://
[email protected]
:30303?raftport=50400&discport=0", "enode://
[email protected]
:30303?raftport=50400&discport=0", "enode://
[email protected]
:30303?raftport=50400&discport=0", "enode://
[email protected]
:30303?raftport=50400&discport=0" ]
起動方法の違い(追加ノード) • 既存クラスターに新規ノードを追加する場合 a. static-nodes.jsonには自分のenodeだけ記述すればよい b. geth の起動前に raft.addPeer(enode) しておく必要がある
c. raft.addPeer することで RaftID が発番される d. RaftIDを指定して geth を起動する(--raftjoinexisting) geth 起動前にノード情報をクラスターに事前通知しておく RaftIDを指定して起動すると既存メンバーからの接続待受けモードになる static-nodes.json はもうどうでもいい
無限ループして起動できない問題 起動には RaftID が必要 ↓ RaftID を取得するには raft.addPeer を実行する必要 ↓
raft.addPeer を実行するには引数として enode が必要 ↓ enode を作るには IP が必要 ↓ Fargateはタスクの IP を指定できない (ElasticIPは指定できた気がする ) ↓ IP は起動時に決まる ↓ 起動には RaftID が必要 (振り出しに戻る)
起動スクリプト 解決策 • Fargateタスクの起動からgethの起動の間にraft.addPeerすればいける • 起動スクリプトより別コンテナに分けたほうがいいかも Fargateタスク起動 ↓ IP取得、enode作成 ↓
raft.addPeer(enode)でRaftID取得 ↓ RaftIDを指定してgethを起動
Quorumの全体構成
起動イベント 停止イベント Event Bridge default イベントバス Fargate Quorumクラスター Step Functions
Expressワークフロー Cloud Map ノード情報参照 ノード情報 登録・削除 その他、 ・ALBへのIP登録・削除 ・raft.removePeer ・CloudMap更新の進捗確認 なども行っている
Fargate Quorumクラスター Event Bridge default イベントバス Step Functions Expressワークフロー 起動イベント
StartExecution Cloud Map RegisterInstance WaitOperation ALB TargetGroup RegisterTargets ヘルスチェック ノード情報参照
Fargate Quorumクラスター Event Bridge default イベントバス Step Functions Expressワークフロー 停止イベント
StartExecution Cloud Map DeregisterInstance WaitOperation ALB TargetGroup DeregisterTargets raft.removePeer
Fargateでいいのか • 全ノードが同じデータを持ってる単純で非効率な構成 • Raftの過半数割れ前にノード追加すれば大丈夫 • 用途やRaftのせいでブロックがさほど増えない • なので「Fargateでええじゃろ・・・」 •
初期ノードと追加ノードで起動方法が違うのでECSのサービ スは使えなかった=個別にタスク起動
CloudMapでのノード管理 • フルマネージドなサービスディスカバリ • DNSかAPIかその両方で情報を取得(今回はAPIのみ利用) ◦ QuorumのDNSサポートが実装されたので DNSを使ってもいいかも • ノード管理のためのプロセスを運用したくなかったので使っ
てみた • consul-templateのような構成の変化をイベントで検知する 機能はなかった ◦ Event BridgeにはCloudMap関連のイベントはなさそうだった ◦ 定期的にプルしてくる処理を実装した
StepFunctions Expressワークフ ロー • 最長5分の高速ワークフロー • 標準ワークフローはat-most-onceだが、こちらは at-least-once • 同じ入力の複数の同時実行が考慮されてること(冪等性)
◦ CloudMapあたりの処理はあまり自信がない …
起動処理
起動イベント • カスタムイベント • 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
初期クラスターの構築 • 各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
初期クラスターの構築 ノード情報を揃える ノード情報を含めて起動イベント発火 EventBridgeで起動イベント受信 StepFunctionsのワークフロー開始 CloudMapにノード情報登録 指定台数が起動するまで CloudMap監視 指定台数揃ったらstatic-nodes.json生成 ALBターゲットグループに
IP登録 geth起動 ALBヘルスチェックOK
ノードの追加 • Dockerの起動スクリプトで諸々初期化 • 同じenvの既存ノード一覧をCloudMapから取得 • 必要な情報を用意してJSON-RPCで raft.addPeer(enode)を実行→RaftIDゲット ◦ どれかのノードで成功すればあとはクラスター内で新参者情報
は共有される • 必要な情報を用意してEventBridgeに起動イベントを送 信 • RaftIDを付けてgethを起動 ◦ CloudMapへの登録は待たない ◦ static-nodes.jsonには自身のenodeだけ記述 5 5 raft.addPeer 6
ノードの追加 ノード情報を揃える CloudMapから既存ノード情報を取得 EventBridgeで起動イベント受信 StepFunctionsのワークフロー開始 CloudMapにノード情報登録 ALBターゲットグループに IP登録 geth起動 (RaftID付き)
ALBヘルスチェックOK ノード情報を含めて起動イベント発火 既存ノードに対してraft.addPeerを実行
停止処理
停止イベント • ECSのTaskStateChangeイベント • FargateタスクのlastStatus, desiredStatusが変化すると発火
ノードの停止 • 停止したノードと同じenvのALBターゲットグループARNを取 得 • ALBからIPを登録解除 • 既存ノードに対してJSON-RPCで raft.removePeer(RaftID) を実行
• CloudMapから該当ノードの情報を削除
その他の処理
ALBのターゲットグループも CloudMapで管理 • envごとにALBのターゲットグループもCloudMapで管理して いる • 起動/停止イベントの対象ノードのenvでターゲットグループ を探す ◦ 登録は手作業で、あまりちゃんと設計してない
Learnerの同期→Verifier昇格→ALB 追加 • ブロックの同期が終わるまで最新の情報が取得できない • 取得できないがALBには登録されてしまう • 同期完了イベントが発火できれば、昇格→ALB追加まで出 来そう ◦
まだ実装してない
完