ここは今からストレージです。

Cephの紹介

f:id:ututaq:20191125022735p:plain

この記事はRookだらけの Advent Calendar 2019 2日目の記事です。

Rookとは少し離れますが、Cephの説明をしたいと思います。

Ceph

Cephの特徴はググればたくさん出てくるので、詳しく知りたい人はググって下さい。ざっくり簡単に書きます。

RADOS

RADOSとはReliable Autonomous Distributed Object Storeの頭字語です。RADOSはCephの核となるオブジェクトストアで、Cephに書かれるデータは全てオブジェクトの形式でRADOSに格納されます。
RADOSを構成する要素として、OSDとMONとMGRがあります。

f:id:ututaq:20191201232106p:plain

OSD

OSDはObject Storage Deviceの頭字語です。ざっくり言うと、Cephクラスタの保存媒体であるデバイスを抽象化した姿です。

  • OSD = device(HDD, SDD) + ロケーションを管理するシステム + read/writeのリクエストを受ける daemon
  • ロケーションを管理するシステムは、FileStoreの場合はファイルシステム、BlueStoreの場合はrocksDB
  • 1デバイス = 1OSDの割り当てが基本。NVMeなど高性能のFlashバイスの場合は1デバイス = 複数OSDに割り当てることもある
  • クラスタ内で一意の通しIDと名前を持つ

MON

MONはMonitorです。ざっくり言うと、Cephクラスタライフセーバーみたいな役割です。平常時は正直それほど働かないのであんまり目立たないんですが、超重用な役割なんです。

  • MONはクラスタを常時監視し、“Cluster Map”というクラスタ全体の状態を把握する情報を管理する
  • 障害や拡張によるクラスタトポロジーの変化を察知し、望ましい姿への復帰(下がった冗長性の復旧など)を司る
  • クラスタに通常複数存在し、分散したMON同士で単一のクラスタ状態を共有するためにPaxosアルゴリズムによる分散合意形成を行う
  • クラスターには3つ以上の奇数(2N+1)個のMONが必要で、N個までMONがDownしても合意形成が可能
  • クライアントの認証も行う

MGR

MGRはManagerです。ざっくり言うと、矢吹丈に対する丹下段平みたいにMONと常に一緒にいてサポートします。

  • CephのGUI(Dashboard)を提供する
  • Prometheus,Zabbixなど外部の管理/監視ツールへのAPIを提供する
  • 補助的にクラスタ監視の役割

あとCephFS使う場合はMDSというものも出てきますが今は置いときます。

Pool と Placement Group(PG)

PoolとPlacement Group(PG)はRADOSの中でも重要な概念です。

Pool

f:id:ututaq:20191201235421p:plain

Poolは論理的なデータの保存領域です。CephクライアントはPoolに対してデータをRead/Writeします。
PoolはObject, Block, Fileのクライアントの利用用途によらず共通で利用することができますが、用途が変われば冗長性や性能等の要件が異なることが多いので、基本的には用途ごとにPoolは分けるのが普通です。
Poolを作成する時には"CRUSH rule"を指定します。ruleを指定しなければ、Cephのconfigファイル(ceph.conf)に記載されるデフォルトのruleが適用されます。

Replicated Pool と Erasure Coded Pool

f:id:ututaq:20191201235425p:plain

指定したCRUSH ruleに従ってPoolのPGが作成されますが、ruleの書き方によってPoolは2つのタイプに大別されます。

  • Replicated Pool

    • オブジェクトを複製して冗長化
    • 容量効率は低いがI/O性能とリカバリの早さにはEC Poolより優れる
    • 一般的によく利用される標準のタイプ
  • Erasure Coded(EC) Pool

    • Erasure Codingの仕組みで冗長化
    • I/O性能とリカバリはReplicated Poolに劣るが容量効率は高い
    • 大容量が必要なケースで利用される

BlockやFileで使う場合はReplicated Poolの方がレスポンスがいいのでよいでしょう。Objectで使う場合はEC Poolの方が容量効率が高いのでいいかもしれません。

