以下は、2014年11月時点の、http://ceph.com/docs/master/architecture の kanda.motohiro@gmail.com による全訳です。 原文と同じ、Creative Commons Attribution-Share Alike license で公開します。 Google sites に置くために、原文とレイアウトは変わります。リンクが切れているのはごあいきょう。製版前の rst ファイルも置きました。
Ceph は、1つの統一されたシステムで、 オブジェクト, ブロック, そしてファイルのストレージ を提供するユニークなシステムです。 Ceph は、高信頼で、 管理が簡単で、そして フリーです。 Ceph のパワーはあなたの会社の IT インフラストラクチャを変革し、あなたが 大量のデータを扱う能力を高めます。Ceph は素晴らしいスケーラビリティを提供します。 数千のクライアントがペタバイト、エクサバイトのデータをアクセスできます。 Ceph ノード はコモディティハードウエアと賢いデーモンを活用します。 Ceph ストレージ クラスタ は多数のノードを持ち、ノードは互いに、データをダイナミックに複製と再分配するために通信しあいます。
Ceph は、RADOS に基づく無限にスケーラブルな Ceph ストレージ クラスタ を提供します。 RADOS については、 RADOS - A Scalable, Reliable Storage Service for Petabyte-scale Storage Clusters を参照下さい。
Ceph ストレージ クラスタ には、2つのタイプのデーモンがあります:
Ceph モニタ
Ceph OSD デーモン
Ceph モニタ は、クラスタマップのマスターコピーを維持します。 Ceph モニタ のクラスタは、あるモニタデーモンが落ちた時でも高可用性を保証します。ストレージ クラスタ クライアント は、クラスタマップのコピーを、Ceph モニタ から取得します。
Ceph OSD デーモン は自分自身の状態と、他の OSD の状態をチェックして、モニタに報告します。
ストレージ クラスタ クライアントと、それぞれの Ceph OSD デーモン は、 CRUSH アルゴリズムを使って、データの位置についての情報を効率よく計算します。 中心的な検索表に依存する必要はありません。 Ceph の高レベルの機能には、librados を使った、Ceph ストレージ クラスタ への ネイティブインタフェースの提供と、 librados の上に作られた多くのサービス インタフェースが含まれます。
Ceph ストレージ クラスタ は、データを Ceph クライアント から受信します。 クライアントは、 Ceph ブロックデバイス, Ceph オブジェクト ストレージ, Ceph ファイルシステム あるいは、あなたが librados で作ったカスタム実装かもしれません。どこから来たデータでも、 Ceph ストレージ クラスタ はデータをオブジェクトとして格納します。 それぞれのオブジェクトは、ファイルシステムのファイルに対応し、 オブジェクト ストレージ デバイス に格納されます。 Ceph OSD デーモン が、ストレージディスクへの読み書きを処理します。
Ceph OSD デーモン はすべてのデータを、フラットな名前空間のオブジェクトとして 格納します。(例えば、階層やディレクトリはありません。) オブジェクトは識別子と、バイナリデータ、それに、名前と値の対の集合からなる メタデータを持ちます。セマンティックは、完全に、 Ceph クライアント が 決めます。例えば、 CephFS はメタデータを、ファイル所有者、作成日付、 最後の更新日付などのファイル属性を格納するために使います。
ノート
オブジェクト ID は、ローカルファイルシステムだけでなく、クラスタ全体で一意です。
伝統的なアーキテクチャでは、クライアントは中心的なコンポーネント (例えば、ゲートウェイ、ブローカ、API、ファサードなど)と話しました。 それらが、複雑なサブシステムへの単一の入り口として働きました。 これは、性能とスケーラビリティを制限し、単一故障点ともなりました。 (つまり、中心的なコンポーネントが落ちると、システム全体も落ちます。)
Ceph はこの中心的なゲートウェイを取り払って、クライアントを直接、 Ceph OSD デーモン に接続させます。 Ceph OSD デーモン は、オブジェクトの複製を 他の Ceph ノード に作り、データの安全性と高可用性を保証します。 Ceph はまた、モニタのクラスタを使って、高可用性を保証します。中心への集中を 除くために、Ceph は CRUSH というアルゴリズムを使います。
CRUSH の紹介¶
Ceph クライアント と Ceph OSD デーモン の両方は、 CRUSH アルゴリズムを使って、オブジェクト の位置に関する情報を効率的に計算します。中心的な検索表は必要ありません。 CRUSH は昔のアプローチに比べて、優れたデータ管理機構を提供し、仕事を、 クラスタのすべてのクライアントと OSD デーモンにきれいに配分することが 可能なために、マッシブなスケーリングが可能です。 CRUSH は、賢いデータ複製を行い、データ回復可能性を保証します。それは、ハイパースケールなストレージにより適しています。 以下の節は、CRUSH がどのように動作するかを詳しく述べます。 CRUSH についての詳細な議論は、 CRUSH - Controlled, Scalable, Decentralized Placement of Replicated data を参照下さい。
クラスタ マップ¶
Ceph は、 Ceph クライアントと Ceph OSD デーモンが クラスタトポロジーの知識を持っていることを前提とします。 それは、 5 つのマップからなり、これらすべてを “クラスタ マップ”と呼びます。
モニタマップ: は、それぞれのモニタの、クラスタ fsid, 位置、 name address そしてポートを持ちます。それはさらに、現在の世代, マップが作成された時刻, そしてマップが最後に更新された時刻を示します。 モニタマップを見るには、 ceph mon dump を実行します。
OSD マップ: は、クラスタ fsid, マップが作成された時刻, そしてマップが最後に更新された時刻、 プールのリスト、複製の数、 PG の数、 OSD のリストと状態 (例えば, up, in)を持ちます。 OSD マップを見るには、 ceph osd dump を実行します。
PG マップ: は、 PG バージョン, そのタイムスタンプ, 最後の OSD マップの世代, 満杯率, そしてそれぞれの placement group の詳細、例えば、 PG ID, Up Set, Acting Set, PG の状態(例えば, active + clean), そして、それぞれのプールのデータ使用統計を持ちます。 PG マップを見るには、 ceph pg dump を実行します。
CRUSH マップ: は、ストレージデバイスのリスト, failure domain 階層 (例えば, device, host, rack, row, room, etc.), そして、 データを格納する時に階層をたどるときの規則を持ちます。CRUSH マップを見るには、 ceph osd getcrushmap -o {filename} を実行して、次に、 crushtool -d {comp-crushmap-filename} -o {decomp-crushmap-filename} を実行してデコンパイルします。 デコンパイルされたマップは、テキストエディタや、 cat で読めます。
MDS マップ: は、現在の MDS マップの世代, マップが作成された時刻, そしてマップが最後に更新された時刻を持ちます。 それはさらに、 メタデータを格納するためのプール、メタデータサーバーのリスト、 どのメタデータサーバが up であり in であるかを持ちます。 MDS マップを見るには, ceph mds dump を実行します。
それぞれのマップは自身の操作状態の変化の履歴を持ち、列挙することができます。 Ceph モニタは、クラスタマップのマスターコピーを持ちます。それには、クラスタ メンバ, 状態, 変更, そして、 Ceph ストレージクラスタの全体としての健常性が含まれます。
高信頼モニタ¶
Ceph クライアントがデータを読み書きすることができるようになる前に、 Ceph モニタ にコンタクトして、最新の クラスタ マップのコピーを得る必要があります。 Ceph ストレージ クラスタ は、1台だけのモニタでも動作しますが、そうすると、単一故障点となります。 (つまり, モニタが落ちると Ceph クライアントはデータを読み書きできません)。
より良い信頼性とフォールトトレランスのため、 Ceph はモニタのクラスタをサポートします。 モニタのクラスタでは、遅延などの障害のために 1つ以上のモニタが、現在のクラスタ状態から遅れることがあります。このため、 Ceph は、いろいろなモニタインスタンスの間で、クラスタの状態についての合意を必要とします。 Ceph は常にモニタの多数決を使います。 (例えば, 1, 2:3, 3:5, 4:6, など。) そして、 Paxos アルゴリズムを使うことで、モニタの間で、クラスタの状態についての合意を確立します。
モニタの設定について詳しくは、 Monitor Config Reference を参照下さい。
高信頼認証¶
ユーザを識別して、 man-in-the-middle 攻撃を防ぐために、 Ceph は、 cephx 認証システムを使って、ユーザとデーモンを認証します。
ノート
cephx プロトコルは、トランスポートでのデータ暗号化 (例えば, SSL/TLS) も、データ格納時の暗号化もしません。
Cephx は、共用された秘密鍵を認証に使います。ということは、クライアントと モニタクラスタはクライアントの秘密鍵のコピーを持っているということです。認証 プロトコルは、両方のパーティが互いに、鍵のコピーをもっていることを、 実際に鍵をさらさないで証明します。これによって、相互の 認証が得られます。つまり、クラスタはユーザが秘密鍵を持っていることがわかり、 ユーザはクラスタが秘密鍵のコピーを持っていることがわかります。
Ceph の鍵となるスケーラビリティ機能は、Ceph オブジェクトストアへの中央集権的 インタフェースを避けることです。これはつまり、 Ceph クライアント は OSD に直接接続する必要があるということです。データを保護するために Ceph は cephx 認証 システムを提供します。それは、 Ceph クライアントを操作するユーザを認証します。 cephx プロトコルは、 Kerberos に似たように働きます。
ユーザあるいはアクタは、 Ceph クライアントを呼んで、モニタに接続します。 Kerberos とは異なり、それぞれの モニタはユーザを認証でき、鍵を配布できるために、 cephx を使う場合に 単一故障点もボトルネックもありません。モニタは、Kerberos チケットに似た 認証データ構造を返します。それには、 Ceph サービスを得る時に使うセッション鍵が含まれます。 このセッション鍵自身は、ユーザの永続的秘密鍵で暗号化されています。なので、 そのユーザだけが、 Ceph モニタからサービスを受けられます。次にクライアント はこのセッション鍵を使って、モニタに目的のサービスを要求します。 モニタはクライアントに、チケットを提供し、それが実際にデータを 操作する OSDにクライアントを認証します。Ceph モニタ と OSD は秘密を共有しているので、 クライアント はモニタが提供したチケットを、クラスタ内のどの OSD あるいはメタデータサーバに対しても使うことができます。 Kerberos と同じく、 cephx は期限切れしますから、攻撃者は不正に入手した、 期限が切れたチケットやセッション鍵を使うことはできません。 この形式の認証は、通信媒体にアクセス可能な攻撃者が、他のユーザの識別子の元で いんちきのメッセージを作成したり、他のユーザの正当なメッセージを変更したりすることを防ぎます。ユーザの秘密鍵が、期限のあるうちに漏洩しない限り。
cephx を使うには、管理者はまず ユーザを設定しなければいけません。 以下の図で、client.admin ユーザは、コマンドラインから ceph auth get-or-create-key を打って、ユーザ名と秘密鍵を生成します。 Ceph の auth サブシステムは、ユーザ名と鍵を生成し、そのコピーをモニタに格納し、 ユーザの秘密を client.admin ユーザに送り返します。 これはつまり、クライアントとモニタは秘密鍵を共用するということです。
ノート
client.admin ユーザは、ユーザ ID と 秘密鍵を、ユーザに、秘密裏に提供しなくてはいけません。
モニタに認証するには、クライアントはユーザ名を モニタに渡します。モニタはセッション鍵を生成し、そのユーザ名に対応する秘密鍵で 暗号化します。次にモニタはその暗号化されたチケットをクライアントに送ります。 クライアントはそのペイロードを共通の 秘密鍵で復号して、セッション鍵を取得します。セッション鍵は、そのユーザを このセッションの間特定します。クライアントは次にセッション鍵でサインされたチケットをこのユーザのために取得します。 モニタはチケットを生成し、ユーザの秘密鍵で暗号化し、クライアントに送り返します。 クライアントはそのチケットを復号化し、このクラスタの OSD とメタデータサーバへの 要求をサインするために使います。
cephx プロトコルは、クライアントマシンと Ceph サーバの間に行われる通信を認証します。最初の認証の後、クライアントとサーバの間で 送られるメッセージはチケットでサインされ、 モニタ, OSD そしてメタデータ サーバはそれを自分の共用された秘密で検証できます。
この認証は、 Ceph クライアント と Ceph サーバホストの間を保護します。この認証を Ceph クライアントを越えて拡張する ことはできません。もしユーザが Ceph クライアントをリモートホストからアクセス するときは、 Ceph 認証 はユーザのホストとクライアントとの間のコネクションには 適用されません。
設定の詳細は、 Cephx Config Guide を参照下さい。ユーザ管理の詳細は、 ユーザ管理 を参照下さい。
賢いデーモンはハイパースケールを可能とします¶
多くのクラスタ化されたアーキテクチャでは、クラスタメンバーシップの主な目的は、 中心的なインタフェースがそれがアクセスできるノードを知ることです。 そしてその中心的なインタフェースはサービスをクライアントに、二重ディスパッチ によって提供します。これはペタバイトからエクサバイトスケールでは、 大変な ボトルネックになります。
Ceph はボトルネックを除去します。: Ceph の OSD デーモン と Ceph クライアント は、クラスタアウェアです。 Ceph クライアントと同様、それぞれの Ceph OSD デーモンはクラスタ内の他の Ceph OSD デーモンを知っています。これによって、Ceph OSD デーモン は、 他の Ceph OSD デーモン と Ceph モニタに直接相互作用できます。 さらに、 Ceph クライアントも、 Ceph OSD デーモンに直接相互作用できます。
Ceph クライアント, Ceph モニタ そして Ceph OSD デーモン が直接相互作用できる ということは、 Ceph OSD デーモン は Ceph ノード の CPU と RAM を有効活用することができ、中央集権的サーバならば 負荷のためにダウンしてしまうようなタスクを簡単に実行できるということです:
OSD はクライアントに直接サービスします: いかなるネットワークデバイスでも、 サポートできる同時実行するコネクションの数には限界があります。中央集権的システム は、高いスケールでは低い物理的限界を持ちます。Ceph クライアントが Ceph OSD デーモンに直接コンタクトすることができる結果、 Ceph は性能とシステム キャパシティ合計の両方を増加させ、単一故障点を除去できます。Ceph クライアントは必要な時にセッションを維持し、相手は中央集権的サーバではなく特定の Ceph OSD デーモンであることができます。
OSD メンバーシップと状態: Ceph OSD デーモンはクラスタに加入し、自分の 状態を報告します。最も低いレベルでは、 Ceph OSD デーモンの状態は up あるいは down であり、それが実行中で、Ceph クライアントの要求をサービス できるかどうかを示します。もし Ceph OSD デーモン が down かつ in Ceph ストレージクラスタであるならば、この状態は Ceph OSD デーモンの障害を意味します。Ceph OSD デーモン が実行していない (つまり, 落ちているとき), Ceph OSD デーモンは Ceph モニタに、自分が down であるとは報告できません。 Ceph モニタ は、 Ceph OSD デーモンを定期的に ping して、それが実行中であるかを確認することがあります。 しかし、 Ceph では、 Ceph OSD デーモン が隣の OSD が down であると決定することもでき、クラスタ マップを更新し、それを Ceph モニタに報告することができます。これはつまり、 Ceph モニタ が、軽量のプロセス であることができるということです。 詳しくは、OSD をモニタする と ハートビート を参照下さい。
データスクラビング: データ一貫性と清潔さを維持する一環として、 Ceph OSD デーモンは、placement group 内のオブジェクトをスクラブします。つまり、Ceph OSD デーモンは1つの placement group のオブジェクトメタデータをその 他の OSD に格納されている複製と比較します。スクラビング(通常は一日に一回 行われます)は、バグやファイルシステムエラーを捉えることができます。 Ceph OSD デーモン はさらに、深いスクラビングを行い、オブジェクト内のデータをビットごとに比較する こともあります。深いスクラビング(通常は1週間に一度行われます)は、ドライブの 不良セクタを捉えることもでき、それは、軽いスクラビングではわからないことです。 スクラビングの設定について詳しくは、 データスクラビング を参照下さい。
複製: Ceph クライアントと同様に、Ceph OSD デーモンは CRUSH アルゴリズムを使います。しかし、Ceph OSD デーモンはそれを、オブジェクトの複製 をどこに置いたらいいかを計算するために使います。(そして、リバランス)典型的な ライトシナリオでは、クライアントが CRUSH アルゴリズムを使ってオブジェクトを 格納するところを計算し、オプジェクトをプールと placement group にマップし、 次に CRUSH マップを見てその placement group のプライマリ OSD を識別します。
クライアントは、オブジェクトを識別されたプライマリ OSD の placement group に 書きます。次に、自分自身の CRUSH マップのコピーを持っているプライマリ OSD は、 複製の目的のために、セカンダリとターシャリー OSD を位置づけます。そして、 オブジェクトをセカンダリとターシャリー OSD の適当な placement groups に 複製します。 (必要な複製の数だけの OSD を使います。)最後に、 オブジェクトがたしかに格納されたことを確認したら、クライアントに応答します。
Ceph OSD デーモン は自分でデータ複製を行います。Ceph クライアントがそれをする必要はありません。データ可用性とデータ安全性は保証されます。
スケーラビリティと高信頼性 の節で、 Ceph が CRUSH, クラスタアウェアネス、賢いデーモンを使って、スケーラビリティと高可用性を 実現するのを見ました。Ceph の設計で鍵となるのは、自律性、自己修復、そして、賢い Ceph OSD デーモンです。CRUSH が、 データを配置し、クラスタをリバランスし、ダイナミックに障害から回復することによって、 現代的なクラウドストレージインフラストラクチャを可能としているところを 詳しく見ましょう。
プールについて¶
Ceph ストレージ システムは、’プール’ という概念をサポートします。 それは、 オブジェクトを格納するための論理パーティションです。
Ceph クライアントは、 クラスタ マップ を Ceph モニタから得て、オブジェクトを プールに書きます。プールの サイズ や、複製の数、 CRUSH ルールセット、さらに、 placement group の数により、 Ceph がデータをどのように配置するかが決まります。
プールには、少なくても以下のパラメタを設定します:
所有者/オブジェクトへのアクセス
Placement Groups 数
使う CRUSH ルール
詳しくは、 Set Pool Values を参照下さい。
PG を OSD にマップする¶
それぞれのプールはいくつかの placement group を持ちます。 CRUSH は、 PG を OSD にダイナミックにマップします。 Ceph クライアントがオブジェクトを格納するとき、 CRUSH はそれぞれのオブジェクトを placement group にマップします。
オブジェクトを placement group にマップすることで、 Ceph OSD デーモン と Ceph クライアントの間に間接層ができます。 Ceph ストレージクラスタ は、ダイナミックに、拡張(あるいは縮小)したり、オブジェクトを格納するところをリバランス する必要があります。もし、 Ceph クライアントがどの Ceph OSD デーモン がどのオブジェクトを持っているかを”知っていた” ら、それは Ceph クライアント と Ceph OSD デーモンの間に緊密な結合を作ります。 そうしないで、 CRUSH アルゴリズムはそれぞれのオブジェクトを placement group にマップし、さらに、それぞれの placement group を1つ以上の Ceph OSD デーモンにマップします。この間接層により、 Ceph は新しい Ceph OSD デーモン とそれが持つ OSD デバイスがオンラインに なったときに、ダイナミックにリバランスができます。以下の図は、 CRUSH がオブジェクトを placement group にマップし、 placement group を OSD にマップする様子を示します。
クラスタ マップのコピーと CRUSH アルゴリズムにより、クライアントはあるオブジェクトを 読み書きする時に、正確にどの OSD を使えば良いかを計算することができます。
PG ID を計算する¶
Ceph クライアント が Ceph モニタにバインドするとき、最新の クラスタ マップ を取得します。クラスタ マップを使ってクライアントは、クラスタ内のすべてのモニタ、 OSD、そしてメタデータ サーバを知ることができます。 しかし、クライアントはオブジェクトの 位置については何も知りません。
オブジェクトの位置は計算されます。
クライアントに必要な入力は、オブジェクト ID とプールだけです。 単純なことです: Ceph はデータを名前のあるプール (例えば, “liverpool”)に格納します。 クライアントが名前のあるオブジェクト (例えば, “john,” “paul,” “george,” “ringo”, etc.) を格納するときには、クライアントはオブジェクト名、ハッシュコード、プール内の PG 数、そしてプール名から placement group を計算します。 Ceph クライアントは 以下のステップで PG ID を計算します。
クライアントは、プール ID とオブジェクト ID を入力します。 (例えば, プール = “liverpool” そしてオブジェクト-id = “john”)
Ceph はオブジェクト ID を取り出して、ハッシュします。
Ceph はハッシュを PG 数で割った余りを計算します。 (例えば, 58) これが PG ID です。
Ceph は、与えられたプール名からプール IDを得ます。 (例えば, “liverpool” = 4)
Ceph はプール ID を PG ID の前につけます。(例えば, 4.58).
オブジェクト位置を計算するのは、おしゃべりなセッションでオブジェクト位置を問い合わせる よりずっと高速です。 CRUSH アルゴリズムを使ってクライアントは、オブジェクトが格納される べき 場所を計算できます。クライアントはプライマリ OSD にコンタクトして、 オブジェクトを格納あるいは取得することができます。
Peering とセット¶
以前の節で、 Ceph OSD デーモン がそれぞれのハートビートをチェックして、 Ceph モニタに報告していることを見ました。Ceph OSD デーモンが行うもうひとつの事は、 ‘peering’ と呼ばれます。これは、ある Placement Group (PG) を格納する すべての OSD が、その PG のすべてのオブジェクト(とそのメタデータ)の状態について 合意するプロセスです。 実際、 Ceph OSD デーモンは Ceph モニタに、 Peering の失敗 を報告します。 Peering は、普通は、自然に解決しますが、問題が解決しない時は、 Peering 失敗のトラブルシュート の節を調べる必要があります。
ノート
状態について合意することと、 PG が最新の内容を持つことは別です。
Ceph ストレージ クラスタは、少なくても2つのオブジェクトのコピーを格納するように 設計されました。 (つまり, size = 2)これは、データ安全性のための最低限の要求です。高信頼のためには、 Ceph ストレージ クラスタは2つ以上のオブジェクトのコピーを格納するべきです。 (例えば, size = 3 and min size = 2) そうすれば、 縮退 状態のまま運用してもデータ安全性が保たれます。
賢いデーモンはハイパースケールを可能とします の図をもう一度見ましょう。 Ceph OSD デーモンには特別な名前はつけません。(例えば, osd.0, osd.1, etc.) その代わりに、 プライマリ , セカンダリ などと呼びます。慣例として、 Acting Set の最初の OSD が プライマリ です。それは、自分が プライマリ である それぞれの placement group において、peering 処理をコーディネイトする責任があります。 そして、それが、自分が プライマリ である placement group において、 クライアントから来るオブジェクトへの書き込みを受けつける 唯一の OSDです。
いくつかの OSD がある placement group に責任を持っているとき、それらを、 Acting Set と呼びます。 Acting Set は、現在その placement group に 責任を持つ Ceph OSD デーモン のこともありますし、その placement group にかつて どこかの世代において責任を持った Ceph OSD デーモンのこともあります。
Acting Set に属する Ceph OSD デーモン は、いつでも up とは限りません。 Acting Set に属する Ceph OSD デーモンが up の時、それは、 Up Set の 一部です。 Up Set は重要な違いです。なぜならば、 Ceph は、OSD が落ちた時には、 PG を他の Ceph OSD デーモン にリマップすることがあるからです。
ノート
ある PG の Acting Set が osd.25, osd.32 and osd.61 だとすると、最初の OSD, osd.25, が プライマリ です。もし その OSD が落ちたら、 セカンダリ, osd.32 が プライマリ になり、 osd.25 は Up Set から除かれます。
リバランシング¶
Ceph OSD デーモン を Ceph ストレージ クラスタに加えると、クラスタ マップは 新しい OSD を含めた形で更新されます。 PG ID を計算する に戻って考えると、これはクラスタ マップを変えます。 この結果、オブジェクト位置も変わります。計算の入力を変えるためです。 以下の図に、リバランス処理を示します。 (少し、おおざっぱです。大きなクラスタでは、こんなにインパクトはありません。) PG のすべてではないですがいくらかが、元の OSD (OSD 1, and OSD 2) から、新しい OSD (OSD 3)に引っ越します。リバランスしている ときでも、 CRUSH は安定しています。多くの placement group は元の設定のままです。 それぞれの OSD は、追加の容量を得ます。なので、リバランスが完了した時に、 新しい OSD に負荷が集中することはありません。
データ一貫性¶
データ一貫性と清潔性を維持するために、 Ceph OSD は placement group の オブジェクトをスクラブすることがあります。つまり、 Ceph OSDは、ある placement group のオブジェクトメタデータを、他の OSD に格納されている 同じ placement group の複製と比較します。スクラビング(普通、1日に一度。)は、 OSD バグや、ファイルシステムエラーを捉えます。 OSD は、オブジェクトのデータをビットごとに比較する深いスクラビングを行うことも あります。深いスクラビング(普通、1週間に1度。)は、軽いスクラビングではわからない ディスクの不良セクタを見つけることができます。
スクラビングの設定については、 データスクラビング を参照下さい。
erasure コードされたプールは、それぞれのオブジェクトを K+M チャンクとして格納します。 K データ チャンク と、 M コーディングチャンクです。プールは、 K+M の大きさを持つように設定されますから、それぞれのチャンクは OSD の acting set に格納されます。 チャンクのランクは、オブジェクトの属性として格納されます。
例えば、erasure コードされたプールが、5つの OSD (K+M = 5) を使うように作成 された場合、そのうちの2つの損失 (M = 2) に耐えることができます。
エンコードされたチャンクを読み書きする¶
ABCDEFGHI の値を持つオブジェクト NYAN がプールに書かれた時、 erasure エンコーディング関数は、値を3つのデータチャンクに分けます。 単純に、値を3つに分けます。最初は ABC, 2つめは DEF 最後は GHI です。 値の長さが、 K の倍数でない時は、値はパッドされます。関数はさらに、2つの coding チャンクを作ります。: 4つ目は YXY で5つ目は GQC です。 それぞれのチャンクは、 OSD の acting set に格納されます。 チャンクは、同じ名前( NYAN )を持つオブジェクトで、異なる OSDにあるものに格納されます。 チャンクが作成された順序は保たれなくてはならず、それは、名前とともに、 オブジェクトの属性 ( shard_t )として格納されます。 チャンク 1 は ABC を持ち、 OSD5 にあります。チャンク 4 は YXY を 持ち、 OSD3 にあります。
オブジェクト NYAN が erasure コードされたプールから読まれた時、デコード関数は 3つのチャンクを読みます。チャンク 1 は ABC, チャンク 3 は GHI そして チャンク 4 は YXY そして、 オブジェクトの元の値、 ABCDEFGHI を再作成します。デコード関数は、チャンク 2 と 5 が無いことを伝えられます。 (それらは ‘erasures’ と呼ばれます。) チャンク 5 は、 OSD4 が落ちているため読めません。デコード関数は、 3つのチャンクが読まれたらすぐに呼ぶことができます。 OSD2 は一番遅かったので、そこのチャンクは使われません。
中断された完全なライト¶
erasure コードされたプールでは、up set のプライマリ OSD がすべてのライト操作を 受けます。それは、ペイロードを K+M チャンクにエンコードして、他の OSD に送る責任があります。また、それは、placement group ログの 権威あるバージョンを維持する責任があります。
以下の図で、erasure コードされた placement group が、 K = 2 + M = 1 で作成され、3つの OSD によってサポートされています。 K に2つ、M に1つです。placement group の acting set は、 OSD 1, OSD 2 そして OSD 3 です。オブジェクトがエンコードされ、 OSD に格納されました。チャンク D1v1 (つまりデータ チャンク number 1, バージョン 1) は OSD 1 にあり、 D2v1 は OSD 2 にあり、 C1v1 (つまり Coding チャンク number 1, バージョン 1) は OSD 3 にあります。それぞれの OSD の placement group ログは等しいです。 (つまり 1,1 for epoch 1, バージョン 1).
OSD 1 はプライマリで、クライアントから WRITE FULL を受けます。 それは、ペイロードがオブジェクトを完全に書き換えるのであって、その一部だけを上書きする のではないということです。オブジェクトのバージョン 2 (v2) が作成され、バージョン 1 (v1)を 上書きします。 OSD 1 はペイロードを3つのチャンクにエンコードします。 D1v2 (つまりデータ チャンク number 1 バージョン 2) は OSD 1 に, D2v2 は OSD 2 に、 そして C1v2 (つまり Coding チャンク number 1 バージョン 2) は OSD 3 に置かれます。それぞれのチャンクは目的の OSD に送られます。これには、プライマリ OSD も含まれます。それは、チャンクを格納する 他に、ライト操作を処理したり、placement group ログの権威あるバージョンを維持する責任も持ちます。 OSD がチャンクを書くように指示するメッセージを受けた時、それは、 placement group ログに、その変更を示す新しいエントリを作ります。例えば、 OSD 3 が C1v2 を格納するとき、 1,2 ( つまり epoch 1, バージョン 2 ) をログに書きます。 OSD は非同期に動くので、あるチャンクが承認され、ディスクにあるとき、 ( C1v1 と D1v1 のように)他のチャンクは処理の途中かもしれません。 ( D2v2 のように)
すべてがうまくいったら、チャンクは acting set のそれぞれの OSD で承認され、 ログの last_complete ポインタは 1,1 から 1,2 に動くことができます。
最後に、以前のバージョンのオブジェクトを格納するために使われたファイルは削除できます。 D1v1 on OSD 1, D2v1 on OSD 2 and C1v1 on OSD 3.
訳注。上の図の3箇所にある log 1.1 は 1.2 の誤りと思います。 しかし、事故はおきるものです。もし、 D2v2 がまだ処理中のときに OSD 1 が 落ちたならば、オブジェクトのバージョン 2 は部分的に書かれることになります。 OSD 3 はチャンクを1つ持っていますが、回復には十分ではありません。 2つのチャンク: D1v2 と D2v2 が失われ、 erasure コーディングパラメタ K = 2 + M = 1 は、少なくても2つのチャンクが、 3つめを再構成するために必要だと教えます。 OSD 4 が新しいプライマリとなり、 last_complete ログエントリを見ます。 (つまり、このエントリより前の すべてのオブジェクトは、以前の acting set に属するすべての OSD で利用可能なはずです。) それは、 1,1 です。それが、新しい権威あるログの先頭となります。
訳注。上の図の OSD2 の箱は、D1v2 log 1.2 でなく、D2v1 log 1.1 の誤りと思います。 OSD 3 にあるログエントリ 1,2 は、OSD 4 が提供する新しい権威あるログとは 離れているので、捨てられ、C1v2 チャンクを持っているファイルは削除されます。 D1v1 チャンクは、スクラビングの時に、erasure コーディングライブラリの decode 関数によって再作成され、新しいプライマリである OSD 4 に格納されます。
詳しくは、 Erasure Code Notes を参照下さい。
キャッシュティアは、元となるストレージティアに格納されたデータの一部に対して、 Ceph クライアントへのより良い I/O 性能を提供します。 キャッシュティアリングは、比較的高速/高価なストレージデバイス (例えば、SSD)のプールを キャッシュティアの役割を果たすものとして作り、さらに元となるプールとして、 消失訂正符号化あるいは比較的低速/安価なデバイスを経済的なストレージティアの役割を 果たすものとして作ります。 Ceph objecter はオブジェクトをどこに置くかを決め、ティアリングエージェントが、 オブジェクトをキャッシュから元となるストレージにいつフラッシュするのかを決めます。 このため、Ceph クライアントからは、キャッシュティアも元となるストレージティアも 完全に見えません。
詳しくは、 キャッシュティアリング を参照下さい。
あなたは、’Ceph Classes’ と呼ばれる共用オブジェクトクラスを作ることで、 Ceph を拡張できます。 Ceph は、osd class dir ディレクトリ (つまり、デフォルトで $libdir/rados-classes )にある .so クラスを、 ダイナミックにロードします。 クラスを実装する時は、Ceph オブジェクト Store にあるネイティブメソッド、 ライブラリから持ってきたクラスメソッド、あるいは自分で作ったものなどを呼ぶことができる 新しいオブジェクトメソッドを作ることができます。
ライトの時、 Ceph クラスはネイティブあるいはクラスメソッドを呼ぶことができ、 入力されたデータに対して任意の操作の列を実行し、その結果、ライトトランザクションを 発生させることができます。 Ceph はそれらを自動で適用します。
リードの時、 Ceph クラスはネイティブあるいはクラスメソッドを呼ぶことができ、 出力されるデータに任意の操作の列を実行し、そのデータをクライアントに返すことができます。
Ceph クラスの例
content management system のための Ceph クラスを考えます。 それは、特定の大きさとアスペクト比の写真を提供します。入力ビットマップイメージを得て、 適当なアスペクト比になるように切り取り、サイズ変更して、さらに、見えない 著作権表示や透かしを埋め込んで知的財産権を守ります。 そして最後に、できたビットマップイメージをオブジェクトストアに格納します。
実装の例は、 src/objclass/objclass.h, src/fooclass.cc と src/barclass を参照下さい。
Ceph ストレージ クラスタは、生き物のようにダイナミックです。 多くのストレージアプライアンスが、典型的なコモディティサーバの CPU や RAM を完全には 活用できないのに比べ、Ceph はそれが可能です。ハートビート、peering、クラスタリバランス、 そして障害からの回復に関して、 Ceph は仕事をクライアント (さらに、中心的なゲートウエイからも、でもそれは Ceph アーキテクチャには 存在しませんが)からオフロードし、OSD の計算能力を使って仕事を達成します。 おすすめのハードウエア と ネットワーク設定レファレンス を見る時は、Ceph が どのように計算資源を活用しているか、今述べたことを思い出して下さい。
Ceph クライアントは、Ceph ストレージクラスタと相互作用するとき、ネイティブプロトコル を使います。Ceph はこの機能を、 librados ライブラリにパッケージしていますから、 あなたはご自分のカスタム Ceph クライアントを作ることができます。以下の図は、 基本的アーキテクチャを示します。
現代的なアプリケーションは、非同期通信ができるシンプルなオブジェクトストレージ インタフェースを必要とします。 Ceph ストレージ クラスタはそれを提供します。インタフェースは、クラスタ内のすべての オブジェクトへの直接で並列なアクセスを提供します。
プール操作
スナップショットとコピーオンライトクローニング
Read/Write オブジェクト - Create or Remove - オブジェクト全体もしくはバイト範囲 - Append or Truncate
Create/Set/Get/Remove XATTRs
Create/Set/Get/Remove キー値のペア
複合操作と dual-ack セマンティック
オブジェクトクラス
クライアントはオブジェクトへの恒久的な関心を登録して、プライマリ OSD へのセッション をオープンのままにしておくことができます。 クライアントは通知メッセージとペイロードをすべてのウオッチャーに送ることも、 ウオッチャーが通知を受け取った時に通知を受け取ることもできます。 このようにしてクライアントはどんなオブジェクトでも、同期あるいは通信のチャネルとして 使うことができます。
ストレージデバイスにはスループット限界があり、それが性能とスケーラビリティに影響します。 このため、ストレージシステムはよく、 ストライピング をします。 これは、情報のシーケンシャルな断片を複数のストレージデバイスに格納して、 スループットと性能を向上させます。 データストライピングの最も一般的な形式は、 RAID です。 Ceph のストライピングに最も近い RAID タイプは、 RAID 0 あるいは、 ‘striped volume’ です。 Ceph のストライピング は、 RAID 0 ストライピングのスループットと、 n-way RAID ミラーリングの信頼性と、より高速な回復をもたらします。
Ceph のクライアントのタイプは3つあります: Ceph ブロック デバイス, Ceph ファイルシステム, そして Ceph オブジェクト ストレージです。 Ceph クライアントは、それが自分のユーザに提供しているデータ表現形式 (ブロックデバイスイメージ, RESTful オブジェクト, CephFS ファイルシステムディレクトリ) から、Ceph ストレージ クラスタに格納されるオブジェクトへと変換します。
ちなみに
Ceph ストレージ クラスタに格納されるオブジェクトはストライプされません。 Ceph オブジェクト ストレージ, Ceph ブロックデバイス, そして Ceph ファイルシステム は、自分たちのデータを複数の Ceph ストレージ クラスタ オブジェクトへとストライプします。 librados を使って直接 Ceph ストレージ クラスタに書き込む Ceph クライアント は、上記の利益を得るためには、ストライピング (と並列 I/O)を自分でしなければいけません。
Ceph ストライピング形式の最も簡単なものは、オブジェクト数がストライプ数となります。 Ceph クライアントは、オブジェクトがその最大容量になるまでストライプユニットを Ceph ストレージ クラスタ オブジェクトに書き込みます。そして次に、それ以上の データのストライプのために、他のオブジェクトを作成します。 この最も簡単なストライピング形式は、小さなブロックイメージや、 S3 あるいは Swift オブジェクト、そして CephFS ファイルにとっては十分かもしれません。 しかし、この簡単な形式は、 Ceph がデータを placement group 間に分散できる 能力を最大限に活用してはいません。なので、性能向上は限られます。 以下の図は、最も簡単なストライピング形式です:
大きなイメージ、大きな S3 あるいは Swift オブジェクト (例えばビデオ)あるいは 大きな CephFS ディレクトリがありそうならば、クライアントデータを、オブジェクトセット の中で複数のオブジェクトにストライプすれば、読み書きの性能がかなり向上することがあります。
クライアントがストライプユニットをそれらの対応するオブジェクトに並列で書く時に、 ライト性能は素晴らしいものとなります。オブジェクトは異なる placement group にマップされ、さらに異なる OSD にマップされますから、それぞれのライトは並列に行われ、 最高のライト速度が得られます。 単一のディスクへのライトは、ヘッドの移動(例えばシークごとに 6ms)や、1つのデバイスの バンド幅(例えば 100MB/s)によって制限されます。そのライトを複数のオブジェクト (それらは、異なる placement group と OSD にマップします) に分散させることで、 Ceph はドライブごとのシークを減らし、複数ドライブのスループットを結合させてずっと速い ライト(あるいはリード)を実現することができます。
ノート
ストライピングはオブジェクト複製とは独立しています。 CRUSH はオブジェクトを OSD 内で複製します。なので、ストライプも自動的に複製されます。
以下の図で、クライアント データはオブジェクトセットにわたってストライプされます。 (図の オブジェクトセット 1 ) オブジェクトセットは 4 つのオブジェクトからなり、 最初のストライプユニットが オブジェクト 0 の ストライプユニット 0 で、 4つめのストライプユニットが、オブジェクト 3 の ストライプユニット 3 です。 4つめのストライプを書いた後、クライアントはオブジェクトセットが一杯かを見ます。 一杯でなければ、クライアントはストライプを再び最初のオブジェクトに書き始めます。 (図の オブジェクト 0 です。)オブジェクトセットが一杯なら、クライアントは 新しいオブジェクトセット (図の オブジェクトセット 2)を作って、 新しいオブジェクトセットの最初のオブジェクト(図の オブジェクト 4)の最初のストライプ (ストライプユニット 16)に書き始めます。
Ceph がデータをどのようにストライプするかを決める3つの重要な変数があります:
オブジェクトサイズ: Ceph ストレージ クラスタのオブジェクトは、設定可能な最大の サイズがあります。 (例えば, 2MB, 4MB, etc.). オブジェクトサイズは、多くの ストライプユニットを入れることのできる大きさを持つべきで、 ストライプユニットの倍数であるべきです。
ストライプ幅: ストライプには設定可能な最大のユニットサイズ (例えば, 64kb)があります。 Ceph クライアントはそれがオブジェクトに書き込むデータを等しい大きさのストライプユニット に分割します。なお、最後のストライプユニットの大きさは変わります。ストライプ幅は、 オブジェクトが多くのストライプユニットを含むことができるように、オブジェクトサイズの 分数であるべきです。
ストライプ数: Ceph クライアントはストライプユニットのシーケンスを、 ストライプ数で決まる連続するオブジェクトにわたって書き込みます。 連続するオブジェクトを、オブジェクトセットと呼びます。 Ceph クライアント が オブジェクトセットの最後のオブジェクトに書いた後、そのオブジェクトセットの 最初のオブジェクトに戻ります。
重要
あなたのストライピング設定の性能を、 クラスタを本番で使う前にテストして下さい。これらのストライピングパラメタは、 データをストライプしてオブジェクトに書いた後では変更できません。
Ceph クライアントがデータをストライプユニットにストライプして、そのストライプ をオブジェクトにマップしたら、 Ceph の CRUSH アルゴリズムはオブジェクトを placement group にマップし、 placement group を Ceph OSD デーモンにマップします。その後、オブジェクトは ストレージディスク上のファイルとして格納されます。
ノート
クライアントは単一のプールに書き込みますから、オブジェクトにストライプされる すべてのデータは同じプール内の placement group にマップされます。このため、 それらは同じ CRUSHマップとアクセス制御を使います。
Ceph クライアントには、いくつかのサービスインタフェースがあります。それらは:
ブロックデバイス: Ceph ブロックデバイス (a.k.a., RBD) サービス は、サイズ変更可能で、シンプロビジョンされたブロックデバイスを提供します。 スナップショットとクローニングもできます。 Ceph はブロックデバイスをクラスタ内にストライプして、高性能を達成します。 Ceph はカーネルオブジェクト (KO) と QEMU ハイパーバイザーをサポートします。 後者は、仮想化システムにおいて、 librbd を直接使い、 カーネルオブジェクトのオーバーヘッドを避けられます。
オブジェクトストレージ: Ceph オブジェクトストレージ (a.k.a., RGW) サービスは、 Amazon S3 と OpenStack Swift 互換の RESTful API を提供します。
ファイルシステム: Ceph ファイルシステム (CephFS) サービスは、 POSIX 互換のファイルシステムを提供します。 mount 経由あるいは、 ユーザ空間ファイルシステム(FUSE) として使えます。
Ceph は、スケーラビリティと高信頼性のために、追加の OSD、MDS、そしてモニタのインスタンス を動かすことができます。以下の図は、高レベルのアーキテクチャを示します。
Ceph オブジェクト ストレージデーモン、 radosgw は FastCGI サービスで、 オブジェクトとメタデータを格納するための RESTful HTTP API を提供します。 それは、 Ceph ストレージ クラスタの最上位に位置し、独自のデータ形式を持ち、 自分だけのユーザデータベース、認証、アクセス制御を維持します。 RADOS Gateway は統一された名前空間を使います。これはつまり、 あなたは OpenStack Swift 互換の API も Amazon S3 互換の API も使えるということです。例えば、あなたはあるアプリケーションから S3 互換の API でデータ を書いて、そのデータを他のアプリケーションから Swift 互換の API で読むことができます。
S3/Swift オブジェクトとストレージクラスタオブジェクトを比較する
Ceph オブジェクト ストレージ は、 オブジェクト という用語を、自分が 格納するデータを示すために使います。 S3 と Swift オブジェクトは、Ceph が Ceph ストレージクラスタに書くオブジェクト とは違います。 Ceph オブジェクト ストレージのオブジェクトは、 Ceph ストレージ クラスタ オブジェクトにマップされます。S3 と Swift オブジェクトは、 ストレージクラスタに格納されるオブジェクトと、 1:1 に対応する必要はありません。 S3 と Swift オブジェクトが複数の Ceph オブジェクトにマップすることも可能です。
詳しくは、Ceph オブジェクト ストレージ を参照下さい。
Ceph ブロック デバイスは、ブロック デバイスイメージを、 Ceph ストレージ クラスタの複数のオブジェクトにストライプします。 そしてそれぞれのオブジェクトは placement group にマップされ、分散され、 placement group はクラスタ中のそれぞれの ceph-osd デーモンに分散されます。
重要
ストライピングによって、 RBD ブロック デバイスは、単一のサーバよりも 高性能が可能です!
シンプロビジョニングとスナップショットが可能な Ceph ブロック デバイスは、仮想化と クラウドコンピューティングにおいて魅力ある選択肢です。 仮想マシンシナリオでは、Qemu/KVM において、Ceph ブロック デバイスは、 rbd ネットワークストレージドライバを使って配備されることが多いです。 その場合、ホストマシンは librbd を使ってゲストにブロック デバイス サービスを提供します。多くのクラウドコンピューティングスタックは libvirt を 使ってハイパーバイザーと統合します。 シンプロビジョンされた Ceph ブロック デバイス を、 Qemu と libvirt とともに使って OpenStack や CloudStack などのソリューションを サポートできます。
今のところ、他のハイパーバイザーに対しては、 librbd サポートはありませんが、 Ceph ブロック デバイスカーネルオブジェクトを使って、クライアントに ブロック デバイスを提供することもできます。 その他、Xen のような仮想化技術は、 Ceph ブロックデバイスカーネルオブジェクトを アクセスできます。これは、コマンドラインツール rbd でできます。
Ceph ファイルシステム (Ceph FS) は、 POSIX 互換ファイルシステムを提供します。 それは、オブジェクトベースの Ceph ストレージ クラスタの最上位層にあるサービスです。 Ceph FS ファイルは、Ceph が Ceph ストレージクラスタに格納するオブジェクトに マップされます。 Ceph クライアントは、 CephFS ファイルシステムを、 カーネルオブジェクトを使っても、ユーザ空間ファイルシステム(FUSE) を使ってもマウントできます。
Ceph ファイルシステム サービスには、 Ceph メタデータ サーバ (MDS) があり、 Ceph ストレージ クラスタとともに動作します。 MDS の目的は、すべての ファイルシステム メタデータ (ディレクトリ, ファイル所有者, アクセスモード, etc) を、格納することです。メタデータは、高信頼な Ceph メタデータ サーバのメモリに置かれます。 MDS (ceph-mds というデーモン) がある理由は、ディレクトリをリストしたり、 ディレクトリを変えたりする(ls, cd)単純なファイルシステム操作 が、 Ceph OSD デーモン に不必要な負荷をかけるのを避けるためです。このため、 メタデータ をデータと分離することで、 Ceph ファイルシステムは、 Ceph ストレージ クラスタに負荷をかけずに高性能を提供できます。
Ceph FS は、メタデータをデータから分離します。メタデータを MDS に格納し、 ファイル データをCeph ストレージ クラスタの1つ以上のオブジェクトに格納します。 Ceph ファイルシステムは POSIX 互換を目指します。 ceph-mds は、単一プロセスで 動作することもできますし、高可用性とスケーラビリティのために複数の物理マシンに分散してもよいです。
高可用性: 追加の ceph-mds インスタンスは、 standby になれます。 これは、 active であった、任意の障害中 ceph-mds の役割を引き継ぐことができます。 これは容易です。なぜならば、ジャーナルを含むすべてのデータは、 RADOS に格納されているからです。遷移は自動的に ceph-mon がトリガーします。
スケーラビリティ: 複数の ceph-mds インスタンスは active になれます。 それらは、ディレクトリツリーをサブツリー(そして、単一のビジーなディレクトリの断片)に分割し、 効率的に負荷をすべての active サーバの間で分散できます。
standby と active etc の組み合わせは可能です。例えば、 3つの active ceph-mds インスタンスをスケーリングのため、そして1つの standby インスタンスを高可用性のために使えます。
© Copyright 2010-2014, Inktank Storage, Inc. and contributors. Licensed under Creative Commons BY-SA.