Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

自己紹介します

Slide 4

Slide 4 text

自己紹介 - 高橋 拓也 - GMO ペパボという会社でインフラエンジニアをしています - ストレージは趣味です - https://github.com/takutakahashi - https://twitter.com/takutaka1220 - https://www.takutakahashi.dev

Slide 5

Slide 5 text

突然ですが

Slide 6

Slide 6 text

ZFS はいいぞ

Slide 7

Slide 7 text

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)

Slide 8

Slide 8 text

とある自鯖ユーザーの悩み

Slide 9

Slide 9 text

おうち k8s を作ったぞ! Master * 3 + Node * 3 で冗長構成だ!

Slide 10

Slide 10 text

Node をまたがった Persistent Volume が欲しいぞ

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

ZFS に乗せてみよう!

Slide 15

Slide 15 text

検証環境スペック - 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 - 今回は使わない

Slide 16

Slide 16 text

検証環境スペック - Cluster - k3s Master * 3 (rpi) + Node * 3 - version: v1.18.6+k3s1 - Rook - version: v1.3.7 - Ceph - version: v15.2.4

Slide 17

Slide 17 text

環境構築

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

環境構築 - OSD のストレージプロビジョニング - Block Device? Directory? - Block Device を割り当てる方式が推奨らしい - zvol を使おう!

Slide 20

Slide 20 text

SSD1 zvol OSD zvol OSD zvol OSD Ceph Cluster /dev/rbd0 zfs pool

Slide 21

Slide 21 text

環境構築 - Block Storage を利用する - zvol をどうやってプロビジョニングする? - → pvc による dynamic provisioning を設定する - local provisioning してくれる provisioner が必要 - openebs/zfs-localpv が便利

Slide 22

Slide 22 text

環境構築 - 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

Slide 23

Slide 23 text

環境構築 zfs-localpv のデプロイは一発 kubectl apply -f https://raw.githubusercontent.com/openebs/zfs-localpv/master/deploy/zfs-operator.yaml

Slide 24

Slide 24 text

SSD1 zvol pvc OSD zvol pvc OSD zvol pvc OSD Ceph Cluster /dev/rbd0 zfs pool これを目指す

Slide 25

Slide 25 text

SSD1 zfs pool 今はまだ、これ

Slide 26

Slide 26 text

localpv StorageClass をつくる

Slide 27

Slide 27 text

StorageClass

Slide 28

Slide 28 text

‘zfs’ だと filesystem ‘ext(2-4)|xfs|btrfs’ だと block device(zvol) になる block device でしか OSD on pvc は動作しない allowedTopologies を指定して pool のない node に スケジュールされないようにする

Slide 29

Slide 29 text

環境構築 - Pool の空き容量は考慮してくれない - とにかく zvol 作りに行くし、作れなかったとしても zvol が作れたと嘘を付く - ハマった - デフォルトでは snapshot を持つ vol は削除できない - snapshot を自動生成するようにしていたら削除できずに容量使い果たした

Slide 30

Slide 30 text

SSD1 zvol pvc zvol pvc zvol pvc zfs pool pvc ができた

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

node が足りないので 複数 node に立つことを 許可する

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

SSD1 zvol pvc OSD zvol pvc OSD zvol pvc OSD Ceph Cluster zfs pool クラスタができた

Slide 35

Slide 35 text

クラスタができた

Slide 36

Slide 36 text

計測だ!

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

計測方法 ● 以下の条件で fio を 10回測定し、中央値を計測 ○ rw=read/write ○ size=1g ○ numjobs=1 ● bandwidth, iops を抽出し記録 ● pool の replicated size は 2とする 「妥当な計測」がなんなのか手探りで計測したので これは違うぞ!という内容があったら twitter でメンションください

Slide 39

Slide 39 text

まずは raw device と ZFS の実力

Slide 40

Slide 40 text

まずは raw device と ZFS の実力 1. raw device を ext4 でフォーマットした vol 2. zfs プールから切り出した zvol a. single device b. 2 devices (striped)

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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 にするだけで性能アップ

Slide 43

Slide 43 text

ZFS はキャッシュが命 ● ARC というインメモリキャッシュを持つ ● ARC のキャッシュヒット率が高くなると速い ● ZFS に載せるだけで速くなったのはそのため ● fio の read benchmark はめちゃめちゃキャッシュに乗る...

Slide 44

Slide 44 text

ベンチ中の iostat の様子を 見てみる

Slide 45

Slide 45 text

1 device read iostat の結果

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

x軸は時系列

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

