ストレージオーケストレーター Rook : 第2話 Rook-Ceph出撃す

f:id:ututaq:20191125022735p:plain

こんにちは、レッドハットでストレージを中心にクラウドインフラを生業にしている宇都宮です。
前回は、Kubernetes(k8s)のストレージオーケストレーターのRookを紹介しました。
今回は実際にk8sにRookを入れてCephをPersistent Volume(PV)として使ってみるとこをお見せしたいと思います。

ところで『Operator』ってご存知ですか?このブログでも弊社が誇る正義超人達がちょいちょいOperatorに言及してますが、来る7/26(水)に開催予定のOpenShift Meetup Tokyo #5はなんとこのOperator特集の回なのです!
ご存知でない方はこちらに来場していただけるとバシバシガッテン押せると思いますよ!ブログ/Tweet発信枠と大阪のサテライトは空きがあるので是非来てね!
以上番宣でした!

用意するKubernetesクラスター

Rookは2019年5月にv1.0がリリースされ晴れてメジャーデビューしたので、今回もこれを入れます。
Rook v1.0はv1.10以上のk8sが必要で、あとv1.14以上のk8s clientも必要となります。
僕はv1.14以上が必要だったのでkopsで自炊しましたがGKE,AKS,EKSでも全然オッケーです。
※ minikubeでも問題なく動きます。けれどストレージ的にはマルチノードクラスターの方が面白い実験ができるのでおすすめします。kubeadm-dindやkindを使うのも手かもしれません。

ともかく、僕はAWSで3 masters + 3 workersのクラスターです。ちなみにworkerにはそれぞれ10GBのEBSを3つずつぶら下げています。

[utubo@tutsunom ~]$ kubectl version
Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.3", ...
Server Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.1", ... 
[utubo@tutsunom ~]$ kubectl get node
NAME                            STATUS   ROLES    AGE   VERSION
ip-172-20-117-7.ec2.internal    Ready    master   25d   v1.14.1
ip-172-20-37-237.ec2.internal   Ready    node     25d   v1.14.1
ip-172-20-54-52.ec2.internal    Ready    master   25d   v1.14.1
ip-172-20-77-127.ec2.internal   Ready    node     25d   v1.14.1
ip-172-20-89-111.ec2.internal   Ready    master   25d   v1.14.1
ip-172-20-99-100.ec2.internal   Ready    node     25d   v1.14.1

これからここにRook-Ceph Operatorを入れて、3台のworker nodeでCephのストレージを作っていきます。

OperatorHubからRook-Ceph Operatorを入れよう

operatorhub.io 前回、Rook-Ceph OperatorはOperatorHubで公開されていると書きました。せっかくだから俺は赤い扉をとばかりにここから入れてみましょう。
↑のリンク先に行くと右側に"Install"ってボタンがあります。このボタンを押したらやるべきことがpop-upで表示されるので、それに従うだけでOK。

f:id:ututaq:20190717015543p:plain
pop-up画面。やることはめっちゃシンプル。

Operator Lifecycle Manager(OLM)をインストール

  
☆ OpenShift 4はデフォルトでOLMはインストールされているのでこの作業はいりませんよ ☆

OperatorHubからOperatorをインストールするには、k8sにOperator Lifecycle Manager(OLM)がインストールされている必要があります。
OLMって何という説明はここでは置いといて、とりあえずインストールします。pop-upの中の"Show Prerequisite"の中にあるコマンドをそのままコピペして打てばOK。
olmとoperatorsというnamespaceができていて、olmの中でolm-operatorが動いているはずです。

