#3 "Rook" Up & Running

本記事は[PostgreSQL on Kubernetes Advent Calendar 2018](https://qiita.com/advent-calendar/2018/postgresonk8s)の3日目です。
昨日は「[PostgreSQL on Kubernetesの目指すところ](https://qiita.com/tzkoba/items/cd0d1120ee5bc38cd634)」ということで、分散ストレージRookの上にPostgreSQLを稼動させ、冗長化レイヤを下げる構成を紹介しました。
本日はこのPostgreSQL on Rookの基礎部分となるRookの導入方法をガイドしていきます。

#TL;DR
+ RookはKubernetes上に分散ストレージ：Cephを構築して管理するオペレータ。
+ ストレージサーバとしてノードを3台準備して、Rookの構築をやってみよう。


#Rookの紹介
昨日書いたように、[Rook](https://rook.io/)はKubernetes上に分散ストレージを構築するOSSです。
更に具体的にいえば、OpenStackなどでも利用される分散ストレージである[Ceph](https://ceph.com/)をKubernetes上に展開して管理する**オペレータ**になります。

つまり、データを管理する分散ストレージの実態はRookではなくCephです。
アーキテクチャは公式サイトによれば下図のようになっています。

![Rook](https://rook.io/docs/rook/v0.8/media/kubernetes.png)

Rookとしてデプロイされるポッドは、
- Operator
- Discover ※図中にはありませんが
- Agent
であり、Cephをお使いの方ならば良くご存知であろうポッドとして、
- Mgr
- Mon
- OSD
- MDS
がデプロイされています。

今回はデータベースからブロックデバイスとして利用しますので、OSDは使いますがMDS（ファイルストレージ）は使いません。

# 今回のRookの構成
昨日示した構成図の通り、Rook/Cephが稼動するストレージサーバは3ノードで構成しています。（DBサーバは2台構成）
それぞれ1本ずつディスク(今回はEBS)がアタッチされており、Ceph側でレプリカ数を3とすることで各ノードにデータが冗長化されて配置されることを意図しています。

![pg-rook-archi.PNG](https://qiita-image-store.s3.amazonaws.com/0/54853/512c256d-d2e5-a536-6d3b-7016ae7a2687.png)

### 前提となる環境
以下を含むKubernetesクラスタが必要です。kubectlも使える必要があります。

+ 2台のDBサーバ。Kubernetes上でラベルとして、type=node.db.postgres が付いていること
+ 3台のストレージサーバ。Kubernetes上でラベルとして、type=node.st.rook が付いていること
+ 1台のツール用サーバ。Kubernetes上でラベルとして、type=node.mon.bench が付いていること

私の環境ではストレージサーバに40G以上のディスクを割り当てています。

# Up & Running
では、Rook環境の構築をしてみましょう。

まず、リポジトリからgit cloneで必要なファイルを取得して下さい。
そして、Rookのインストール用のディレクトリに移動します。

```
$ git clone https://github.com/tzkoba/postgres-on-k8s.git
$ cd ./postgres-on-k8s/rook-install/
```

最初にRookのオペレータをデプロイします。

```
$ kubectl apply -f rook-operator.yaml
```

デプロイ状況を確認してみましょう。

```
$ kubectl get all -n rook-ceph-system
NAME                                   READY     STATUS    RESTARTS   AGE
pod/rook-ceph-agent-2l9cp              1/1       Running   0          4s
pod/rook-ceph-agent-75cxk              1/1       Running   0          4s
pod/rook-ceph-agent-87wrz              1/1       Running   0          4s
pod/rook-ceph-agent-dfb8s              1/1       Running   0          4s
pod/rook-ceph-agent-htmlg              1/1       Running   0          4s
pod/rook-ceph-operator-5d6cc97-ckgb8   1/1       Running   0          23s
pod/rook-discover-5pz5j                1/1       Running   0          4s
pod/rook-discover-8hl2m                1/1       Running   0          4s
pod/rook-discover-9z6wh                1/1       Running   0          4s
pod/rook-discover-f4qj5                1/1       Running   0          4s
pod/rook-discover-mgdst                1/1       Running   0          4s

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

NAME                                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/rook-ceph-operator   1         1         1            1           23s

NAME                                         DESIRED   CURRENT   READY     AGE
replicaset.apps/rook-ceph-operator-5d6cc97   1         1         1         23s
```

rook-ceph-systemというNamespace内にoperatorのデプロイメントとagent、discoverのデーモンセットが構築されました。
また、[オペレータのyamlファイル](https://github.com/tzkoba/postgres-on-k8s/blob/master/rook-install/rook-operator.yaml)を見ると分かりますが、この時点でCustom ResourceとしてClusterが作成されています。
ここまででオペレータの準備が完了です。

次にRookのクラスタを構築します。

```
$ kubectl apply -f rook-cluster.yaml
```

こちらはしばらく時間がかかりますが、同じように状況を確認してみます。

```
$ kubectl get pod -n rook-ceph
NAME                                           READY     STATUS        RESTARTS   AGE
rook-ceph-mgr-a-988657f6b-f8smn                1/1       Running       0          57s
rook-ceph-mon-a-78f57c7b9d-q4mc7               1/1       Running       0          1m
rook-ceph-mon-b-7b5dd49dc-vbmfh                1/1       Running       0          1m
rook-ceph-mon-c-6c44488c57-swjc5               1/1       Running       0          1m
rook-ceph-osd-0-664d99c74c-gnphh               1/1       Running       0          40s
rook-ceph-osd-1-5cbcc686bd-sp2sc               0/1       Running       0          40s
rook-ceph-osd-2-668f468f96-tshgf               1/1       Running       0          40s
rook-ceph-osd-prepare-ip-172-31-12-36-dwl9j    0/2       Completed     0          8s
rook-ceph-osd-prepare-ip-172-31-14-253-jpsv9   0/2       Completed     0          6s
rook-ceph-osd-prepare-ip-172-31-5-238-46qrj    0/2       Completed     0          4s
```

rook-cephというネームスペース内にmgrが一つ、monが3つ、osdが3つ構築されています。

最後に明日以降にPostgreSQLからブロックデバイスをマウントする際に必要なStorageClassを作成しておきましょう。

```
$ kubectl apply -f storageclass.yaml
```

上記の手順でRook・Cephの環境が構築できました。
なお、上記は2018年11月時点のRookリポジトリで試していますが、Rookバージョンやイメージのバージョン等により正常に稼動しないケースもありましたので、上手くいかない場合は最新の公式ドキュメントを参照下さい。

### toolboxコンテナの導入
Cephのコマンドを発行するためにtoolbaokのポッドも導入しておきましょう。

```
$ kubectl apply -f toolbox.yaml
```

このtoolboxのポッドからはCephやRBDの各種コマンドが発行できます。

```
$ kubectl exec -it -n rook-ceph rook-ceph-tools-57f88967f4-kvvkl ceph status
  cluster:
    id:     4d1dd83e-1735-4241-9c2b-ba91e3e36bd5
    health: HEALTH_WARN

  services:
    mon: 3 daemons, quorum b,c,a
    mgr: a(active)
    osd: 3 osds: 3 up, 3 in

  data:
    pools:   1 pools, 100 pgs
    objects: 2  objects, 19 B
    usage:   103 GiB used, 37 GiB / 140 GiB avail
    pgs:     100 active+clean

  io:
    client:   1.7 KiB/s rd, 0 B/s wr, 2 op/s rd, 31 op/s wr

$ kubectl exec -it -n rook-ceph rook-ceph-tools-57f88967f4-kvvkl ceph df
GLOBAL:
    SIZE        AVAIL      RAW USED     %RAW USED
    140 GiB     40 GiB      100 GiB         71.59
POOLS:
    NAME            ID     USED     %USED     MAX AVAIL     OBJECTS
    replicapool     1      19 B         0       7.9 GiB           2

```

こちらでもmonとosdが3つずつ配置され、プールが1つ出来ていることも分かります。
ceph dfコマンドでは現在のサイズ、プールの利用量も確認できました。


### Rookクリーンアップ時の注意点
環境をクリーンアップしたい際などは、下記のdeleteを行うことで初期化が可能です。

```
$ kubectl delete -f rook-cluster.yaml
$ kubectl delete -f rook-operator.yaml
$ kubectl delete -f storageclass.yaml
$ kubectl delete -f toolbox.yaml
```

但し、上記では完全なクリーンアップになりません。
公式ドキュメントにもあるように、ストレージサーバ側で/var/lib/rookのディレクトリ内を削除する必要があります。
上記ディレクトリに前回構築時のファイル等が残っている場合、次回のインストール時にエラーを吐きますので気を付けましょう。

#まとめ
本日は少し長めの投稿となりましたが、Rookの導入方法をガイドしました。
明日からはこのRookの上にPostgreSQLの環境を構築して動作を確認していきたいと思います。

# 注釈（12/7）
本日、Rookクラスタの再構築をしていて気付きましたが、12月には言ってからかなりの変更があったようで、tzkobaのリポジトリにあるYAMLではクラスタが構築できません。
[ヒストリはこのようになっています。](https://github.com/rook/rook/commits/master/cluster/examples/kubernetes/ceph/cluster.yaml)

後ほど当記事も更新します。
根本的な解決策はイメージも含めて、別の箇所に格納しないといけないですね。