LoginSignup
2
1

More than 1 year has passed since last update.

シングルノードKubernetesクラスタでPVとPVCを触ってみる

Last updated at Posted at 2023-05-10

こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。

前回、docker上でvolumeの作成やそれをコンテナにマウントする方法を学び、実際に試してみました。
以下がその内容です。

今回はKubernetes上で上記と同じようなことをやっていきたいと思います。
KubernetesはマルチノードでPod(コンテナ)をデプロイしたり管理できたりするのが長所であると思いますが、いきなりマルチノードでやると頭が混乱しかねないので、いったんシングルノードのk8sクラスタでやってみて、後日マルチノードのk8sクラスタ環境で触っていければと思っています。

環境

ubuntu22.04でVMを起動。
microk8sをインストールしてKubernetes環境を作っています。

root@ansible-tower:~# kubectl get node -o wide
NAME            STATUS   ROLES    AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
ansible-tower   Ready    <none>   23h   v1.26.4   192.168.2.35   <none>        Ubuntu 22.04.2 LTS   5.15.0-71-generic   containerd://1.6.15

用語

PV

PersistentVolume (PV)はストレージクラスを使って管理者もしくは動的にプロビジョニングされるクラスターのストレージの一部です。これはNodeと同じようにクラスターリソースの一部です。PVはVolumeのようなボリュームプラグインですが、PVを使う個別のPodとは独立したライフサイクルを持っています。

PVC