[utubo@tutsunom operatorhub]$ curl -sL https://github.com/operator-framework/operator-lifecycle-manager/releases/download/0.10.0/install.sh | bash -s 0.10.0
customresourcedefinition.apiextensions.k8s.io/clusterserviceversions.operators.coreos.com created
customresourcedefinition.apiextensions.k8s.io/installplans.operators.coreos.com created
customresourcedefinition.apiextensions.k8s.io/subscriptions.operators.coreos.com created
customresourcedefinition.apiextensions.k8s.io/catalogsources.operators.coreos.com created
customresourcedefinition.apiextensions.k8s.io/operatorgroups.operators.coreos.com created
namespace/olm created
namespace/operators created
clusterrole.rbac.authorization.k8s.io/system:controller:operator-lifecycle-manager created
serviceaccount/olm-operator-serviceaccount created
clusterrolebinding.rbac.authorization.k8s.io/olm-operator-binding-olm created
deployment.apps/olm-operator created
deployment.apps/catalog-operator created
clusterrole.rbac.authorization.k8s.io/aggregate-olm-edit created
clusterrole.rbac.authorization.k8s.io/aggregate-olm-view created
configmap/olm-operators created
catalogsource.operators.coreos.com/olm-operators created
operatorgroup.operators.coreos.com/global-operators created
operatorgroup.operators.coreos.com/olm-operators created
subscription.operators.coreos.com/packageserver created
catalogsource.operators.coreos.com/operatorhubio-catalog created
Waiting for deployment "olm-operator" rollout to finish: 0 of 1 updated replicas are available...
deployment "olm-operator" successfully rolled out
deployment "catalog-operator" successfully rolled out
Package server phase: Installing
Package server phase: Succeeded
deployment "packageserver" successfully rolled out
[utubo@tutsunom operatorhub]$
[utubo@tutsunom operatorhub]$ kubectl get namespaces
NAME              STATUS   AGE
default           Active   25d
kube-node-lease   Active   25d
kube-public       Active   25d
kube-system       Active   25d
olm               Active   3m27s
operators         Active   3m27s
[utubo@tutsunom operatorhub]$
[utubo@tutsunom operatorhub]$ kubectl get pod -n olm
NAME                                READY   STATUS    RESTARTS   AGE
catalog-operator-6c6dd66dc9-jl8jt   1/1     Running   0          5m31s
olm-operator-54bfd7d46c-hrrg7       1/1     Running   0          5m32s
olm-operators-n9svq                 1/1     Running   0          5m28s
operatorhubio-catalog-j8sw4         1/1     Running   0          5m25s
packageserver-5c8965964-59dj8       1/1     Running   0          5m19s
packageserver-5c8965964-5v26s       1/1     Running   0          5m19s

Rook-Ceph Operatorをインストール

次にRook-Ceph Operatorをインストールしましょう。さっきのpop-upに表示されたkubectl createコマンドを実行します。
my-rook-cephというnamespaceができていて、その中で色々なrook系のpodが見えると思います。
今回は、まずはRook-Cephを使ってみようという趣旨なので、各podがどんな役割かなどアーキテクチャー的な部分はひとまず置いておこうと思います。(第4話くらいにアーキの説明をしようかなと思ってます)

[utubo@tutsunom operatorhub]$ kubectl create -f https://operatorhub.io/install/rook-ceph.yaml
namespace/my-rook-ceph created
operatorgroup.operators.coreos.com/operatorgroup created
subscription.operators.coreos.com/my-rook-ceph created
[utubo@tutsunom operatorhub]$
[utubo@tutsunom operatorhub]$ kubectl get ns
NAME              STATUS   AGE
default           Active   25d
kube-node-lease   Active   25d
kube-public       Active   25d
kube-system       Active   25d
my-rook-ceph      Active   8s
olm               Active   14m
operators         Active   14m
[utubo@tutsunom operatorhub]$
[utubo@tutsunom operatorhub]$ kubectl get all -n my-rook-ceph
NAME                                      READY   STATUS    RESTARTS   AGE
pod/rook-ceph-agent-klc8s                 1/1     Running   0          5m45s
pod/rook-ceph-agent-rfp7f                 1/1     Running   0          5m45s
pod/rook-ceph-agent-sxqtv                 1/1     Running   0          5m45s
pod/rook-ceph-operator-54cbc5bf7c-5vmjp   1/1     Running   0          5m46s
pod/rook-discover-6mw4s                   1/1     Running   0          5m45s
pod/rook-discover-7tpbj                   1/1     Running   0          5m45s
pod/rook-discover-z46hf                   1/1     Running   0          5m45s

