k8s+rook.ioな環境で、filesystemを使ってみた

# はじめに

rook.ioを導入してBlock Storage (StorageClass)を試してみたので、次はfilesystemを試してみることにしました。

いまのところrookで作るCephFileSystemには、名前を変えて複数作成（定義）できない制限が存在します。
そのためシステム内で共通のShared FileSystemとして利用するためには、/appのようなマウントポイントを利用し、その階層をしっかり管理する必要がありそうです。

> 【2021/02/05追記】この記事ではFlex Volumeを前提としています。現在はCSIがデフォルトですので、この記事の内容はかなり古くなっています。特に spec.volumes.flexVolume によるファイルシステムのマウントはCSI環境では利用できませんので注意してください。

## 参考資料
* https://rook.io/docs/rook/v0.8/filesystem.html
* https://kubernetes.io/docs/tasks/run-application/run-stateless-application-deployment/

# 準備

xfsを指定する場合、Ubuntuではxfsprogsパッケージを導入しておく必要があります。

    $ sudo apt install xfsprogs

また、rookの導入時に使った cluster.yaml などと同じディレクトリにあるfilesystem.yamlを利用します。

```bash
$ cd cluster/examples/kubernetes/ceph/
$ kubectl create -f filesystem.yaml
```

必須ではないですが、公式ドキュメントに合わせてレプリケーション数などを増やしています。

```diff:filesystem.yaml
--- a/cluster/examples/kubernetes/ceph/filesystem.yaml
+++ b/cluster/examples/kubernetes/ceph/filesystem.yaml
@@ -8,16 +8,16 @@ spec:
   metadataPool:
     replicated:
       # Increase the replication size if you have more than one osd
-      size: 1
+      size: 2
   # The list of data pool specs
   dataPools:
     - failureDomain: osd
       replicated:
-        size: 1
+        size: 3
       # If you have at least three osds, erasure coding can be specified
       # erasureCoded:
       #   dataChunks: 2
       #   codingChunks: 1
```

これで基本的な準備は整ったので、実際にKubernetesの公式ドキュメントにあるnginxを例に使ってみます。

# nginxのデプロイメント

とりあえず次の2つのファイルをapplyします。

```bash
$ kubectl create ns nginx
$ kubectl -n nginx apply -f nginx-deployment-filesystem.yaml 
$ kubectl -n nginx apply -f nginx-service.yaml
```

これが終ると、2つのPodが稼動しているはずです。

```bash
$ kubectl -n nginx get pods
NAME                                READY     STATUS    RESTARTS   AGE
nginx-deployment-7f6c758cd4-9drbd   1/1       Running   0          25m
nginx-deployment-7f6c758cd4-dfcc7   1/1       Running   0          25m
```

ServiceのタイプをLoadBalancerにしたり、ポートフォワードしたりするなど変更して、ブラウザで確認できるようにしています。

## YAMLファイル
```yaml:nginx-deployment-filesystem.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-data
          mountPath: /usr/share/nginx/html
      volumes:
      - name: nginx-data
        flexVolume:
          driver: ceph.rook.io/rook
          fsType: ceph
          options:
            fsName: myfs
            clusterNamespace: rook-ceph
```

```yaml:nginx-service.yaml 
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  type: NodePort
  ports:
     -  port: 80
        protocol: TCP
        targetPort: 80
  selector:
    app: nginx
```

## コンテンツの作成

空のfilesystemをマウントしたので、ブラウザは空白です。
手作業でコンテンツを作成してみます。

```bash
$ kubectl -n nginx exec -it nginx-deployment-7f6c758cd4-9drbd /bin/bash
..# cd /usr/share/nginx/html
..# cat > index.html <<EOF
> <html>
> <h1>Hello World!</h1>
> <p>Hello, Yasu!</p>
> </html>
> EOF
```

ファイルシステムが共有されているはずなので、この内容がもう片側のPodからも見えることを確認します。

```bash
$ kubectl -n nginx exec -it nginx-deployment-7f6c758cd4-dfcc7 cat /usr/share/nginx/html/index.html
<html>
<h1>Hello World!</h1>
<p>Hello, Yasu!</p>
</html>
```

# さいごに

複数のPodから共有ファイルシステムとして使えるので、フロントエンドWebサーバーのコンテンツ提供や構成ファイルの配置には便利だと思います。

一方で、サンプルのままだとセキュリティ面で実利用には少し課題がありそうです。
サブディレクトリをマウントしたり、複数のCephFileSystemを定義できない制限のため、システム管理的なインフラ目線では便利な使い方はありそうですが、アプリケーション側からみると、あまり実用的ではないかな

以上