AWS スポットインスタンスを利用した ABT チェーンネットワークの構築方法

著者: Tyr Chen(ArcBlock エンジニアリング担当 VP)
編集: Matt McKinney
3月29日金曜日、ABT Network が正式にリリースされました。ABT Network は、クラウドノードと相互接続されたチェーンを利用してネットワークを構築し、完全に分散化された形でブロックチェーン同士を接続することで、次世代のブロックチェーンインフラを再定義します。この記事では、アイデアから一般公開へと進んだこの数か月間に、私たちのチームが経験した実験、障害、成功など、特に興味深いいくつかの出来事を振り返ります。

この記事を十分に理解していただくために、まず基本的な概念をいくつか紹介します。
- ABT Network: ArcBlock の技術を使って構築された、複数のブロックチェーンネットワーク。
- ABT Chain Node: Forge Framework によって作成される ArcBlock のブロックチェーン「ノード」。
- Forge Framework: DApp の構築と実行に必要なものをすべて備えた、完全な開発フレームワーク。
誰でもノードをデプロイできる
Forge Framework と ABT Chain Node の開発にあたり、私たちはこれらが1日数百万件のトランザクションを処理する大規模アプリケーションにも、DIY プロジェクトや小規模な独立開発プロジェクトにも利用できるべきだと考えています。そのため ABT Network 上では、ABT Node は大規模でも小規模でも、その中間でもかまいません。私たちの目標は、サーバーの規模を問わず優れたユーザー体験を提供し、大半のユースケースと要件に対応できるようにすることです。
一例として、単一ノードの費用を15ドルに設定しました。Digital Ocean では、これは次の構成に相当します。

つまり、月額15ドルの予算では、1GB / 1CPU / 25GB ディスクから 2GB / 2CPU / 60GB のホスティングプランまで利用できます。
1月から2月にかけて、開発テストの大部分では5ドルの Extreme Edition ホストを使用し、西部(SF)、東部(NY)、西ヨーロッパ(ロンドン)、東南アジア(シンガポール)にノードをデプロイして P2P ネットワークを形成し、Forge を開発しました。このように非常に制約のある環境を作ることで、あらゆる問題を事前に表面化させ、ソフトウェアの堅牢性と実用性をテストして確認できました。
ネットワークを構築したら、現実のユースケースを再現できるだけのトラフィックが必要です。そのため、社内で開発した記述言語を使ってシミュレーションの開始方法を記述するシミュレーターも開発しました。
pools:
account_migrate: 5
create_asset: 5
declare: 5
exchange: 5
transfer: 10
update_asset: 5
consume_asset: 5
poke: 5
meta:
tick: 500
simulations:
- name: exchange token and assets
interval: 2
num: 2
type: exchange
settings:
value: "1000..20000"
- name: transfer token and assets
interval: 5
num: 2
type: transfer
settings:
value: "1000..5000"
after:
- interval: 1
action: consume_asset変数を変更することで、コンセンサスやスループットなど、テストのさまざまな要素を簡単に調整できます。また、シミュレーションを追加してトラフィックの多様性を変えることで、異なるシナリオも作成できます。
シミュレーターを起動すると、メモリ不足、開いているファイルが多すぎる、gen_server のタイムアウト、TCP 送受信バッファの飽和などの問題により、開発ネットワークは3日間連続でクラッシュしました。
単にノードをより大容量のものに置き換えれば、こうした問題が起きる可能性はほぼゼロになります。しかし私たちの目標は、開発環境であえて問題を発生させ、その大部分を特定して適切に処理することでした。たとえば、使用していたコンセンサスエンジンが不安定で、ときどきクラッシュすること、そしてクラッシュ後に state DB(状態データベース)へ書き込みやすく、その結果ノードが完全にクラッシュして復旧不能になることが分かりました。そこで、コンセンサスエンジンがクラッシュしたら Forge も自動的にクラッシュさせ、私たちが開発した forge starter を使って Forge を再起動する方式を採用しました。再起動後は直近のブロックのデータまで戻って再適用します。コンセンサスエンジンを復元できれば、古いものは引き続き後退し、できなければクラッシュとバックトラックを繰り返します。
このような過酷な環境の中で Forge は徐々に成長し、ノードのネットワークは死んでは生まれ変わり続けました。トム・クルーズ主演の「オール・ユー・ニード・イズ・キル」を見たことがある方なら、この概念が Forge とよく似ていると分かるでしょう。学び、失敗し、また始めるのです。極めて限られたリソースでも、反復するたびにノードはより長く稼働できるようになりました。しかし改善を重ねても、順調な時間は長く続きません。150万 TX 付近に達すると、ネットワークは再びクラッシュしました。

