TT Lab
ブログ

한국어 English 日本語 中文

はじめる
ブログ

ブログ

Rook-Ceph 解説 1: Ceph はデータをどこにどのように配置するか

状態: ドラフト (2026-10-29)、公式ドキュメントおよび論文基準、実測なし。 説明は Ceph v20.2 (Tentacle) の公式ドキュメント (docs.ceph.com/en/tentacle) と Ceph の原論文で確認したもののみを記載しています。デフォルト値はすべてそのドキュメントに記載されている値です。 TT Lab の検証クラスターで ceph status と同様の出力で確認する作業は、本シリーズの第 4 篇(生データが集まり次第執筆します)で行います。 執筆ルール: 実測データを基本とし、測定できなかったものは「未測定」、ドキュメントから見つからなかったものは「未確認」と表記します。

目次

1. 一言で言うと: データの位置を記録した中央のリストがない

Kubernetes で Pod がディスクを要求する (PVC) と、誰かが実際のディスクスペースを提供する必要があります。1 つのノードのディスクを使用すると、そのノードが 停止したときにデータも一緒に失われます。複数のノードのディスクを束ねて 1 つのストレージのように見せかけ、データを複数コピーして保持することで、1 つのノードが 停止しても読み書きを継続できるようにするのが 分散ストレージです。Ceph はその代表的なオープンソースであり、Rook は Ceph を Kubernetes 上で 稼働させるオペレーターです。本シリーズでは、Ceph のアーキテクチャ(第 1 篇)、Rook オペレーターの役割(第 2 篇)、Helm チャートの設定オプション(第 3 篇)を順に解説します。

多くのストレージシステムは、「ファイル X の断片はサーバー 3 番のディスクのどこにあるか」というリスト(メタデータサーバー、割り当てテーブル)を 1 か所に保持します。 読み書きのたびにそのリストに問い合わせる必要があるため、リストがボトルネックおよび単一障害点になります。Ceph を最初に紹介した論文 (Weil ほか、OSDI 2006「Ceph: A Scalable, High-Performance Distributed File System」)は、 この割り当てテーブルを CRUSH という疑似乱数分散関数に置き換えるとまとめています。データがどこにあるかは記録せず、 計算します。 クライアントとストレージデーモンが同じマップと同じ関数を持っていれば、誰でも同じ答えを得ることができます。

Ceph 의 층: 한 RADOS 위의 세 얼굴 블록·파일·S3 가 모두 RADOS 객체로 내려앉는다 VM·파드의 디스크 여러 파드가 공유 S3 클라이언트 RBD 블록 장치, RWO CephFS 파일, RWX(+MDS) RGW S3·Swift HTTP librados: RADOS 에 객체를 읽고 쓰는 라이브러리 RADOS: 신뢰성 있는 자율 분산 객체 저장소 MON ×3 클러스터 맵 원본, Paxos 과반 MGR 대시보드·지표·모듈 osd.0 BlueStore → 디스크 osd.1 BlueStore → 디스크 osd.2 BlueStore → 디스크 클라이언트는 MON 에서 맵을 받고, 데이터는 OSD 와 직접 주고받는다
図: Ceph のレイヤー: RADOS の上に位置する RBD、CephFS、RGW

図の最下層が RADOS(Reliable Autonomic Distributed Object Store) です。Ceph が受け取る データは、ブロックであれ、ファイルであれ、S3 オブジェクトであれ、最終的に RADOS の オブジェクト(名前、バイト列、名前と値のメタデータのセット)に変換されて保存されます。 オブジェクトはディレクトリのないフラットな名前空間に配置されます。その上の RBD、CephFS、RGW は、RADOS をブロックデバイス、ファイルシステム、S3 として見せるための翻訳レイヤーであり、これら 3 つが RADOS にリクエストを送るための共通ライブラリが librados です (公式ドキュメント: Architecture).

2. RADOS を構成するデーモン群

Ceph クラスターは、役割の異なる 4 種類のデーモン(バックグラウンドプロセス)で構成されます。Rook では、通常 1 つのデーモンが 1 つの Pod に対応します。