PersistentVolumeClaim (PVC)はユーザーによって要求されるストレージです。これはPodと似ています。PodはNodeリソースを消費し、PVCはPVリソースを消費します。Podは特定レベルのCPUとメモリーリソースを要求することができます。クレームは特定のサイズやアクセスモード(例えば、ReadWriteOnce、ReadOnlyMany、ReadWriteManyにマウントできます。

私のイメージですが、PVで大きくストレージを作って、それをPVCで論理的に切って使うことができるようです。
イメージとしては以下となるでしょうか?

名称未設定ファイル-ページ11 drawio

検証:spec.persistentVolumeReclaimPolicyを"Delete"でPVやPVCをデプロイして使ってみる

まずはPVを用意しいていきます。
今回用意したyamlファイルは以下となります。

my-vol.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-vol
spec:
  capacity:
    storage: 5Gi
  accessModes:
  - ReadWriteOnce 
  persistentVolumeReclaimPolicy: Delete
  storageClassName: my-vol-class
  hostPath:
    path: /tmp/k8s-vol
    type: DirectoryOrCreate

yamlファイルに書いていることの詳細をざっくり書きます。

コンテンツ 意味
spec.accessModes:ReadWriteOnce 1つのNodeからR/Wでマウントすることができる。このほかにReadOnlyManyやReadWriteManyがある
参考:Kubernetes: ReadWriteOnceとReadWriteOncePodの動作検証
spec:persistentVolumeReclaimPolicy:Delete PVCが削除されるとPVも削除するような挙動にする。このほかにRetainなどもある。
参考:Kubernetes: ReadWriteOnceとReadWriteOncePodの動作検証
spec.hostpath.path:/tmp/k8s-vol 作成するPVをノードのどのディレクトリに作成するかを指定している。今回のyamlでは/tmp/k8s-vol配下に作ることになる。
spec.hostpath.type:DirectoryOrCreate spec.hostpath.pathで指定したディレクトリが存在しない場合作成する
参考:KubernetesでHostPathを使う

デプロイしていきます。
作成できていそうですね。

root@ansible-tower:~/yaml# kubectl create -f my-vol.yaml
persistentvolume/my-vol created

root@ansible-tower:~/yaml# kubectl get pv -o wide
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE   VOLUMEMODE
my-vol   5Gi        RWO            Delete           Available           my-vol-class            6s    Filesystem

PVや後述するPVCに対して、podなどと同様にdescribeをすることができます。
以下がその結果になります。yamlに書いていることがこちらでも確認できますね。

root@ansible-tower:~/yaml# kubectl describe pv my-vol
Name:            my-vol
Labels:          <none>
Annotations:     <none>
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    my-vol-class
Status:          Available
Claim:
Reclaim Policy:  Delete
Access Modes:    RWO
VolumeMode:      Filesystem
Capacity:        5Gi
Node Affinity:   <none>
Message:
Source:
    Type:          HostPath (bare host directory volume)
    Path:          /tmp/k8s-vol
    HostPathType:  DirectoryOrCreate
Events:            <none>

このタイミングではノードの/tmp配下には作成されていません。

root@ansible-tower:~/yaml# ls /tmp/
snap-private-tmp                                                                systemd-private-e9093ba59c54473c8be00fd9efae24cd-systemd-resolved.service-8TljcD   ubuntu-advantage
systemd-private-e9093ba59c54473c8be00fd9efae24cd-ModemManager.service-YQKnnw    systemd-private-e9093ba59c54473c8be00fd9efae24cd-systemd-timesyncd.service-NfUEnV
systemd-private-e9093ba59c54473c8be00fd9efae24cd-systemd-logind.service-VAqu3p  systemd-private-e9093ba59c54473c8be00fd9efae24cd-upower.service-oEMHBO

PVCを作成していきます。
今回用意したyamlファイルは以下

pvc01-my-vol.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc01-my-vol
spec:
  resources:
    requests:
      storage: 5Gi 
  accessModes:
  - ReadWriteOnce
  storageClassName: my-vol-class

yamlをもとにデプロイします。
PVCのStatusがBoundになっていればPVとPVCがうまく紐づいていることとなります。

root@ansible-tower:~/yaml# kubectl create -f pvc01-my-vol.yaml
persistentvolumeclaim/pvc01-my-vol created

root@ansible-tower:~/yaml# kubectl get pv,pvc -o wide
NAME                      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                  STORAGECLASS   REASON   AGE   VOLUMEMODE
persistentvolume/my-vol   5Gi        RWO            Delete           Bound    default/pvc01-my-vol   my-vol-class            13s   Filesystem

NAME                                 STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE   VOLUMEMODE
persistentvolumeclaim/pvc01-my-vol   Bound    my-vol   5Gi        RWO            my-vol-class   46s   Filesystem

PVCもdescribeで詳細を確認してみます。

root@ansible-tower:~/yaml# kubectl describe pvc pvc01-my-vol
Name:          pvc01-my-vol
Namespace:     default
StorageClass:  my-vol-class
Status:        Bound
Volume:        my-vol
Labels:        <none>
Annotations:   pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      5Gi
Access Modes:  RWO
VolumeMode:    Filesystem
Used By:       <none>

かなりざっくりですがイメージです。my-volという名前のPVの中にpvc01-my-volという名前のPVCが存在しています。
名称未設定ファイル-ページ9 drawio

PostgreSQLのpodを作成し、/var/lib/postgresql/dataにPVCをマウントしていきます。
yamlは以下を用意

vol-postgresql01.yaml
apiVersion: v1
kind: Pod
metadata:
  name: postgres01
spec:
  containers:
  - name: postgres01
    image: postgres:latest
    env:
    - name: POSTGRES_PASSWORD
      value: "postgres"
    volumeMounts:
    - mountPath: /var/lib/postgresql/data
      name: pvc01-my-vol
  volumes:
  - name: pvc01-my-vol
    persistentVolumeClaim:
      claimName: pvc01-my-vol

podをデプロイします。

root@ansible-tower:~/yaml# kubectl create -f vol-postgresql01.yaml
pod/postgres01 created

root@ansible-tower:~/yaml# kubectl get pod -o wide
NAME         READY   STATUS    RESTARTS   AGE    IP           NODE            NOMINATED NODE   READINESS GATES
postgres01   1/1     Running   0          108s   10.1.108.9   ansible-tower   <none>           <none>

podの詳細を確認してみますが、以下の出力からマウントできていそうです。

root@ansible-tower:~/yaml# kubectl describe pod postgres01
~中略~
Volumes:
  pvc01-my-vol:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  pvc01-my-vol
    ReadOnly:   false

このタイミングで/tmp/k8s-volが作成されます。
実際に確認したログが以下となります。/tmp配下に指定したk8s-volという名前のディレクトリが自動で作成され、その配下にはPostgreSQLのデータが確認できます。

root@ansible-tower:/# cd /tmp
root@ansible-tower:/tmp# ls
k8s-vol           systemd-private-7b30335e5c3847888ee14c9d4ae96fea-ModemManager.service-9JtOcV    systemd-private-7b30335e5c3847888ee14c9d4ae96fea-systemd-resolved.service-y1Y1GA
snap-private-tmp  systemd-private-7b30335e5c3847888ee14c9d4ae96fea-systemd-logind.service-f83oWV  systemd-private-7b30335e5c3847888ee14c9d4ae96fea-systemd-timesyncd.service-Mr4GTU
root@ansible-tower:/tmp/k8s-vol# ls
base    pg_commit_ts  pg_hba.conf    pg_logical    pg_notify    pg_serial     pg_stat      pg_subtrans  pg_twophase  pg_wal   postgresql.auto.conf  postmaster.opts
global  pg_dynshmem   pg_ident.conf  pg_multixact  pg_replslot  pg_snapshots  pg_stat_tmp  pg_tblspc    PG_VERSION   pg_xact  postgresql.conf       postmaster.pid

デプロイしたpodでも確認してみます。
/tmp/k8s-vol/と内容は同じですね。

root@ansible-tower:~# kubectl get pod
NAME         READY   STATUS    RESTARTS   AGE
postgres01   1/1     Running   0          7h13m
root@ansible-tower:~# kubectl exec -it postgres01 -- /bin/bash
root@postgres01:/# cd /var/lib/postgresql/data
root@postgres01:/var/lib/postgresql/data# ls
base    pg_commit_ts  pg_hba.conf    pg_logical    pg_notify    pg_serial     pg_stat      pg_subtrans  pg_twophase  pg_wal   postgresql.auto.conf  postmaster.opts
global  pg_dynshmem   pg_ident.conf  pg_multixact  pg_replslot  pg_snapshots  pg_stat_tmp  pg_tblspc    PG_VERSION   pg_xact  postgresql.conf       postmaster.pid

pod側からデータを作成し、ノード側でも確認できるか確かめます。
podでtext.txtという空ファイルを作成

root@postgres01:/var/lib/postgresql/data# touch test.txt
root@postgres01:/var/lib/postgresql/data# ls -ltr test.txt
-rw-r--r-- 1 root root 0 May 10 21:15 test.txt

ノード側で確認します。問題なさそうですね。

root@ansible-tower:~# cd /tmp/k8s-vol/
root@ansible-tower:/tmp/k8s-vol# ls -ltr test.txt
-rw-r--r-- 1 root root 0 May 10 21:15 test.txt

イメージに起こすと以下のようになるでしょう。
赤点線で繋がっているのがイコールだと思っていったんは問題ないかと。。。
名称未設定ファイル-ページ10 drawio (1)

再利用できることを確認します。
まずPVCをマウントしているpodを削除します。

root@ansible-tower:~# kubectl delete pod postgres01

root@ansible-tower:~# kubectl get pod,pv,pvc -o wide
NAME                      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                  STORAGECLASS   REASON   AGE     VOLUMEMODE
persistentvolume/my-vol   5Gi        RWO            Delete           Bound    default/pvc01-my-vol   my-vol-class            7h31m   Filesystem

NAME                                 STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE     VOLUMEMODE
persistentvolumeclaim/pvc01-my-vol   Bound    my-vol   5Gi        RWO            my-vol-class   7h31m   Filesystem

root@ansible-tower:~# ls /tmp/k8s-vol/
base    pg_commit_ts  pg_hba.conf    pg_logical    pg_notify    pg_serial     pg_stat      pg_subtrans  pg_twophase  pg_wal   postgresql.auto.conf  postmaster.opts  test.txt
global  pg_dynshmem   pg_ident.conf  pg_multixact  pg_replslot  pg_snapshots  pg_stat_tmp  pg_tblspc    PG_VERSION   pg_xact  postgresql.conf       postmaster.pid

同じymalを使って再度podをデプロイ

root@ansible-tower:~/yaml# kubectl get pod,pv,pvc -o wide
NAME             READY   STATUS    RESTARTS   AGE   IP            NODE            NOMINATED NODE   READINESS GATES
pod/postgres01   1/1     Running   0          21s   10.1.108.10   ansible-tower   <none>           <none>

NAME                      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                  STORAGECLASS   REASON   AGE     VOLUMEMODE
persistentvolume/my-vol   5Gi        RWO            Delete           Bound    default/pvc01-my-vol   my-vol-class            7h33m   Filesystem

NAME                                 STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE     VOLUMEMODE
persistentvolumeclaim/pvc01-my-vol   Bound    my-vol   5Gi        RWO            my-vol-class   7h33m   Filesystem

再デプロイしたpodの/var/lib/postgresql/data配下を確認し、text.txtがあることを確認します。
下記ログから再利用できることがわかりました。

root@ansible-tower:~/yaml# kubectl exec -it postgres01 -- /bin/bash
root@postgres01:/# cd /var/lib/postgresql/data/
root@postgres01:/var/lib/postgresql/data# ls
base    pg_commit_ts  pg_hba.conf    pg_logical    pg_notify    pg_serial     pg_stat      pg_subtrans  pg_twophase  pg_wal   postgresql.auto.conf  postmaster.opts  test.txt
global  pg_dynshmem   pg_ident.conf  pg_multixact  pg_replslot  pg_snapshots  pg_stat_tmp  pg_tblspc    PG_VERSION   pg_xact  postgresql.conf       postmaster.pid

podとPVCを削除します。PV作成時にDeleteを指定していることからPVC削除と同時にPVが削除されるはず。。。
getで何も出力されないことからPVC削除と同時にPVも削除されていると確認できます。

root@ansible-tower:~# kubectl delete pod postgres0
persistentvolumeclaim "pvc01-my-vol" deleted

root@ansible-tower:~# kubectl get pod,pv,pvc
No resources found

/tmp配下も削除されています。

root@ansible-tower:~# cd /tmp
root@ansible-tower:/tmp# ls
snap-private-tmp                                                                systemd-private-7b30335e5c3847888ee14c9d4ae96fea-systemd-resolved.service-y1Y1GA
systemd-private-7b30335e5c3847888ee14c9d4ae96fea-fwupd.service-Srke4w           systemd-private-7b30335e5c3847888ee14c9d4ae96fea-systemd-timesyncd.service-Mr4GTU
systemd-private-7b30335e5c3847888ee14c9d4ae96fea-ModemManager.service-9JtOcV    systemd-private-7b30335e5c3847888ee14c9d4ae96fea-upower.service-LLEENP
systemd-private-7b30335e5c3847888ee14c9d4ae96fea-systemd-logind.service-f83oWV

検証:spec.persistentVolumeReclaimPolicyを"Retain"でPVやPVCをデプロイして使ってみる

PVのyamlは以下

cat my-vol-retain.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-vol-retain
spec:
  capacity:
    storage: 5Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: my-vol-retain-class
  hostPath:
    path: /tmp/my-vol-retain
    type: DirectoryOrCreate

デプロイします

root@ansible-tower:~/yaml# kubectl create -f my-vol-retain.yaml
persistentvolume/my-vol-retain created

root@ansible-tower:~/yaml# kubectl get pv
NAME            CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS          REASON   AGE
my-vol-retain   5Gi        RWO            Retain           Available           my-vol-retain-class            6s

PVCのyamlは以下

pvc01-my-vol-retain.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc01-my-vol-retain
spec:
  resources:
    requests:
      storage: 5Gi
  accessModes:
  - ReadWriteOnce
  storageClassName: my-vol-retain-class

デプロイします

root@ansible-tower:~/yaml# kubectl create -f pvc01-my-vol-retain.yaml
persistentvolumeclaim/pvc01-my-vol-retain created

root@ansible-tower:~/yaml# kubectl get pv,pvc -o wide
NAME                             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                         STORAGECLASS          REASON   AGE   VOLUMEMODE
persistentvolume/my-vol-retain   5Gi        RWO            Retain           Bound    default/pvc01-my-vol-retain   my-vol-retain-class            68s   Filesystem

NAME                                        STATUS   VOLUME          CAPACITY   ACCESS MODES   STORAGECLASS          AGE   VOLUMEMODE
persistentvolumeclaim/pvc01-my-vol-retain   Bound    my-vol-retain   5Gi        RWO            my-vol-retain-class   10s   Filesystem

podのyamlは以下

vol-retain-postgresql01.yaml
apiVersion: v1
kind: Pod
metadata:
  name: postgres01
spec:
  containers:
  - name: postgres01
    image: postgres:latest
    env:
    - name: POSTGRES_PASSWORD
      value: "postgres"
    volumeMounts:
    - mountPath: /var/lib/postgresql/data
      name: pvc01-my-vol-retain
  volumes:
  - name: pvc01-my-vol-retain
    persistentVolumeClaim:
      claimName: pvc01-my-vol-retain

デプロイします

root@ansible-tower:~/yaml# kubectl create -f vol-retain-postgresql01.yaml
pod/postgres01 created

root@ansible-tower:~/yaml# kubectl get pod,pv,pvc -o wide
NAME             READY   STATUS    RESTARTS   AGE   IP            NODE            NOMINATED NODE   READINESS GATES
pod/postgres01   1/1     Running   0          24s   10.1.108.11   ansible-tower   <none>           <none>

NAME                             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                         STORAGECLASS          REASON   AGE     VOLUMEMODE
persistentvolume/my-vol-retain   5Gi        RWO            Retain           Bound    default/pvc01-my-vol-retain   my-vol-retain-class            5m12s   Filesystem

NAME                                        STATUS   VOLUME          CAPACITY   ACCESS MODES   STORAGECLASS          AGE     VOLUMEMODE
persistentvolumeclaim/pvc01-my-vol-retain   Bound    my-vol-retain   5Gi        RWO            my-vol-retain-class   4m14s   Filesystem

podの中に入ってtest.txtを/var/lib/postgresql/data配下に作成します。

root@ansible-tower:~/yaml# kubectl exec -it postgres01 -- /bin/bash
root@postgres01:/# cd /var/lib/postgresql/data/
root@postgres01:/var/lib/postgresql/data# touch test.txt
root@postgres01:/var/lib/postgresql/data# ls
base    pg_commit_ts  pg_hba.conf    pg_logical    pg_notify    pg_serial     pg_stat      pg_subtrans  pg_twophase  pg_wal   postgresql.auto.conf  postmaster.opts  test.txt
global  pg_dynshmem   pg_ident.conf  pg_multixact  pg_replslot  pg_snapshots  pg_stat_tmp  pg_tblspc    PG_VERSION   pg_xact  postgresql.conf       postmaster.pid

ホストの/tmp/my-vol-retainにデータがあることを確認します。

root@ansible-tower:~# cd /tmp/my-vol-retain/
root@ansible-tower:/tmp/my-vol-retain# ls
base    pg_commit_ts  pg_hba.conf    pg_logical    pg_notify    pg_serial     pg_stat      pg_subtrans  pg_twophase  pg_wal   postgresql.auto.conf  postmaster.opts  test.txt
global  pg_dynshmem   pg_ident.conf  pg_multixact  pg_replslot  pg_snapshots  pg_stat_tmp  pg_tblspc    PG_VERSION   pg_xact  postgresql.conf       postmaster.pid

podやPVCを削除しても自動で削除されないことを確認します。

root@ansible-tower:~/yaml# kubectl get pod,pv,pvc -o wide
NAME             READY   STATUS    RESTARTS   AGE     IP            NODE            NOMINATED NODE   READINESS GATES
pod/postgres01   1/1     Running   0          3m22s   10.1.108.11   ansible-tower   <none>           <none>

NAME                             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                         STORAGECLASS          REASON   AGE     VOLUMEMODE
persistentvolume/my-vol-retain   5Gi        RWO            Retain           Bound    default/pvc01-my-vol-retain   my-vol-retain-class            8m10s   Filesystem

NAME                                        STATUS   VOLUME          CAPACITY   ACCESS MODES   STORAGECLASS          AGE     VOLUMEMODE
persistentvolumeclaim/pvc01-my-vol-retain   Bound    my-vol-retain   5Gi        RWO            my-vol-retain-class   7m12s   Filesystem

root@ansible-tower:~/yaml# kubectl delete pod postgres01
pod "postgres01" deleted
root@ansible-tower:~/yaml# kubectl delete pvc pvc01-my-vol-retain

PVが残っており、ホストからもデータが残っていることが確認ができますね。

root@ansible-tower:~/yaml# kubectl get pod,pv,pvc -o wide
NAME                             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM                         STORAGECLASS          REASON   AGE   VOLUMEMODE
persistentvolume/my-vol-retain   5Gi        RWO            Retain           Released   default/pvc01-my-vol-retain   my-vol-retain-class            25m   Filesystem

root@ansible-tower:~/yaml# cd /tmp/my-vol-retain/
root@ansible-tower:/tmp/my-vol-retain# ls
base    pg_commit_ts  pg_hba.conf    pg_logical    pg_notify    pg_serial     pg_stat      pg_subtrans  pg_twophase  pg_wal   postgresql.auto.conf  postmaster.opts  test.txt
global  pg_dynshmem   pg_ident.conf  pg_multixact  pg_replslot  pg_snapshots  pg_stat_tmp  pg_tblspc    PG_VERSION   pg_xact  postgresql.conf       postmaster.pid

これを再利用するには少し手間が必要なのかも?です。

1.PersistentVolumeを削除します。PVが削除された後も、外部インフラストラクチャー(AWS EBS、GCE PD、Azure Disk、Cinderボリュームなど)に関連付けられたストレージアセットは依然として残ります。
2.ストレージアセットに関連するのデータを手動で適切にクリーンアップします。
3.関連するストレージアセットを手動で削除するか、同じストレージアセットを再利用したい場合、新しいストレージアセット定義と共にPersistentVolumeを作成します。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1