Ceph RBD Dynamic Provisioning for OpenShift 3.9

せっかく、[Ceph のインストール](https://qiita.com/nak3/items/402ddbf01982e34de0e5)ができたので、OpenShift 3.9 から Dynamic Provisioning を使って利用してみたいと思います。

### 0. 環境情報

Kernelのバージョンも関連するので、`uname -a`も載せておきます。

OpenShift Cluster:

~~~
# oc version
oc v3.9.14
kubernetes v1.9.1+a0ce1bc657
features: Basic-Auth GSSAPI Kerberos SPNEGO

Server https://knakayam-ose39-all.example.com:8443
openshift v3.9.14
kubernetes v1.9.1+a0ce1bc657

// ceph-common パッケージをインストールした後に確認可能です。
[root@knakayam-ose39-all ~]# rbd --version
ceph version 0.94.5 (9764da52395923e0b32908d83a9f7304401fee43)

[root@knakayam-ose39-all ~]# uname -a
Linux knakayam-ose39-all 3.10.0-693.21.1.el7.x86_64 #1 SMP Fri Feb 23 18:54:16 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
~~~

Ceph Side

~~~
[root@knakayam-ceph-c1 ~]# uname -a
Linux knakayam-ceph-c1 3.10.0-862.6.3.el7.x86_64 #1 SMP Fri Jun 15 17:57:37 EDT 2018 x86_64 x86_64 x86_64 GNU/Linux
[root@knakayam-ceph-c1 ~]# rbd --version
ceph version 12.2.4-10.el7cp (03fd19535b3701f3322c68b5f424335d6fc8dd66) luminous (stable)
~~~


それでは、早速はじめていきましょう。1~3 は Ceph 上で作業します。

### 1. Ceph 上で pool の作成

~~~
ceph osd pool create kube 1024
ceph auth get-or-create client.kube mon 'allow r' osd 'allow class-read object_prefix rbd_children, allow rwx pool=kube' -o ceph.client.kube.keyring
~~~

### 2. client key の取得

出力は、後述の6.で使います。

~~~
ceph auth get-key client.admin | base64

ceph auth get-key client.kube | base64
~~~

### 3. tunables profile を HAMMER に設定。

環境情報に記載したバージョンでは、この設定が必要でした。設定していない場合、*1のようなエラーが出ます。(逆を言うとエラーが出ないなら設定の必要もありません。)

~~~
ceph osd crush tunables hammer
~~~

以降の作業は、OpenShiftのクラスタ上で実施します。

### 4. すべてのNodeにceph-commonパッケージをインストール

~~~
yum install -y ceph-common
~~~

### 5. admin secret を作成

admin secret の作成。以降、TODO: のところは手作業で変更してください。

~~~
cat <<EOF > ceph-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: ceph-secret
  namespace: default
data:
  key: <TODO: THE VALUE GET BY "ceph auth get-key client.admin | base64">
type: kubernetes.io/rbd
EOF

oc create -f ceph-secret.yaml
~~~

### 6. client 用の secret を作成

一般ユーザーが使います。後述しますが、このsecretはPVCでboundするすべてのプロジェクトに必要になります。

~~~
cat <<EOF > ceph-user-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: ceph-user-secret
  namespace: <TODO: REPLACE YOUR PROJECT NAME>
data:
  key: <TODO: THE VALUE GET BY "ceph auth get-key client.admin | base64">
type: kubernetes.io/rbd
EOF

oc create -f ceph-user-secret.yaml
~~~

### 7. StorageClassの作成

~~~
cat <<EOF > ceph-storageclass.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: dynamic
provisioner: kubernetes.io/rbd
parameters:
  monitors: <TODO: ceph monノードに変更 xx.xx.xx.xx:6789,yy.yy.yy.yy:6789みたいになるはずです。>
  adminId: admin
  adminSecretName: ceph-secret
  adminSecretNamespace: default
  pool: kube
  userSecretName: ceph-user-secret
  imageFormat: "1"
EOF

oc create -f ceph-storageclass.yaml
~~~~

**重要:** 上記で間違いやすいポイントは以下です。

1. `imageFormat: "1"` この設定は、ceph version v12.2 で必要でした.
2. `adminSecretNamespace: default` このnamespace "default" は `ceph-secret` を作成したnamespaceと一致させます。

### 8. PVC と Pod をテスト

**重要:** project内に#6で作成したsecret(ceph-user-secret)が必須になります。

~~~
cat <<EOF > ceph-pvc.yaml
apiVersion: v1
metadata:
  name: ceph-claim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
  storageClassName: dynamic
EOF

oc create -f ceph-pvc.yaml
~~~

PVCのステータスがBoundになったことを確認します。

~~~
$ oc get pvc
NAME         STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ceph-claim   Bound     pvc-b40f6f92-85c6-11e8-a320-001a4a40dc35   2Gi        RWO            dynamic        1m
~~~

Podも作ってみます。

~~~
cat <<EOF > ceph-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: ceph-pod1
spec:
  containers:
  - name: ceph-busybox
    image: busybox
    command: ["sleep", "60000"]
    volumeMounts:
    - name: ceph-vol1
      mountPath: /usr/share/busybox
      readOnly: false
  volumes:
  - name: ceph-vol1
    persistentVolumeClaim:
      claimName: ceph-claim

oc create -f ceph-pod.yaml
~~~

マウントされたことを確認します。

~~~
$ oc rsh ceph-pod1  mount | grep rbd
/dev/rbd0 on /usr/share/busybox type ext4 (rw,seclabel,relatime,stripe=1024,data=ordered)
~~~

以上が、簡単にCeph RBDを OpenShiftの Dynamic Provisioning で使う手順でした。


-----------------------

*1 NOTE: RHEL 7.4 kernel では、以下のエラーがでました。

~~~
$ oc get event -w
LAST SEEN                       FIRST SEEN                      COUNT     NAME                          KIND                    SUBOBJECT   TYPE      REASON               SOURCE                        MESSAGE
2018-07-11 23:48:32 -0400 EDT   2018-07-11 07:15:14 -0400 EDT   216       ceph-claim.15404c40d6f4b6f9   PersistentVolumeClaim               Warning   ProvisioningFailed   persistentvolume-controller   (combined from similar events): Failed to provision volume with StorageClass "dynamic": failed to create rbd image: exit status 1, command output: 2018-07-11 23:43:32.243374 7ff2f4cc17c0 -1 did not load config file, using default settings.
2018-07-11 23:43:32.349110 7ff2f4cbf700  0 -- 10.64.220.218:0/1025292 >> 10.64.222.2:6789/0 pipe(0x4191310 sd=3 :39982 s=1 pgs=0 cs=0 l=1 c=0x4195600).connect protocol feature mismatch, my 83ffffffffffff < peer 481dff8eea4fffb missing 400000000000000
  ....
2018-07-11 23:48:29.624710 7ff2e84b4700  0 -- 10.64.220.218:0/1025292 >> 10.64.222.2:6789/0 pipe(0x7ff2d40008c0 sd=3 :43214 s=1 pgs=0 cs=0 l=1 c=0x7ff2d400fad0).connect protocol feature mismatch, my 83ffffffffffff < peer 481dff8eea4fffb missing 400000000000000
2018-07-11 23:48:30.029012 7ff2e84b4700  0 -- 10.64.220.218:0/1025292 >> 10.64.222.2:6789/0 pipe(0x7ff2d40008c0 sd=3 :43220 s=1 pgs=0 cs=0 l=1 c=0x7ff2d400fad0).connect protocol feature mismatch, my 83ffffffffffff < peer 481dff8eea4fffb missing 400000000000000
2018-07-11 23:48:30.831470 7ff2e84b4700  0 -- 10.64.220.218:0/1025292 >> 10.64.222.2:6789/0 pipe(0x7ff2d40008c0 sd=3 :43232 s=1 pgs=0 cs=0 l=1 c=0x7ff2d400fad0).connect protocol feature mismatch, my 83ffffffffffff < peer 481dff8eea4fffb missing 400000000000000
2018-07-11 23:48:32.339458 7ff2f4cc17c0  0 monclient(hunting): authenticate timed out after 300
2018-07-11 23:48:32.339585 7ff2f4cc17c0  0 librados: client.admin authentication error (110) Connection timed out
rbd: couldn't connect to the cluster!
~~~