デーモン 役割 数量 Rook の Pod 名
MON (モニター) クラスターマップのマスターコピーを維持し、クライアントに配布する。認証 (CephX) も担当する 通常 3、奇数を推奨 rook-ceph-mon-a など
MGR (マネージャー) モニタリング、オーケストレーション、プラグインモジュールのエンドポイント。ダッシュボードやメトリクスはここから提供される 1(スタンバイ 1台を追加して 2) rook-ceph-mgr-a など
OSD (Object Storage Daemon) ディスクにオブジェクトを保存し、レプリケーション、リカバリ、スクラブを直接実行する 通常 1 ディスクにつき 1 つ rook-ceph-osd-0 など
MDS (メタデータサーバー) CephFS のディレクトリ、オーナー、パーミッションなどのファイルメタデータを管理する CephFS 使用時のみ ファイルシステムごとにアクティブおよびスタンバイのペア以上

MON: クラスターマップと Paxos クォーラム

クライアントが Ceph からデータの読み書きを行うには、まず MON に接続して最新の クラスターマップを取得する必要があります。公式ドキュメントによると、クラスターマップは 実際には 5 つのマップのセットです。

マップ 含まれる内容 確認コマンド
Monitor マップ クラスターの fsid、各 MON の名前・アドレス・ポート ceph mon dump
OSD マップ プール一覧、レプリケーション数、PG 数、各 OSD の状態 (up/down, in/out) ceph osd dump
PG マップ PG ごとの状態(例: active+clean)、Up Set / Acting Set、使用量 (ドキュメントに例なし)
CRUSH マップ ストレージデバイス一覧、障害ドメイン階層(デバイス、ホスト、ラックなど)、配置ルール ceph osd getcrushmap および crushtool -d
MDS マップ CephFS メタデータプール、MDS の一覧と状態 ceph fs dump

マップには更新されるたびにインクリメントされるバージョン番号 (epoch) が存在します。MON が 1 つだけの場合、その MON が停止した瞬間に誰もマップを取得できなくなるため、通常は複数のインスタンスを配置します。複数の MON が異なるマップを提示してはならないため、Ceph は Paxos という合意アルゴリズムを使用してマップの変更を決定し、 過半数が稼働している状態でなければ決定を下しません。ドキュメントの例によると、MON が 1 台の場合は 1、3台の場合は 2、5台の場合は 3、6台の場合は 4 が過半数となります。そのため、3台は 1台、5台は 2台が停止しても耐えられますが、4台にしても 3台と比べて耐障害性は向上しません。これが奇数が推奨される理由です (Monitor Config Reference). MON はマップの変更を単一の Paxos インスタンスとして記録し、その結果を RocksDB キーバリューストアに書き込みます。

OSD と BlueStore

OSD は 1 つのディスクを担当し、その上にオブジェクトを保存するデーモンです。現在のデフォルトストレージエンジンである BlueStore は、ディスク上に ext4 や XFS などの ファイルシステムを作成せず、 デバイスに直接 (raw) 書き込みます。オブジェクトのメタデータは内蔵の RocksDB に格納されます。デバイスは最大 3 つに分割できます (BlueStore Configuration Reference).

BlueStore は書き込まれるすべてのデータとメタデータに チェックサムを付与し(デフォルトは crc32c)、読み込み時に検証します。メモリはキャッシュを自律的に調整し、 osd_memory_target(デフォルト 4Gi、最小値 896M)を超えないように動作します。この値は第 2 篇と第 3 篇における Rook のリソース設定に関連して再び登場します。

OSD は隣接する OSD と互いに heartbeat を送受信します。デフォルトでは 6 秒ごとに ping を送信し (osd_heartbeat_interval)、20 秒間応答がない場合 (osd_heartbeat_grace) にその OSD がダウンしたと MON に通知します。MON はダウンした OSD が 10 分間 (mon_osd_down_out_interval) 復帰しない場合、その OSD をデータ配置から除外します (out)。その時点から、その OSD の担当分を他の OSD が分担する再配置が開始されます。ただし mon_osd_down_out_subtree_limit(デフォルト rack)より大きな単位が丸ごとダウンした場合は、自動的に除外されません。ラック全体の停電を大量のデータ移動として誤認しないためです (Configuring Monitor/OSD Interaction).

). OSD はさらに スクラブを実行します。同一 PG のレプリカ間でメタデータを比較する軽量なスクラブは通常毎日実行され、データをビット単位で比較するディープスクラブはデフォルトで毎週実行されます。軽量なスクラブでは検出できないディスクの不良ブロックをディープスクラブが検出します。

MGR と MDS