このクラッシュではノードが完全に破壊され、ssh でさえノードにアクセスできなくなりました。この時点で Digital Ocean ノードの監視を見ると CPU は0で、原因はすぐにディスク容量の枯渇だと特定されました。25GB をすべて使い切っていたのです。そこでスナップショットを取得し、次の段階へ進みました。
3月初旬、月額5ドルのクラウドマシンをやめ、月額15ドルの「大型」ノードに置き換えました。Digital Ocean のアカウントでは複数のネットワークを同時に稼働させ、ローリングアップグレードを行いました。当初は週に1回のマイルストーンでしたが、3月第2週には毎日新しいバージョンが出るようになりました。ネットワーク上のノードを更新したことで、100万 TX というマイルストーンは次の500万 TX という目標に置き換わりました。

そこからすぐに600万 TX、続いて700万 TX を超え、最終的にいくつかの破壊的変更を実装したところで計測を止めました。
ArcBlock のエンジニアリングチームは、月額15ドルの小さなクラウドマシン上でブロックチェーンノードを安定稼働させる取り組みに示されるように、業界をリードする開発を数多く行っています。過去1年間、私たちは他社のパブリックチェーンノードにも取り組んできましたが、推奨構成ではクラウドサーバーが月額1,000ドルを超えることも珍しくありませんでした。
アプリケーション開発者が、当初は自分のノードを通してユーザーにサービスを提供する独自チェーンをデプロイしたい場合(世界の4地域に各2ノードを配置すると仮定)、その開発者の費用は月に数万ドルになります。小規模な開発会社、開発者、ユーザーには、プロジェクトを支えるだけの資金がありません。私たちの目標は、この金額を100分の1に減らし、開発者が月にわずか数百ドルでブロックチェーンプロジェクトを構築できるようにすることでした。
以上は1つのユースケースです。では、非常に大きなクラウドサーバーを使う本番環境にデプロイする必要がある、エンタープライズ対応 DApp はどうでしょうか。ArcBlock のノードと環境もエンタープライズ対応であり、現在利用可能な最大規模の DApp をはるかに超えるアプリケーションを支えるよう設計されています。ArcBlock 自身の ABT Network は Amazon Web Services 上で稼働しており、AWS、Azure、IBM といった主要クラウドプロバイダーとすでに提携し、独自環境を簡単に立ち上げられる ABT Node イメージを提供しています。独自の ABT Network を構築する方法を、さらに詳しく見ていきましょう。
シンプルだが単純ではない本番環境
ABT Network はチェーン同士を接続してネットワークを形成することを重視しているため、私たちは周期表の元素にちなんで「Argon」「Bromine」「Titanium」と名付けた3つのチェーンから始めました(Bromine は最新のナイトリービルド版を実行するテスト用チェーンです)。この3つのチェーンのために、安全で信頼できる本番環境を用意する必要があります。
本番環境の要件は次のとおりです。
- 各チェーンをアジア太平洋およびヨーロッパの4地域にデプロイする。
- Argon と Titanium はそれぞれ16ノード、Bromine は4ノードを使用する。
- すべてのノードで公開するのは p2p ポートだけとする。
- ノードの GraphQL RPC と専用ブロックブラウザーには ELB 経由で外部からアクセスできるようにし、gRPC はローカルアクセスのみ許可する。
- 各地域にある各チェーンの ELB ドメイン名を、レイテンシーに基づいて route 53 で負荷分散する。
これらすべてのデプロイを管理するために、Ansible と Terraform を使って大幅に自動化しています。私たちが行うあらゆることと同様に、環境の本番品質を高めながら同時にコストを削減する方法を探しています。
上記の構成で安価な c4.large / c5.large のみを使用し、各ノードに 110G EBS、各チェーンの各地域に ELB を配置すると、1か月の固定費は3,721ドルです。
計算式:0.11(c4.large の価格)x 36 x 24 x 31 + 36 x 110 x 0.12(EBS の価格)+ 25(ELB の価格)x 12
このうち大部分を占めるのが EC2 の費用で、月額3,000ドル近くになります。
では、可用性の基準を維持した本番対応環境を確保しつつ、コストも削減する方法はあるでしょうか。AWS での答えは、いくつかの小さな注意点はあるものの、実に明快です。
その答えはスポットインスタンスです。スポットインスタンスの前提は単純です。ユーザーは、使用されていない Amazon EC2 の容量を大幅な割引価格で購入できます。この EC2 インスタンスは通常の EC2 インスタンスと同じですが、いつでも中断される可能性があります。
次の画像は、us-east-2 と ap-southeast-1 におけるスポットインスタンスの価格推移を示しています。


