本記事はAnoop Jawahar氏 および Sandeep Madanala氏が 2021年10月4日に投稿した記事の翻訳版です。
原文はこちら。
歴史、背景、動機
Nutanixクラウドオペレーティングシステムは、Webスケール、スケールアウトな設計を通じて、高可用性、レジリエンス、障害無害化能力とともに、包括的なストレージとコンピュートの仮想化を提供し、オンプレミスのデータセンターでパブリッククラウドのエクスペリエンスを、提供しています。
当社のソフトウェアの基盤となる2つの主な技術は、Nutanixの分散ストレージと、コンピュート管理のためのKubernetesベースのマイクロサービス・プラットフォーム(MSP)です。あらゆるパブリッククラウドサービスで同じようなテクノロジーを利用することができます。例えば、ストレージであればAmazon Web Services(AWS)のElastic Block Store(EBS)やAzureのマネージドディスク、コンテナのオーケストレーションであればAWS Elastic Kubernetes Service(EKS)、Azure Kubernetes Service(AKS)、Google Kubernetes Engine(GKE)などが挙げられます。
今日の分散型データベースやデータサービスは、こうしたクラウドインフラストラクチャーの構造を活用することで、より軽量で先進的なものになります。また、モダンなデータアプリケーションは、あらゆるパブリッククラウドやプライベートクラウドで実行できるように、一定の原則に従う必要があります。
アプリケーションをクラウド対応にするには、通常、オープンソースのAPI標準へ準拠したり、標準化されたiSCSIストレージをエンドポイントとしたり、
インフラストラクチャ運用管理用のKubernetes(K8s)のようなオープンコンテナオーケストレーションフレームワークが必要です。
Nutanix ObjectsチームがChakrDBとの協業を開始したとき、Nutanixの開発チームは当社のクラウドOS上のストレージサービスを作成していました。Nutanix Objectsは、非構造化データ向けのS3準拠のハイブリッドクラウドストレージで、クラウドの構造を活用できるよう構成されています。
クラウド内の分散キーバリューストア(KVS)の基盤としてRocksDBを選択し、複数のRocksDBインスタンス上にChakrDBと名付けた分散レイヤーを実装して、スタンドアロンのマルチノードクラスタシステムを作成しました。
このブログは2部構成になっています。
・第1部;クラウドで分散KVSを実装する理由と理論について説明します。設計の複雑さを回避しながら、耐障害性、HA、一貫性、シームレスなDev/Opsワークフローなどを実現する方法について説明します。
・第2部;ChakrDBのアーキテクチャ、ベンチマーク結果、製品の予測ロードマップを詳細に説明します。
Objects メタデータレイヤーの要件
ObjectsはかつてクラウドネイティブのスケーラブルなKVSを必要とするNutanixの製品でした。メタデータについては、Objectsは以下のようなエンタープライズグレードのKVSとクラウドネイティブの設計要件を満たすKVSを必要としていました。
- スケールとパフォーマンス - 私たちは、非常に大規模なスケールを想定してObjectsを実装しました。Objects の初期のユースケースには、セカンダリーストレージやバックアップデータが含まれていたため、コストを最適化するためにディープストレージノード(ノードあたり 120~300 TB の容量)の利用と、CPU およびメモリリソースの最小化を行う必要がありました。120-300TBのデータがある場合には、単一ノードでデータが満タンの場合、メタデータも複数テラバイトにもなります。しかし、キャパシティとコストのためにObjectsを最適化するという際に、我々はパフォーマンスへは妥協はしませんでした。我々はObjectsを、人工知能(AI)や機械学習(ML)、データレイク、ビッグデータ分析などのハイパフォーマンスなワークロードが動かせるように非常に高速にしたいと考えていました。仮想的にではあるものの、すべてのクラウドアプリケーションは、永続的なストレージとしてブロブストアを使用しているため、我々はメタデータレイヤーは、大規模で膨大なワーキングセットサイズでも、低レイテンシーと高スループットを実現する必要があると理解していました。最小構成の製品(MVP - Minimum Viable Product)では、歯が立たないのです。
- スケールアウトした分散システム - Objectsは、基盤となる高可用性Nutanix分散ファイルシステムにすべてのオブジェクトを格納するステートレスマイクロサービスモデルから始まりました。メタデータ層はObjectsのすべてのステートとシャーディング構造を処理します。Objectsをスケールアウトさせるには、スケールアウト可能なメタデータレイヤーも必要でした。つまり、分散KVSかステートフルな分散レイヤーを作成する必要があったのです。
- 厳密な一貫性と強力なレジリエンス - Objectsがエンタープライズ対応のストレージシステムであるためには、メタデータ層にも読み取り後に読み取り、書き込み後に読み取る動作の一貫性を保証する必要がありました。同時に、ハードウェア領域の障害やデータ損失が発生した場合に備えて、高いレジリエンスを持つシステムである必要がありました。
- トランザクション機能 - オブジェクトには複数のアトミックなメタデータ操作があるため、少なくともシャードレベルのトランザクション機能が必要でした。
- クラウドネイティブ - Objectsをクラウドネイティブサービスとして我々のK8sベースのマイクロサービスプラットフォーム(MSP)として実装したため、分散KVSも計算とメモリのワークフローにK8sの構造を使用する必要がありました。
- シームレスで自動化されたクラウドワークフロー- Objectsがインフラストラクチャーソフトウェアとして、あらゆるプラットフォームで動作するようにするため、管理者がインスタンスのスケールアウトやリソースのスケールアップに使用するワークフローはコンシューマーグレード(説明書を読む必要のないほど簡単に操作できる)でなければなりません、これはNutanix の設計原則の一つです。
- あらゆるクラウドやリモートストレージで - 私たちは、KVSをあらゆるクラウド、複数のクラウド、またはリモートストレージで実行できるようにしたいと考えていました。この要件はObjectsとはあまり関係なく、むしろKVSの設計を将来的にNutanixのすべてのクラウド製品をまたがって利用していくための話です。設計中に、将来的にシステムをどこで使用できるかを常に考慮することは良いことです。
これらの設計要件を満たすためには、クラウドストレージやコンピューティングインフラを活用し、リファクタリングや余分な作業をすることなく、
必要に応じてあらゆるパブリッククラウド、オンプレミス、ハイブリッドクラウド環境でシームレスにアプリケーションが動かせるという結果になることを保証する必要がありました。
設計上考慮すべき検討事項
いったんこれらの要件を特定した後、仮説を検証するための最小構成を作るだけでも大変な労力を要するため、PoCを実施する前に、理論的な理由付けを行いました。また、このKVSが将来的にハイブリッドクラウドやマルチクラウドをまたがる要件を我々の製品全体で確実に満たせるようにしたいと思っていました。
これらの要件や課題 ― 規模、一貫性、パフォーマンス、耐障害性、スケールアウトアーキテクチャなど ― は、私たちにとって目新しいものではありませんでした。私たちは、Nutanix の分散ストレージ ファブリックのメタデータにCassandra のフォーク バージョンを利用し、長年に渡り取り組んできました。NutanixストレージでCassandraのデータパスとワークフローを最適化し自動化する8年の間に、私たちは多くのことを学んできました。具体的な教訓については、ブログ記事「The Wonderful World of Distributed Systems and the Art of Metadata Management(訳注:今後翻訳予定)」とUSENIXの論文「Fine-Grained Replicated State Machines for a Cluster Storage System」をご参照ください。
私たちの豊富な経験は、単に過去の成果物をクラウド用に再利用したり、再パッケージ化したりしたものではありません。クラウドインフラの機能を最大限に活用し、ハイブリッドクラウドやマルチクラウド環境との互換性を確保する方法を熟慮しなければなりませんでした。高速で分散された一貫性のあるクラウド対応のKVSは、私たちのコアストレージレイヤー、Files、Prism Central、長期保管向けセカンダリストレージサービスプロジェクトなどを含む、Nutanixで開発中の複数のインフラ製品をサポートすることができるはずです。
クラウドストレージやKubernetesは、すでにスケールアウト、高可用性、一貫性のあるストレージやコンピュートを提供しているため、KVSでもこれらを活用する必要があると考えました。従来からの分散KVSはデータレプリケーション、アクティブスタンバイ、データ移行などを利用し、高可用性とレジリエンスを実現していますが、これらの構成は、インフラストラクチャーがすでに高可用性・回復力・一貫性・拡張性を備えたクラウドの中では、不必要な複雑さとリソースのオーバーヘッドを加えるだけに思われました。クラウドインフラストラクチャーは、さまざまな障害のドメイン(ディスク、ホスト、ブロックなど)を数秒で復旧することができます。これは、システムのヘルスチェックで障害ホストを検出し、レプリカリーダーを変更するのに数秒を要する、ほとんどのレプリケーションベースの戦略で経験する遅延とほぼ同じです。高可用性を備えたクラウドインフラの世界では、複雑なレプリケーション、HA、一貫性、スケーリングの問題の幾ばくかを、基盤となるクラウドプラットフォームに容易にオフロードすることができるのです。分散型データベースについて、これまでとは考え方を変えるタイミングに来ているのです。
一般的に、KVSの要件を満たすそうとした場合、ほとんどの場合には3つの選択肢があります。
- ユースケースに対応した新しいオープンソースシステムを使用する。
- 既存のシステムを再利用または再パッケージ化する。
- 新製品を開発する。
以下のセクションには、それぞれの選択肢を検討する際の考え方のプロセスをまとめました。
新しいオープンソースシステムを利用する
新しいオープンソースシステムを導入することは、通常、大掛かりな作業になります。PoCや小規模で低パフォーマンスのユースケースであれば、簡単に始められますが、非常に低いレイテンシーや最小限のリソース消費で高いスループットといった要件だと、選択肢が少なくなります。
新しいオープンソースDBの専門知識の獲得と最適化には、数ヶ月から数年かかることもあります。しかし、必要な時間と労力は別として、私たちが必要とする機能を備えていると現実的に主張できるオープンソースDBはごくわずかです。ストレージシステムには、遅延時間が短く、高スループットを実現できる、非常に軽量な分散KVSが必要です。ほとんどのオープンソースDBは、機能、リソース、性能のバランスを取ろうとして、重くなりがちです。いくつかの分散KVSオプションは、レジリエンスや一貫性に重点を置いていません。ほとんどのシステムが、標準では耐久性の低い、最終的な一貫性の設定になっており、DBをより耐久性の高い、厳格な一貫性にするための様々な変更は、性能を大幅に低下させる結果に繋がりかねません。オープンソースのDBは、大抵はメモリ上のバッファに書き込みを行い、標準では非同期でレプリケーションを実施します。ですが、このやり方では、Objectのようなエンタープライズストレージの要件を満たさないのです。それだけではなく、ほとんどのオープンソースのKVSの選択肢は、オンプレミスまたは特定のクラウドプラットフォームで動作するように実装されており、ハイブリッドクラウドに対応するものはほとんどありません。
既存のNutanix Cassandraの再利用
もうひとつの選択肢は、我々の派生分岐したバージョンのCassandraを使うことです。これまで8年間使ってきたCassandraのフォーク版は、スループット、一貫性、レジリエンス、自動化されたワークフローなどの面で私たちによく貢献してくれましたが、いくつかの欠点もありました。ひとつは、ディスクと仮想マシン(VM)という従来のインフラの世界向けに実装されたものであるということです。クラウドインフラ上で動作するアプリケーションのためではなく、クラウドインフラのためにカスタマイズしていたのです。我々のカスタマイズしたCassandraは、仮想ノードなどの高度なシャーディング機能をサポートしていなかったため、各シャードやノードが非常に大きくなってしまう可能性がありました。単一ノードのシャード範囲を複数のディスクに分割したとしても、単一のコミットログやログ構造化合成(LSM - Log Structure Merge)ツリーの先行書き込みログ(WAL – Write Ahead Log)のI/Oパスが次なるボトルネックになる可能性がありました。我々は仮想ノードでシャーディングを行うことで、スループットを拡張して、レイテンシーを加速し、データの移動と配置の柔軟性を向上させることができると考えていたので、各仮想ノードをKVSエンジンにすることで、リソースを完全に分散させることができるようになると考えたのです。
Cassandraは負荷が高くなると、コンパクション(圧縮)処理や重いJavaガベージコレクション(GC)により速度が低下してしまいます。大規模なGCによるポーズ(停止)が発生すると、一貫したCassandra内での一貫した低レイテンシーを達成することが難しくなります。この制限は、Nutanixでお客様がさまざまなミッションクリティカルなワークロードを稼働させるにあたって重要な課題でした。NutanixのCassandraはわずか3~6GBのメモリでインスタンスあたり100GB~1TBのデータを保存することがあるため、GCによる停止を回避するためにCassandraに割り当てるメモリを増やし続けなければならなかったのです。Cassandraのメモリを増やすことは、ワークロードのサイズによっては一定の説得力のある数字ではありますが、オンプレミスで動作するインフラストラクチャ・ソフトウェアにとっては欠点となります。
私たちはNutanixのCassandraをK8sの世界向けではなく、VMや物理サーバ向けに設計したので、新しいクラウドストレージやコンピュートインフラ向けに、ビルトインのレプリケーションやフォールトトレランスの考え方を変え、最適化する必要があったのです。強力なPaxos(コンセンサス形成プロトコル)による一貫性を持つCassandraのレプリケーションは、クラウドにすでに備えている高可用性を持ったストレージ、コンピュート、メモリーレイヤー上ではオーバーヘッドになるだけのように思えました。
VMとKubernetesの両方で同じCassandraのコードを動作させることは、結果としてこれまでの設計と同じスケーリングとパフォーマンス上の制限を持つ、アーキテクチャに再度コストをかけて取り組むだけように思えたのです。また、Cassandraの再実装は、Nutanixオペレーティングシステム(AOS)に同梱されているNutanix分散ストレージファブリックの既存のリリース計画にも支障をきたすことになるでしょう。
新製品の開発
これらの選択肢を検討している間、RocksDBはAOSのディスクローカルなメタデータDBであるAES(autonomous extent store)で、有望なパフォーマンス結果を示していました。(AESについては、以前のRocksDB at Nutanix(訳注:今後翻訳予定)のブログ記事で詳しく説明しています)。RocksDBが素晴らしい結果を出していたので、他のストレージエンジンを実装することには意味はありませんでした。
EBSやNutanixのストレージファブリックのような高可用性を備えたクラウドストレージが既に実装されているので、分散KVSのためにPaxosやRAFTのような複雑な一貫したレプリケーションプロトコルを実装する必要はありませんでした - RocksDBに分散層を追加するだけで良かったのです。レプリケーションを考える必要がなくなったことで、レプリカを保存するための多くのメモリやストレージリソースを必要とせず、パフォーマンスを向上させることができました。
RocksDBは最小限のメモリで、大量のデータ保存が可能です。(RocksDBのメモリについては、コンパクションについての記事で詳しく説明する予定です)。理論的には、RocksDBでは、より多くのデータを保存するために、より多くのメモリを必要とはしません。メモリが増えれば、それは単にパフォーマンスが向上するということになります。
RocksDBは他のプロセスに組み込むことができるので、レイテンシーとスループットで大きなアドバンテージがあり、クライアントソフトウェアに組み込める分散KVSが実現できるのです。ローカルのプロシージャコールを1つでも追加すると、TCP接続とepoll(I/Oイベント通知のためのシステムコール)のオーバーヘッドにより、レイテンシーが増加し、スループットが大幅に低下します。CassandraはJavaで実装されており、きれいに、簡単に組み込むことができないのです。
RocksDBにはバックエンド環境もあり、基盤となるストレージ層を自由にプラグインすることができます。この機構を使えば、KVSをストレージに依存しない形で、Nutanixの分散ストレージやEBS、Azureのマネージドディスクなど様々な基盤のストレージをサポートできるようになります。
進むべき道
このような分析と私たち自身での検証の結果、私たちはRocksDBをベースに、数十テラバイトから数ペタバイトまでの規模に対応できる、分散された、クラウドネイティブの、高可用性を備えた、高パフォーマンスのKVSを実装することに決めました。ChakrDBの実装を開始したとき、チームはすでにRocksDBに精通していました。低レイテンシーで高いパフォーマンスを発揮できることを分かっていました。分散型のスケールアウト設計とインスタンス全体のシャードや仮想ノードの数に応じてリニアな拡張ができることもわかっていました。そして、クラウドインフラストラクチャーの構造を利用して、既存のKVSをマルチクラウドやハイブリッドクラウド環境に対応するように、設計し直さなければならないことも分かっていました。また、エンタープライズストレージの標準に匹敵するような新しいDBを開発するには、膨大な労力が必要になるであろうことも分かっていました。
そこで、RocksDB上に軽量なDB分散層、すなわち、ChakrDBを実装することを選択しました。K8sのようなクラウドインフラストラクチャーと高可用性ブロックストレージが、この分散KVSの実装に伴う多くの難問を解決しながら、クラウドネイティブソフトウェアのシンプルさと拡張性のすべて実現することができたのです。ハイブリッドクラウドやマルチクラウドの新時代のインフラストラクチャーでは、データベースソフトウェアの設計を根本から見つめ直す必要があるのです。
第2部では、ChakrDBの分散KVSアーキテクチャを詳しく解説し、ここで取り上げた推論や理論がどのように実用化されたかをレビューしていきます。