MGR は、MON にとって重い処理(メトリクス収集、ダッシュボード、各種モジュール)を担当するエンドポイントです。MDS は CephFS を使用する場合にのみ必要です。ディレクトリの一覧表示や移動などのls, cdメタデータ操作が OSD に負荷をかけないよう、メタデータをメモリ上に保持して個別に処理します。ファイルの実データ自体は MDS を経由せず、直接 RADOS オブジェクトとして処理されます。これら 2 つについては第 7 節で再度解説します。

3. オブジェクトが OSD を見つけ出す 2 回の計算: プール、PG、CRUSH

プール

プール(pool) は、オブジェクトを格納する論理的な区画です。プールごとに少なくとも 3 つの要素が定義されます。レプリカ数 (size)、どの CRUSH ルールを使用して配置するか、そして PG をいくつに分割するか (pg_num) です。ブロックストレージ用プール、ファイルシステムメタデータ用プール、S3 データ用プールなど、用途ごとに個別に作成します。

1 回目の計算: オブジェクト名から PG へ

PG(placement group、プレースメントグループ) は、プールを細かく分割したグループです。Ceph は個々のオブジェクト単位ではなく、PG 単位で位置を決定し移動させます。 ドキュメントの例をそのまま使用すると、 liverpool プール(プール番号 4)に john というオブジェクトを書き込む際、クライアントは次のように計算します。

  1. オブジェクト名 john をハッシュ化します。
  2. ハッシュ値をプールの PG 数で割った余りを PG 番号として使用します(例: 58)。
  3. プール番号を先頭に付与して PG ID を生成します: 4.58.

2 回目の計算: PG から OSD リストへ

次に CRUSH(Controlled Replication Under Scalable Hashing) アルゴリズムが、PG ID、CRUSH マップ、プールのルールを受け取り、「この PG を格納する OSD リスト」を返します。リストの最初の OSD が primary、残りが secondary となります (Architecture: Calculating PG IDs, Peering and Sets).

객체가 OSD 를 찾아가는 두 번의 계산 문서의 예: liverpool 풀(번호 4)의 객체 john. OSD 번호는 설명용 ① 해시로 PG 를 정한다(클라이언트 혼자 계산) 객체 john hash(john) mod pg_num → 58 PG 4.58 ② CRUSH 로 OSD 목록을 정한다 CRUSH(PG 4.58, CRUSH 맵, 풀의 규칙) [osd.1, osd.5, osd.7] 첫째 osd.1 이 primary ③ 장애 단위 host: 사본마다 다른 호스트 host A osd.0 osd.1 host B osd.4 osd.5 host C osd.6 osd.7 호스트 하나가 통째로 죽어도 남은 두 사본은 다른 호스트에 있다
図: オブジェクト名が PG を経由して 3 つの OSD に配置されるまでの 2 回の計算

CRUSH マップには、ストレージデバイス (OSD) の一覧と、それらのデバイスをまとめる バケットの階層が含まれています。デフォルトのバケット種類は下から上に向かって osd, host, chassis, rack, row, pdu, pod, room, datacenter, zone, region, root です。OSD が新しくデプロイされると、 そのノード名の host バケットの下に自動的に配置されます。プールのルールには failure domain(障害ドメイン)が指定されており、これを host に設定すると、CRUSH はレプリカごとに異なるホストを選択します。1つのホストが丸ごとダウンしても、同じ PG の別のレプリカは別のホストに残るということです。規模の大きい環境では、障害ドメインを rack に引き上げることもあります (CRUSH Maps).

計算を2回に分ける理由は 間接層です。クライアントが「オブジェクト X は OSD 3番にある」と直接知っている場合、OSD を追加・削除するたびにすべてのオブジェクトの位置を再通知しなければなりません。オブジェクトを PG に固定し、PG のみが OSD の間を移動するようにすれば、クラスターが拡大・縮小するときに移動する単位が数十億個のオブジェクトではなく数千個の PG になります。CRUSH 自体は Weil らによる SC 2006 の論文 「CRUSH: Controlled, Scalable, Decentralized Placement of Replicated Data」で初めて紹介されました。

PG を保持する OSD 同士が「この PG のオブジェクトの状態はすべて同じである」と合意するプロセスを peering と呼びます。現在その PG を担当する OSD のセットが Acting Set、その中で稼働しているものが Up Set です。primary がダウンすると、次の OSD が primary を引き継ぎます。

PG はいくつが適切か:PG オートスケーラー