NAME                             DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
daemonset.apps/rook-ceph-agent   3         3         3       3            3           <none>          5m46s
daemonset.apps/rook-discover     3         3         3       3            3           <none>          5m46s

NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/rook-ceph-operator   1/1     1            1           5m47s

NAME                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/rook-ceph-operator-54cbc5bf7c   1         1         1       5m47s

これでRook-Ceph Operatorはインストール完了です。

Cephをデプロイしてアプリから使ってみよう

それではいよいよCephクラスターをデプロイします。大まかな流れとしては、

  1. Cephクラスターを作る
  2. Poolを作る
  3. StorageClassを作って、PVCでクレームする

です。さっそくいってみましょう。

1. Cephクラスターを作る

OperatorHubのRook-Cephのページの下の方から、"Ceph Cluster"と書かれたCRDのyamlファイルの例を見ることができます。例の中身はこんな感じです。

apiVersion: ceph.rook.io/v1
kind: CephCluster
metadata:
  name: my-rook-ceph
  namespace: my-rook-ceph
spec:
  cephVersion:
    image: 'ceph/ceph:v14.2.1-20190430'
  dataDirHostPath: /var/lib/rook
  mon:
    count: 3
  dashboard:
    enabled: true
  network:
    hostNetwork: false
  rbdMirroring:
    workers: 0
  storage:
    useAllNodes: true
    useAllDevices: true

細かい事は考えずに、全部のworkerと全部の利用可能なデバイスを使ってCephクラスターを作るぜ、と書いています。シンプルイズベスト、レスイズモア。男気溢れてステキ。
ひとまずこの内容をcreate-cluster.yamlというファイルに書いてkubectl createします。
あ!別のターミナルでwatch kubectl get all -n my-rook-cephとかやっておくと、Ceph系のPodがメキメキできていくので面白いですよ☆

[utubo@tutsunom operatorhub]$ kubectl apply -f create-cluster.yaml 
cephcluster.ceph.rook.io/rook-ceph created
...(5,6分後)
[utubo@tutsunom operatorhub]$ kubectl get pod -n my-rook-ceph
NAME                                                            READY   STATUS      RESTARTS   AGE
pod/rook-ceph-agent-klc8s                                       1/1     Running     0          35m
pod/rook-ceph-agent-rfp7f                                       1/1     Running     0          35m
pod/rook-ceph-agent-sxqtv                                       1/1     Running     0          35m
pod/rook-ceph-mgr-a-cf5968ddb-75tgm                             1/1     Running     0          9m8s
pod/rook-ceph-mon-a-6686b6bd65-pl4h6                            1/1     Running     0          9m43s
pod/rook-ceph-mon-b-6c8f9cff55-svdm8                            1/1     Running     0          9m35s
pod/rook-ceph-mon-c-67f4bb647d-dm7c7                            1/1     Running     0          9m23s
pod/rook-ceph-operator-54cbc5bf7c-5vmjp                         1/1     Running     0          35m
pod/rook-ceph-osd-0-5666c486c4-k5tq7                            1/1     Running     0          6m45s
pod/rook-ceph-osd-1-5b6477d48-lxhvq                             1/1     Running     0          6m45s
pod/rook-ceph-osd-2-b5f68db68-5wndl                             1/1     Running     0          6m48s
pod/rook-ceph-osd-3-66d7cd8fc8-khglj                            1/1     Running     0          6m45s
pod/rook-ceph-osd-4-7df5d7d4b6-krcqj                            1/1     Running     0          6m48s
pod/rook-ceph-osd-5-d554bf64f-swrll                             1/1     Running     0          6m45s
pod/rook-ceph-osd-6-58654d7bf7-5mnz4                            1/1     Running     0          6m45s
pod/rook-ceph-osd-7-75cfdc75f9-98q8s                            1/1     Running     0          6m48s
pod/rook-ceph-osd-8-7676675694-25cj7                            1/1     Running     0          6m45s
pod/rook-ceph-osd-prepare-ip-172-20-37-237.ec2.internal-lkddk   0/2     Completed   0          8m44s
pod/rook-ceph-osd-prepare-ip-172-20-77-127.ec2.internal-np5zc   0/2     Completed   1          8m44s
pod/rook-ceph-osd-prepare-ip-172-20-99-100.ec2.internal-cxt9f   0/2     Completed   0          8m44s
pod/rook-discover-6mw4s                                         1/1     Running     0          35m
pod/rook-discover-7tpbj                                         1/1     Running     0          35m
pod/rook-discover-z46hf                                         1/1     Running     0          35m

