Upgrade to Pro — share decks privately, control downloads, hide ads and more …

徹底比較!LonghornとCephのアーキテクチャ&パフォーマンス

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

 徹底比較!LonghornとCephのアーキテクチャ&パフォーマンス

2026/06/09 RancherJP Online Meetup #09
徹底比較!LonghornとCephのアーキテクチャ&パフォーマンス

More Decks by システム開発部広報委員会

Transcript

  1. 2026/6/9 RancherJP #9 徹底比較!Longhorn と Ceph の アーキテクチャ & パフォーマンス

    齊藤 大貴 株式会社マイクロアド システム開発部 Platform Engineering Unit 1
  2. 自己紹介 名前 齊藤 大貴(さいとう だいき) 所属 株式会社マイクロアド システム開発部 Platform Engineering

    Unit 趣味 カラオケ、ウォーキング Linkedin https://www.linkedin.com/in/daiki-saito/ 4
  3. 事業:広告プラットフォーム 6 DSP(Demand Side Platform) SSP(Supply Side Platform) 「広告を出したい」 「広告枠を売りたい

    広告主/代理店 広告代理店 広告主 広告主 ・・・ 広告 広告A 広告B 広告C ・・・ 来訪ユーザー ユーザーA ユーザーB ユーザーC ・・・ メディア ニュース コスメ グルメ ・・・ Ad 広告出稿料 広告表示 ✕ リアルタイムオークション 数億のWEB行動データ Data Management Platform 分析
  4. K8s におけるデータの永続化 データの永続化が必要になるケース • コンテナログが膨大なのでログローテートするコンテナをサイドカーで入れたい... • DB 等のステートフルなアプリを K8s で動かしたい...

    10 node pod: app log-nginx log-app container: nginx /var/log/nginx/ container: logrotate /log/nginx/ container: app /log/ /log/app/ mount mount ログが膨大過ぎて、 K8s が提供するローテーション では不十分 ログディレクトリを共有して、 自分でローテーション設定する
  5. K8s におけるデータの永続化 データの永続化が必要になるケース • コンテナログが膨大なのでログローテートするコンテナをサイドカーで入れたい... • DB 等のステートフルなアプリを K8s で動かしたい...

    永続化を実現する方法 11 node log-nginx container /var/log/ mount ホストマシンの領域を使う方法 hostPath, emptyDIr 外部のストレージを使う方法 PersistentVolume 外部ストレージ ( Longhorn, Ceph, NFS, ete... ) node container /var/log/ mount
  6. ホストマシンの領域を使う方法 hostPath • Docker のバインドマウント • ホストのディレクトリを Pod にマウントする •

    ユースケース:特殊 kube-apiserver が ホストの証明書をマウント する等 12 kind: Pod ... spec: containers: - image: nginx volumeMounts: - name: vol mountPath: /mnt volumes: - name: vol hostPath: path: /etc # ホストの /etc kind: Pod ... spec: containers: - image: nginx volumeMounts: - name: vol mountPath: /mnt volumes: - name: vol emptyDir: {} emptyDir • Docker のボリュームマウント • ホスト上にボリュームを作成して Pod にマウン トする • ユースケース:コンテナ間のディレクトリ共有 など(先ほどの例) 💡ボリュームの実態 /var/lib/kubelet/pods/<pod uid>/volumes/ 等に作られる
  7. PersistentVolume を使う方法 13 kind: Pod ... spec: containers: - image:

    nginx volumeMounts: - name: vol mountPath: /mnt volumes: - name: vol persistentVolumeClaim: claimName: pvc-ceph node Pod /mnt マウント 1. 外部ストレージに ボリュームを作る 2. 外部ストレージに作った ボリュームをマウントする volume (20GB) kind: PersistentVolumeClaim metadata: name: pvc-ceph spec: storageClassName: ceph accessModes: - ReadWriteOnce resources: requests: storage: 20Gi 外部ストレージ ( Longhorn, Ceph, NFS, ete... ) 💡StorageClass 外部ストレージと K8s を繋ぐ ための仕組み(今回は省略)
  8. Ceph cluster Ceph Client Ceph の登場人物 16 node 4 node

    1 node 2 node 3 MON MON MON MON(Monitor) ・node/disk の死活管理 ・CRUSH map の作成・配布 OSD OSD OSD OSD OSD OSD OSD(Object Storage Daemon) ・SSD の管理(SSD 毎に起動) ・OSD 間でレプリケーション CRUSH map ・OSD がどこにいるか (DC → ラック → node) を木構造で管理 ・OSD の生死状態を管理 CRUSH algorithm ・CRUSH map を元に対象の OSD を一意 に決める(クライアントでアクセス先を 計算する) CRUSH algorithm
  9. Pool について Ceph は CRUSH アルゴリズムに基づいて、Pool を作る Pool は複数の Placement

    Group(PG)で構成される クライアントは Primary の disk (OSD) に対して読み書きする Pool node 4 node 1 node 2 node 3 Ceph cluster disk0 disk1 disk2 disk3 disk4 disk5 17 PG Primary Replica Replica ホスト分布 0 disk 5 disk 1 disk 2 node4, node1, node2 1 disk 2 disk 1 disk 5 node2, node1, node4 2 disk 4 disk 0 disk 3 node3, node1, node2 3 disk 1 disk 3 disk 5 node1, node2, node4 4 disk 3 disk 0 disk 4 node2, node1, node3 5 disk 0 disk 2 disk 4 node1, node2, node3 6 disk 0 disk 3 disk 5 node1, node2, node4 7 disk 2 disk 1 disk 4 node2, node1, node3 FailureDomain = host にすることで、 PG 内に同じサーバの disk が無いようにする
  10. Ceph 書込み動作 1. Client: 書込むデータの場所から object_id を取得 2. object_id から

    pg_id を取得: hash(pool_id, object_id) mod pg_num = pg_id 3. CRUSH アルゴリズムで OSD を算出: CRUSH(clush_map, pg_id) = osd_primary 18 … 0003 0004 0005 … 12 16 20 24 /dev/rbd0 書込むデータ: 7MB (位置: 15MB ~ 22MB) ・hash(pool_id=2, object_id=0003) mod 8 → pg_id=5  CRUSH(clush_map, pg_id=5) → osd_primary=0 ・hash(pool_id=2, object_id=0004) mod 8 → pg_id=0  CRUSH(clush_map, pg_id=0) → osd_primary=5 ・hash(pool_id=2, object_id=0005) mod 8 → pg_id=2  CRUSH(clush_map, pg_id=2) → osd_primary=4 PG Primary Replica Replica 0 disk 5 disk 1 disk 2 1 disk 2 disk 1 disk 5 2 disk 4 disk 0 disk 3 3 disk 1 disk 3 disk 5 4 disk 3 disk 0 disk 4 5 disk 0 disk 2 disk 4 6 disk 0 disk 3 disk 5 7 disk 2 disk 1 disk 4 Pool 位置
  11. Ceph 書込み動作 1. Client: 書込むデータの場所から object_id を取得 2. object_id から

    pg_id を取得: hash(pool_id, object_id) mod pg_num = pg_id 3. CRUSH アルゴリズムで OSD を算出: CRUSH(clush_map, pg_id) = osd_primary 4. osd_primary に書込む → osd_primary が Replica の OSD に書込む node 4 node 1 node 2 node 3 Ceph cluster Ceph Client /dev/rbd0 disk0 disk1 disk2 disk3 disk4 disk5 ストレージ専用の NW があると、クライアン トからの Write 帯域を圧迫しない PG 5 PG 0 PG 2 19 Pool PG Primary Replica Replica 0 disk 5 disk 1 disk 2 1 disk 2 disk 1 disk 5 2 disk 4 disk 0 disk 3 3 disk 1 disk 3 disk 5 4 disk 3 disk 0 disk 4 5 disk 0 disk 2 disk 4 6 disk 0 disk 3 disk 5 7 disk 2 disk 1 disk 4
  12. Ceph 読込み動作 1. Client: 読込むデータの場所から object_id を取得 2. object_id から

    pg_id を取得: hash(pool_id, object_id) mod pg_num = pg_id 3. CRUSH アルゴリズムで OSD を算出: CRUSH(clush_map, pg_id) = osd_primary 4. osd_primary から読込む 20 Pool PG Primary Replica Replica 0 disk 5 disk 1 disk 2 1 disk 2 disk 1 disk 5 2 disk 4 disk 0 disk 3 3 disk 1 disk 3 disk 5 4 disk 3 disk 0 disk 4 5 disk 0 disk 2 disk 4 6 disk 0 disk 3 disk 5 7 disk 2 disk 1 disk 4 node 4 node 1 node 2 node 3 Ceph cluster Ceph Client /dev/rbd0 disk0 disk1 disk2 disk3 disk4 disk5 PG 5 PG 0 PG 2
  13. K8s に Ceph をデプロイする Rook という Ceph のライフサイクルを管理できる CNCF プロジェクトがある

    21 helm repo add rook-release https://charts.rook.io/release helm install --create-namespace - -namespace rook-ceph rook-ceph-cluster \ --set operatorNamespace=rook-ceph rook-release/rook-ceph-cluster -f values.yaml Rook を使うと Helm で簡単にデプロイできる インストール方法: Ceph Cluster Helm Chart - Rook Ceph Documentation
  14. (おまけ)追加ディスクが無い場合の構築 前提: Ceph は必ず独自形式(Bluestore)でブロックデバイスをフォーマットする • Loopback devices aren't supported by

    Rook · Issue #7206 追加ディスクが無い場合の方法 • ファイルシステム上に loopback デバイスを作る • Operator で loopback デバイスを許可する(allowLoopDevices: true) https://github.com/rook/rook/blob/d6d0fd8d8903fb1e7d0b32a2100454ed3698a6a 1/deploy/charts/rook-ceph/values.yaml#L77-L78 22
  15. (おまけ)OSD と MON 以外の登場人物 • MGR: API、ダッシュボード、メトリクスの提供(Ceph の必須コンポーネント) • MDS:

    ファイルサーバとして使う場合に、ファイルシステムのメタデータを管理する • RGW: オブジェクトストレージとして使う場合のゲートウェイ ※ OSD と MON だけ抑えれば、Ceph RBD の基本設計は理解できる 23
  16. Longhorn の概要 K8s ネイティブな軽量分散ブロックストレージ • Rancher Labs (現 SUSE) によって

    2015 年から開発 • 2019 年に CNCF に寄贈され 2021 年から Incubating project 開発の経緯(https://longhorn.io/ から引用) • クラウド以外の環境で、K8s にストレージ環境を用意することの難易度が高かった • そのため、多くの K8s は永続ストレージ(PersistentVolume)をサポートしていなかった • また、外部ストレージは移植性がなく、非常に高価になる場合があった → 簡単に導入とアップグレードができる OSS の分散永続ストレージを作った 25
  17. instance-manager (pod) instance-manager (pod) instance-manager (pod) Longhorn のアーキテクチャ(引用) 26 Pod

    A volume Engine process Replica process Replica process Node 2 Node 3 Pod A volume Engine process Node 1 引用: Architecture – Volume Details, Longhorn - v1.2.2 - Shuo Wu.pptx Engine プロセス volume をマウントする Pod と同じ node 上で起動 Replica プロセス 実データを保存する SSD と同じ node 上で起動
  18. instance-manager (pod) instance-manager (pod) instance-manager (pod) Longhorn のアーキテクチャ(引用) 27 Pod

    A volume Engine process Replica process Replica process Pod B volume Engine process Replica process Engine process Replica process Replica process Node 2 Node 3 Pod C volume Pod A volume Engine process Node 1 Replica process 引用: Architecture – Volume Details, Longhorn - v1.2.2 - Shuo Wu.pptx
  19. Longhorn の書込み 28 node 1 node 2 node 3 disk0

    disk1 disk2 disk3 disk4 Pod Longhorn Engine 全ての Replica に同期書込み 3GB の書込み 3 GB 3 GB 3 GB
  20. node 1 Longhorn の書込み(ちょっと詳しく) 29 Pod 全ての Replica に同期書込み ①

    ② ③ ④ … node 2 ① ② ③ ④ … node 3 ① ② ③ ④ … Longhorn Engine Volume Volume Volume 計 3GB分 計 3GB分 計 3GB分 iSCSI 別色の矢印は同時に書込まれる 3GB の書込み メモ 一見 Ceph に比べて遅く見えるが、 Ceph は OSD 同士で Primary から Secondary へレプリケーションが走る
  21. Longhorn の読込み 30 node 1 node 2 node 3 disk0

    disk1 disk2 disk3 disk4 Pod Longhorn Engine 全ての Replica から分散読込み 3GB の読込み 1 GB 1 GB 1 GB
  22. node 1 Longhorn の読込み(ちょっと詳しく) 31 Pod 全ての Replica にラウンドロビンで読込 みリクエストを送信

    最大でも max_sectors_kb 毎に切替わる (実験機は 1.25 MB でした) ① ② ③ ④ … node 2 ① ② ③ ④ … node 3 ① ② ③ ④ … Longhorn Engine 4 kB ブロックサイズが 4kB の場合 (dd コマンドの bs 等) Volume Volume Volume 4 kB 4 kB 4 kB ここは並列で読込む iSCSI
  23. Pod が動いている node から Read すれば良くない? ここで議論されており「ラウンドロビンこそ至高」という結論に至っている [FEATURE] Longhorn should

    ensure reading data from local replica at first priority if there is any to lower the read latency · Issue #3143 32 node 1 ① ② ③ ④ … node 2 ① ② ③ ④ … node 3 ① ② ③ ④ … Longhorn Engine Volume Volume Volume Pod Q. Pod が動いている node からのみ read すればよくない?? A. ラウンドロビンこそ至高 こんな感じで、同じ node 上からの み read すればよくない?
  24. Longhorn のデプロイ Helm で簡単にデプロイできる インストール方法: https://longhorn.io/docs/1.12.0/deploy/install/install-with-helm/ 33 helm repo add

    longhorn https://charts.longhorn.io helm repo update helm install longhorn longhorn/longhorn --namespace longhorn-system \ --create-namespace --version 1.12.0
  25. 実験環境 物理構成 • CPU: Intel Xeon E3-1275 v5 @ 3.60GHz

    • Memory: 32 GB • Network: 2 Gbps • 追加SSD: SAMSUNG MZ7LM240(2.5インチ SATA SSD) • K8s: 3 node RKE2 クラスタ 実験条件 • ストレージのレプリカ数: 3 • ベンチマークツール: fio-3.6 • プロセス数(numjobs): 1, 8 • ブロックサイズ: 4kB ~ 32MB(1回の write/read システムコールでアクセスする単位) • マウント形式: ブロックデバイス or ファイルシステム • バージョン: Ceph=19.2.3, longhorn=1.11.1 36
  26. 実験環境(詳細) 37 filename=/dev/pv or /mnt/test/test direct=1 size=2G numjobs=1 or 8

    runtime=60 iodepth=8 ioengine=libaio invalidate=1 bs=4k, 8k, 16k, 64k, 1m, 4m, 32m rw=read, write, randread, randwrite fio の引数 kind: Pod spec: containers: - name: fio ... volumeMounts: - name: conf mountPath: /conf/ - name: vol mountPath: /mnt/test --- kind: PersistentVolumeClaim spec: volumeMode: Filesystem accessModes: - "ReadWriteOnce" ... kind: Pod spec: containers: - name: fio ... volumeMounts: - name: conf mountPath: /conf/ volumeDevices: - name: vol devicePath: /dev/pv --- kind: PersistentVolumeClaim spec: volumeMode: Block accessModes: - "ReadWriteOnce" ... Filesystem としてマウント Block デバイスとしてマウント
  27. 実験メモ • 本番では、実験で使用した Pod 以外にも読み書きしている Pod は存在するため、実際は もっとパフォーマンスは低くなる • Longhorn

    は、ファイルシステム上にデータを書込むため、追加ディスクが無い場合でもパ フォーマンスの劣化は少ない • Ceph は、ブロックデバイスを独自形式(bluestore)でフォーマットする必要があるため、 追加ディスクがないと、ファイルシステム上に loopback デバイスを作らないといけず、パ フォーマンスが劣化する 42
  28. 設計の比較 44 Ceph Longhorn 開発 フルスクラッチで開発 流用できる所は既に存在するストレージ技術を使用 ボリューム の場所 独自形式でフォーマットされたブロックデバイス上

    (無い場合は loopback デバイスを作る) ファイルシステム上 プロセス ディスクごと(OSD) • 影響範囲大: 複数のボリュームに影響 • リソース効率: 良い ボリュームごと(Engine, Replica) • 影響範囲小:1つのボリュームのみに影響 • リソース効率: 悪い 管理 一部手動管理が必要 (OSD の削除やコンフィグ確認など) 完全にマニフェスト管理できる 提供範囲 K8s 以外にも提供可 (NFS, iSCSI などで外部に提供できる) K8s のみ(Harvester を使えば VM にも払い出せる) 要望はある: [FEATURE] Expose iSCSI targets to clients outside of the cluster · Issue #2813
  29. さいごに ズバリ!どちらを使えばよい?? • 全て当てはまるなら Ceph ◦ ✅ OS 領域とは別に追加ディスクが使える ◦

    ✅ Ceph について詳しい人がいる ◦ ✅ K8s 以外にもボリュームを払い出したい • どれか当てはまるなら Longhorn ◦ ✅ OS 領域とは別に追加ディスクが使えない ◦ ✅ Ceph に詳しい人がいない ◦ ✅ UI からリソースを操作したい or K8s ネイティブに管理したい まとめ • Ceph & Longhorn は K8s で使える分散ストレージ基盤 • Longhorn はシンプルさと使いやすさを追求している • Ceph はパフォーマンスを最大限引き出すことを追求している 45