Placement Group(PG)

f:id:ututaq:20191202005121p:plain

前述の通り、PGはPool作成時に自動的に作成される、CRUSH ruleに沿って構成されるOSDのグループです。
例えば3x Replicated Poolを作った場合、1つのPGには3つのOSDがランダムに割り当たります。Pool作成時にpg-numで指定した数だけ、このPGが作られます。
通常PGはOSDよりも多く作られ、1つのOSDは複数のPGで重複して割り当てられます。1OSDは50〜100くらいのPGに割り当たるようにPool作成時にpg-numで調節するのが一般的な構成では良いようですが、OSDの数によって変わるのでPGCalcでシミュレートするのがよいです。

Ceph PGCalc - Ceph

CephクライアントがPoolにWriteすると、データは既定のサイズのオブジェクトにストライプされ、各ストライプでCRUSHアルゴリズムによって1つのPGが選択され、そのPGが持つ複数のOSDに書き込まれます。

PGのOSDには順序が存在します。例えば、[0,1,2]と[2,1,0]は、同じOSDの割り当てながら順序が違うため異なるPGとなります。
先頭のPrimary OSDがそのPGの代表として(ストライプされた)オブジェクトのRead/Write処理を行います。Read/Write時の動作はPoolのタイプによって異なります。

f:id:ututaq:20191202005212p:plain f:id:ututaq:20191202005233p:plain

また、PGはOSDの数に対して結構多く作られるので、全く同じOSD順序のPGが2つ以上作られることが普通にあります。
ですが、これ自身は全く問題ありません。別にどちらのPGが使われてもOSDに分散されることには違いないのですから。
それだとデバイスの利用率に偏りが出るのでは?という疑問が湧いてきますが、そもそもRADOSは、

「全部の玉のutilizationをきれいに揃える必要ないよ、何百何千発にもスケールした時そんな管理してたらオーバーヘッドなだけでしょ?ゆるく揃ってればいいじゃん。目立つ偏りがあったらアラート上げるからrebalanceかけるんだよ」

というコンセプトで作られています。なのでOSDの割り当てで発生する偏りは構わないのです。
またrebalanceはSDSで一番問題になりやすい強敵ですが、rebalanceの問題は『きれいに利用率を揃えようとして必要以上にデータの移動が発生し、結果ネットワークトラフィックが重い時間が長くなること』です。Cephではゆるく揃えばそれでいいので、必要最小限のデータ移動で済むようになってます。

CRUSH rule

CRUSH ruleは早い話が、PGに割り当てるOSDの決め方のルールです。
例えばruleなく1つのPGに3つのOSDをランダムに割り当てると、同一ノード上の3つのOSDを選択する可能性があります。これだとそのノードが壊れた時データロスになります。
しかし『ノードから1個ずつOSDを選択する』というruleを書いておけば、そのようにOSDが選択されるので、3つのノードにレプリカされることになります。 CRUSH ruleを駆使することで、任意のfailure domainでデータを冗長化することができます。

まとめ

今日はCephっていうかRADOSを説明しました。RADOSはとても良くできた仕組み(特にCRUSHが)で、うつぼはCephと出会ってこの仕組みに目から鱗が落ち、Cephが大好きになりました。

みなさんもCephが大好きになってくれたらうれしいです。(小並感)

BGMは回レ!雪月花でした。

Rookの概要とRook-Ceph

f:id:ututaq:20191125022735p:plain

この記事はRookだらけの Advent Calendar 2019 1日目の記事です。

うつぼです。Advent Calendar用にRookの記事を書きます。赤帽エンジニアブログに(勝手に)連載中のストレージオーケストレーター Rookよりも、ちょっとおとなしい感じで書こうと思います。

とは言え初日はRookの概要的なことをまとめたりRook-Cephをやってみます。赤帽エンジニアブログで書いた内容と思いっきりカブりますが、これがないと2日目以降がやりにくくなると思うので…

Rookとは何か

