Rancher Kubernetes Storages

2018年、Kubernetes がやっと日本でも本格化してきた感じですね。
Rancher JP では、Rancher Meetup Tokyo #15で Storage特集をしたのですが、
その時用に作成していた資料を発表しないままになっていたのでQiitaに書いておこうと思います。

# 1. Rancher のストレージとは？
* 基本的にKubernetesのストレージRancherはそのUIをしています
* PV,PVC,StorageClassが実装されています  
* Kubernetesなストレージなので、基本的にそのまま使えます
* CloudProviderRancherからKubernetesをデプロイする場合は、CloudProviderの指定が必須です

# 2. Kubernetes のストレージおさらい
今回の記事は、@hhiroshell (早川博)さんの資料をご本人に許可をいただいて使用しております。
早川さん、ありがとうございました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/ed271c10-197e-6315-5a4c-fecb52e600e3.png)

https://speakerdeck.com/hhiroshell/kubernetesbiao-zhun-falsesutoreziji-neng-woosaraisiyou

# 3. Kubernetesでストレージを利用する方法
以下の3種類
* Volumeを直接指定してContainerにマウントする
* Volumeの要件を指定して、満たすものを自動的にマウントする
* Volumeの要件を指定して、満たすストレージを動的にプロビジョニングしてマウントする

## 3-1. Volume

* コンテナにマウント可能なボリュームを定義する情報
* ストレージの実態をポイントする

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/f1dbb5cf-17db-24e0-2aaa-f56b31ecfd98.png)

## 3-2. PersistentVolume(PV)/PersistentVolumeClaim(PVC)

* PVでストレージの実態をポイントする
* PVCで必要なディスクの要件（容量／書き込み権限の有無など）を指定しておき、それをVolumeから参照する
* PVCの要件を満たすPVが自動的に選択され、使用される

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/f461c08c-8a87-9776-2880-d7a865bfbb6f.png)

## 3-3. StorageClassを使ったPVCの動的プロビジョニング

* PVCでPVの代わりにStorageClassを指定
* 上記PVCをKubernetes内に作ると、StorageClassで設定されたProvisionerがストレージをプロビジョニングし、それが利用される
* StorageClassでは、ディスク速度やサービスレベル等のパラメータを指定

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/5dc862e7-77b9-60c0-3f9d-21de3f987f35.png)

## 4. 今回作った構成
 ![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/1f37decf-0c19-65a7-8905-fca6a0fb9e93.png)
Rancher ＋ Minikube ＋ NFS の構成を作ってみました。
RancherをMinikubeに入れなかったのは、minikube環境をminikubeコマンドで作ったり消したり気軽にできるようにしておきたかったからです。NFSはUbuntu上で設定しました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/319fc51a-e6fd-b3f1-3af9-34fe36675aae.png)

## 4-1. 2つのNFSマウント方法
上の図のようにNFSサーバーをストレージとして利用する方法は2つあります。

* ①通常のNFSサーバーとしてマウントする  
   * メリット  
    ・他のコンテナー(or Pod)からも共有できる  
    ・通常のNFSサーバーの使い方  
    ・他のストレージを用意するよりも楽  
   * デメリット  
    ・セキュリティーなし  
    ・どこからでもマウント可能  

* ②Storage ClassとしてNFSサーバーをマウントする  
   * メリット  
     ・コンテナ固有のストレージとして利用可能  
     ・Namespace(or Project)間で覗かれることはない  
   * デメリット  
     ・NFSサーバーというよりもストレージクラスとしての利用

## 4-2. NFSサーバーの作り方

NFSサーバーの作り方は一般的なので今回は省略します

# 5. 通常のNFSサーバーとしてマウントする

## 5-1. NFS ボリュームマウントを作るのに必要なもの

NFSサーバーがあればOK

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/f36acd2e-6063-1524-b9ad-cdb6ad517be0.png)

## 5-2. 通常のNFSサーバーとしてマウントする
manifestファイルならこう

```yaml:pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: welcome-nfs
spec:
  containers:
  - name: welcome-nfs
    image: busybox
    args: [/bin/sh, -c, 'tail -f /mnt/ngs/hello.txt']
    volumeMounts:
      - name: nfs-example
        mountPath: "/mnt/nfs"
  volumes:
  - name: nfs-example
    nfs:
      server: 10.0.40.8
      path: "/nfs-example"

```

`Rancherでどうなるかも知りたいですよね。。`

## 5-3. RancherでのNFSマウントの仕方
ワークロードをデプロイする
![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/eafd97a9-e1f8-42c8-0636-6d3ee4052d2e.png)

## 5-4. ボリュームを追加

「ボリューム」を開いて、「ボリュームを追加▽」を押して「エフェメラルボリュームを追加」をクリックします
![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/7a959f59-24dd-699e-ae61-b462cc52eb4b.png)

## 5-5. NFS共有を選択

エフェメラルボリュームを定義で「NFS共有」を選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/084e11ac-867e-1394-f855-adbe381139b8.png)

## 5-6. NFSサーバーの設定

NFSサーバー側のパスとサーバーIPアドレスを入力してvolumesを定義
![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/d256c83c-c5da-2a5a-7504-da2bac76853a.png)