こんな感じでmon,mgr,osdと名付けられたPodがバリバリできました。
ホントにCephとして動いているのぉ??ってなわけでoperator Podでceph statusを打ってみると分かります。

[utubo@tutsunom operatorhub]$ kubectl exec -n my-rook-ceph -it rook-ceph-operator-54cbc5bf7c-5vmjp -- ceph status
  cluster:
    id:     65c058be-a8c0-42cd-9aa8-d42294a430e9
    health: HEALTH_OK
 
  services:
    mon: 3 daemons, quorum a,b,c (age 17m)
    mgr: a(active, since 16m)
    osd: 9 osds: 9 up (since 14m), 9 in (since 14m)
 
  data:
    pools:   0 pools, 0 pgs
    objects: 0 objects, 0 B
    usage:   9.0 GiB used, 72 GiB / 81 GiB avail
    pgs:     

[utubo@tutsunom operatorhub]$ kubectl exec -n my-rook-ceph -it rook-ceph-operator-54cbc5bf7c-5vmjp -- ceph osd tree
ID CLASS WEIGHT  TYPE NAME                              STATUS REWEIGHT PRI-AFF 
-1       0.07910 root default                                                   
-5       0.02637     host ip-172-20-37-237-ec2-internal                         
 0   ssd 0.00879         osd.0                              up  1.00000 1.00000 
 5   ssd 0.00879         osd.5                              up  1.00000 1.00000 
 8   ssd 0.00879         osd.8                              up  1.00000 1.00000 
-3       0.02637     host ip-172-20-77-127-ec2-internal                         
 2   ssd 0.00879         osd.2                              up  1.00000 1.00000 
 4   ssd 0.00879         osd.4                              up  1.00000 1.00000 
 7   ssd 0.00879         osd.7                              up  1.00000 1.00000 
-7       0.02637     host ip-172-20-99-100-ec2-internal                         
 1   ssd 0.00879         osd.1                              up  1.00000 1.00000 
 3   ssd 0.00879         osd.3                              up  1.00000 1.00000 
 6   ssd 0.00879         osd.6                              up  1.00000 1.00000 

ceph osd treeの出力から、3台のworkerにそれぞれぶら下げた3つのEBSがosdとして全て up で見えています。動いていますね。

2. Poolを作る

PoolというのはCeph用語で、論理的に分割されたストレージ領域のことです。Poolごとに冗長性を変えたり利用できるユーザーを限定したりできるので、用途・目的ごとにPoolを作ることが一般的でしょう。

さっきと同様にOperatorHubのページからブロックデバイス用のPoolを作るyamlファイルの例を見ることができます。例の中身はこんな感じです。

apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
  name: replicapool
  namespace: my-rook-ceph
spec:
  failureDomain: host
  replicated:
    size: 3
  annotations: null

Poolの名前はreplicapoolで、書き込みデータは全て3台のworkerをまたいで三重でコピーされて保存されます。
これをそのままcreate-blockpool.yamlに書いて、kubectl createします。さっきと同じようにceph dfを実行してみましょう。

[utubo@tutsunom operatorhub]$ kubectl create -f create-blockpool.yaml 
cephblockpool.ceph.rook.io/replicapool created
[utubo@tutsunom operatorhub]$ kubectl exec -n my-rook-ceph -it rook-ceph-operator-54cbc5bf7c-5vmjp -- ceph df
RAW STORAGE:
    CLASS     SIZE       AVAIL      USED        RAW USED     %RAW USED 
    ssd       81 GiB     72 GiB     8.0 MiB      9.0 GiB         11.12 
    TOTAL     81 GiB     72 GiB     8.0 MiB      9.0 GiB         11.12 
 