Rookとは、Kubernetesで使うストレージオーケストレーターです。
RookによってCephやEdgeFSなどのSDSや、CockroachDBやYugabyteDBといった分散データベースを、Kubernetesクラスタ上で簡単に展開して分散ストレージクラスタを作ることができます。 Rookは対応するソフトウェアごとにOperatorが用意されます。OperatorによってDay1およびDay 2のオペレーションが(全部ではないが)自動化されることで、Kubernetesのストレージ周りの運用を楽にしてくれます。

Rookは2018年にCNCFの15番目のプロジェクトとして承認され、現在IncubatingなOSSです。日に日に開発が行われている、現在アツいストレージ関連のソフトウェアの一つと言えるでしょう。

Rookに対応するソフトウェア

Rookに対応するソフトウェアは、12/1の時点で7つです。

Name API Group Status
Ceph ceph.rook.io/v1 V1(Stable)
EdgeFS edgefs.rook.io/v1 V1(Stable)
Cassandra cassandra.rook.io/v1alpha1 Alpha
CockroachDB cockroachdb.rook.io/v1alpha1 Alpha
Minio minio.rook.io/v1alpha1 Alpha
NFS nfs.rook.io/v1alpha1 Alpha
YugabyteDB yugabytedb.rook.io/v1alpha1 Alpha

https://rook.io/docs/rook/v1.1/quickstart-toc.html

kubernetesクラスター上でストレージを展開する意義

ストレージやDBと言えば止まったら大事故に繋がるシステムなので、直感的には、コンテナで構成するのはどうなの?と感じるかもしれません。しかし大きなメリットがあるのです。

Kubernetesの神がかったリソース管理の仕組みを使える

Kubernetesクラスター上でストレージが展開されるということで、これらは全てPodで稼働します。
例えば仮にストレージソフトウェアのPodが落ちたとしても、自動で配置可能なノードにPodを再スケジュールしてストレージクラスタに再加入させて、自動修復させることができます。ストレージクラスタの拡張/縮小はkubernetes scaleをベースに行えるし、ソフトウェアアップグレードもコンテナイメージを順次新しい物に置き換えてPodを上げればいいです。データの冗長性や整合性はストレージソフトウェアの機能によって担保します。

インフラ管理者の宿命と諦めていた従来のストレージ運用作業はかなり楽になります。

Interoperabilityという名の鎖から解き放たれる

Kubernetesのバージョンさえ満たしていればどんな環境でも展開できます。オンプレだろうがクラウドだろうが関係ありません。OSやハイパーバイザーのバージョンだとかI/Oアダプターの型番だとかドライバーのバージョンだとか、従来のストレージでネックになっていた事をほとんど考慮しなくていいという実践的な嬉しさもあります。

アップグレードやストレージ更改のたびに戦ってきたInteroeprabilityとほとんど戦わなくてすみます。

Rook-Cephをやってみる

Twitterでjapan_rookとか名乗ってるわりに、うつぼはRook-Cephしか芸がありません。恥ずかしいですが、ここでもRook-Cephをやってみます。
普通にやるだけではさすがに芸がないので、Cephクラスターが展開される様子を追っかけてみましょう。

Kubernetesクラスターを用意します

master x 3, worker(kubernetes.io/role=node) x 3です。workerにはそれぞれ20GiBのデバイスを1つずつ搭載しています。このデバイスをCephで使います。

[utubo@tutsunom ceph]$ kubectl get node --sort-by=".metadata.creationTimestamp" 
NAME                             STATUS   ROLES    AGE     VERSION
ip-172-20-104-194.ec2.internal   Ready    master   4m20s   v1.15.5
ip-172-20-36-239.ec2.internal    Ready    master   4m4s    v1.15.5
ip-172-20-79-199.ec2.internal    Ready    master   3m32s   v1.15.5
ip-172-20-32-157.ec2.internal    Ready    node     103s    v1.15.5
ip-172-20-82-111.ec2.internal    Ready    node     101s    v1.15.5
ip-172-20-103-26.ec2.internal    Ready    node     99s     v1.15.5

