Kubernetesクラスタ上でRookとLonghornを構築してIOPS測ってみた

# はじめに

開発用のKubernetesクラスタを構築する流れで、永続ストレージの検証を行います。
Kubernetesへ永続ストレージを提供するため、Rook(Ceph)とLonghornのIOPS測ってみます。

社内に余ってるオンプレリソースを用いて、安価に構築するためにクラウド系のストレージは使いません。磁気ディスクです！！

## Rookについて

2018年1月にCNCFに加わった、Kubernetes上にCephを始めとしたストレージ系のソリューションをデプロイしてくれるツールです。
Toolboxとかもありますが、現状はDashboardもCephのを利用しますし、機能的にはだいぶCephに依存している印象です。
Kubernetesと組み合わせることでCeph自体の運用コストが下げられている点が嬉しいですね。

## Longhornについて

OpenEBSをベースにしたRancherが開発するストレージプロジェクトらしい。
ストレージ形式としてはブロックストレージでRancherからカタログを使ってインストールするとさらっと動いてくれます。
至極シンプルなDashboardもついて来ますが状況が少し見えるだけなので心配な気もします。

# 環境

- H/W
  - Dell R630
  - Magnetic 10k rpm / RAID10 (6台で3Span構成) 
- Ubuntu 16.04
  - Clusterにするので3インスタンス
  - バージョンはRancherのDocを参照して選択。
- Docker 17.03.2
  - こちらもRancher基準で。
- Rancher 2.x

## 蛇足

これらをRancherOS上で動かしたRancherにて構築しようとしたら動きませんでした。理由は大凡調べられましたが、RancherOSはまだこの辺考えると難しいかもしれません。

# 事前にやること

k8sとかRancherとか、各アプリケーションのインストールはそれぞれのドキュメントをご覧下さい。
どちらもFlexvolumeを利用するので、Kubeletと各ストレージアプリケーションのPluginPathを合わせる必要があるのでそこだけ書いておきます。

## kubelet

Rancher経由ならKubernetesクラスタのオプションからYAMLを編集、services配下に以下を追記してあげると良いです。

```
services: 
  kubelet: 
    extra_args: 
      volume-plugin-dir: "/var/lib/kubelet/volumeplugins"
```

他の方々はkubeletに起動オプションとして
  `--volume-plugin-dir=/var/lib/kubelet/volumeplugins`
を追加してあげましょう。

## Rook

kubectlでoperator.yamlを流す前に、Operator用のコンテナに環境変数を設定します。

```
spec:
  template:
    spec:
      serviceAccountName: rook-ceph-system
      containers:
      - name: rook-ceph-operator
        env:
        - name: FLEXVOLUME_DIR_PATH
          value: "/var/lib/kubelet/volumeplugins"
```

あとは手順通りです。

## Longhorn

Rancherからのカタログ起動を行う際にFlexvolume plugin pathという設定項目があるので、`/var/lib/kubelet/volumeplugins` へ設定しましょう。

## そのあと

RookもLonghornも、ストレージクラスとして定義されるので、これを用いてコンテナ用の永続ボリュームを作成します。
手動で事前に生成しておいても良いですし、テスト用のUbuntuコンテナ起動時に設定してもらっても良いです。

なお、一貫して `/var/lib/kubelet/volumeplugins` というディレクトリを指定してきましたが、必要に応じて変更していただいても構いません。明示的に設定しないとそれぞれデフォルトが異なるので多分動かないです。

# IOPSの計測

前提はここまで。fioを用いて実際に付加をかけていきます。

## Ubuntuコンテナの準備

まずはUbuntuコンテナを起動しましょう。

- 利用するコンテナイメージ: ubuntu:xenial

Volumeは適当なサイズで指定しておくと、PVCが用意されます。
RookとLonghornのVolumeをそれぞれ追加しておいて下さい。

RancherだとGUIでぽちぽちですが、YAMLだとこんな感じで出るっぽいので残しておきます。

```
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: longhorn-vol1
  namespace: default
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: longhorn
  volumeName: pvc-fc90cd1b-90a8-11e8-8f13-000c29c71dcf

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: rook-vol1
  namespace: default
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: rook-ceph-block
  volumeName: pvc-10670380-907c-11e8-a03a-000c29383b10
```

Ubuntuコンテナ起動時にそれぞれマウントされるようにするYAML。

```
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: ubuntu-storages
  namespace: default
spec:
  replicas: 1
  template:
    spec:
      containers:
      - image: ubuntu:xenial
        name: ubuntu-rook
        volumeMounts:
        - mountPath: /mnt/rook-vol1
          name: rook-vol1
        - mountPath: /mnt/longhorn-vol1
          name: longhorn-vol1
      volumes:
      - name: rook-vol1
        persistentVolumeClaim:
          claimName: rook-vol1
      - name: longhorn-vol1
        persistentVolumeClaim:
          claimName: longhorn-vol1
```

さて、Ubuntuが起動したら、kubectlからbashをexecしてコンテナ内部に侵入します。
コンテナ名は正しいものを指定してあげて下さい。
```
$ kubectl get pods -n default
NAME                               READY     STATUS    RESTARTS   AGE
ubuntu-storages-545b977bcb-s7878   1/1       Running   0          4d
$ kubectl exec -it ubuntu-storages-545b977bcb-s7878 /bin/bash
root@ubuntu-storages-545b977bcb-s7878:/#
```

入り込んだらfioをインストールします。

```
apt-get -y update
apt-get -y install fio
```

使い方は他の方に譲るとして、インストールが済んだらひたすら実行していく感じですね。


# 結果

|S/W|SR|SW|RR|RW|RRW|
|:--------|----:|--:|--:|--:|--:|
|Rook    | 18412 | 7791 | 14768 | 690 | 621 |
|Longhorn| 13501 | 5283 | 1628 | 1457 | 90 |

```
SR : Sequential Read
SW : Sequential Write
RR : Random Read
RW : Random Write
RRW: Random Read&Write
```

# 考察

LonghornはRookよりちょっと遅いかなと思いきやRandomReadがボロボロでちょっと笑いました。RRWが低いのもRRに引っ張られてのことでしょうね。単純にWrite目的ならLonghornでもありかもしれません。
総合的にはRookのほうが数値が高く、安定して使えるように見えます。ただしRook自体がまだテストバージョンなのでサービス環境に入れるには不安が大きいですね。

# おわりに

今どき磁気ディスクで検証っていうのもアレですが、こういう検証ではSSD入れとけばいいや！みたいな感じにならないので結構好きだったりします。
開発環境でしばらくRook使ってみながらリリースを待ちつつ、ステージや本番環境はクラウド側かなぁ。