POOLS:
    POOL            ID     STORED     OBJECTS     USED     %USED     MAX AVAIL 
    replicapool      1        0 B           0      0 B         0        23 GiB 

replicapoolというPoolがありますね。

3. StorageClassを作って、PVCでクレームする

ここまできたら後はアプリから使うだけです。default namespaceでアプリを起動してPVとして動くのか見てみましょう。
まずStorageClassを作ります。

[utubo@tutsunom operatorhub]$ more sc.yaml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: rbd
provisioner: ceph.rook.io/block
parameters:
  blockPool: replicapool
  clusterNamespace: my-rook-ceph
  fstype: xfs
[utubo@tutsunom operatorhub]$ 
[utubo@tutsunom operatorhub]$ kubectl create -f sc.yaml
storageclass.storage.k8s.io/rbd created
[utubo@tutsunom operatorhub]$ kubectl get sc
NAME              PROVISIONER             AGE
default           kubernetes.io/aws-ebs   28d
gp2 (default)     kubernetes.io/aws-ebs   28d
rbd               ceph.rook.io/block      4s

fstype: xfsで指定してますが、worker nodeにxfsprogsがインストールされてないと後で失敗する(PVをattachできない)のでご注意を。妙ですねぇ、こんな当たり前の話をここで書くなんて。こんな事に引っかかるとは、ずいぶん迂闊な人のようですねぇ。

次はアプリのPodとPVCです。
別に何でもいいんですけどね、今日は初っ端に「HELLO, PV!!!!」と快哉を叫んだ後、PVに毎秒dateをひたすら出力し続けるという、近年稀に見るuselessでゴキゲンなアプリ起動します。こんな感じ。

[utubo@tutsunom operatorhub]$ more date.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: date
spec:
  replicas: 1
  selector:
    matchLabels:
      app: date
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: date
    spec:
      containers:
      - name: date
        image: busybox
        command: ["/bin/sh", "-c", "echo 'HELLO, PV!!!!' >> /mnt/date; while true; do date >> /mnt/date; sleep 1; done"]
        volumeMounts:
        - name: date-pv
          mountPath: "/mnt"
      volumes:
      - name: date-pv
        persistentVolumeClaim:
          claimName: rbd-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: rbd-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: rbd

はいそれではやってみます。

[utubo@tutsunom operatorhub]$ kubectl create -f date.yaml
deployment.apps/date created
persistentvolumeclaim/rbd-pvc created
[utubo@tutsunom operatorhub]$
[utubo@tutsunom operatorhub]$ kubectl get pod,pv,pvc
NAME                                                        READY   STATUS              RESTARTS   AGE
pod/date-6cb7ccf7dc-v89qz                                   0/1     ContainerCreating   0          3m35s

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                  STORAGECLASS   REASON   AGE
persistentvolume/pvc-896cd11f-a78e-11e9-9777-0a4a204d3aa2   1Gi        RWO            Delete           Bound    my-rook-ceph/rbd-pvc   rbd                     33s

NAME                            STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/rbd-pvc   Bound    pvc-896cd11f-a78e-11e9-9777-0a4a204d3aa2   1Gi        RWO            rbd            34s

あれ?止まってる?イベントを見る。

[utubo@tutsunom operatorhub]$ kubectl describe pod/date-6cb7ccf7dc-v89qz
Name:               date-6cb7ccf7dc-v89qz
Namespace:          default
...(中略)
Events:
  Type     Reason            Age                From                                    Message
  ----     ------            ----               ----                                    -------
  Warning  FailedScheduling  82s                default-scheduler                       persistentvolumeclaim "rbd-pvc" not found
  Warning  FailedScheduling  81s                default-scheduler                       pod has unbound immediate PersistentVolumeClaims (repeated 3 times)
  Normal   Scheduled         78s                default-scheduler                       Successfully assigned my-rook-ceph/date-pod to ip-172-20-37-237.ec2.internal
  Warning  FailedMount       14s (x8 over 78s)  kubelet, ip-172-20-37-237.ec2.internal  MountVolume.SetUp failed for volume "pvc-896cd11f-a78e-11e9-9777-0a4a204d3aa2" : mount command failed, status: Failure, reason: Rook: Mount volume failed: failed to create volume CRD pvc-896cd11f-a78e-11e9-9777-0a4a204d3aa2. the server could not find the requested resource (post volumes.rook.io)

