2018年9月4日火曜日

minikube + Persistent Volume でデータを永続化してみた

概要

minikube 上で Persistent Volume を試してみました
Persistent Volume はコンテナのデータを永続化するための仕組みです
Persistent Volume にはたくさんのタイプがあります
クラウドサービスのストレージを選択したりすることもできます
今回は一番簡単に構築できる nfs を使ってみます

環境

  • macOS 10.13.6
  • minikube v0.28.2
  • kubectl 1.11.2
  • Ubuntu 16.04 (nfs)
  • nfs-kernel-server 1.2.8 (nfs)

nfs サーバ構築

VirtualBox 上に 1 台 Ubuntu を構築してその上に nfs サーバを構築します
minikube に接続されているネットワーク (vboxnet1 など) を同じように接続して minikube と通信できる必要があります

  • apt -y update
  • apt -y install nfs-kernel-server
  • mkdir -p /opt/nfs
  • echo "/opt/nfs 192.168.99.0/24(rw,async,no_subtree_check,no_root_squash)" >> /etc/exports
  • exportfs -ra
  • systemctl start nfs-kernel-server

マウントできるか確認 (任意)

  • minikube ssh

ログインします

  • sudo mkdir -p /opt/nfs
  • sudo mount -t nfs 192.168.99.200:/opt/nfs /opt/nfs
  • sudo umount /opt/nfs/

Persistent Volume の作成

  • vim pv1.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
  annotations:
    volume.beta.kubernetes.io/storage-class: "slow"
spec:
  capacity:
    storage: 2Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    server: 192.168.99.200
    path: /opt/nfs

ポイントは spec -> nfs の部分です
ここで先程構築した nfs サーバの IP と export したマウントポイントを指定します
persistentVolumeReclaimPolicy: Recycle にするとコンテナが削除されたときにマウントした領域のデータを削除します
あまり領域の空きがないのでとりあえず 2GB 分だけ使います
storageClass の名前を「slow」にしておきます
あとは Persistent Volume を作成して確認しましょう

  • kubectl create -f pv1.yaml
  • kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM     STORAGECLASS   REASON    AGE
pv1       2Gi        RWO            Recycle          Available             slow                     48s

この 2GB の領域から更に pod にどれくらい割り当てるか要求します

Persistent Volume Claim の作成

  • vim pvc1.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: slow

先程作成した Persistent Volume から 1GB 使うように要求します
storageClassName: slow で先程の作成した Persistent Volume を指定します
Claim を作成して確認しましょう

  • kubectl create -f pvc1.yaml
  • kubectl get pvc
NAME      STATUS    VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc1      Bound     pv1       2Gi        RWO            slow           3s

VOLUME がちゃんと作成した Persistent Volume の名前になっていることを確認します
この Claim を pod に紐づけます

Pod の作成

分かりやすいように nginx のドキュメントルートを nfs の領域にして index.html を書き換えることで挙動を確認します

  • deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 1
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
        - name: my-nginx
          image: nginx
          ports:
            - containerPort: 80
          volumeMounts:
            - name: pvc1
              mountPath: "/usr/share/nginx/html"
      volumes:
        - name: pvc1
          persistentVolumeClaim:
            claimName: pvc1

deployment, replicaset, pod を定義します
ポイントは volumesvolumeMounts でまず volumes で Claim を指定します
そして Claim の領域を volumeMounts で Pod にマウントするように定義します
あとは普通に nginx の deployment, replicaset, pod を定義する感じです

  • kubectl create -f pod.yaml
  • kubectl get all
NAME                            READY     STATUS    RESTARTS   AGE
pod/my-nginx-67bccc7c55-r7m54   1/1       Running   0          6s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   21h

NAME                       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/my-nginx   1         1         1            1           6s

NAME                                  DESIRED   CURRENT   READY     AGE
replicaset.apps/my-nginx-67bccc7c55   1         1         1         6s

サービスを作成する

nginx にアクセスできるようにします

  • kubectl expose deployment my-nginx --type=NodePort
  • kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        21h
my-nginx     NodePort    10.101.28.191   <none>        80:32257/TCP   3m
  • curl http://$(minikube ip):32257

たぶんこれで 403 が返ってくると思います
403 が返ってくるのはまだ nfs の領域に index.html がないからです

  • kubectl exec my-nginx-67bccc7c55-r7m54 ls /usr/share/nginx/html

index.html を作成する

nfs 上に index.html を作成してみます
nfs サーバ上で直接実行しました

  • cd /opt/nfs
  • echo 'Hello nfs server!' > index.html

これで再度 curl を実行すると上記の文字列が返ってくると思います
また pod に直接ファイルがあるか確認しても良いと思います

自分が確認した感じだと nfs 側にファイルを作成してからコンテナ側に反映されるまでに 10 秒くらいラグがありました
仕組みを詳しくわかりませんがリアルタイムではなさそうです (環境依存の可能性もあるかも)

最後に

minikube で Persistent Volume を試してみました
流れとしては Persistent Volume 作成 -> Persistent Volume Claim 作成 -> Pod でマウントという感じでした

Pod の定義をするときに YAML でちゃんと Claim とコンテナでマウントする際のマウントポイントをちゃんと指定する必要があります
また PV -> PVC を作成するときにちゃんと PVC が作成した PV を使っているのか確認しましょう

あとは若干ラグがあるのが気になりました
もしかすると nfs の export 時のオプションを変更するともう少し早く同期するかもしれません

参考サイト

0 件のコメント:

コメントを投稿