Quickstartの手順にしたがってみます

Ceph Storage Quickstartkuberctl create3発が一番簡単にCephをデプロイする方法です。

[utubo@tutsunom ~]$ git clone -b release-1.1 https://github.com/rook/rook.git
[utubo@tutsunom ~]$ cd rook/cluster/examples/kubernetes/ceph
kubectl create -f common.yaml

最初にnamespaceを作って、CRDやRBAC, ServiceAccountなどのリソースを作ってくれます。

[utubo@tutsunom ceph]$ kubectl create -f common.yaml
namespace/rook-ceph created
customresourcedefinition.apiextensions.k8s.io/cephclusters.ceph.rook.io created
customresourcedefinition.apiextensions.k8s.io/cephfilesystems.ceph.rook.io created
customresourcedefinition.apiextensions.k8s.io/cephnfses.ceph.rook.io created
customresourcedefinition.apiextensions.k8s.io/cephobjectstores.ceph.rook.io created
customresourcedefinition.apiextensions.k8s.io/cephobjectstoreusers.ceph.rook.io created
customresourcedefinition.apiextensions.k8s.io/cephblockpools.ceph.rook.io created
customresourcedefinition.apiextensions.k8s.io/volumes.rook.io created
customresourcedefinition.apiextensions.k8s.io/objectbuckets.objectbucket.io created
customresourcedefinition.apiextensions.k8s.io/objectbucketclaims.objectbucket.io created
clusterrolebinding.rbac.authorization.k8s.io/rook-ceph-object-bucket created
clusterrole.rbac.authorization.k8s.io/rook-ceph-cluster-mgmt created
clusterrole.rbac.authorization.k8s.io/rook-ceph-cluster-mgmt-rules created
role.rbac.authorization.k8s.io/rook-ceph-system created
clusterrole.rbac.authorization.k8s.io/rook-ceph-global created
clusterrole.rbac.authorization.k8s.io/rook-ceph-global-rules created
clusterrole.rbac.authorization.k8s.io/rook-ceph-mgr-cluster created
clusterrole.rbac.authorization.k8s.io/rook-ceph-mgr-cluster-rules created
clusterrole.rbac.authorization.k8s.io/rook-ceph-object-bucket created
serviceaccount/rook-ceph-system created
rolebinding.rbac.authorization.k8s.io/rook-ceph-system created
clusterrolebinding.rbac.authorization.k8s.io/rook-ceph-global created
serviceaccount/rook-ceph-osd created
serviceaccount/rook-ceph-mgr created
serviceaccount/rook-ceph-cmd-reporter created
role.rbac.authorization.k8s.io/rook-ceph-osd created
clusterrole.rbac.authorization.k8s.io/rook-ceph-osd created
clusterrole.rbac.authorization.k8s.io/rook-ceph-mgr-system created
clusterrole.rbac.authorization.k8s.io/rook-ceph-mgr-system-rules created
role.rbac.authorization.k8s.io/rook-ceph-mgr created
role.rbac.authorization.k8s.io/rook-ceph-cmd-reporter created
rolebinding.rbac.authorization.k8s.io/rook-ceph-cluster-mgmt created
rolebinding.rbac.authorization.k8s.io/rook-ceph-osd created
rolebinding.rbac.authorization.k8s.io/rook-ceph-mgr created
rolebinding.rbac.authorization.k8s.io/rook-ceph-mgr-system created
clusterrolebinding.rbac.authorization.k8s.io/rook-ceph-mgr-cluster created
clusterrolebinding.rbac.authorization.k8s.io/rook-ceph-osd created
rolebinding.rbac.authorization.k8s.io/rook-ceph-cmd-reporter created
podsecuritypolicy.policy/rook-privileged created
clusterrole.rbac.authorization.k8s.io/psp:rook created
clusterrolebinding.rbac.authorization.k8s.io/rook-ceph-system-psp created
rolebinding.rbac.authorization.k8s.io/rook-ceph-default-psp created
rolebinding.rbac.authorization.k8s.io/rook-ceph-osd-psp created
rolebinding.rbac.authorization.k8s.io/rook-ceph-mgr-psp created
rolebinding.rbac.authorization.k8s.io/rook-ceph-cmd-reporter-psp created
serviceaccount/rook-csi-cephfs-plugin-sa created
serviceaccount/rook-csi-cephfs-provisioner-sa created
role.rbac.authorization.k8s.io/cephfs-external-provisioner-cfg created
rolebinding.rbac.authorization.k8s.io/cephfs-csi-provisioner-role-cfg created
clusterrole.rbac.authorization.k8s.io/cephfs-csi-nodeplugin created
clusterrole.rbac.authorization.k8s.io/cephfs-csi-nodeplugin-rules created
clusterrole.rbac.authorization.k8s.io/cephfs-external-provisioner-runner created
clusterrole.rbac.authorization.k8s.io/cephfs-external-provisioner-runner-rules created
clusterrolebinding.rbac.authorization.k8s.io/rook-csi-cephfs-plugin-sa-psp created
clusterrolebinding.rbac.authorization.k8s.io/rook-csi-cephfs-provisioner-sa-psp created
clusterrolebinding.rbac.authorization.k8s.io/cephfs-csi-nodeplugin created
clusterrolebinding.rbac.authorization.k8s.io/cephfs-csi-provisioner-role created
serviceaccount/rook-csi-rbd-plugin-sa created
serviceaccount/rook-csi-rbd-provisioner-sa created
role.rbac.authorization.k8s.io/rbd-external-provisioner-cfg created
rolebinding.rbac.authorization.k8s.io/rbd-csi-provisioner-role-cfg created
clusterrole.rbac.authorization.k8s.io/rbd-csi-nodeplugin created
clusterrole.rbac.authorization.k8s.io/rbd-csi-nodeplugin-rules created
clusterrole.rbac.authorization.k8s.io/rbd-external-provisioner-runner created
clusterrole.rbac.authorization.k8s.io/rbd-external-provisioner-runner-rules created
clusterrolebinding.rbac.authorization.k8s.io/rook-csi-rbd-plugin-sa-psp created
clusterrolebinding.rbac.authorization.k8s.io/rook-csi-rbd-provisioner-sa-psp created
clusterrolebinding.rbac.authorization.k8s.io/rbd-csi-nodeplugin created
clusterrolebinding.rbac.authorization.k8s.io/rbd-csi-provisioner-role created
kubectl create -f operator.yaml