## 5-7. コンテナー側マウント設定

コンテナー内部でのマウント先を設定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/5ca57740-5817-80bc-fbc1-fd747fca59fa.png)

# 6. Storage ClassとしてNFSサーバーをマウントする

## 6-1. Storage Classを作るのに必要なもの
Rancher ＋ Minikube ＋ NFS
![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/1474c2d3-b689-eb6f-be95-a75d1eb69e93.png)

* NFS
* nfs-client-provisioner
* NFS Client ProvisionerのRBAC
* NFSのStorage Class
を用意する

## 6-2. Manifest
### 6-2-1. nfs-provisioner-deployment.yaml
nfs-provisioner-deployment.yamlは以下の通り

```yaml:nfs-provisioner-deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nfs-client-provisioner
spec:
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          image: quay.io/external_storage/nfs-client-provisioner:latest
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: minikube.stylez.co.jp/nfs
            - name: NFS_SERVER
              value: 192.168.99.1
            - name: NFS_PATH
              value: /home/t-yano/ext/nfs
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.99.1
            path: /home/t-yano/ext/nfs
```

### 6-2-2. nfs-storageclass.yaml
nfs-storageclass.yamlは以下の通り

```yaml:nfs-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-nfs
provisioner: minikube.stylez.co.jp/nfs
```

### 6-2-3. nfs-client-provisioner-rbac.yaml

nfs-client-provisioner-rbac.yamlは以下の通り

```yaml:nfs-client-provisioner-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["list", "watch", "create", "update", "patch"]
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: run-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
```

# 7. Rancherの3つのメニューレベル

これらをRancherで同じように適用すればOK
なのですが、その前にRancherが持っているメニューのレベル(設定適用範囲)が３つあります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/3e362afb-6443-5c72-d6ca-dd4153c69072.png)

それぞれのManifestをメニューレベルに応じた設定をする必要があります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/c5587ffc-a707-99ac-7afa-4d2fd5b0f671.png)

## 7-1. Rancher カタログの nfs-provisionerについて

Rancher カタログに nfs-provisioner ってのがあるよね？これ使えないの？

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/8c9d868c-2ec9-a1d3-31b8-0d53cd7bf6b3.png)

このNFSプロビジョナーは、KubernetesホストがNFSサーバーをマウントしているのが前提です
これは使えず、nfs-client-provisionerを利用する必要があります

## 7-2. NFSクライアントプロビジョナーをデプロイ

### 7-2-1. 名前とDockerイメージ

名前とイメージを設定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/5357d6a9-b9a0-80f2-4c45-9ae2528a4e86.png)

### 7-2-2. 環境変数

環境変数を設定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/9757c76b-cf28-eacb-2dd5-73e09cdbd2e8.png)

### 7-2-3. ボリューム

ボリュームを指定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/7948517b-7682-d5ef-bc17-1aad100f6b1e.png)

### 7-2-4. ラベル& アノテーション

ラベル& アノテーションを指定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/eb8e31c3-c793-454b-7ace-81bea2336092.png)

### 7-2-5. ストレージクラスの作成

ストレージクラスの作成を作成
![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/1b5c22c8-58a2-8842-1c03-b286419d634c.png)

### 7-2-6. Storage Classを作成
local-nfsでプロビジョナーを追加
![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/2f289bc0-0c35-0632-5fec-92408f7f9d16.png)

アノテーションでキーを追加
![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/ed16b5fa-e88e-96c6-9c17-22b71fe6a49d.png)

### 7-2-7. nfs-client-rbacを設定

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/06899ba8-c8a3-409f-8cc0-02f9936ef02c.png)

### 7-2-8. Rancher UIから設定

残念ながら、Rancher UIから設定できず。。
kubectl で nfs-rbac.yamlを適用します

```yaml:nfs-client-rbac.yaml
$ cat <<EOF | kubectl create -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["list", "watch", "create", "update", "patch"]
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: run-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
EOF
```

## 8. Pod をデプロイ
ここまで来てやっとPodをデプロイできます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/5b17fece-b44f-0153-9d41-625e67144c2f.png)

### 8-1. ワークロードを作成

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/8fcf7f2b-ce32-56e3-a0ff-8cb3ee397704.png)

### 8-1-1. 適当にPod名とイメージを指定

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/2b0c575a-d3b2-9c0d-3efb-15ef91cb0e3d.png)

### 8-1-2. 新しい永続ボリュームを付けてみる

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/59960187-180e-bde1-f92f-cce87895c865.png)

### 8-1-3. PVC設定(1)名前とストレージクラスを指定

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/e370a060-c821-9ce4-98bd-06b23f68eab7.png)

### 8-1-4. PVC設定(2) 容量とアクセスモードを指定

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/66897643-464b-c1ba-8c5b-4bbf51b789f8.png)

### 8-1-5. コンテナー側のマウント先を指定

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/e204a7d3-0026-ed57-8025-5203062eafdf.png)

### 8-1-6. コンテナー起動後確認

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/67e7a58e-c05c-c5dc-041f-bca9080d1900.png)

### 8-1-6. マウントされているのを確認

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/be4fecbe-e0ad-4089-ba55-f444a8461604.png)