PG が少なすぎるとデータが OSD 間で均等に分散されず、多すぎると peering のトラフィックとメモリが増加します。かつては人間が計算して pg_num を決定していましたが、現在は PG オートスケーラーがプールごとの使用量に基づいて決定します (Placement Groups).

設定 デフォルト値 意味
osd_pool_default_pg_autoscale_mode on 新規プールのオートスケールモード。 on の場合、 pg_num を指定していない新規プールは PG 1個から開始する
mon_target_pg_per_osd 100 1つの OSD が担当する PG レプリカ数の目標値。ドキュメントでは、非常に小規模なクラスターでない限り 200 を推奨している
調整閾値 3倍 推奨値と現在値に3倍以上の乖離がある場合にのみ変更する(増やす際、推奨値が 512・1024 なら 1.0、2048 なら 2.0 に引き下げる)
bulk プール表示 オフ 有効にすると「大きなプール」とみなされ、最初から多めの PG が割り当てられる

ceph osd pool autoscale-status はプールごとの推奨値(NEW PG_NUM)を表示します。パート3で見る Rook チャートのオブジェクトストアデータプールは、 bulk: "true" を有効にしておきます。

4. レプリケーションとイレイジャーコーディング

データを保護する方法には2つあります。

レプリケーション(replication)は、同じオブジェクトをそのまま複数コピーして保持します。 osd_pool_default_size のデフォルトは3です。 min_size は「レプリカが最低何部書き込まれてからクライアントに成功を通知するか」であり、デフォルトの0は size - (size / 2) を意味します(整数除算のため、size が3の場合は2)。そのため、size 3 のプールはレプリカを1つ失っても読み書きを継続しますが、2つ失うとその PG は I/O を停止します (Pool, PG and CRUSH Config Reference).

イレイジャーコーディング(erasure coding, EC)は、オブジェクトを K 個のデータ断片に分割し、M 個のコーディング断片を計算して合計 K+M 個を異なる OSD に配置します。K 個さえ残っていれば元のデータを復元できます。空間コストは (K+M)/K です (Erasure Code).

方式 耐えうる同時障害数 元データ 1 GiB に必要な容量 公式ドキュメントの評価
レプリケーション size 3 2 3.0 GiB デフォルト値
EC K=2, M=1 1 1.5 GiB 最も単純な EC。M=1 は本番データでの使用を強く非推奨
EC K=2, M=2 2 2.0 GiB EC プールのデフォルトプロファイル
EC K=4, M=2 2 1.5 GiB プロファイル選びに迷った場合に推奨される

ドキュメントでは、EC をタダの昼食(タダより高いものはない)のように勘違いしないよう記されています。特に HDD やリカバリ・バックフィル中の性能低下が大きいです。M=1 の場合、メンテナンス中にデータが使用不能になり、障害が重なるとデータが失われると警告しています。また、EC プールは omap(オブジェクトに付随するキー・バリューデータ)をサポートしていないため、RBD や CephFS はメタデータをレプリケーションプールに置き、データのみを EC プールに配置する必要があり、EC プールには allow_ec_overwrites を有効にする必要があります。 EC プールの min_size は K+1 以上が推奨されます。プロファイルはプール作成後に変更できないため、変更するには新しいプールを作成してデータを移行する必要があります。

もう1つ、障害ドメインの数がレプリカ数より少ない場合、CRUSH はルールを満たすことができません。障害ドメインが host でホストが3台の場合、レプリケーション size 3 はホストごとに1部ずつ配置され、K+M=3 である EC 2+1 もぴったり収まります。その代わり、ホストが1台ダウンするとレプリカを移動させておく4台目のホストがないため、そのホストが復旧するまで PG はレプリカが不足した(degraded)状態のまま残ります。

5. 書き込みパス:なぜクライアントは OSD と直接通信するのか

복제 풀(size 3)에 객체 하나를 쓰는 여섯 걸음 MON 클러스터 맵 원본 ① 인증하고 맵 받기 클라이언트 ② 혼자 계산 primary OSD osd.1 (PG 4.58) ③ 쓰기 ⑥ 성공 ④ 복제 ⑤ 확인 osd.5 secondary osd.7 secondary MON 은 데이터 경로 밖 복제는 클라이언트가 아니라 primary 가 한다 클라이언트는 한 번만 보낸다
図:レプリケーションプールにオブジェクトを1つ書き込む際の6つのステップ