rook-ceph-operatorを作ってくれます。別窓でwatch kubectl -n rook-ceph get podしていると、operatorの次にrook-discover agentが生まれるのが見えます。rook-discoverはdaemonsetなので各worker上で動きます。

[utubo@tutsunom ceph]$ kubectl create -f operator.yaml 
deployment.apps/rook-ceph-operator created

別窓

[utubo@tutsunom ceph]$ watch kubectl -n rook-ceph get pod
 
NAME                                 READY   STATUS              RESTARTS   AGE
rook-ceph-operator-fb8b96548-rxzn6   0/1     ContainerCreating   0          11s
↓
NAME                                 READY   STATUS              RESTARTS   AGE
rook-ceph-operator-fb8b96548-rxzn6   1/1     Running             0          33s
rook-discover-5qqs8                  1/1     Running             0          9s
rook-discover-8jn4w                  0/1     ContainerCreating   0          9s
rook-discover-msfjm                  0/1     ContainerCreating   0          9s
↓
NAME                                 READY   STATUS    RESTARTS   AGE
rook-ceph-operator-fb8b96548-rxzn6   1/1     Running   0          52s
rook-discover-5qqs8                  1/1     Running   0          28s
rook-discover-8jn4w                  1/1     Running   0          28s
rook-discover-msfjm                  1/1     Running   0          28s
kubectl create -f cluster.yaml