スポットインスタンスを使うだけで、費用を月額600ドル、つまり上記の月額3,000ドル超と比べて総額月額1,300ドルまで削減できます。コスト面は魅力的ですが、スポットインスタンスが終了したらどうなるのでしょうか。どうすればできるだけ早くサービスを復旧できるでしょうか。また、マシンを自動的に切り替えてオンラインにするために、どうすれば開発サイクルを短縮できるでしょうか。
この制約を克服するため、ルートディスクとデータディスクを分離しました。Forge が保存するすべてのデータはデータディスクに置きます。Forge の設定、ノードの秘密鍵、認証者の秘密鍵はルートディスクに置き、初期化後に AES で暗号化してバックアップします。S3 バケットへの書き込みは1回だけ許可されます。その後ノードの稼働中は、各チェーンの各地域にある健全なノードのデータディスクを定期的にバックアップします。こうして認証者ノードが停止された場合、最新のバックアップからデータディスクを復元し、S3 から認証者ノードの秘密鍵と設定を取得できます。
このアイデアは非常にシンプルで直感的だと考えていますが、機能させるにはある程度の計画が必要です。ABT Network では、スポットインスタンスをテストして検証し、現在も本番対応環境の運用に利用しています。この方法は実用的であり、dApp 開発者やブロックチェーン分野の仲間にとって、スポットインスタンスでブロックチェーンノードを運用する際の参照設計になります。
スポットインスタンスが説明どおり機能するように、私たちのデプロイスクリプト forge-deploy は4つの部分に分かれています。
- 1回だけ必要なスクリプト。たとえば、各地域の各 VPC にセキュリティグループを作成する。
- Forge AMI を作成するスクリプト。新しいバージョンをリリースするたびに、新しい AMI を作成する。
- 新しいチェーンに必要なリソースを作成するスクリプト。スポットリクエスト、EBS、ELB、ターゲットグループを作成し、リスナー(およびリスナールール)を設定し、ドメイン名とドメイン名解決ポリシーを作成する。
- 既存チェーンを管理するスクリプト。チェーンの初期化、ノードの再起動、ノードのアップグレード、破損したノードの修復、新しいノードの追加などを行う。
3月最後の2週間、エンジニアは元の断片的なスクリプト(Digital Ocean マシン用のスクリプト)を基に forge-deploy を開発し、テストしました。毎日の日課は、チェーンを作って破棄し、別のチェーンを作っては破棄することの繰り返しでした。この2週間で、ほとんどのブロックチェーンチームなら丸1年かかりかねない問題を解決しました。デプロイのピーク時には6つのチェーンが並行稼働していました。合計で30を超えるチェーンを作成・破棄し、その中には1日しか存在しなかった abtchain、origin、bigbang、test、abc などもありました。ここでいう「チェーン」とは、単一ノードのチェーンではなく、複数ノードで構成される地域横断型のチェーンを指すことに注意してください。
それまでの経験から得た自信があったため、ABT Network の稼働開始予定日には、最終カウントダウンの30分足らず前に3つのチェーンを破棄しました。チェーンを再作成し、最初のブロックが生まれる瞬間をコミュニティ全体に見届けてもらうためです。スクリプトの実行は予想より遅かったものの、カウントダウンから20分後、Argon、Bromine、Titanium の3チェーンすべてが稼働を開始しました。チェーンのデプロイに必要なコマンドは2つだけです。

そのうち create_fleet は、4地域で次の処理を行います。
- 現在のゾーンのデフォルト VPC id を取得する。
- VPC の subnet id を取得する。
- 事前に作成した複数の security group の id を取得する。
- デフォルト設定で certifier node 用の spot fleet を申請する。
- プリセット設定で sentinel node 用の spot fleet を申請する。
- 申請したすべての instance が正常に動作するまで待つ。
- ELB を作成する。
- target group を作成し、すべての instance を target group に追加する。
- 事前にアップロードした certificate id を取得する。
- 2つの ELB listener を作成する。port 80 は 443 へ直接 301 リダイレクトし、port 443 はトラフィックを target group に転送する。
- DNS domain record を作成し、latency based policy を設定する。
4地域すべてが完了したら、後続処理のためにチェーンの全インスタンスを含む ansible inventory を作成します。

次に init_forge_network では、次の処理を行います。
- データディスクを対応するインスタンスにマウントし、ファイルシステムを XFS でフォーマットする。
- 一時設定ファイルで Forge を起動し、node key と validator key を生成する。
- 生成した key を S3 にバックアップする。
- inventory file を基に certifier node を見つけ、その validator address を genesis configuration に書き込む。
- forge を起動する。
すべてのノードが起動したあと、しばらく待てば、チェーンの誕生です!
ABT Network について詳しく知りたい方は、https://www.abtnetwork.io をご覧ください。
このページに関わるもの
製品
-
ArcBlock Chain
active
アプリのアイデンティティ、資産、合意のための Layer 1。ArcBlock Chain は日常的な操作をプロトコルに組み込み、公開ネットワークのネイティブトークンとして ABT を使います。
用語
-
Decentralization
単一の性質ではなく、部分ごとに問うべき問いです。誰がこれを変更できるか、誰が差し止められるか、そして後から誰が検証できるか。多くのシステムは一部の要素だけが分散的です。
-
ブロックチェーン
記録を暗号学的に結び付け、共通の検証・合意形成ルールに従って取引履歴を確定する分散台帳。