Ceph Pool の利用可能容量の計算法
こんにちは、うつぼです。
今日は小ネタで Ceph の capacity usage について説明します。
Ceph はどれくらいの容量が使えるのか分かりづらいことで定評があります。
いや分かることは分かるんですが、「なんでそーなるの?」と欽ちゃんライクになる人もいるでしょう。今日はそこを紐解いていきましょう。
ceph df を見ていく
ceph df の出力
まず、Ceph の Pool の capacity usage は、ceph df
コマンドで見ることができます。
0.5 TiB (512 GiB) の osd を1つだけ持つシンプルな 3 node の Ceph クラスターを用意します。直後に、
- 3x replicated pool
- 2x replicated pool
- 2+1 erasure coded pool
の3つの Pool を作り、ceph df
を実行してみます。
sh-4.4# ceph df RAW STORAGE: CLASS SIZE AVAIL USED RAW USED %RAW USED ssd 1.5 TiB 1.5 TiB 47 MiB 3.0 GiB 0.20 TOTAL 1.5 TiB 1.5 TiB 47 MiB 3.0 GiB 0.20 POOLS: POOL ID STORED OBJECTS USED %USED MAX AVAIL pool_3rep 1 0 B 0 0 B 0 433 GiB pool_2rep 2 0 B 0 0 B 0 650 GiB pool_2+1ec 3 0 B 0 0 B 0 867 GiB
これはまだクライアントから全然使われてない状態です。
上の RAW STORAGE
には全ての osd を合算した usage が書かれます。ここはここでまあいいとして、問題は下の POOLS
です。
妙に少ない MAX AVAIL と full ratio
右端の MAX AVAIL
が Pool ごとに違います。名前からしても、冗長度が違う Pool ごとに値が違うところからしても、Pool に保存できる最大のデータ容量のようですね。でも、ちょっと少ないですよね。
1 node あたり 512 GiB あるのだから、例えば 3x replicated pool の場合、仮に何やかんや無条件に内部処理で引かれる分 (個人的にこれを税金と呼んでいる) があるとしても、433 GiB は少なすぎる。
なぜこんなに少ないのか?どういう計算をしているのか?
これは、osd に設定されている full ratio が主な原因です。
sh-4.4# ceph osd dump | grep ^full_ratio full_ratio 0.85
full ratio は、『osd の使用可能容量の何%まで使ったら osd は容量フルとして write できないようにする』というパラメータです。
つまり osd の容量に full ratio をかけた分が、Ceph で使える容量ということですね。
デフォルトは 0.95 なんですが、この環境では上の通り 0.85 でした。これを頭に入れて 3x replicated pool で計算をしてみると、
512 GiB x 0.85 = 435.2 GiB
大分近い数値になりました。
Pool の MAX AVAIL を計算する式
正確な計算式は、次のようになります。
osd.AVAIL は、その時点の osd の空き容量 であり、osd.SIZE は元々の osd の容量です。(ややこしい)
これらは ceph osd df
で確認できます。
sh-4.4# ceph osd df ID CLASS WEIGHT REWEIGHT SIZE RAW USE DATA OMAP META AVAIL %USE VAR PGS STATUS 0 ssd 0.49899 1.00000 511 GiB 1.0 GiB 19 MiB 0 B 1 GiB 510 GiB 0.20 1.00 147 up 1 ssd 0.49899 1.00000 511 GiB 1.0 GiB 19 MiB 0 B 1 GiB 510 GiB 0.20 1.00 146 up 2 ssd 0.49899 1.00000 511 GiB 1.0 GiB 19 MiB 0 B 1 GiB 510 GiB 0.20 1.00 147 up TOTAL 1.5 TiB 3.1 GiB 56 MiB 0 B 3 GiB 1.5 TiB 0.20
どの osd も osd.AVAIL = 510 GiB、osd.SIZE = 511 GiB であることが分かります。これらと num of osd(osdの数) = 3 とpool.size=3(3x replicated pool) を式に代入すると、
{ 510 - ( 511 x ( 1 - 0.85 ) ) } x 3 / 3 = 433.35
となって MAX AVAIL
が出てきます。
2x replicated pool では pool.size=2 として、2+1 ec pool では pool.size を (2+1)/2 とすることで、同様に計算できます。
- 2x replicated pool --> pool.size = 2 : { 510 - ( 511 x ( 1 - 0.85 ) ) } x 3 / 2 = 650.025
- 2+1 ec pool --> pool.size = (2+1)/2 : { 510 - ( 511 x ( 1 - 0.85 ) ) } x 3 / { (2+1) / 2 } = 866.7
osd の AVAIL がバラバラな場合
クラスター作成直後だとデータが入っていないので osd の AVAIL は同じでした。しかしデータが入ってくると osd の AVAIL はバラバラになります。Ceph は精密に全ての osd を均等に利用することはないからです。
先程のクラスターにデータを入れ始めて、途中で osd を 6つに増やしてまた入れた結果が次の例です。
sh-4.4# ceph df RAW STORAGE: CLASS SIZE AVAIL USED RAW USED %RAW USED ssd 3.0 TiB 2.3 TiB 658 GiB 664 GiB 21.65 TOTAL 3.0 TiB 2.3 TiB 658 GiB 664 GiB 21.65 POOLS: POOL ID STORED OBJECTS USED %USED MAX AVAIL pool_3rep 1 112 GiB 28.23k 337 GiB 18.76 487 GiB pool_2rep 2 113 GiB 26.95k 227 GiB 13.45 730 GiB pool_2+1ec 3 62 GiB 15.49k 93 GiB 6.01 973 GiB sh-4.4# sh-4.4# ceph osd df ID CLASS WEIGHT REWEIGHT SIZE RAW USE DATA OMAP META AVAIL %USE VAR PGS STATUS 0 ssd 0.49899 1.00000 511 GiB 191 GiB 190 GiB 36 KiB 1024 MiB 320 GiB 37.31 1.72 110 up 3 ssd 0.49899 1.00000 511 GiB 43 GiB 42 GiB 0 B 1 GiB 468 GiB 8.33 0.38 70 up 1 ssd 0.49899 1.00000 511 GiB 184 GiB 183 GiB 35 KiB 1024 MiB 327 GiB 35.96 1.66 112 up 4 ssd 0.49899 1.00000 511 GiB 15 GiB 14 GiB 0 B 1 GiB 496 GiB 3.00 0.14 64 up 2 ssd 0.49899 1.00000 511 GiB 186 GiB 185 GiB 36 KiB 1024 MiB 325 GiB 36.39 1.68 101 up 5 ssd 0.49899 1.00000 511 GiB 45 GiB 44 GiB 0 B 1 GiB 466 GiB 8.89 0.41 79 up TOTAL 3.0 TiB 664 GiB 658 GiB 108 KiB 6.0 GiB 2.3 TiB 21.65 MIN/MAX VAR: 0.14/1.72 STDDEV: 15.03
osd の AVAIL がばらついています。この場合でも Pool の MAX AVAIL
は表示されているのですが、これの場合はどう計算するのでしょうか。
正解は、『一番少ない osd.AVAIL を数値を先の計算式に入れて計算する』です。
上の 6 つの osd の内、最も osd.AVAIL が少ないのは、osd.0 の 320 GiB です。これと osd.SIZE = 511 と num of osd=6 を計算式に入れると、
- 3x replicated pool: { 320 - ( 511 x ( 1 - 0.85 ) ) } x 6 / 3 = 486.7
- 2x replicated pool: { 320 - ( 511 x ( 1 - 0.85 ) ) } x 6 / 2 = 730.05
- 2+1 ec pool : { 320 - ( 511 x ( 1 - 0.85 ) ) } x 6 / { (2+1) / 2 } = 973.4
となり、MAX AVAIL
と同じことが分かります。
改めて全ての osd.AVAIL の中で最小の値を採用することを反映した計算式と、この様子を図で表したものを載せます。
まとめ
Ceph Pool の capacity usage について説明しました。
Ceph の設計をする時には、full ratio を加味して容量を見積もる必要があることは盲点になりやすいので、注意しましょう。full ratio line の上にある屋根裏部屋は (デフォルトで) 5% ですが、12 TB の玉を使えば 600GB ですから、なかなかバカになりません。
また MAX AVAIL の計算方法も紹介しましたが、はっきり言ってこれが分からないことで運用上すごく困ることにはあんまりならないと思います。あくまで小ネタです。
Pool で利用できる領域が減ってくると、そのうち osd nearfull の WARNING が出てきます。もうすぐ full になるから対処してねというやつです。nearful ratio はデフォルトで 0.85 です。
nearfull が来たらすぐに osd を追加しましょう。それが本道です。とは言え、どうしても新しい玉が来るまで持ちこたえられないという時の緊急対処として、full ratio を引き上げるとか、(pg のばらつきが大きくないと効果ゼロだが) osd を reweight して rebalance してみるとかして、既存 osd の AVAIL を押し広げて多少持ちこたえる小技があります。
とまあ最後まで小ネタでした。今日はここまで。
Cephクラスタのupgrade
この記事はRookだらけの Advent Calendar 2019 8日目の記事です。
今日は超軽くRook-Cephで作ったCephクラスタのupgradeを説明します。
Cephのupgrade
Cephは基本的にコンポーネントが冗長化されて動いているので、1つずつrolling upgradeすることでストレージ的にはNon-disruptiveなupgradeができます。
Rook-Cephではoperatorがその辺りを自動的にやってくれるので、人がやることは超少ないです。というわけでやってみましょう。
いつもどおり3master+3workerで各workerにそれぞれ2つOSDをぶら下げたCephクラスタを作ります。
[utubo@tutsunom ceph]$ kubectl get node --sort-by=".metadata.creationTimestamp" NAME STATUS ROLES AGE VERSION ip-172-20-110-218.ec2.internal Ready master 38h v1.15.5 ip-172-20-58-245.ec2.internal Ready master 38h v1.15.5 ip-172-20-68-55.ec2.internal Ready master 38h v1.15.5 ip-172-20-125-18.ec2.internal Ready node 38h v1.15.5 ip-172-20-60-20.ec2.internal Ready node 12h v1.15.5 ip-172-20-81-195.ec2.internal Ready node 12h v1.15.5 [utubo@tutsunom ceph]$ kubectl -n rook-ceph get pod NAME READY STATUS RESTARTS AGE csi-cephfsplugin-provisioner-974b566d9-8svhf 4/4 Running 0 6h21m csi-cephfsplugin-provisioner-974b566d9-hxfx2 4/4 Running 0 6h21m csi-cephfsplugin-q7m66 3/3 Running 0 6h21m csi-cephfsplugin-r58wx 3/3 Running 0 6h21m csi-cephfsplugin-w4pfg 3/3 Running 0 6h21m csi-rbdplugin-fhbqj 3/3 Running 0 6h21m csi-rbdplugin-jf5c9 3/3 Running 0 6h21m csi-rbdplugin-provisioner-579c546f5-9nh7z 5/5 Running 0 6h21m csi-rbdplugin-provisioner-579c546f5-pvf76 5/5 Running 0 6h21m csi-rbdplugin-v9p2k 3/3 Running 0 6h21m rook-ceph-mgr-a-649dcd8f8-z4bf9 1/1 Running 0 6h14m rook-ceph-mon-a-fb9dc8bf7-7tpfh 1/1 Running 0 6h14m rook-ceph-mon-b-7cbdf8b8bf-q8m89 1/1 Running 0 6h15m rook-ceph-mon-c-764f6b7c48-crlhc 1/1 Running 0 6h15m rook-ceph-operator-fb8b96548-cjzsp 1/1 Running 0 6h21m rook-ceph-osd-0-54cc869884-s7lx7 1/1 Running 0 6h13m rook-ceph-osd-1-69bb658d69-2x72t 1/1 Running 0 6h12m rook-ceph-osd-2-6886955f66-xxmjk 1/1 Running 0 6h13m rook-ceph-osd-3-c9fd5bdb6-l7n6r 1/1 Running 0 6h13m rook-ceph-osd-4-6fdc7dbb45-vvmqb 1/1 Running 0 6h12m rook-ceph-osd-5-66cbbf745-f6dwx 1/1 Running 0 6h13m rook-ceph-osd-prepare-ip-172-20-125-18.ec2.internal-h2rxc 0/1 Completed 0 6h14m rook-ceph-osd-prepare-ip-172-20-60-20.ec2.internal-fm8h5 0/1 Completed 0 6h14m rook-ceph-osd-prepare-ip-172-20-81-195.ec2.internal-rd9zk 0/1 Completed 0 6h14m rook-ceph-tools-5bc668d889-44wq2 1/1 Running 0 6h18m rook-discover-dmgtp 1/1 Running 0 6h21m rook-discover-p94l5 1/1 Running 0 6h21m rook-discover-x97hw 1/1 Running 0 6h21m [utubo@tutsunom ceph]$ kubectl exec -it `kubectl get pod -l app=rook-ceph-tools -o 'jsonpath={.items[].metadata.name}'` ceph version ceph version 14.2.2 (4f8fa0a0024755aae7d95567c63f11d6862d55be) nautilus (stable)
はいはい。
それではこのCephクラスタを14.2.2から14.2.4にupgradeします。やることは一つです。CephClusterリソースのimageのタグを書き換えるだけ。
[utubo@tutsunom ceph]$ kubectl -n rook-ceph patch CephCluster rook-ceph --type=merge -p "{\"spec\": {\"cephVersion\": {\"image\": \"ceph/ceph:v14.2.4-20191204\"}}}"
これだけで後はRook-Ceph Operatorが全部やってくれます。その様子を追っかけてみましょう。
upgrade中、別窓で↓のようにDeploymentの"READY/UP-TO-DATE/AVAILABLE"とceph-versionをwatchで見ておくとどうなるか。
※出力が長くなるので注目する部分だけ書きます。
[utubo@tutsunom ceph]$ watch --exec kubectl -n rook-ceph get deploy -l rook_cluster=rook-ceph -o jsonpath='{range .items[*]}{.metadata.name}{" \treq/upd/avl: "}{.spec.replicas}{"/"}{.status.updatedReplicas}{"/"}{.status.readyReplicas}{" \tceph-version="}{.metadata.labels.ceph-version}{"\n"}{end}' rook-ceph-mgr-a req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-mon-a req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-mon-b req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-mon-c req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-0 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-1 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-2 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-3 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-4 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-5 req/upd/avl: 1/1/1 ceph-version=14.2.2 ↓ rook-ceph-mon-a req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-mon-b req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-mon-c req/upd/avl: 1// ceph-version=14.2.4 ↓ rook-ceph-mon-a req/upd/avl: 1/1/ ceph-version=14.2.4 rook-ceph-mon-b req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-mon-c req/upd/avl: 1/1/1 ceph-version=14.2.4 ↓ rook-ceph-mon-a req/upd/avl: 1/1/1 ceph-version=14.2.4 rook-ceph-mon-b req/upd/avl: 1/1/ ceph-version=14.2.4 rook-ceph-mon-c req/upd/avl: 1/1/1 ceph-version=14.2.4
まず初めにMONがupgradeされ。今回はmon-c -> mon-a -> mon-bの順序でしたが、別の機会はまた違った順序だったので特に順番は決まって居ないようです。1つずつupgradeするのは間違いないです。
続き、
↓ rook-ceph-mgr-a req/upd/avl: 1// ceph-version=14.2.4 ↓ rook-ceph-mgr-a req/upd/avl: 1/1/1 ceph-version=14.2.4
次にMGRがupgrade。続いて、
rook-ceph-osd-0 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-1 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-2 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-3 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-4 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-5 req/upd/avl: 1/1/ ceph-version=14.2.4 ↓ rook-ceph-osd-0 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-1 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-2 req/upd/avl: 1// ceph-version=14.2.4 rook-ceph-osd-3 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-4 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-5 req/upd/avl: 1/1/1 ceph-version=14.2.4 ↓ rook-ceph-osd-0 req/upd/avl: 1/1/ ceph-version=14.2.4 rook-ceph-osd-1 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-2 req/upd/avl: 1/1/1 ceph-version=14.2.4 rook-ceph-osd-3 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-4 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-5 req/upd/avl: 1/1/1 ceph-version=14.2.4 ↓ rook-ceph-osd-0 req/upd/avl: 1/1/1 ceph-version=14.2.4 rook-ceph-osd-1 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-2 req/upd/avl: 1/1/1 ceph-version=14.2.4 rook-ceph-osd-3 req/upd/avl: 1// ceph-version=14.2.4 rook-ceph-osd-4 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-5 req/upd/avl: 1/1/1 ceph-version=14.2.4 ↓ rook-ceph-osd-0 req/upd/avl: 1/1/1 ceph-version=14.2.4 rook-ceph-osd-1 req/upd/avl: 1/1/ ceph-version=14.2.4 rook-ceph-osd-2 req/upd/avl: 1/1/1 ceph-version=14.2.4 rook-ceph-osd-3 req/upd/avl: 1/1/1 ceph-version=14.2.4 rook-ceph-osd-4 req/upd/avl: 1/1/1 ceph-version=14.2.2 rook-ceph-osd-5 req/upd/avl: 1/1/1 ceph-version=14.2.4 ↓ rook-ceph-osd-0 req/upd/avl: 1/1/1 ceph-version=14.2.4 rook-ceph-osd-1 req/upd/avl: 1/1/1 ceph-version=14.2.4 rook-ceph-osd-2 req/upd/avl: 1/1/1 ceph-version=14.2.4 rook-ceph-osd-3 req/upd/avl: 1/1/1 ceph-version=14.2.4 rook-ceph-osd-4 req/upd/avl: 1/1/1 ceph-version=14.2.4 rook-ceph-osd-5 req/upd/avl: 1/1/1 ceph-version=14.2.4
という感じで最後にOSDがupgradeされます。
ここではosdが5,2,0,3,1,4という順序でupgradeされました。Cephのosd treeを見てみるとworker nodeごとにupgradeをかけていることがわかります。
[utubo@tutsunom ceph]$ kubectl exec -it `kubectl get pod -l app=rook-ceph-tools -o 'jsonpath={.items[].metadata.name}'` ceph osd tree ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF -1 0.16974 root default -5 0.16974 region us-east-1 -4 0.05658 zone us-east-1a -3 0.05658 host ip-172-20-60-20-ec2-internal 0 ssd 0.02829 osd.0 up 1.00000 1.00000 3 ssd 0.02829 osd.3 up 1.00000 1.00000 -10 0.05658 zone us-east-1b -9 0.05658 host ip-172-20-81-195-ec2-internal 1 ssd 0.02829 osd.1 up 1.00000 1.00000 4 ssd 0.02829 osd.4 up 1.00000 1.00000 -14 0.05658 zone us-east-1c -13 0.05658 host ip-172-20-125-18-ec2-internal 2 ssd 0.02829 osd.2 up 1.00000 1.00000 5 ssd 0.02829 osd.5 up 1.00000 1.00000
最後にCephクラスタでバージョンを確認すると、
[utubo@tutsunom ceph]$ kubectl exec -it `kubectl get pod -l app=rook-ceph-tools -o 'jsonpath={.items[].metadata.name}'` ceph version ceph version 14.2.4 (75f4de193b3ea58512f204623e6c5a16e6c1e1ba) nautilus (stable)
はいおわり。
コマンド一個打つだけでMON -> MGR -> OSDとそれぞれ1つずつupgradeしてくれるのだからRook-Ceph operatorは偉大です。
まとめ
今日は軽くCephクラスタのupgradeについて説明しました。
今回は同一メジャーバージョン間のupgradeでしたが、メジャーバージョンをまたぐとOSDのメタデータの持ち方とかが変わってデバイスをattachできないとか(特にBlueStoreの場合)があるかもしれないので注意が必要かもです(適当) ※13->14のupgradeにことごとく失敗して、原因がまだ調査できていない(汗)
あと、本当はRook-Ceph operator自身のupgradeも説明すべきですが、時間がなくて検証できていないので続きは赤帽エンジニアブログで書きます。
Rookは対応するSDSやDBのoperatorで、ストレージの構築から運用まで強力に手助けしてくれる革命的なオーケストレーションツールです。
みなさんぜひ試してみて下さいね。
それでは今日でRookだらけのAdvent Calendar 2019の私のパートは終わりです。8日連続でお付き合いいただきありがとうございました。
引き続きtzkobaさんとmakotowさんという豪華顔ぶれの説明をお楽しみください!
Rook-Ceph OSD on PVC(後半)
この記事はRookだらけの Advent Calendar 2019 7日目の記事です。
昨日はOSD on PVCのCephクラスタをデプロイできたのはいいものの、OSDがうまく散らばってくれないという問題に直面しました。
しかも織り込み済みの問題だという。今回はこの問題を回避する方法の一例を紹介します。
そういうわけで、今の時点ではマニュアルで3nodeの散らばるように書く必要がありそうです。
3nodeに散らばるようにする方法
Kubernetesにまかせてカッコよくosdを散らすのは難しそうなので、マニュアルで散らせます。
色々失敗した検討した結果、こんな感じでNode Affinityを使ったら3osdずつ散らばりました。
[utubo@tutsunom ceph]$ cat my-cluster-on-pvc.yaml apiVersion: ceph.rook.io/v1 kind: CephCluster metadata: name: rook-ceph namespace: rook-ceph spec: dataDirHostPath: /var/lib/rook mon: count: 3 allowMultiplePerNode: false volumeClaimTemplate: spec: storageClassName: my-gp2 resources: requests: storage: 10Gi cephVersion: image: ceph/ceph:v14.2.4-20190917 allowUnsupported: false dashboard: enabled: true ssl: true network: hostNetwork: false storage: topologyAware: true storageClassDeviceSets: - name: set-1a count: 3 portable: true placement: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: failure-domain.beta.kubernetes.io/zone operator: In values: - us-east-1a resources: volumeClaimTemplates: - metadata: name: data spec: resources: requests: storage: 10Gi storageClassName: my-gp2 volumeMode: Block accessModes: - ReadWriteOnce - name: set-1b count: 3 portable: true placement: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: failure-domain.beta.kubernetes.io/zone operator: In values: - us-east-1b resources: volumeClaimTemplates: - metadata: name: data spec: resources: requests: storage: 10Gi storageClassName: my-gp2 volumeMode: Block accessModes: - ReadWriteOnce - name: set-1c count: 3 portable: true placement: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: failure-domain.beta.kubernetes.io/zone operator: In values: - us-east-1c resources: volumeClaimTemplates: - metadata: name: data spec: resources: requests: storage: 10Gi storageClassName: my-gp2 volumeMode: Block accessModes: - ReadWriteOnce disruptionManagement: managePodBudgets: false osdMaintenanceTimeout: 30 manageMachineDisruptionBudgets: false machineDisruptionBudgetNamespace: openshift-machine-api
どうですか。ダサい、ダサすぎる。と風が語りかけてくるようです。
恥ずかしい思いをグッと我慢して解説すると、storageClassDeviceSets:
はOSDのセットを指定します。
サンプルのyamlだと、9個のOSDを1つのセットにするからPod AntiAffinity ruleでうまく分けろって言っているのです。
しかし、9個の唐揚げを1枚の皿に乗せて3人の子供達に仲良く分けて食えと言ってもうまくいかないように、(今のルールだと)意図するように分けるのはなかなか難しい。
そこで3個のOSDのセットを3つ用意してそれぞれのzoneにあるworker nodeに分けさせるruleにしてるのが、上のyamlです。
3枚の皿に3個ずつ唐揚げを乗せて1皿ずつ取れって形にしたら話早いやん、という感じです。
めっちゃhard codedなんで結局これかい感満々ですが、これでもう一回クラスタをデプロイしてみましょう。
[utubo@tutsunom ceph]$ kubectl create -f my-cluster-on-pvc.yaml [utubo@tutsunom ceph]$ kubectl -n rook-ceph get pod NAME READY STATUS RESTARTS AGE csi-cephfsplugin-5cp9g 3/3 Running 0 5m44s csi-cephfsplugin-fhr5b 3/3 Running 0 5m44s csi-cephfsplugin-l6556 3/3 Running 0 5m44s csi-cephfsplugin-provisioner-974b566d9-frwz6 4/4 Running 0 5m44s csi-cephfsplugin-provisioner-974b566d9-tqswk 4/4 Running 0 5m44s csi-rbdplugin-4qxgj 3/3 Running 0 5m44s csi-rbdplugin-crc8t 3/3 Running 0 5m44s csi-rbdplugin-h5dkw 3/3 Running 0 5m44s csi-rbdplugin-provisioner-579c546f5-sfx72 5/5 Running 0 5m44s csi-rbdplugin-provisioner-579c546f5-z7rmk 5/5 Running 0 5m44s rook-ceph-mgr-a-7cf896f748-m7czk 1/1 Running 0 3m37s rook-ceph-mon-a-568dc96b5f-xl9x4 1/1 Running 0 4m49s rook-ceph-mon-b-5cbc9dcd9d-gxnjp 1/1 Running 0 4m32s rook-ceph-mon-c-647db6d4b5-wmkzg 1/1 Running 0 4m1s rook-ceph-operator-fb8b96548-n9jv6 1/1 Running 0 5m52s rook-ceph-osd-0-8cbc88874-k6dlj 1/1 Running 0 2m2s rook-ceph-osd-1-5b746b478f-fzs8z 1/1 Running 0 2m3s rook-ceph-osd-2-64c746c558-mwzn2 1/1 Running 0 2m7s rook-ceph-osd-3-86f8984495-b7b7n 1/1 Running 0 2m5s rook-ceph-osd-4-67889676b9-wjswz 1/1 Running 0 2m2s rook-ceph-osd-5-687847c9f-6z7ps 1/1 Running 0 2m3s rook-ceph-osd-6-f8997d5b7-bmblb 1/1 Running 0 114s rook-ceph-osd-7-65dc45747c-fckw7 1/1 Running 0 111s rook-ceph-osd-8-76bf67bcf8-s9vmm 1/1 Running 0 114s rook-ceph-osd-prepare-set-1a-0-data-kx7k4-n4wrn 0/1 Completed 0 3m10s rook-ceph-osd-prepare-set-1a-1-data-kdwjp-n4fm9 0/1 Completed 0 3m9s rook-ceph-osd-prepare-set-1a-2-data-j5fm6-7vjwg 0/1 Completed 0 3m8s rook-ceph-osd-prepare-set-1b-0-data-tsv5x-mcx9q 0/1 Completed 0 3m8s rook-ceph-osd-prepare-set-1b-1-data-gdpqg-9knxk 0/1 Completed 0 3m7s rook-ceph-osd-prepare-set-1b-2-data-jfwcn-d67gp 0/1 Completed 0 3m7s rook-ceph-osd-prepare-set-1c-0-data-9tcl4-87946 0/1 Completed 0 3m6s rook-ceph-osd-prepare-set-1c-1-data-h4wk7-c9d76 0/1 Completed 0 3m5s rook-ceph-osd-prepare-set-1c-2-data-svq64-9sdzb 0/1 Completed 0 3m5s rook-discover-fmprp 1/1 Running 0 5m51s rook-discover-m895f 1/1 Running 0 5m51s rook-discover-wnpj7 1/1 Running 0 5m51s
[utubo@tutsunom ceph]$ kubectl -n rook-ceph get pod -l app=rook-ceph-mon -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES rook-ceph-mon-a-568dc96b5f-xl9x4 1/1 Running 0 5m19s 100.96.6.111 ip-172-20-93-28.ec2.internal <none> <none> rook-ceph-mon-b-5cbc9dcd9d-gxnjp 1/1 Running 0 5m2s 100.96.7.178 ip-172-20-42-193.ec2.internal <none> <none> rook-ceph-mon-c-647db6d4b5-wmkzg 1/1 Running 0 4m31s 100.96.8.99 ip-172-20-102-19.ec2.internal <none> <none> [utubo@tutsunom ceph]$ kubectl -n rook-ceph get pod -l app=rook-ceph-osd -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES rook-ceph-osd-0-8cbc88874-k6dlj 1/1 Running 0 2m37s 100.96.6.118 ip-172-20-93-28.ec2.internal <none> <none> rook-ceph-osd-1-5b746b478f-fzs8z 1/1 Running 0 2m38s 100.96.8.104 ip-172-20-102-19.ec2.internal <none> <none> rook-ceph-osd-2-64c746c558-mwzn2 1/1 Running 0 2m42s 100.96.8.103 ip-172-20-102-19.ec2.internal <none> <none> rook-ceph-osd-3-86f8984495-b7b7n 1/1 Running 0 2m40s 100.96.6.116 ip-172-20-93-28.ec2.internal <none> <none> rook-ceph-osd-4-67889676b9-wjswz 1/1 Running 0 2m37s 100.96.6.117 ip-172-20-93-28.ec2.internal <none> <none> rook-ceph-osd-5-687847c9f-6z7ps 1/1 Running 0 2m38s 100.96.7.182 ip-172-20-42-193.ec2.internal <none> <none> rook-ceph-osd-6-f8997d5b7-bmblb 1/1 Running 0 2m29s 100.96.8.105 ip-172-20-102-19.ec2.internal <none> <none> rook-ceph-osd-7-65dc45747c-fckw7 1/1 Running 0 2m26s 100.96.7.184 ip-172-20-42-193.ec2.internal <none> <none> rook-ceph-osd-8-76bf67bcf8-s9vmm 1/1 Running 0 2m29s 100.96.7.183 ip-172-20-42-193.ec2.internal <none> <none>
お、3個ずつ散らばってますね。(そらそうやろ
Cephの観点で見た注意点
ここでちょっとCephクラスタを見てみましょう。
[utubo@tutsunom ceph]$ kubectl create -f toolbox.yaml [utubo@tutsunom ceph]$ kubectl -n rook-ceph exec -it `kubectl get pod -l app=rook-ceph-tools -o 'jsonpath={.items[].metadata.name}'` ceph osd tree ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF -1 0.07910 root default -5 0.07910 region us-east-1 -14 0.02637 zone us-east-1a -13 0.00879 host set-1a-0-data-kx7k4 5 ssd 0.00879 osd.5 up 1.00000 1.00000 -27 0.00879 host set-1a-1-data-kdwjp 7 ssd 0.00879 osd.7 up 1.00000 1.00000 -23 0.00879 host set-1a-2-data-j5fm6 8 ssd 0.00879 osd.8 up 1.00000 1.00000 -10 0.02637 zone us-east-1b -9 0.00879 host set-1b-0-data-tsv5x 3 ssd 0.00879 osd.3 up 1.00000 1.00000 -17 0.00879 host set-1b-1-data-gdpqg 0 ssd 0.00879 osd.0 up 1.00000 1.00000 -19 0.00879 host set-1b-2-data-jfwcn 4 ssd 0.00879 osd.4 up 1.00000 1.00000 -4 0.02637 zone us-east-1c -3 0.00879 host set-1c-0-data-9tcl4 2 ssd 0.00879 osd.2 up 1.00000 1.00000 -25 0.00879 host set-1c-1-data-h4wk7 6 ssd 0.00879 osd.6 up 1.00000 1.00000 -21 0.00879 host set-1c-2-data-svq64 1 ssd 0.00879 osd.1 up 1.00000 1.00000
なんか3つずつに分かれて良さそうに見えますね。しかしこのトポロジーではCephのデフォルトのCRUSH ruleを使う場合に落とし穴があります。
各zoneの中に3つのhostがありますね。この3つのhostは実際は同一のworker nodeなんですが、Cephとしては異なるhostが3つあるトポロジーとして捉えます。そして各hostが1つosdを持ちます。
デフォルトのreplicated_ruleは「regionとかzoneとか無視して、とにかく1つhostを選んでその中のosdを1つ選ぶ」というルールになっています。
[utubo@tutsunom ceph]$ kubectl -n rook-ceph exec -it `kubectl get pod -l app=rook-ceph-tools -o 'jsonpath={.items[].metadata.name}'` sh sh-4.2# ceph osd getcrushmap -o crushmap.bin sh-4.2# crushtool -d crushmap.bin -o crushmap.txt sh-4.2# grep -A 10 rules crushmap.txt # rules rule replicated_rule { id 0 type replicated min_size 1 max_size 10 step take default step chooseleaf firstn 0 type host step emit }
つまり、上記のようなトポロジーのCephクラスタでreplicated_ruleを使って3x Replicated Poolを作ると、同一のzoneから3つのOSDを選んだPGが作られる可能性があります。
実際やって見てみましょう。面倒なんでCephで直接コマンド打ってPoolを作ります。すんません。
[utubo@tutsunom ceph]$ kubectl -n rook-ceph exec -it `kubectl get pod -l app=rook-ceph-tools -o 'jsonpath={.items[].metadata.name}'` ceph osd pool create test 256 256 pool 'test' created [utubo@tutsunom ceph]$ kubectl -n rook-ceph exec -it `kubectl get pod -l app=rook-ceph-tools -o 'jsonpath={.items[].metadata.name}'` ceph pg ls-by-pool test PG OBJECTS DEGRADED MISPLACED UNFOUND BYTES OMAP_BYTES* OMAP_KEYS* LOG STATE SINCE VERSION REPORTED UP ACTING SCRUB_STAMP DEEP_SCRUB_STAMP 1.0 0 0 0 0 0 0 0 0 active+clean 26s 0'0 26:10 [0,1,2]p0 [0,1,2]p0 2019-12-05 03:57:01.395376 2019-12-05 03:57:01.395376 1.1 0 0 0 0 0 0 0 0 active+clean 26s 0'0 26:10 [5,2,0]p5 [5,2,0]p5 2019-12-05 03:57:01.395376 2019-12-05 03:57:01.395376 1.2 0 0 0 0 0 0 0 0 active+clean 26s 0'0 26:10 [4,1,2]p4 [4,1,2]p4 2019-12-05 03:57:01.395376 2019-12-05 03:57:01.395376 1.3 0 0 0 0 0 0 0 0 active+clean 26s 0'0 26:10 [7,2,4]p7 [7,2,4]p7 2019-12-05 03:57:01.395376 2019-12-05 03:57:01.395376 1.4 0 0 0 0 0 0 0 0 active+clean 26s 0'0 26:10 [7,4,2]p7 [7,4,2]p7 2019-12-05 03:57:01.395376 2019-12-05 03:57:01.395376 1.5 0 0 0 0 0 0 0 0 active+clean 26s 0'0 26:10 [8,1,4]p8 [8,1,4]p8 2019-12-05 03:57:01.395376 2019-12-05 03:57:01.395376 ... 1.34 0 0 0 0 0 0 0 0 active+clean 26s 0'0 26:10 [6,2,1]p6 [6,2,1]p6 2019-12-05 03:57:01.395376 2019-12-05 03:57:01.395376 ... 1.97 0 0 0 0 0 0 0 0 active+clean 26s 0'0 26:10 [5,7,8]p5 [5,7,8]p5 2019-12-05 03:57:01.395376 2019-12-05 03:57:01.395376 ... 1.c2 0 0 0 0 0 0 0 0 active+clean 26s 0'0 26:10 [0,3,4]p0 [0,3,4]p0 2019-12-05 03:57:01.395376 2019-12-05 03:57:01.395376 ...
ceph osd pool create
コマンドでruleを指定せずにpoolを作るとデフォルトのreplicated_ruleが使われるのですが、どうでしょう。
1.34
に割り当てられたOSD[6,2,1]
は、ceph osd tree
を見ると3つともzone us-east-1c
から取られています。が、実際は1つのworker nodeにattachされてるOSDです。1.97
も1.c2
も同様です。
つまりworker nodeに障害が起きるとこれらのPGは完全にアウトとなり、データロスとなります。全然冗長化されてないpoolなので、これはアカン。
だから何かしら対応しなくてはいけません。
トポロジーを変えるのはRook-Ceph側の扱いになって難しそうなので、適切なCRUSH ruleを作って指定する方がよいでしょう。例えばこんな感じのruleを作ったらいけるはずです。
# rules rule spread_across_all_zones { ruleset 1 type replicated min_size 1 max_size 10 step take default step choose firstn 0 type zone step chooseleaf firstn 1 type host step emit }
まとめ
前後半にわたって、OSD on PVCについて説明しました。worker nodeにブロックデバイスをぶら下げる作業がしなくていいのでKubernetes側でデバイス管理でき、Cloud Native Infra感出ますよね。本当に便利だと思います。
でも個人的にOSD on PVCで一番うれしいのは、Cephクラスタを作り直すたびにworker nodeに入ってMONが使うCephの構成ファイル(/var/lib/rook
以下)をいちいち消さなくてよかったり、OSDになるデバイスをきれいに消してLVMのエントリーを消したりしなくていいところだったりします。クラスタ消したら全部自動的にPVCも消えてきれいさっぱり無くなるからです。本番のKubernetesクラスタでは全然関係ないけれど、テストする上ではスムーズにクラスタのdelete/createが繰り返しができるので、ホントーーーーにありがたい。
OSDをきれいに散らす方法は、Kubernetes一年生のうつぼではNode Affinityを使ったダサい方法しか思いつかなかったけど、やっぱりPod (Anti)Affinityをうまく使ったやりかたがあるんでしょうね。それかPod Topology Spread Constraintsを待つんでしょう。
こちらのissueを見ると、Rook 1.2にはPod Topology Spread Constraintsに対応するとのことです。
Pod Topology Spread Constraintsについてはsatさんが追究されています。やはり今日本で一番のRook-Cepherだと思います。最敬礼。
というわけで、今回はおしまい。
BGMは境界の彼方でした。
Rook-Ceph OSD on PVC(前半)
この記事はRookだらけの Advent Calendar 2019 6日目の記事です。
Rook 1.1でできるようになった OSD on PVC の説明をします。
OSD on PVC ???
OSD on PVCというのは、ceph-osdをPVC から作ろうということです。
CephはブロックデバイスからOSDを作成するため、言うまでもなくceph-osdにはブロックデバイスが必要です。
osdのブロックデバイスはrook-ceph-osd Podが稼働するworker nodeから取ってくるので、事前に何らかの方法でworker nodeにブロックデバイスをattachしておかなくてはなりません。
しかしこのworker nodeにブロックデバイスをattachする作業は、Kubernetesが乗るプラットフォーム側の操作です。Kubernetesで何かしらやりようはあると思いますが、基本的にはKubernetes外の管理操作だと思います。
せっかくRookでKubernetes内で完結できるストレージシステムが作れるというのに、根本にある保存媒体はKubernetes外でmanageされる。それってなんかイケてないですよね。
そういうわけで、
「既存のPV/PVCの仕組みでceph-osdのPodにブロックデバイスを直でattachしようや、そしたら何もないところから自動でOSDが作れるやろ」
を実現するのがOSD on PVCです。
この考えの元にあるのがKubernetes 1.11からでてきたRaw Block Volumeのfeatureです。(1.14でbetaながらデフォルトでenableになっているfeature)
この技術を使ってPVをブロックデバイスとして見せることができるようになりました。
https://kubernetes.io/docs/concepts/storage/volumes/#csi-raw-block-volume-support
これってまるでCloud(Container) Native Storageのためにあるようなfeature。ええやん、ステキやん。
実際にやってみる
OSDはベースのPVC-baseのブロックデバイスにするとし、MONの構成ファイルをどうするかという選択肢もあります。
これまでMONの構成ファイルはworker nodeの/var/lib/rook
などyamlで記載されたディレクトリに置かれていたのですが、これもPVC-baseのファイルPVに置くというパターンが選べます。せっかくだからこっちでやってみましょう。
前回までと同じように3master+3workerのクラスタです。
[utubo@tutsunom ceph]$ kubectl get node --sort-by=".metadata.creationTimestamp" --show-labels NAME STATUS ROLES AGE VERSION LABELS ip-172-20-91-64.ec2.internal Ready master 25h v1.15.5 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=t2.medium,beta.kubernetes.io/os=linux,failure-domain.beta.kubernetes.io/region=us-east-1,failure-domain.beta.kubernetes.io/zone=us-east-1b,kops.k8s.io/instancegroup=master-us-east-1b,kubernetes.io/arch=amd64,kubernetes.io/hostname=ip-172-20-74-29.ec2.internal,kubernetes.io/os=linux,kubernetes.io/role=master,node-role.kubernetes.io/master= ip-172-20-53-29.ec2.internal Ready master 25h v1.15.5 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=t2.medium,beta.kubernetes.io/os=linux,failure-domain.beta.kubernetes.io/region=us-east-1,failure-domain.beta.kubernetes.io/zone=us-east-1a,kops.k8s.io/instancegroup=master-us-east-1a,kubernetes.io/arch=amd64,kubernetes.io/hostname=ip-172-20-63-169.ec2.internal,kubernetes.io/os=linux,kubernetes.io/role=master,node-role.kubernetes.io/master= ip-172-20-113-40.ec2.internal Ready master 25h v1.15.5 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=t2.medium,beta.kubernetes.io/os=linux,failure-domain.beta.kubernetes.io/region=us-east-1,failure-domain.beta.kubernetes.io/zone=us-east-1c,kops.k8s.io/instancegroup=master-us-east-1c,kubernetes.io/arch=amd64,kubernetes.io/hostname=ip-172-20-121-240.ec2.internal,kubernetes.io/os=linux,kubernetes.io/role=master,node-role.kubernetes.io/master= ip-172-20-93-28.ec2.internal Ready node 25h v1.15.5 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=t2.large,beta.kubernetes.io/os=linux,failure-domain.beta.kubernetes.io/region=us-east-1,failure-domain.beta.kubernetes.io/zone=us-east-1a,kops.k8s.io/instancegroup=nodes,kubernetes.io/arch=amd64,kubernetes.io/hostname=ip-172-20-52-182.ec2.internal,kubernetes.io/os=linux,kubernetes.io/role=node,node-role.kubernetes.io/node= ip-172-20-42-193.ec2.internal Ready node 25h v1.15.5 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=t2.large,beta.kubernetes.io/os=linux,failure-domain.beta.kubernetes.io/region=us-east-1,failure-domain.beta.kubernetes.io/zone=us-east-1c,kops.k8s.io/instancegroup=nodes,kubernetes.io/arch=amd64,kubernetes.io/hostname=ip-172-20-118-92.ec2.internal,kubernetes.io/os=linux,kubernetes.io/role=node,node-role.kubernetes.io/node= ip-172-20-102-19.ec2.internal Ready node 25h v1.15.5 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=t2.large,beta.kubernetes.io/os=linux,failure-domain.beta.kubernetes.io/region=us-east-1,failure-domain.beta.kubernetes.io/zone=us-east-1b,kops.k8s.io/instancegroup=nodes,kubernetes.io/arch=amd64,kubernetes.io/hostname=ip-172-20-74-57.ec2.internal,kubernetes.io/os=linux,kubernetes.io/role=node,node-role.kubernetes.io/node=
まず、ベースの元になるPV/PVCのStorageClassをチェックしましょう。
ベースのStorageClassがvolumeBindingMode: WaitForFirstConsumer
で定義されていることが大事です。volumeBindingMode: Immediate
だと動きません。ダメです。ここちょっとハマりました。
[utubo@tutsunom ceph]$ cat my-sc-gp2.yaml kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: my-gp2 annotations: storageclass.kubernetes.io/is-default-class: "true" provisioner: kubernetes.io/aws-ebs volumeBindingMode: WaitForFirstConsumer [utubo@tutsunom ceph]$ kubectl create -f my-sc-gp2.yaml
それではgithubにあるサンプルのcluster-on-pvc.yaml
から、StorageClassと(gp2 --> my-gp2)とosdの数(count:3 --> 9)だけ変更して、Cephクラスタを作ってみます。(長いのでコメント行は省略)
yamlの中のmon:
とstorage:
(=osd)にあるvolumeClaimTemplate
がPVC-baseの証。
[utubo@tutsunom ceph]$ cat my-cluster-on-pvc.yaml apiVersion: ceph.rook.io/v1 kind: CephCluster metadata: name: rook-ceph namespace: rook-ceph spec: dataDirHostPath: /var/lib/rook mon: count: 3 allowMultiplePerNode: false volumeClaimTemplate: spec: storageClassName: my-gp2 resources: requests: storage: 10Gi cephVersion: image: ceph/ceph:v14.2.4-20190917 allowUnsupported: false dashboard: enabled: true ssl: true network: hostNetwork: false storage: topologyAware: true storageClassDeviceSets: - name: set1 count: 9 portable: true placement: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - rook-ceph-osd - key: app operator: In values: - rook-ceph-osd-prepare topologyKey: kubernetes.io/hostname resources: volumeClaimTemplates: - metadata: name: data spec: resources: requests: storage: 10Gi storageClassName: my-gp2 volumeMode: Block accessModes: - ReadWriteOnce disruptionManagement: managePodBudgets: false osdMaintenanceTimeout: 30 manageMachineDisruptionBudgets: false machineDisruptionBudgetNamespace: openshift-machine-api [utubo@tutsunom ceph]$ [utubo@tutsunom ceph]$ kubectl create -f common.yaml [utubo@tutsunom ceph]$ kubectl create -f operator.yaml [utubo@tutsunom ceph]$ kubectl create -f my-cluster-on-pvc.yaml [utubo@tutsunom ceph]$ [utubo@tutsunom ceph]$ kubectl -n rook-ceph get pod NAME READY STATUS RESTARTS AGE csi-cephfsplugin-jbs7g 3/3 Running 0 4m53s csi-cephfsplugin-lvtg9 3/3 Running 0 4m53s csi-cephfsplugin-provisioner-974b566d9-b24zs 4/4 Running 0 4m53s csi-cephfsplugin-provisioner-974b566d9-wgx4l 4/4 Running 0 4m53s csi-cephfsplugin-rpg6v 3/3 Running 0 4m53s csi-rbdplugin-4pvjd 3/3 Running 0 4m53s csi-rbdplugin-hw59q 3/3 Running 0 4m53s csi-rbdplugin-mrq2g 3/3 Running 0 4m53s csi-rbdplugin-provisioner-579c546f5-k4x78 5/5 Running 0 4m53s csi-rbdplugin-provisioner-579c546f5-tlb8s 5/5 Running 0 4m53s rook-ceph-mgr-a-8656964c64-d6rxd 1/1 Running 0 2m50s rook-ceph-mon-a-5964fd74f7-fpqhl 1/1 Running 0 4m3s rook-ceph-mon-b-858958c794-mwfzz 1/1 Running 0 3m36s rook-ceph-mon-c-576b4d7687-94ts9 1/1 Running 0 3m14s rook-ceph-operator-fb8b96548-f5dl5 1/1 Running 0 5m1s rook-ceph-osd-0-66db6b5bbc-6v82x 1/1 Running 0 59s rook-ceph-osd-1-7b76f55b96-bqknl 1/1 Running 0 49s rook-ceph-osd-2-57f696464b-jlzjr 1/1 Running 0 74s rook-ceph-osd-3-7b975f57c7-6snsr 1/1 Running 0 78s rook-ceph-osd-4-5d485c8997-8fq7r 1/1 Running 0 75s rook-ceph-osd-5-6f4f87db77-b52z6 1/1 Running 0 43s rook-ceph-osd-6-6999896cdf-7d4mv 1/1 Running 0 26s rook-ceph-osd-7-c66d49fcb-5lrwr 1/1 Running 0 29s rook-ceph-osd-8-6bdf79c57c-prnzq 1/1 Running 0 28s rook-ceph-osd-prepare-set1-0-data-bhmrj-rjbnk 0/1 Completed 0 2m22s rook-ceph-osd-prepare-set1-1-data-dcr5r-gcdl8 0/1 Completed 0 2m21s rook-ceph-osd-prepare-set1-2-data-klbr2-bnlqv 0/1 Completed 0 2m21s rook-ceph-osd-prepare-set1-3-data-7b2pk-7n6wl 0/1 Completed 0 2m21s rook-ceph-osd-prepare-set1-4-data-249gz-b2z79 0/1 Completed 0 2m20s rook-ceph-osd-prepare-set1-5-data-znf49-l7xbz 0/1 Completed 0 2m19s rook-ceph-osd-prepare-set1-6-data-57bft-qtnwt 0/1 Completed 0 2m19s rook-ceph-osd-prepare-set1-7-data-sm244-v546c 0/1 Completed 0 2m18s rook-ceph-osd-prepare-set1-8-data-cd5hb-zt2gk 0/1 Completed 0 2m18s rook-discover-5jzcr 1/1 Running 0 5m rook-discover-glvgr 1/1 Running 0 5m rook-discover-jh9pr 1/1 Running 0 5m
おっ、イケるやん。worker nodeにあらかじめブロックデバイスをつけることなくCephクラスタが作れました。
[utubo@tutsunom ceph]$ kubectl -n rook-ceph get pod -l app=rook-ceph-mon -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES rook-ceph-mon-a-5964fd74f7-fpqhl 1/1 Running 0 4m56s 100.96.6.128 ip-172-20-93-28.ec2.internal <none> <none> rook-ceph-mon-b-858958c794-mwfzz 1/1 Running 0 4m29s 100.96.7.198 ip-172-20-42-193.ec2.internal <none> <none> rook-ceph-mon-c-576b4d7687-94ts9 1/1 Running 0 4m7s 100.96.8.117 ip-172-20-102-19.ec2.internal <none> <none>
MONはしっかり3ノードに分かれています。OSDは、
[utubo@tutsunom ceph]$ kubectl -n rook-ceph get pod -l app=rook-ceph-osd -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES rook-ceph-osd-0-66db6b5bbc-6v82x 1/1 Running 0 119s 100.96.6.136 ip-172-20-93-28.ec2.internal <none> <none> rook-ceph-osd-1-7b76f55b96-bqknl 1/1 Running 0 109s 100.96.6.137 ip-172-20-93-28.ec2.internal <none> <none> rook-ceph-osd-2-57f696464b-jlzjr 1/1 Running 0 2m14s 100.96.7.204 ip-172-20-42-193.ec2.internal <none> <none> rook-ceph-osd-3-7b975f57c7-6snsr 1/1 Running 0 2m18s 100.96.7.202 ip-172-20-42-193.ec2.internal <none> <none> rook-ceph-osd-4-5d485c8997-8fq7r 1/1 Running 0 2m15s 100.96.7.203 ip-172-20-42-193.ec2.internal <none> <none> rook-ceph-osd-5-6f4f87db77-b52z6 1/1 Running 0 103s 100.96.6.138 ip-172-20-93-28.ec2.internal <none> <none> rook-ceph-osd-6-6999896cdf-7d4mv 1/1 Running 0 86s 100.96.6.141 ip-172-20-93-28.ec2.internal <none> <none> rook-ceph-osd-7-c66d49fcb-5lrwr 1/1 Running 0 89s 100.96.6.139 ip-172-20-93-28.ec2.internal <none> <none> rook-ceph-osd-8-6bdf79c57c-prnzq 1/1 Running 0 88s 100.96.6.140 ip-172-20-93-28.ec2.internal <none> <none>
ええー!osd全然3ノードにバラけてないやん!!一応Cephで見てみると…
[utubo@tutsunom ceph]$ kubectl create -f toolbox.yaml [utubo@tutsunom ceph]$ kubectl -n rook-ceph exec -it `kubectl get pod -l app=rook-ceph-tools -o 'jsonpath={.items[].metadata.name}'` ceph osd tree ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF -1 0.07910 root default -5 0.07910 region us-east-1 -4 0.02637 zone us-east-1a -9 0.00879 host set1-0-data-bhmrj 4 ssd 0.00879 osd.4 up 1.00000 1.00000 -11 0.00879 host set1-2-data-klbr2 2 ssd 0.00879 osd.2 up 1.00000 1.00000 -3 0.00879 host set1-6-data-57bft 3 ssd 0.00879 osd.3 up 1.00000 1.00000 -14 0.05273 zone us-east-1b -13 0.00879 host set1-1-data-dcr5r 0 ssd 0.00879 osd.0 up 1.00000 1.00000 -19 0.00879 host set1-3-data-7b2pk 5 ssd 0.00879 osd.5 up 1.00000 1.00000 -17 0.00879 host set1-4-data-249gz 1 ssd 0.00879 osd.1 up 1.00000 1.00000 -23 0.00879 host set1-5-data-znf49 6 ssd 0.00879 osd.6 up 1.00000 1.00000 -21 0.00879 host set1-7-data-sm244 8 ssd 0.00879 osd.8 up 1.00000 1.00000 -25 0.00879 host set1-8-data-cd5hb 7 ssd 0.00879 osd.7 up 1.00000 1.00000
(´・ω・`)
yamlのosd Affinity ruleを見ると、
placement: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - rook-ceph-osd - key: app operator: In values: - rook-ceph-osd-prepare topologyKey: kubernetes.io/hostname
うーん…確かに3osdより多くなるとうまく散らばらなそうやけど3nodeにすら散らばらんのはどうなっとるんや…
実はコレ想定内の問題なんです。サンプルのcluster-on-pvc.yaml
で使われているpodAntiAffinity ruleではうまく散らばらないのは織り込み済みです。yamlのコメントをよく読んでみると次のことが書かれています。
# Since the OSDs could end up on any node, an effort needs to be made to spread the OSDs # across nodes as much as possible. Unfortunately the pod anti-affinity breaks down # as soon as you have more than one OSD per node. If you have more OSDs than nodes, K8s may # choose to schedule many of them on the same node. What we need is the Pod Topology # Spread Constraints, which is alpha in K8s 1.16. This means that a feature gate must be # enabled for this feature, and Rook also still needs to add support for this feature. # Another approach for a small number of OSDs is to create a separate device set for each # zone (or other set of nodes with a common label) so that the OSDs will end up on different
なるほど。要約すると、
- いまのPod Anti-Affinityだと上手くosdをバラけさせられない。まだ努力が必要やわ。
- Pod Topology Spread Constraints(k8s 1.16 alpha)を使えばピチッとバラけさせられるけど、Rookがまだ対応してないねん。これからの子やねん。
- Node Affinityも使った組み合わせたらイケるかも。それでどないや?
ということです。そうか、この分野ではRookはまだまだこれからの子なんか。それならしゃーない。
そういうわけで、今の時点ではマニュアルで3nodeの散らばるように書く必要がありそうですね。
まとめ
今回はOSD on PVCのコンセプトの紹介をし、実際にやってみて問題に直面しました。
この悲しき現実に立ち向かう方法たるやいかに。次回バジリスク甲賀忍法帖…というノリはやめといて、次回はこの問題を回避する方法を紹介します。
BGMは甲賀忍法帖でした。(やっぱり)
Rook-CephでSSDとHDDを使い分ける
この記事はRookだらけの Advent Calendar 2019 3日目の記事です。
Rook-CephでSSDとHDDの使い分けの例を説明します。
SSDにOSDメタデータを分けて置く
Cephをご存知の方だと、『OSDのユーザーデータとメタデータ領域は分けたほうがいい』というプラクティスを知っていると思います。
メタデータはsmall I/Oがバンバン来るのでFlashデバイスの方がいいということです。そのとおりで、特にsmall I/Oに強くないHDDにとっては性能的に望ましくないです。
CephではユーザーデータはHDDへ、メタデータだけSSDやNVMeへと分けることができるので、Rook-Cephでやってみます。
3台のworkerにそれぞれ5つのデバイスをぶら下げます。
[utubo@tutsunom ceph]$ ssh xxxxxx.compute-1.amazonaws.com lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT xvda 202:0 0 128G 0 disk ├─xvda1 202:1 0 1007.5K 0 part └─xvda2 202:2 0 128G 0 part / xvdf 202:80 0 5G 0 disk ← ssd(metadata用) xvdg 202:96 0 10G 0 disk ← ssd(osd用) xvdh 202:112 0 10G 0 disk ← ssd(osd用) xvdi 202:128 0 20G 0 disk ← hdd(osd用) xvdj 202:144 0 20G 0 disk ← hdd(osd用)
何も考えずにkubectl create -f cluster.yaml
をやってしまうと、
[utubo@tutsunom ceph]$ kubectl exec -it `kubectl get pod -l app=rook-ceph-tools -o 'jsonpath={.items[].metadata.name}'` ceph osd df tree ID CLASS WEIGHT REWEIGHT SIZE RAW USE DATA OMAP META AVAIL %USE VAR PGS STATUS TYPE NAME -1 0.19061 - 195 GiB 15 GiB 15 MiB 0 B 15 GiB 180 GiB 7.70 1.00 - root default -5 0.19061 - 195 GiB 15 GiB 15 MiB 0 B 15 GiB 180 GiB 7.70 1.00 - region us-east-1 -4 0.06354 - 65 GiB 5.0 GiB 4.8 MiB 0 B 5 GiB 60 GiB 7.70 1.00 - zone us-east-1a -3 0.06354 - 65 GiB 5.0 GiB 4.8 MiB 0 B 5 GiB 60 GiB 7.70 1.00 - host ip-172-20-42-193-ec2-internal 0 ssd 0.01859 1.00000 19 GiB 1.0 GiB 992 KiB 0 B 1 GiB 18 GiB 5.27 0.68 0 up osd.0 3 ssd 0.00879 1.00000 9 GiB 1.0 GiB 992 KiB 0 B 1 GiB 8.0 GiB 11.12 1.44 0 up osd.3 6 ssd 0.00879 1.00000 9 GiB 1.0 GiB 992 KiB 0 B 1 GiB 8.0 GiB 11.12 1.44 0 up osd.6 9 ssd 0.01859 1.00000 19 GiB 1.0 GiB 992 KiB 0 B 1 GiB 18 GiB 5.27 0.68 0 up osd.9 12 ssd 0.00879 1.00000 9 GiB 1.0 GiB 992 KiB 0 B 1 GiB 8.0 GiB 11.12 1.44 0 up osd.12 -14 0.06354 - 65 GiB 5.0 GiB 4.8 MiB 0 B 5 GiB 60 GiB 7.70 1.00 - zone us-east-1b -13 0.06354 - 65 GiB 5.0 GiB 4.8 MiB 0 B 5 GiB 60 GiB 7.70 1.00 - host ip-172-20-93-28-ec2-internal 1 ssd 0.00879 1.00000 9 GiB 1.0 GiB 992 KiB 0 B 1 GiB 8.0 GiB 11.12 1.44 0 up osd.1 4 ssd 0.01859 1.00000 19 GiB 1.0 GiB 992 KiB 0 B 1 GiB 18 GiB 5.27 0.68 0 up osd.4 7 ssd 0.00879 1.00000 9 GiB 1.0 GiB 992 KiB 0 B 1 GiB 8.0 GiB 11.12 1.44 0 up osd.7 11 ssd 0.00879 1.00000 9 GiB 1.0 GiB 992 KiB 0 B 1 GiB 8.0 GiB 11.12 1.44 0 up osd.11 14 ssd 0.01859 1.00000 19 GiB 1.0 GiB 992 KiB 0 B 1 GiB 18 GiB 5.27 0.68 0 up osd.14 -10 0.06354 - 65 GiB 5.0 GiB 4.8 MiB 0 B 5 GiB 60 GiB 7.70 1.00 - zone us-east-1c -9 0.06354 - 65 GiB 5.0 GiB 4.8 MiB 0 B 5 GiB 60 GiB 7.70 1.00 - host ip-172-20-102-19-ec2-internal 2 ssd 0.01859 1.00000 19 GiB 1.0 GiB 992 KiB 0 B 1 GiB 18 GiB 5.27 0.68 0 up osd.2 5 ssd 0.00879 1.00000 9 GiB 1.0 GiB 992 KiB 0 B 1 GiB 8.0 GiB 11.12 1.44 0 up osd.5 8 ssd 0.01859 1.00000 19 GiB 1.0 GiB 992 KiB 0 B 1 GiB 18 GiB 5.27 0.68 0 up osd.8 10 ssd 0.00879 1.00000 9 GiB 1.0 GiB 992 KiB 0 B 1 GiB 8.0 GiB 11.12 1.44 0 up osd.10 13 ssd 0.00879 1.00000 9 GiB 1.0 GiB 992 KiB 0 B 1 GiB 8.0 GiB 11.12 1.44 0 up osd.13
という風に全部のデバイスがosdとなってしまいました。あー。ノードではこんな感じでLVが作られる。
[utubo@tutsunom ceph]$ ssh xxxxxx.compute-1.amazonaws.com lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT xvda 202:0 0 128G 0 disk ├─xvda1 202:1 0 1007.5K 0 part └─xvda2 202:2 0 128G 0 part / xvdf 202:80 0 10G 0 disk └─ceph--8e673497--53a0--457f--9b7a--b48ea1f6e6d8-osd--data--e7021f4d--29f2--4c49--ba75--d242b0288181 254:2 0 9G 0 lvm xvdg 202:96 0 10G 0 disk └─ceph--0698a316--b2c8--4301--b076--0ed7c854649a-osd--data--a4f8a81f--1b17--483f--8ed6--7c3c299cc394 254:4 0 9G 0 lvm xvdh 202:112 0 10G 0 disk └─ceph--77603f3c--1bf5--4a22--8e98--4e90a06863af-osd--data--91c9407d--4b7f--4975--b1ae--2a2fffd8330e 254:1 0 9G 0 lvm xvdi 202:128 0 20G 0 disk └─ceph--0d73aa24--76db--4993--a455--07de990a7032-osd--data--67b5ef67--40d4--486e--a7f4--a92a974c19a4 254:3 0 19G 0 lvm xvdj 202:144 0 20G 0 disk └─ceph--e33ac0e4--633c--4af7--8fbf--f65a125bb1a3-osd--data--e952dada--1dea--4f24--8efd--2a4884914ea1 254:0 0 19G 0 lvm
各デバイスのLVでユーザー領域とメタデータ領域が同居することになってしまってます。
メタデータ専用のデバイスを指定できればできればいいですね。cluster.yaml
ファイルのstorage
のセクションで、
storage: # cluster level storage configuration and selection useAllNodes: true useAllDevices: true topologyAware: true deviceFilter: location: config: storeType: bluestore metadataDevice: "xvdf" databaseSizeMB: "1024" # uncomment if the disks are smaller than 100 GB
みたいな感じにconfig:
以下を指定してあげましょう。
[utubo@tutsunom ceph]$ kubectl exec -it `kubectl get pod -l app=rook-ceph-tools -o 'jsonpath={.items[].metadata.name}'` ceph osd df tree ID CLASS WEIGHT REWEIGHT SIZE RAW USE DATA OMAP META AVAIL %USE VAR PGS STATUS TYPE NAME -1 0.17569 - 180 GiB 24 GiB 10 MiB 0 B 12 GiB 156 GiB 13.34 1.00 - root default -5 0.17569 - 180 GiB 24 GiB 10 MiB 0 B 12 GiB 156 GiB 13.34 1.00 - region us-east-1 -4 0.05856 - 60 GiB 8.0 GiB 3.5 MiB 0 B 4 GiB 52 GiB 13.34 1.00 - zone us-east-1a -3 0.05856 - 60 GiB 8.0 GiB 3.5 MiB 0 B 4 GiB 52 GiB 13.34 1.00 - host ip-172-20-42-193-ec2-internal 0 ssd 0.01949 1.00000 20 GiB 2.0 GiB 896 KiB 0 B 1 GiB 18 GiB 10.00 0.75 0 up osd.0 3 ssd 0.00980 1.00000 10 GiB 2.0 GiB 896 KiB 0 B 1 GiB 8.0 GiB 20.01 1.50 0 up osd.3 6 ssd 0.01949 1.00000 20 GiB 2.0 GiB 896 KiB 0 B 1 GiB 18 GiB 10.00 0.75 0 up osd.6 9 ssd 0.00980 1.00000 10 GiB 2.0 GiB 896 KiB 0 B 1 GiB 8.0 GiB 20.01 1.50 0 up osd.9 -14 0.05856 - 60 GiB 8.0 GiB 3.5 MiB 0 B 4 GiB 52 GiB 13.34 1.00 - zone us-east-1b -13 0.05856 - 60 GiB 8.0 GiB 3.5 MiB 0 B 4 GiB 52 GiB 13.34 1.00 - host ip-172-20-93-28-ec2-internal 2 ssd 0.01949 1.00000 20 GiB 2.0 GiB 896 KiB 0 B 1 GiB 18 GiB 10.00 0.75 0 up osd.2 5 ssd 0.00980 1.00000 10 GiB 2.0 GiB 896 KiB 0 B 1 GiB 8.0 GiB 20.01 1.50 0 up osd.5 8 ssd 0.01949 1.00000 20 GiB 2.0 GiB 896 KiB 0 B 1 GiB 18 GiB 10.00 0.75 0 up osd.8 11 ssd 0.00980 1.00000 10 GiB 2.0 GiB 896 KiB 0 B 1 GiB 8.0 GiB 20.01 1.50 0 up osd.11 -10 0.05856 - 60 GiB 8.0 GiB 3.5 MiB 0 B 4 GiB 52 GiB 13.34 1.00 - zone us-east-1c -9 0.05856 - 60 GiB 8.0 GiB 3.5 MiB 0 B 4 GiB 52 GiB 13.34 1.00 - host ip-172-20-102-19-ec2-internal 1 ssd 0.01949 1.00000 20 GiB 2.0 GiB 896 KiB 0 B 1 GiB 18 GiB 10.00 0.75 0 up osd.1 4 ssd 0.00980 1.00000 10 GiB 2.0 GiB 896 KiB 0 B 1 GiB 8.0 GiB 20.01 1.50 0 up osd.4 7 ssd 0.01949 1.00000 20 GiB 2.0 GiB 896 KiB 0 B 1 GiB 18 GiB 10.00 0.75 0 up osd.7 10 ssd 0.00980 1.00000 10 GiB 2.0 GiB 896 KiB 0 B 1 GiB 8.0 GiB 20.01 1.50 0 up osd.10 TOTAL 180 GiB 24 GiB 10 MiB 0 B 12 GiB 156 GiB 13.34 MIN/MAX VAR: 0.75/1.50 STDDEV: 5.27
ノードではこうなってます。希望通り/dev/xvdf
にメタデータ(dbs; rocksDB)領域のLVがまとまっています。
[utubo@tutsunom ceph]$ ssh xxxxxx.compute-1.amazonaws.com lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT xvda 202:0 0 128G 0 disk ├─xvda1 202:1 0 1007.5K 0 part └─xvda2 202:2 0 128G 0 part / xvdf 202:80 0 10G 0 disk ├─ceph--block--dbs--3d572391--5d90--4499--9777--1882fdb2d032-osd--block--db--0a9417fd--1f1e--4847--901b--abc1bc7a6f76 254:1 0 1G 0 lvm ├─ceph--block--dbs--3d572391--5d90--4499--9777--1882fdb2d032-osd--block--db--209b10e9--9712--462a--a354--e1e74321252c 254:3 0 1G 0 lvm ├─ceph--block--dbs--3d572391--5d90--4499--9777--1882fdb2d032-osd--block--db--5743ece9--2e47--4a80--bd65--85a5e8ded997 254:5 0 1G 0 lvm └─ceph--block--dbs--3d572391--5d90--4499--9777--1882fdb2d032-osd--block--db--69a7ef92--0c0f--4921--9276--754b1eb0aade 254:7 0 1G 0 lvm xvdg 202:96 0 10G 0 disk └─ceph--block--690c01e5--5df9--4f76--a0b7--5cda604029f3-osd--block--438cc4b8--acc4--4bc2--844f--4169f7d15eb4 254:6 0 9G 0 lvm xvdh 202:112 0 10G 0 disk └─ceph--block--63789610--ea4f--4c4d--b7d3--3a9cc61aab7b-osd--block--f00ca520--0ce4--4458--b2ca--8836ec16719f 254:2 0 9G 0 lvm xvdi 202:128 0 20G 0 disk └─ceph--block--2df2e114--9da7--44e6--ab0b--971511841130-osd--block--fad745f3--d7f6--4734--a0ab--081456857402 254:4 0 19G 0 lvm xvdj 202:144 0 20G 0 disk └─ceph--block--071efb65--60b2--4a97--94b4--da0a60fc2022-osd--block--fc1da0af--0c9a--4f12--b31b--6ac9438d9e1c 254:0 0 19G 0 lvm
Device Classを指定してPoolを作る
この状態で素直にPoolを作ってしまうと、SSDとHDDがごちゃまぜになったPoolになってしまって、SSDの性能がHDDに引っ張られてしまってもったいないことになります。だからSSDとHDDは分けて使いましょう。
それはそうと、SSDとHDDが混在する環境なのにCLASSのカラムが全部ssdってのはいただけません。クラウドではありがちな感じでしょうね。github見てると近いうちにデバイス毎にdeviceClassが指定できるようになるでしょう。いまのところは手で変更しときます。CRUSH mapをいじくってもいいです。
[utubo@tutsunom ceph]$ kubectl exec -it `kubectl get pod -l app=rook-ceph-tools -o 'jsonpath={.items[].metadata.name}'` ceph osd crush rm-device-class 0 1 2 6 7 8 done removing class of osd(s): 0,1,2,6,7,8 [utubo@tutsunom ceph]$ kubectl exec -it `kubectl get pod -l app=rook-ceph-tools -o 'jsonpath={.items[].metadata.name}'` ceph osd crush set-device-class hdd 0 1 2 6 7 8 set osd(s) 0,1,2,6,7,8 to class 'hdd' [utubo@tutsunom ceph]$ kubectl exec -it `kubectl get pod -l app=rook-ceph-tools -o 'jsonpath={.items[].metadata.name}'` ceph osd df tree ID CLASS WEIGHT REWEIGHT SIZE RAW USE DATA OMAP META AVAIL %USE VAR PGS STATUS TYPE NAME -1 0.17569 - 180 GiB 24 GiB 11 MiB 0 B 12 GiB 156 GiB 13.34 1.00 - root default -5 0.17569 - 180 GiB 24 GiB 11 MiB 0 B 12 GiB 156 GiB 13.34 1.00 - region us-east-1 -4 0.05856 - 60 GiB 8.0 GiB 3.8 MiB 0 B 4 GiB 52 GiB 13.34 1.00 - zone us-east-1a -3 0.05856 - 60 GiB 8.0 GiB 3.8 MiB 0 B 4 GiB 52 GiB 13.34 1.00 - host ip-172-20-42-193-ec2-internal 0 hdd 0.01949 1.00000 20 GiB 2.0 GiB 960 KiB 0 B 1 GiB 18 GiB 10.00 0.75 0 up osd.0 6 hdd 0.01949 1.00000 20 GiB 2.0 GiB 960 KiB 0 B 1 GiB 18 GiB 10.00 0.75 0 up osd.6 3 ssd 0.00980 1.00000 10 GiB 2.0 GiB 960 KiB 0 B 1 GiB 8.0 GiB 20.01 1.50 0 up osd.3 9 ssd 0.00980 1.00000 10 GiB 2.0 GiB 960 KiB 0 B 1 GiB 8.0 GiB 20.01 1.50 0 up osd.9 -14 0.05856 - 60 GiB 8.0 GiB 3.8 MiB 0 B 4 GiB 52 GiB 13.34 1.00 - zone us-east-1b -13 0.05856 - 60 GiB 8.0 GiB 3.8 MiB 0 B 4 GiB 52 GiB 13.34 1.00 - host ip-172-20-93-28-ec2-internal 2 hdd 0.01949 1.00000 20 GiB 2.0 GiB 960 KiB 0 B 1 GiB 18 GiB 10.00 0.75 0 up osd.2 8 hdd 0.01949 1.00000 20 GiB 2.0 GiB 960 KiB 0 B 1 GiB 18 GiB 10.00 0.75 0 up osd.8 5 ssd 0.00980 1.00000 10 GiB 2.0 GiB 960 KiB 0 B 1 GiB 8.0 GiB 20.01 1.50 0 up osd.5 11 ssd 0.00980 1.00000 10 GiB 2.0 GiB 960 KiB 0 B 1 GiB 8.0 GiB 20.01 1.50 0 up osd.11 -10 0.05856 - 60 GiB 8.0 GiB 3.8 MiB 0 B 4 GiB 52 GiB 13.34 1.00 - zone us-east-1c -9 0.05856 - 60 GiB 8.0 GiB 3.8 MiB 0 B 4 GiB 52 GiB 13.34 1.00 - host ip-172-20-102-19-ec2-internal 1 hdd 0.01949 1.00000 20 GiB 2.0 GiB 960 KiB 0 B 1 GiB 18 GiB 10.00 0.75 0 up osd.1 7 hdd 0.01949 1.00000 20 GiB 2.0 GiB 960 KiB 0 B 1 GiB 18 GiB 10.00 0.75 0 up osd.7 4 ssd 0.00980 1.00000 10 GiB 2.0 GiB 960 KiB 0 B 1 GiB 8.0 GiB 20.01 1.50 0 up osd.4 10 ssd 0.00980 1.00000 10 GiB 2.0 GiB 960 KiB 0 B 1 GiB 8.0 GiB 20.01 1.50 0 up osd.10 TOTAL 180 GiB 24 GiB 11 MiB 0 B 12 GiB 156 GiB 13.34 MIN/MAX VAR: 0.75/1.50 STDDEV: 5.27
それではDeviceClassを指定してPoolを作りましょう。
[utubo@tutsunom ceph]$ cat pool-ssd-hdd.yaml apiVersion: ceph.rook.io/v1 kind: CephBlockPool metadata: name: ssd-pool namespace: rook-ceph spec: failureDomain: host replicated: size: 3 deviceClass: ssd --- apiVersion: ceph.rook.io/v1 kind: CephBlockPool metadata: name: hdd-pool namespace: rook-ceph spec: failureDomain: host replicated: size: 3 deviceClass: hdd [utubo@tutsunom ceph]$ kubectl create -f pool-ssd-hdd.yaml cephblockpool.ceph.rook.io/ssd-pool created cephblockpool.ceph.rook.io/hdd-pool created [utubo@tutsunom ceph]$ kubectl exec -it `kubectl get pod -l app=rook-ceph-tools -o 'jsonpath={.items[].metadata.name}'` ceph df RAW STORAGE: CLASS SIZE AVAIL USED RAW USED %RAW USED hdd 120 GiB 108 GiB 6.0 GiB 12 GiB 10.01 ssd 60 GiB 48 GiB 6.0 GiB 12 GiB 20.01 TOTAL 180 GiB 156 GiB 12 GiB 24 GiB 13.34 POOLS: POOL ID STORED OBJECTS USED %USED MAX AVAIL ssd-pool 1 0 B 0 0 B 0 15 GiB hdd-pool 2 0 B 0 0 B 0 34 GiB [utubo@tutsunom ceph]$ kubectl exec -it `kubectl get pod -l app=rook-ceph-tools -o 'jsonpath={.items[].metadata.name}'` ceph pg ls-by-pool ssd-pool PG OBJECTS DEGRADED MISPLACED UNFOUND BYTES OMAP_BYTES* OMAP_KEYS* LOG STATE SINCE VERSION REPORTED UP ACTING SCRUB_STAMP DEEP_SCRUB_STAMP 1.0 0 0 0 0 0 0 0 0 active+clean 26m 0'0 36:14 [11,9,10]p11 [11,9,10]p11 2019-12-02 03:55:47.245350 2019-12-02 03:55:47.245350 1.1 0 0 0 0 0 0 0 0 active+clean 26m 0'0 36:14 [3,5,10]p3 [3,5,10]p3 2019-12-02 03:55:47.245350 2019-12-02 03:55:47.245350 1.2 0 0 0 0 0 0 0 0 active+clean 26m 0'0 36:14 [9,4,11]p9 [9,4,11]p9 2019-12-02 03:55:47.245350 2019-12-02 03:55:47.245350 1.3 0 0 0 0 0 0 0 0 active+clean 26m 0'0 36:14 [11,10,3]p11 [11,10,3]p11 2019-12-02 03:55:47.245350 2019-12-02 03:55:47.245350 1.4 0 0 0 0 0 0 0 0 active+clean 26m 0'0 36:14 [3,5,10]p3 [3,5,10]p3 2019-12-02 03:55:47.245350 2019-12-02 03:55:47.245350 1.5 0 0 0 0 0 0 0 0 active+clean 26m 0'0 36:14 [3,11,4]p3 [3,11,4]p3 2019-12-02 03:55:47.245350 2019-12-02 03:55:47.245350 1.6 0 0 0 0 0 0 0 0 active+clean 26m 0'0 36:14 [3,10,11]p3 [3,10,11]p3 2019-12-02 03:55:47.245350 2019-12-02 03:55:47.245350 1.7 0 0 0 0 0 0 0 0 active+clean 26m 0'0 36:14 [5,4,9]p5 [5,4,9]p5 2019-12-02 03:55:47.245350 2019-12-02 03:55:47.245350 * NOTE: Omap statistics are gathered during deep scrub and may be inaccurate soon afterwards depending on utilisation. See http://docs.ceph.com/docs/master/dev/placement-group/#omap-statistics for further details. [utubo@tutsunom ceph]$ kubectl exec -it `kubectl get pod -l app=rook-ceph-tools -o 'jsonpath={.items[].metadata.name}'` ceph pg ls-by-pool hdd-pool PG OBJECTS DEGRADED MISPLACED UNFOUND BYTES OMAP_BYTES* OMAP_KEYS* LOG STATE SINCE VERSION REPORTED UP ACTING SCRUB_STAMP DEEP_SCRUB_STAMP 2.0 0 0 0 0 0 0 0 0 active+clean 26m 0'0 36:10 [7,8,0]p7 [7,8,0]p7 2019-12-02 03:55:51.450649 2019-12-02 03:55:51.450649 2.1 0 0 0 0 0 0 0 0 active+clean 26m 0'0 36:10 [7,8,0]p7 [7,8,0]p7 2019-12-02 03:55:51.450649 2019-12-02 03:55:51.450649 2.2 0 0 0 0 0 0 0 0 active+clean 26m 0'0 36:10 [8,1,0]p8 [8,1,0]p8 2019-12-02 03:55:51.450649 2019-12-02 03:55:51.450649 2.3 0 0 0 0 0 0 0 0 active+clean 26m 0'0 36:10 [8,0,1]p8 [8,0,1]p8 2019-12-02 03:55:51.450649 2019-12-02 03:55:51.450649 2.4 0 0 0 0 0 0 0 0 active+clean 26m 0'0 36:10 [6,2,1]p6 [6,2,1]p6 2019-12-02 03:55:51.450649 2019-12-02 03:55:51.450649 2.5 0 0 0 0 0 0 0 0 active+clean 26m 0'0 36:10 [7,0,8]p7 [7,0,8]p7 2019-12-02 03:55:51.450649 2019-12-02 03:55:51.450649 2.6 0 0 0 0 0 0 0 0 active+clean 26m 0'0 36:10 [6,8,1]p6 [6,8,1]p6 2019-12-02 03:55:51.450649 2019-12-02 03:55:51.450649 2.7 0 0 0 0 0 0 0 0 active+clean 26m 0'0 36:10 [6,7,8]p6 [6,7,8]p6 2019-12-02 03:55:51.450649 2019-12-02 03:55:51.450649 * NOTE: Omap statistics are gathered during deep scrub and may be inaccurate soon afterwards depending on utilisation. See http://docs.ceph.com/docs/master/dev/placement-group/#omap-statistics for further details.
ssd-poolのPG割り当てられているのはDevice ClassがssdのOSDで、hdd-poolのそれはDevice Classがhddのものと確認できますね。
あとはStorageClassを別々に作って使い分けていくことができます。
まとめ
Cephはいろんなデバイスをクラスタにごった煮に入れて使えるので、有効な使い方ができるように多少の設計は必要ですが、最初のうちはそんなに細かく考えなくていいと思います。
まずはこれだけ留意しておきましょう。