ここが見どころです。operatorによって次々とCephのコンポーネントが生成される様子は圧巻。ぜひここでも別窓でwatch kubectl -n rook-ceph get podしておいて下さい。
※出力が長くなるので生まれるPodだけ書きます。

[utubo@tutsunom ceph]$ kubectl create -f cluster.yaml 
cephcluster.ceph.rook.io/rook-ceph created

別窓

[utubo@tutsunom ceph]$ watch kubectl -n rook-ceph get pod
1. Ceph-CSIのpluginを生成
NAME                                           READY   STATUS              RESTARTS   AGE
csi-cephfsplugin-79hrg                         3/3     Running             0          8s
csi-cephfsplugin-pnrg9                         3/3     Running             0          8s
csi-cephfsplugin-provisioner-974b566d9-kk95l   4/4     Running             0          8s
csi-cephfsplugin-provisioner-974b566d9-r8p5d   0/4     ContainerCreating   0          8s
csi-cephfsplugin-zwm4m                         0/3     ContainerCreating   0          8s
csi-rbdplugin-4mhvb                            3/3     Running             0          8s
csi-rbdplugin-5gwtb                            3/3     Running             0          8s
csi-rbdplugin-j7kx9                            0/3     ContainerCreating   0          8s
csi-rbdplugin-provisioner-579c546f5-s7j7q      0/5     ContainerCreating   0          8s
csi-rbdplugin-provisioner-579c546f5-z84jx      0/5     ContainerCreating   0          8s
rook-ceph-detect-version-vfxrt                 0/1     Init:0/1            0          2s
---略---

↓

2. rook-ceph-mon-x-canary --> rook-ceph-mon-x の順でCeph MONを生成
NAME                                           READY   STATUS        RESTARTS   AGE
---略---
rook-ceph-mon-a-canary-7469b766b6-4r9wn        0/1     Terminating   0          11s
rook-ceph-mon-b-canary-795fb574cc-ldmwr        1/1     Running       0          10s
rook-ceph-mon-c-canary-9c4dbbd5b-6ff8b         1/1     Running       0          10s
---略---
↓
NAME                                           READY   STATUS     RESTARTS   AGE
---略---
rook-ceph-mon-a-9b889cd9f-dvmr2                1/1     Running    0          24s
rook-ceph-mon-b-758455b88f-cw6pz               1/1     Running    0          15s
rook-ceph-mon-c-698785577b-plhb2               0/1     Init:0/2   0          1s
---略---

↓

3. Ceph MGRを生成
NAME                                           READY   STATUS    RESTARTS   AGE
---略---
rook-ceph-mgr-a-546669c64f-pvr4d               1/1     Running   0          16s
---略---

↓

4. rook-ceph-osd-prepare --> rook-ceph-osd-x の順でCeph OSDを生成
NAME                                                        READY   STATUS            RESTARTS   AGE
---略---
rook-ceph-osd-prepare-ip-172-20-103-26.ec2.internal-hmpl5   0/1     PodInitializing   0          3s
rook-ceph-osd-prepare-ip-172-20-32-157.ec2.internal-9jsgh   0/1     PodInitializing   0          3s
rook-ceph-osd-prepare-ip-172-20-82-111.ec2.internal-6d4b9   0/1     PodInitializing   0          3s
---略---
↓
NAME                                                        READY   STATUS      RESTARTS   AGE
---略---
rook-ceph-osd-0-757bf68778-p9qx8                            1/1     Running     0          8s
rook-ceph-osd-1-6d4b48bb84-r7mdz                            1/1     Running     0          7s
rook-ceph-osd-2-5bcf8c96dc-snxx2                            1/1     Running     0          7s
rook-ceph-osd-prepare-ip-172-20-103-26.ec2.internal-hmpl5   0/1     Completed   0          39s
rook-ceph-osd-prepare-ip-172-20-32-157.ec2.internal-9jsgh   0/1     Completed   0          39s
rook-ceph-osd-prepare-ip-172-20-82-111.ec2.internal-6d4b9   0/1     Completed   0          39s
---略---

以上で終わりです。最後はこんな感じになります。