ファー。どうも"volumes.rook.io"というCustom Resourceがないぞと言っているようです。

[utubo@tutsunom operatorhub]$ kubectl get crd
NAME                                             CREATED AT
catalogsources.operators.coreos.com              2019-07-16T05:33:49Z
cephblockpools.ceph.rook.io                      2019-07-16T05:34:56Z
cephclusters.ceph.rook.io                        2019-07-16T05:34:56Z
cephobjectstores.ceph.rook.io                    2019-07-16T05:34:56Z
cephobjectstoreusers.ceph.rook.io                2019-07-16T05:34:56Z
clusterserviceversions.operators.coreos.com      2019-07-16T05:33:48Z
installplans.operators.coreos.com                2019-07-16T05:33:48Z
operatorgroups.operators.coreos.com              2019-07-16T05:33:50Z
subscriptions.operators.coreos.com               2019-07-16T05:33:49Z

たしかに。そしたら足しましょう。

[utubo@tutsunom operatorhub]$ cat volumes-rook-crd.yaml 
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: volumes.rook.io
spec:
  group: rook.io
  names:
    kind: Volume
    listKind: VolumeList
    plural: volumes
    singular: volume
    shortNames:
    - rv
  scope: Namespaced
  version: v1alpha2
[utubo@tutsunom operatorhub]$
[utubo@tutsunom operatorhub]$ kubectl create -f volumes-rook-crd.yaml 
customresourcedefinition.apiextensions.k8s.io/volumes.rook.io created
[utubo@tutsunom operatorhub]$
[utubo@tutsunom operatorhub]$ kubectl get crd
NAME                                             CREATED AT
catalogsources.operators.coreos.com              2019-07-16T05:33:49Z
cephblockpools.ceph.rook.io                      2019-07-16T05:34:56Z
cephclusters.ceph.rook.io                        2019-07-16T05:34:56Z
cephobjectstores.ceph.rook.io                    2019-07-16T05:34:56Z
cephobjectstoreusers.ceph.rook.io                2019-07-16T05:34:56Z
clusterserviceversions.operators.coreos.com      2019-07-16T05:33:48Z
installplans.operators.coreos.com                2019-07-16T05:33:48Z
operatorgroups.operators.coreos.com              2019-07-16T05:33:50Z
subscriptions.operators.coreos.com               2019-07-16T05:33:49Z
volumes.rook.io                                  2019-07-16T05:47:46Z

これでどうよ。

[utubo@tutsunom operatorhub]$ kubectl delete -f date.yaml
deployment.apps "date" deleted
persistentvolumeclaim "rbd-pvc" deleted
[utubo@tutsunom operatorhub]$ kubectl create -f date.yaml
deployment.apps/date created
persistentvolumeclaim/rbd-pvc created
[utubo@tutsunom operatorhub]$
[utubo@tutsunom operatorhub]$ kubectl get pod,pv,pvc
NAME                        READY   STATUS    RESTARTS   AGE
pod/date-6cb7ccf7dc-bwlq8   1/1     Running   0          30s

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE
persistentvolume/pvc-d105d4b5-a7dc-11e9-a140-120aa05f7e3e   1Gi        RWO            Delete           Bound    default/rbd-pvc   rbd                     31s

NAME                            STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/rbd-pvc   Bound    pvc-d105d4b5-a7dc-11e9-a140-120aa05f7e3e   1Gi        RWO            rbd            31s

うひー、よかったよかった。
どうも現状OperatorHubからRook-Cephを入れると"volumes.rook.io"が足りなくてエラーが起こるようですね。上に書いたようなマニフェストで"volumes.rook.io"を後乗せすればいけます。
※ちなみにgithubのquickstartに沿うと、common.yamlの中でvolumes.rook.ioを定義するのでエラーは起きません。

それじゃPVの中身をのぞいてみましょう。