レプリケーションプールにオブジェクトを書き込む手順は、公式ドキュメントに次のように記載されています。

  1. クライアントが MON に接続して CephX で認証を行い、最新のクラスターマップを取得します。
  2. クライアントがセクション3の2つの計算により、PG と OSD のリストを自ら算出します。この計算の際、誰とも通信を行いません。
  3. クライアントが PG の primary OSD にオブジェクトを送信します。
  4. primary が自身の CRUSH マップのコピーを使用して secondary OSD を見つけ、オブジェクトを複製します(ドキュメントではこの複製を subop と呼びます)。
  5. secondary が保存完了の確認を primary に送信します。
  6. primary がクライアントに成功を通知します。

クライアントではなく primary が複製を行うおかげで、クライアントのネットワークが送信するデータは1回分だけで済みます。さらに、データが中央のゲートウェイやメタデータサーバーを経由しないため、中央のコンポーネントがボトルネックや単一障害点(SPOF)になりません。MON はマップを配布するだけで、データパス上に立ちません。これがセクション1で述べた「リストではなく計算」の実効的なメリットです。

EC プールでは、primary がオブジェクトを受け取って断片を計算し、それらの断片を Acting Set の各 OSD に分散して書き込みます。すべての断片の書き込みが確認されると、クライアントに成功を通知します。

マップは変化します。OSD がダウンしたり新しく参加したりすると OSD マップのエポック(epoch)が上がり、同じ PG であっても CRUSH 計算の結果が変わります。ドキュメントでは、オブジェクトの位置をサーバーに問い合わせる対話方式よりも、クライアントが直接計算する方がはるかに高速であると述べており、OSD の障害も通常は隣接する OSD が真っ先に検知して MON に報告するため、MON を軽量なプロセスのまま維持できると説明しています。古いマップを受け取ったクライアントと OSD が具体的にどのようなメッセージでマップを同期させるかについては、この記事では扱いませんでした(未確認)。

6. その上の3つの顔:RBD、CephFS、RGW

名前 何に見えるか 主要な動作 Kubernetes において
RBD(RADOS Block Device) ブロックデバイス(ディスク) ディスクイメージを複数の RADOS オブジェクトに分割してストライピング保存する。シンプロビジョニング・スナップショットをサポート 1つのノードがアタッチする RWO ボリューム、VM ディスク
CephFS POSIX ファイルシステム メタデータは MDS、ファイルデータは RADOS オブジェクト。カーネルクライアントや FUSE でマウント 複数のポッドが共同で利用する RWX ボリューム
RGW(RADOS Gateway) HTTP オブジェクトストレージ S3・Swift 互換の REST API。独自のユーザー DB・認証・アクセス制御を持つ バケット要求(ObjectBucketClaim)、S3 クライアント

いくつか押さえておくべきポイントがあります。

7. まとめ:次回予告

概念 一言で言うと
RADOS ブロック・ファイル・S3 のすべての基盤となるオブジェクトストレージ
MON クラスターマップのマスター、Paxos の過半数合意で決定。3台あれば1台失っても耐えられる
OSD + BlueStore ディスク1台につきデーモン1つ、ファイルシステムを介さずデバイスに直接アクセス、チェックサム
プール → PG → OSD ハッシュで PG を決定し、CRUSH で OSD リストを決定。リストの先頭が primary
failure domain レプリケーションをどの単位(ホスト・ラック)で分けるか
レプリケーション vs EC 3.0倍の容量で2つの障害に耐えるか、(K+M)/K 倍の容量で M 個の障害に耐えるか
書き込みパス クライアント → primary → secondary → primary → クライアント。MON はデータムーブメントの枠外

ここまでが Ceph 自体の解説です。これらのデーモンを Kubernetes 上で誰が起動し、どのディスクを選択し、MON がダウンしたときに誰が再構築するのかが パート2のテーマです。そして、それらの動作をどのようなパラメータで調整するのかについては、 パート3でチャートの values.yaml を1行ずつ読み解きながら見ていきます。

Titi のひと言: Ceph には「このファイルはどこにありますか?」と尋ねるための案内係がいません。その代わり、全員が同じ地図(クラスターマップ)と、同じ計算方法(CRUSH)を持ち歩いています。だから、案内係が混雑して動かなくなったり、倒れたりすることはありません。地図さえ最新であればいいのです!

参考資料

すべてのドキュメントは 2026-10-29 に閲覧しました。Ceph のドキュメントは Tentacle (v20) 版です。

ログインするといいねできます

コメント

まだコメントはありません。

ログインするとコメントできます