[utubo@tutsunom ceph]$ kubectl -n rook-ceph get pod
NAME                                                        READY   STATUS      RESTARTS   AGE
csi-cephfsplugin-79hrg                                      3/3     Running     0          2m11s
csi-cephfsplugin-pnrg9                                      3/3     Running     0          2m11s
csi-cephfsplugin-provisioner-974b566d9-kk95l                4/4     Running     0          2m11s
csi-cephfsplugin-provisioner-974b566d9-r8p5d                4/4     Running     0          2m11s
csi-cephfsplugin-zwm4m                                      3/3     Running     0          2m11s
csi-rbdplugin-4mhvb                                         3/3     Running     0          2m11s
csi-rbdplugin-5gwtb                                         3/3     Running     0          2m11s
csi-rbdplugin-j7kx9                                         3/3     Running     0          2m11s
csi-rbdplugin-provisioner-579c546f5-s7j7q                   5/5     Running     0          2m11s
csi-rbdplugin-provisioner-579c546f5-z84jx                   5/5     Running     0          2m11s
rook-ceph-mgr-a-546669c64f-pvr4d                            1/1     Running     0          63s
rook-ceph-mon-a-9b889cd9f-dvmr2                             1/1     Running     0          100s
rook-ceph-mon-b-758455b88f-cw6pz                            1/1     Running     0          91s
rook-ceph-mon-c-698785577b-plhb2                            1/1     Running     0          77s
rook-ceph-operator-fb8b96548-rxzn6                          1/1     Running     0          4m6s
rook-ceph-osd-0-757bf68778-p9qx8                            1/1     Running     0          8s
rook-ceph-osd-1-6d4b48bb84-r7mdz                            1/1     Running     0          7s
rook-ceph-osd-2-5bcf8c96dc-snxx2                            1/1     Running     0          7s
rook-ceph-osd-prepare-ip-172-20-103-26.ec2.internal-hmpl5   0/1     Completed   0          39s
rook-ceph-osd-prepare-ip-172-20-32-157.ec2.internal-9jsgh   0/1     Completed   0          39s
rook-ceph-osd-prepare-ip-172-20-82-111.ec2.internal-6d4b9   0/1     Completed   0          39s
rook-discover-5qqs8                                         1/1     Running     0          3m42s
rook-discover-8jn4w                                         1/1     Running     0          3m42s
rook-discover-msfjm                                         1/1     Running     0          3m42s

ちゃんとCephとして稼働してることも確認できます。

[utubo@tutsunom ceph]$ kubectl create -f toolbox.yaml 
deployment.apps/rook-ceph-tools created
[utubo@tutsunom ceph]$ kubectl exec -it `kubectl get pod -l app=rook-ceph-tools -o 'jsonpath={.items[].metadata.name}'` \
> ceph status
  cluster:
    id:     a12e3584-b4b0-4939-98ba-1a086579d233
    health: HEALTH_OK
 
  services:
    mon: 3 daemons, quorum a,b,c (age 3m)
    mgr: a(active, since 3m)
    osd: 3 osds: 3 up (since 2m), 3 in (since 2m)
 
  data:
    pools:   0 pools, 0 pgs
    objects: 0 objects, 0 B
    usage:   3.0 GiB used, 54 GiB / 57 GiB avail
    pgs:     

コマンド3発だけで、CSI pluginとMON, MGR, OSDが次々と生まれてCephクラスタができました。こんなに簡単にクラスタを作れるのは衝撃的です。
しかもAGEのカラムに注目すると、rook-ceph-operatorを作ってからわずか4分です。Rookのおかげで4分でストレージが作れます。これはもう革命だ!

まとめ

Rookは対応するSDSやDBのoperatorでストレージのオーケストレーションを行うツールです。
ストレージの構築から運用まで、強力に手助けしてくれる革命的なツールです。
後半はRookでCephクラスタを作るところを追っかけてみましたが、実際に試してみるとよりRookの威力を実感すると思います。ぜひ試してみて下さいね。