Pro Yearly is on sale from $80 to $50! »

Rook/Ceph on ZFS

Rook/Ceph on ZFS

Japan Rook Meetup #4 でお話した内容です。

Defdf943f6e9bfc3d3cd856d9d9e0f9b?s=128

Takuya TAKAHASHI

October 02, 2020
Tweet

Transcript

  1. Rook/Ceph on ZFS Japan Rook Meetup #4 @takutaka1220 Takuya Takahashi

  2. アジェンダ - 自己紹介 - 環境構築 - 計測 - 考察

  3. 自己紹介します

  4. 自己紹介 - 高橋 拓也 - GMO ペパボという会社でインフラエンジニアをしています - ストレージは趣味です -

    https://github.com/takutakahashi - https://twitter.com/takutaka1220 - https://www.takutakahashi.dev
  5. 突然ですが

  6. ZFS はいいぞ

  7. ZFS (Zettabyte File System) とは? - CoW な多機能ファイルシステム - Block

    Device をまとめて Storage Pool を構成 - RAID (シングルパリティの RAIDZ, ダブルパリティの RAIDZ2 など) - SnapShot, Clone - Export - 圧縮 - 重複排除 - Storage Pool から filesystem や Block Device (zvol) の切り出しができる - Solaris が源流、FreeBSD が主流、Linux にもあり (ZFS on Linux) - 最近 Ubuntu でデフォルトで利用できるようになった - macOS や Windows でも使えるらしい (OpenZFS)
  8. とある自鯖ユーザーの悩み

  9. おうち k8s を作ったぞ! Master * 3 + Node * 3

    で冗長構成だ!
  10. Node をまたがった Persistent Volume が欲しいぞ

  11. Rook/Cephというものがあるらしい

  12. たくさんの Block Device を ひとつにまとめるらしいぞ

  13. ZFS なら 無限に Block Device を生やせるぞ

  14. ZFS に乗せてみよう!

  15. 検証環境スペック - Node 1 - Intel(R) Core(TM) i5-10210U CPU @

    1.60GHz - 32GB Memory (single channel) - SanDisk SSD Ultra 3D 1TB * 2 - Node 2 - Intel(R) Core(TM) i5-4460 CPU @ 3.20GHz - 16GB Memory - SanDisk SSD Ultra 3D 1TB * 2 - Node 3 - 今回は使わない
  16. 検証環境スペック - Cluster - k3s Master * 3 (rpi) +

    Node * 3 - version: v1.18.6+k3s1 - Rook - version: v1.3.7 - Ceph - version: v15.2.4
  17. 環境構築

  18. SSD1 zvol ZFS でできたなにか OSD OSD OSD Ceph Cluster /dev/rbd0

  19. 環境構築 - OSD のストレージプロビジョニング - Block Device? Directory? - Block

    Device を割り当てる方式が推奨らしい - zvol を使おう!
  20. SSD1 zvol OSD zvol OSD zvol OSD Ceph Cluster /dev/rbd0

    zfs pool
  21. 環境構築 - Block Storage を利用する - zvol をどうやってプロビジョニングする? - →

    pvc による dynamic provisioning を設定する - local provisioning してくれる provisioner が必要 - openebs/zfs-localpv が便利
  22. 環境構築 - openebs/zfs-localpv が便利 - https://github.com/openebs/zfs-localpv - zfs pool から

    fs, zvol を dynamic provisioning してくれるやつ - local provision なので、ノードを跨いでマウントできる pvc は作成できない - openEBS - https://openebs.io/ - rook 競合な Cloud Native SDS
  23. 環境構築 zfs-localpv のデプロイは一発 kubectl apply -f https://raw.githubusercontent.com/openebs/zfs-localpv/master/deploy/zfs-operator.yaml

  24. SSD1 zvol pvc OSD zvol pvc OSD zvol pvc OSD

    Ceph Cluster /dev/rbd0 zfs pool これを目指す
  25. SSD1 zfs pool 今はまだ、これ

  26. localpv StorageClass をつくる

  27. StorageClass

  28. ‘zfs’ だと filesystem ‘ext(2-4)|xfs|btrfs’ だと block device(zvol) になる block device

    でしか OSD on pvc は動作しない allowedTopologies を指定して pool のない node に スケジュールされないようにする
  29. 環境構築 - Pool の空き容量は考慮してくれない - とにかく zvol 作りに行くし、作れなかったとしても zvol が作れたと嘘を付く

    - ハマった - デフォルトでは snapshot を持つ vol は削除できない - snapshot を自動生成するようにしていたら削除できずに容量使い果たした
  30. SSD1 zvol pvc zvol pvc zvol pvc zfs pool pvc

    ができた
  31. 環境構築 - cephcluster.yaml を書く - node が少ないので、以下の設定が必要となる - mon が同一ノードに起動することを許可する

    - osd を同一ノードに建てるために topologySpreadConstraints.maxSkew を増やす
  32. node が足りないので 複数 node に立つことを 許可する

  33. maxSkew: いくつまで 障害ドメインの差を許容するか 1node なのでたくさん設定する OSD を pvc に載せる設定

  34. SSD1 zvol pvc OSD zvol pvc OSD zvol pvc OSD

    Ceph Cluster zfs pool クラスタができた
  35. クラスタができた

  36. 計測だ!

  37. 計測方法 • 以下の条件で fio を 10回測定し、中央値を計測 ◦ rw=read/write ◦ size=1g

    ◦ numjobs=1 • bandwidth, iops を抽出し記録 • pool の replicated size は 2とする
  38. 計測方法 • 以下の条件で fio を 10回測定し、中央値を計測 ◦ rw=read/write ◦ size=1g

    ◦ numjobs=1 • bandwidth, iops を抽出し記録 • pool の replicated size は 2とする 「妥当な計測」がなんなのか手探りで計測したので これは違うぞ!という内容があったら twitter でメンションください
  39. まずは raw device と ZFS の実力

  40. まずは raw device と ZFS の実力 1. raw device を

    ext4 でフォーマットした vol 2. zfs プールから切り出した zvol a. single device b. 2 devices (striped)
  41. basic benchmark read (bw) read (iops) write (bw) write (iops)

    raw device 415MiB/s 106k 2498MiB/s 639k zfs (single device) 1058MiB/s 271k 2498MiB/s 639k zfs (2 devices) 1100MiB/s 282k 2485MiB/s 636k
  42. basic benchmark read (bw) read (iops) write (bw) write (iops)

    raw device 415MiB/s 106k 2498MiB/s 639k zfs (single device) 1058MiB/s 271k 2498MiB/s 639k zfs (2 devices) 1100MiB/s 282k 2485MiB/s 636k zfs にするだけで性能アップ
  43. ZFS はキャッシュが命 • ARC というインメモリキャッシュを持つ • ARC のキャッシュヒット率が高くなると速い • ZFS

    に載せるだけで速くなったのはそのため • fio の read benchmark はめちゃめちゃキャッシュに乗る...
  44. ベンチ中の iostat の様子を 見てみる

  45. 1 device read iostat の結果

  46. zd0 … zvol raw … raw device (sda とか)

  47. x軸は時系列

  48. raw は zd0 より書き込み開始が遅い (fio は tmpfile を書いてから計測する )

  49. zd0 で read が走るが、 raw は IO が発生しない (すべてキャッシュから読んでいる )

  50. キャッシュヒット率を見たい?

  51. arcstat - ZFS のキャッシュの状況を確認できるスゴイヤツ - キャッシュミスの割合や、キャッシュサイズなどを確認できる - zfsonlinux に同梱されている -

    https://packages.ubuntu.com/ja/xenial-updates/amd64/zfsutils-linux/filelist
  52. 1 device read arcstat の結果

  53. 秒間 arc アクセス

  54. read のうち ミスしたアクセス

  55. キャッシュミス率

  56. arc の容量

  57. arc target size キャッシュに 載せようとしているサイズ

  58. None
  59. read IO が発生したのはここ

  60. キャッシュミスした アクセスはない

  61. striped pool の read iostat

  62. zvol, raw に書いて キャッシュから読む 挙動は同じ

  63. raw1, 2 の IO は 全く同じ量出ている (グラフが重なっている )

  64. シングルノード性能 いよいよ Ceph

  65. シングルノード性能 - OSD を全て node 1 に寄せて計測 - 1 device

    pool, 2 devices pool でそれぞれ計測 - 3台の OSD を起動させた
  66. read (bw) read (iops) write (bw) write (iops) raw device

    415MiB/s 106k 2498MiB/s 639k zfs (single device) 1058MiB/s 271k 2498MiB/s 639k zfs (2 devices) 1100MiB/s 282k 2485MiB/s 636k 1node-1disk 1504MiB/s 385k 2221MiB/s 569k 1node-2disk 1517MiB/s 388k 2265MiB/s 580k シングルノード性能
  67. read の iostat (1 device)

  68. zvol に直接書くより 書き込みが遅い (約半分)

  69. 1 device read iostat の結果

  70. osd へのアクセスは ひとつだけ少ない

  71. キャッシュの状態を arcstat で見る

  72. ここが read のスパイク

  73. 全てキャッシュから読んでいる (miss がゼロ)

  74. write の iostat (1 device)

  75. rbd0 よりも raw device のほうが 転送量が多い

  76. zvol へのアクセスは ひとつだけ突出している read とは逆

  77. シングルノード性能 - OSD を3 → 6 に増やすとどうなる?

  78. read (bw) read (iops) write (bw) write (iops) raw device

    415MiB/s 106k 2498MiB/s 639k zfs (single device) 1058MiB/s 271k 2498MiB/s 639k zfs (2 devices) 1100MiB/s 282k 2485MiB/s 636k 1node-1disk (3osd) 1504MiB/s 385k 2221MiB/s 569k 1node-1disk (6osd) 1333MiB/s 341k 2124MiB/s 544k 1node-2disk (3osd) 1517MiB/s 388k 2265MiB/s 580k 1node-2disk (6osd) 1499MiB/s 384k 2111MiB/s 541k シングルノード性能
  79. read (bw) read (iops) write (bw) write (iops) raw device

    415MiB/s 106k 2498MiB/s 639k zfs (single device) 1058MiB/s 271k 2498MiB/s 639k zfs (2 devices) 1100MiB/s 282k 2485MiB/s 636k 1node-1disk (3osd) 1504MiB/s 385k 2221MiB/s 569k 1node-1disk (6osd) 1333MiB/s 341k 2124MiB/s 544k 1node-2disk (3osd) 1517MiB/s 388k 2265MiB/s 580k 1node-2disk (6osd) 1499MiB/s 384k 2111MiB/s 541k シングルノード性能 1disk, 2disk どちらにおいても若干の性能劣化が見られる
  80. read の iostat (1 device)

  81. osd の分散が大きくなった

  82. write にコブができている IO 待ちしている?

  83. マルチノード性能

  84. マルチノード性能 - 2disk striped なノードを2つ利用して計測 - ノード間は 1GbE で接続

  85. read (bw) read (iops) write (bw) write (iops) raw device

    415MiB/s 106k 2498MiB/s 639k zfs (single device) 1058MiB/s 271k 2498MiB/s 639k zfs (2 devices) 1100MiB/s 282k 2485MiB/s 636k 1node-1disk (3osd) 1504MiB/s 385k 2221MiB/s 569k 1node-1disk (6osd) 1333MiB/s 341k 2124MiB/s 544k 1node-2disk (3osd) 1517MiB/s 388k 2265MiB/s 580k 1node-2disk (6osd) 1499MiB/s 384k 2111MiB/s 541k 2node-2disk (3osd) 計測ノードに 1osd 180MiB/s 46.1k 2188MiB/s 560k 2node-2disk (5osd) 計測ノードに 2osd 155MiB/s 39.6k 2231MiB/s 571k マルチノード性能
  86. read (bw) read (iops) write (bw) write (iops) raw device

    415MiB/s 106k 2498MiB/s 639k zfs (single device) 1058MiB/s 271k 2498MiB/s 639k zfs (2 devices) 1100MiB/s 282k 2485MiB/s 636k 1node-1disk (3osd) 1504MiB/s 385k 2221MiB/s 569k 1node-1disk (6osd) 1333MiB/s 341k 2124MiB/s 544k 1node-2disk (3osd) 1517MiB/s 388k 2265MiB/s 580k 1node-2disk (6osd) 1499MiB/s 384k 2111MiB/s 541k 2node-2disk (3osd) 計測ノードに 2osd 180MiB/s 46.1k 2188MiB/s 560k 2node-2disk (5osd) 計測ノードに 2osd 155MiB/s 39.6k 2231MiB/s 571k マルチノード性能 OSD が増えると 性能が劣化する
  87. read の iostat (1 device)

  88. rbd0 よりも zd0, zd1 のほうが IO が出ている

  89. zd0 + zd1 < rbd0 なので キャッシュはある程度 効いている

  90. 1node の read と スケールを合わせてみた

  91. write は誤差の範囲

  92. read は倍くらい違う

  93. OSD が増えると 性能が劣化している

  94. OSD を極端に増やしてみる

  95. OSD を極端に増やしてみる - 1node 2disk な cluster に大量の OSD を設置する

    - なるべく object が乗る osd が分散するように tmpfile のサイズを 10g にした - 30, 50 osd で計測
  96. None
  97. 一部の OSD が CrashLoopBackOff

  98. None
  99. None
  100. とりあえず増やしたら動いた

  101. read (bw) read (iops) write (bw) write (iops) raw device

    415MiB/s 106k 2498MiB/s 639k zfs (single device) 1058MiB/s 271k 2498MiB/s 639k zfs (2 devices) 1100MiB/s 282k 2485MiB/s 636k 1node-1disk (3osd) 1504MiB/s 385k 2221MiB/s 569k 1node-1disk (6osd) 1333MiB/s 341k 2124MiB/s 544k 1node-2disk (3osd) 1517MiB/s 388k 2265MiB/s 580k 1node-2disk (6osd) 1499MiB/s 384k 2111MiB/s 541k 1node-2disk (30osd) 181MiB/s 46.4k 207MiB/s 52.9k 1node-2disk (50osd) 158MiB/s 40.4k 144MiB/s 36.9k OSD を極端に増やしてみる
  102. osd 30 read の iostat osd を抜粋しました

  103. 書き込みと IO 待ちを 繰り返している

  104. OSD ごとの性能差が 大きくなった

  105. rbd0 に常に write io が 発生している

  106. トップラインが伸びた

  107. arcstat の結果

  108. read io はこのへん ひとけた増えている

  109. ほぼキャッシュヒット (miss がほぼない)

  110. read (bw) read (iops) write (bw) write (iops) raw device

    415MiB/s 106k 2498MiB/s 639k zfs (single device) 1058MiB/s 271k 2498MiB/s 639k zfs (2 devices) 1100MiB/s 282k 2485MiB/s 636k 1node-1disk (3osd) 1504MiB/s 385k 2221MiB/s 569k 1node-1disk (6osd) 1333MiB/s 341k 2124MiB/s 544k 1node-2disk (3osd) 1517MiB/s 388k 2265MiB/s 580k 1node-2disk (6osd) 1499MiB/s 384k 2111MiB/s 541k 1node-2disk (30osd) 181MiB/s 46.4k 207MiB/s 52.9k 1node-2disk (50osd) 158MiB/s 40.4k 144MiB/s 36.9k ベンチマークの結果は悪い...
  111. このトップラインは すべてキャッシュ 30 OSD と 50 OSD の read グラフを

    重ねてみる
  112. このトップラインは すべてキャッシュ write io の 帯域はだいたい同じ

  113. このトップラインは すべてキャッシュ IO 待ちが 長くなっている

  114. このトップラインは すべてキャッシュ トップラインが 非常に低速

  115. 50 OSD の arcstat

  116. 書き込み時は arc に乗っている

  117. read 開始前に キャッシュが 破棄されている

  118. キャッシュミス率が 40% を超えている

  119. なぜ?

  120. 考察

  121. 考察 • Read IO は伸びる ◦ 特にキャッシュを効かせると非常に伸びる ◦ zfs の特性を

    Rook/Ceph でも活かすことができる ▪ 一度ファイルを置いたら read しかしないワークロード ▪ メモリが余っていればだけど ... • Write IO は変化なし ◦ オーバーヘッド分少なくなる ◦ 1 Pool あたりの OSD の数が増えるとオーバーヘッドが大きくなる
  122. 考察 • Rook/Ceph on ZFS 構築の難易度 ◦ めちゃめちゃ簡単 ◦ Multiple

    Devices 界で一番簡単なのでは? ◦ ご家庭に余った k8s クラスタとディスクがあればぜひお試しを
  123. 考察 • 障害ドメイン ◦ Storage Pool が障害ドメイン ▪ OSD 分割しても

    Pool が死んだら全て死ぬ ▪ ceph on zfs による障害リスクの上昇はない • (うまく OSD 分散できれば) • Pool の件があるからドメイン分割には少し気を使う必要がある
  124. 考察 - zfs はいいぞ ◦ ド安定 ◦ わかりやすい CLI ◦

    機能が豊富 ▪ ストレージプールの大きさを動的に増やしたり ▪ ライトホール問題のない RAID 組めたり ▪ pool ごとバックアップ取ったり • (OSD のバックアップいるか? )
  125. ZFS はいいぞ