arcstat - ZFS のキャッシュの状況を確認できるスゴイヤツ - キャッシュミスの割合や、キャッシュサイズなどを確認できる - zfsonlinux に同梱されている - https://packages.ubuntu.com/ja/xenial-updates/amd64/zfsutils-linux/filelist

Slide 52

Slide 52 text

1 device read arcstat の結果

Slide 53

Slide 53 text

秒間 arc アクセス

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

キャッシュミス率

Slide 56

Slide 56 text

arc の容量

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

No content

Slide 59

Slide 59 text

read IO が発生したのはここ

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

striped pool の read iostat

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

シングルノード性能 - OSD を全て node 1 に寄せて計測 - 1 device pool, 2 devices pool でそれぞれ計測 - 3台の OSD を起動させた

Slide 66

Slide 66 text

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 シングルノード性能

Slide 67

Slide 67 text

read の iostat (1 device)

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

1 device read iostat の結果

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

ここが read のスパイク

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

write の iostat (1 device)

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

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 シングルノード性能

Slide 79

Slide 79 text

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 どちらにおいても若干の性能劣化が見られる

Slide 80

Slide 80 text

read の iostat (1 device)

Slide 81

Slide 81 text

osd の分散が大きくなった

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

マルチノード性能

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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 マルチノード性能

Slide 86

Slide 86 text

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 が増えると 性能が劣化する

Slide 87

Slide 87 text

read の iostat (1 device)

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

write は誤差の範囲

Slide 92

Slide 92 text

read は倍くらい違う

Slide 93

Slide 93 text

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

Slide 94

Slide 94 text

OSD を極端に増やしてみる

Slide 95

Slide 95 text

OSD を極端に増やしてみる - 1node 2disk な cluster に大量の OSD を設置する - なるべく object が乗る osd が分散するように tmpfile のサイズを 10g にした - 30, 50 osd で計測

Slide 96

Slide 96 text

No content

Slide 97

Slide 97 text

一部の OSD が CrashLoopBackOff

Slide 98

Slide 98 text

No content

Slide 99

Slide 99 text

No content

Slide 100

Slide 100 text

とりあえず増やしたら動いた

Slide 101

Slide 101 text

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 を極端に増やしてみる

Slide 102

Slide 102 text

osd 30 read の iostat osd を抜粋しました

Slide 103

Slide 103 text

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

Slide 104

Slide 104 text

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

Slide 105

Slide 105 text

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

Slide 106

Slide 106 text

トップラインが伸びた

Slide 107

Slide 107 text

arcstat の結果

Slide 108

Slide 108 text

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

Slide 109

Slide 109 text

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

Slide 110

Slide 110 text

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 ベンチマークの結果は悪い...

Slide 111

Slide 111 text

このトップラインは すべてキャッシュ 30 OSD と 50 OSD の read グラフを 重ねてみる

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

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

Slide 114

Slide 114 text

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

Slide 115

Slide 115 text

50 OSD の arcstat

Slide 116

Slide 116 text

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

Slide 117

Slide 117 text

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

Slide 118

Slide 118 text

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

Slide 119

Slide 119 text

なぜ?

Slide 120

Slide 120 text

考察

Slide 121

Slide 121 text

考察 ● Read IO は伸びる ○ 特にキャッシュを効かせると非常に伸びる ○ zfs の特性を Rook/Ceph でも活かすことができる ■ 一度ファイルを置いたら read しかしないワークロード ■ メモリが余っていればだけど ... ● Write IO は変化なし ○ オーバーヘッド分少なくなる ○ 1 Pool あたりの OSD の数が増えるとオーバーヘッドが大きくなる

Slide 122

Slide 122 text

考察 ● Rook/Ceph on ZFS 構築の難易度 ○ めちゃめちゃ簡単 ○ Multiple Devices 界で一番簡単なのでは? ○ ご家庭に余った k8s クラスタとディスクがあればぜひお試しを

Slide 123

Slide 123 text

考察 ● 障害ドメイン ○ Storage Pool が障害ドメイン ■ OSD 分割しても Pool が死んだら全て死ぬ ■ ceph on zfs による障害リスクの上昇はない ● (うまく OSD 分散できれば) ● Pool の件があるからドメイン分割には少し気を使う必要がある

Slide 124

Slide 124 text

考察 - zfs はいいぞ ○ ド安定 ○ わかりやすい CLI ○ 機能が豊富 ■ ストレージプールの大きさを動的に増やしたり ■ ライトホール問題のない RAID 組めたり ■ pool ごとバックアップ取ったり ● (OSD のバックアップいるか? )

Slide 125

Slide 125 text

ZFS はいいぞ