[utubo@tutsunom operatorhub]$ kubectl exec -it date-cf6b86596-bwlq8 -- more /mnt/date
HELLO, PV!!!!
Tue Jul 16 05:57:42 UTC 2019
Tue Jul 16 05:57:43 UTC 2019
Tue Jul 16 05:57:44 UTC 2019
Tue Jul 16 05:57:45 UTC 2019
Tue Jul 16 05:57:46 UTC 2019
...(省略)

はい、ゴキゲンですね。
じゃあ、このPod消してみましょう。ReplicaSetなんでPodを削除しても自動で復活してきてPVが付け替えられ、消える前の続きから雄叫びが聴けるはずです。

[utubo@tutsunom operatorhub]$ kubectl delete pod/date-6cb7ccf7dc-bwlq8
pod "date-6cb7ccf7dc-bwlq8" deleted
[utubo@tutsunom ceph]$ kubectl get pod
NAME                    READY   STATUS              RESTARTS   AGE
date-6cb7ccf7dc-bwlq8   1/1     Terminating         0          78s
date-6cb7ccf7dc-drcjp   0/1     ContainerCreating   0          9s
[utubo@tutsunom ceph]$ kubectl get pod
NAME                    READY   STATUS    RESTARTS   AGE
date-6cb7ccf7dc-drcjp   1/1     Running   0          69s
[utubo@tutsunom operatorhub]$ kubectl exec -it date-6cb7ccf7dc-drcjp -- more /mnt/date
HELLO, PV!!!!
Tue Jul 16 05:57:42 UTC 2019
Tue Jul 16 05:57:43 UTC 2019
Tue Jul 16 05:57:44 UTC 2019
Tue Jul 16 05:57:45 UTC 2019
...(中略)
Tue Jul 16 05:59:00 UTC 2019
Tue Jul 16 05:59:01 UTC 2019
Tue Jul 16 05:59:02 UTC 2019
Tue Jul 16 05:59:03 UTC 2019
HELLO, PV!!!!
Tue Jul 16 05:59:08 UTC 2019
Tue Jul 16 05:59:09 UTC 2019
Tue Jul 16 05:59:10 UTC 2019
Tue Jul 16 05:59:11 UTC 2019
Tue Jul 16 05:59:12 UTC 2019
...(省略)

5カウントでファイティングポーズとってます。タフですね。
最後にCeph側でブロックデバイスがちゃんと存在するのか見てみましょう。

[utubo@tutsunom operatorhub]$ kubectl -n my-rook-ceph exec -it rook-ceph-operator-54cbc5bf7c-5vmjp -- rbd ls -p replicapool
pvc-d105d4b5-a7dc-11e9-a140-120aa05f7e3e
[utubo@tutsunom operatorhub]$
[utubo@tutsunom operatorhub]$ kubectl -n my-rook-ceph exec -it rook-ceph-operator-54cbc5bf7c-5vmjp -- rbd info pvc-d105d4b5-a7dc-11e9-a140-120aa05f7e3e -p replicapool
rbd image 'pvc-d105d4b5-a7dc-11e9-a140-120aa05f7e3e':
    size 1 GiB in 256 objects
    order 22 (4 MiB objects)
    snapshot_count: 0
    id: 8524adcffa5a
    block_name_prefix: rbd_data.8524adcffa5a
    format: 2
    features: layering
    op_features: 
    flags: 
    create_timestamp: Tue Jul 16 05:57:38 2019
    access_timestamp: Tue Jul 16 05:57:38 2019
    modify_timestamp: Tue Jul 16 05:57:38 2019

はい、PVの名前と同じ1GiBのブロックデバイスがありますね。イヤァオ!

まとめ

そういうわけで今回はRook-Ceph OperatorをOperatorHubからインストールしてCephクラスターを作り、CephのブロックデバイスをRWOのPVとして使えるところをお見せしました。
次回は作ったCephクラスターをちょいちょい壊しながら、どんな動きをするのかを見ていきましょう。作ったら少しずつ壊す。それがストレージ屋のジャスティス。
あと、今回はブロックデバイスだったんでRWOでやりましたが、RWXもやりたいと思います。

というわけで、今回はここまで。

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。