Edited at

Kubernetes PVC と Deployment, StatefulSet の関係を検証してみた

More than 1 year has passed since last update.


はじめに

Persistent Volume とは、Kubernetes の Pod でストレージを管理・使用するためのものです。

Persistent Volume を、Deployment・StatefulSet で使用したときに、どのようにPodへ紐づけられるかが不明だったため、検証を通じて理解を深めていきます。

Master1台・Node2台のKubernetesクラスタに対して、NFSを使用してPersistent Volume の検証をします。


NFSサーバの準備

適当にNFSサーバを準備する

以下のURLを参照

https://qiita.com/sugimount/items/1c1ab9b45b0d862a7dd6


NFS Clientの準備

Node が NFSマウントを実施するため、Nodeに NFS Client の事前準備を行う

念のため、Master と Node全台 で install をしておく

以下のURLを参照

https://qiita.com/sugimount/items/1c1ab9b45b0d862a7dd6


Persistent VolumeとDeploymentの紐づけ検証


Persistent Volumeの作成

KubernetesMaster上で、Persistent Volume を定義するYAMLファイルを作成します

cat <<'EOF' > /root/kube_yaml/persistent_volume/persistent_volume.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0001
spec:
capacity:
storage: 1Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: slow
mountOptions:
- hard
nfs:
server: 192.168.120.230
path: /mnt/nfsserv
EOF

特徴的な各パラメータは以下の通りです

項目
パラメータ概要
内容

spec.capacity.storage
ストレージ容量
PVの容量を定義

spec.volumeMode
PVボリュームの種類
PVボリュームの種類を指定。"Filesystem" or "Block" の2種類を指定可能。何も指定しない場合は、"FileSystem"がDefaultとなる。
Kubernetes 1.9 より、 "Block" がサポートされたため、volumeMode を指定出来るようになった

spec.accessModes
アクセスモード
PVへアクセスするモードを定義する。選択可能なアクセスモードは、PVのVolumePluginに依存している。
ReadWriteOnce : 1つのNodeがPVをmountすることが出来る。読み書き可能。
ReadOnlyMany : 複数のNodeがPVをmountすることが出来る。読み取り専用。
ReadWriteMany : 複数のNodeがPVをmountすることが出来る。読み書き可能

spec.storageClassName
ストレージクラス名
Kubernetesクラスタ管理者が定義しているストレージのクラスから、1種類を選択します。
ストレージの性質をクラスタ管理者が定義するものが、ストレージクラスです。
例えば、fast class は高価な早いストレージと定義し、slow class は安価な遅めなストレージと定義する運用が考えられます

spec.persistentVolumeReclaimPolicy
削除時の動作
PVを削除したときの動作を指定します。
Retain : 削除しない。手動で削除を行う
Recycle : 削除して再利用する "rm -rf /voluma_path/*" のイメージ
Delete : Volumeを削除

PV を作成します

kubectl create -f /root/kube_yaml/persistent_volume/persistent_volume.yaml

確認します

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl get pv -o wide

NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv0001 1Gi RWO Recycle Available slow 22s

現在の段階では、NFS上には何もFileは作成されていません

[root@sugi-nfs nfsserv]# pwd

/mnt/nfsserv
[root@sugi-nfs nfsserv]#
[root@sugi-nfs nfsserv]# ls -la
total 0
drwxr-xr-x 2 root root 6 Jun 1 11:59 .
drwxr-xr-x. 3 root root 21 Jun 1 11:50 ..


Persistent Volume Claims を作成

PVC(Persistent Volume Claims)とは、PVを要求するためのKubernetesリソースです。

PVには、ストレージ提供側の固有の情報(IPアドレスや、NFSエクスポートポイントなど)が含まれています。

Kubernetesクラスタの利用者がPVを作成しようとすると、ストレージ提供側の固有の情報を知る必要があります。

ストレージ固有の情報を抽象化するために、PVCが存在しています。

PVをKubernetesクラスタの管理者が作成し、PVCを利用者が作成することが想定されています。

PVCを作成するために、以下のYAMLファイルを作成します

cat <<'EOF' > /root/kube_yaml/persistent_volume/persistent_volume_claims.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: test-claim
annotations:
volume.kubernetes.io/storage-class: "nfs"
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
storageClassName: slow
resources:
requests:
storage: 1Gi
EOF

PVCを作成します

kubectl create -f /root/kube_yaml/persistent_volume/persistent_volume_claims.yaml

確認します

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl get pvc -o wide

NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
test-claim Bound pv0001 1Gi RWO slow 17s

describe で pvc の詳細を確認すると、pv0001 が 使用されている事がわかります

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl describe pvc test-claim 

Name: test-claim
Namespace: default
StorageClass: slow
Status: Bound
Volume: pv0001
Labels: <none>
Annotations: pv.kubernetes.io/bind-completed=yes
pv.kubernetes.io/bound-by-controller=yes
volume.kubernetes.io/storage-class=nfs
Finalizers: [kubernetes.io/pvc-protection]
Capacity: 1Gi
Access Modes: RWO
Events: <none>

PVを確認すると、Available だった STATUS が、 Bound と変化しており、PVCに紐づけられています

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl get pv -o wide

NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv0001 1Gi RWO Recycle Bound default/test-claim slow 2h


Deployment の作成

Deploymentのために、以下のYAMLファイルを作成します

spec.template.spec.volumes.persistentVolumeClaim.claimName でDeploymentで使用するPVCを指定しています。

実際のコンテナに割り当てるためにspec.template.spec.containers.volumeMountsを指定しています。

PVCをコンテナ内の /persistent-volume に mount する設定となっています。

cat <<'EOF' > /root/kube_yaml/persistent_volume/persistent_deployment.yaml

apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: persistent-deployment
spec:
selector:
matchLabels:
app: persistest_test
replicas: 1
template:
metadata:
labels:
app: persistest_test
spec:
containers:
- name: master
image: nginx
resources:
requests:
cpu: 100m
memory: 100Mi
ports:
- containerPort: 80
volumeMounts:
- mountPath: /persistent-volume
name: pvc-volume
volumes:
- name: pvc-volume
persistentVolumeClaim:
claimName: test-claim
restartPolicy: Always
EOF

deployment を作成します

kubectl create -f /root/kube_yaml/persistent_volume/persistent_deployment.yaml

deploymentが作成され、Pod が作成されます

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl get pods -o wide

NAME READY STATUS RESTARTS AGE IP NODE
persistent-deployment-b9db64785-7fq4z 1/1 Running 0 47s 10.244.1.29 sugi-kubernetes110-node01.localdomain

node01 上で df を確認すると、NFSサーバをmount していることがわかります

[root@sugi-kubernetes110-node01 ~]# df -h

Filesystem Size Used Avail Use% Mounted on
/dev/mapper/cl-root 14G 3.5G 10G 26% /
devtmpfs 1.9G 0 1.9G 0% /dev
tmpfs 1.9G 0 1.9G 0% /dev/shm
tmpfs 1.9G 129M 1.8G 7% /run
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
/dev/sda1 1014M 289M 726M 29% /boot
tmpfs 1.9G 12K 1.9G 1% /var/lib/kubelet/pods/436d9ed6-4ae3-11e8-bbe9-0050569817ee/volumes/kubernetes.io~secret/kube-proxy-token-c9qtq
tmpfs 1.9G 12K 1.9G 1% /var/lib/kubelet/pods/436dce14-4ae3-11e8-bbe9-0050569817ee/volumes/kubernetes.io~secret/flannel-token-6pnqp
tmpfs 380M 0 380M 0% /run/user/0
tmpfs 1.9G 12K 1.9G 1% /var/lib/kubelet/pods/2f404ff6-6562-11e8-8767-0050569817ee/volumes/kubernetes.io~secret/default-token-q65hj
192.168.120.230:/mnt/nfsserv 14G 1.5G 12G 11% /var/lib/kubelet/pods/2f404ff6-6562-11e8-8767-0050569817ee/volumes/kubernetes.io~nfs/pv0001

なお、node01 上で docker 一覧を確認し

[root@sugi-kubernetes110-node01 ~]# docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b7dea7029d25 docker.io/nginx@sha256:0fb320e2a1b1620b4905facb3447e3d84ad36da0b2c8aa8fe3a5a81d1187b884 "nginx -g 'daemon ..." 4 minutes ago Up 4 minutes k8s_master_persistent-deployment-b9db64785-7fq4z_default_2f404ff6-6562-11e8-8767-0050569817ee_0
13deb2cc4164 k8s.gcr.io/pause-amd64:3.1 "/pause" 4 minutes ago Up 4 minutes k8s_POD_persistent-deployment-b9db64785-7fq4z_default_2f404ff6-6562-11e8-8767-0050569817ee_0
b9d65d4ddb1c 2b736d06ca4c "/opt/bin/flanneld..." 4 weeks ago Up 4 weeks k8s_kube-flannel_kube-flannel-ds-d92qj_kube-system_436dce14-4ae3-11e8-bbe9-0050569817ee_1
5592ed89cbe0 77019aa0531a "/usr/local/bin/ku..." 4 weeks ago Up 4 weeks k8s_kube-proxy_kube-proxy-khhwf_kube-system_436d9ed6-4ae3-11e8-bbe9-0050569817ee_1
496d9d63cddd k8s.gcr.io/pause-amd64:3.1 "/pause" 4 weeks ago Up 4 weeks k8s_POD_kube-flannel-ds-d92qj_kube-system_436dce14-4ae3-11e8-bbe9-0050569817ee_1
fab2fd0c0a3b k8s.gcr.io/pause-amd64:3.1 "/pause" 4 weeks ago Up 4 weeks k8s_POD_kube-proxy-khhwf_kube-system_436d9ed6-4ae3-11e8-bbe9-0050569817ee_1

該当のコンテナの詳細情報を表示すると、NFSでmount しているvolume を使用していることが分かります

# docker inspect b7dea7029d25

... snip ....

"Mounts": [
{
"Type": "bind",
"Source": "/var/lib/kubelet/pods/2f404ff6-6562-11e8-8767-0050569817ee/etc-hosts",
"Destination": "/etc/hosts",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "bind",
"Source": "/var/lib/kubelet/pods/2f404ff6-6562-11e8-8767-0050569817ee/containers/master/1abcb732",
"Destination": "/dev/termination-log",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "bind",
"Source": "/var/lib/kubelet/pods/2f404ff6-6562-11e8-8767-0050569817ee/volumes/kubernetes.io~nfs/pv0001",
"Destination": "/persistent-volume", ← ココを見る
"Mode": "rslave",
"RW": true,
"Propagation": "rslave"
},

nginx pod にログインします

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl exec -it persistent-deployment-b9db64785-7fq4z bash

root@persistent-deployment-b9db64785-7fq4z:/#

pod 内でも正常にmountされていることを確認できます

pod内からNFSサーバのIPアドレスが見えますね。StorageのTypeにもよりますが、Pod利用者にストレージ側のIPアドレスが知られても問題ないようにする観点も必要かもしれません

root@persistent-deployment-b9db64785-7fq4z:/# df -h

Filesystem Size Used Avail Use% Mounted on
overlay 14G 3.5G 10G 26% /
tmpfs 1.9G 0 1.9G 0% /dev
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
192.168.120.230:/mnt/nfsserv 14G 1.5G 12G 11% /persistent-volume
/dev/mapper/cl-root 14G 3.5G 10G 26% /etc/hosts
shm 64M 0 64M 0% /dev/shm
tmpfs 1.9G 12K 1.9G 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 1.9G 0 1.9G 0% /proc/scsi
tmpfs 1.9G 0 1.9G 0% /sys/firmware

pod 内でファイルを作成します

root@persistent-deployment-b9db64785-7fq4z:/persistent-volume# touch test_from_pod

root@persistent-deployment-b9db64785-7fq4z:/persistent-volume# pwd
/persistent-volume
root@persistent-deployment-b9db64785-7fq4z:/persistent-volume#
root@persistent-deployment-b9db64785-7fq4z:/persistent-volume# ls -la
total 0
drwxr-xr-x 2 root root 27 Jun 1 06:26 .
drwxr-xr-x 1 root root 53 Jun 1 06:08 ..
-rw-r--r-- 1 root root 0 Jun 1 06:26 test_from_pod

NFSサーバ上でも、上記の作成されたファイルが確認できます

NFSサーバのExportPointと、PVは1対1で対応している事がわかります (NFSのDynamicProvisionerを使用すると、ExportPointが自動的に作成されるのかな?)

[root@sugi-nfs nfsserv]# ls -la

total 0
drwxr-xr-x 2 root root 27 Jun 1 15:26 .
drwxr-xr-x. 3 root root 21 Jun 1 11:50 ..
-rw-r--r-- 1 root root 0 Jun 1 15:26 test_from_pod
[root@sugi-nfs nfsserv]#
[root@sugi-nfs nfsserv]# pwd
/mnt/nfsserv

ここで、DeploymentのReplicaを1から2にするとどうなるのでしょうか。

cat <<'EOF' > /root/kube_yaml/persistent_volume/persistent_deployment.yaml

apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: persistent-deployment
spec:
selector:
matchLabels:
app: persistest_test
replicas: 2
template:
metadata:
labels:
app: persistest_test
spec:
containers:
- name: master
image: nginx
resources:
requests:
cpu: 100m
memory: 100Mi
ports:
- containerPort: 80
volumeMounts:
- mountPath: /persistent-volume
name: pvc-volume
volumes:
- name: pvc-volume
persistentVolumeClaim:
claimName: test-claim
restartPolicy: Always
EOF

apply で更新する

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl apply -f /root/kube_yaml/persistent_volume/persistent_deployment.yaml

Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
deployment.apps "persistent-deployment" configured

確認

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl get replicaset 

NAME DESIRED CURRENT READY AGE
persistent-deployment-b9db64785 2 2 2 44m

podも確認

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl get pods -o wide

NAME READY STATUS RESTARTS AGE IP NODE
persistent-deployment-b9db64785-7fq4z 1/1 Running 0 44m 10.244.1.29 sugi-kubernetes110-node01.localdomain
persistent-deployment-b9db64785-rtbk7 1/1 Running 0 2m 10.244.2.28 sugi-kubernetes110-node02.localdomain

なんと、PVを ReadWriteOnceとして作成していましたが、複数のNodeに接続がされています。

node01 と node02 のそれぞれのコンテナ上でファイルを作成することが出来ます。

バグなのかなんなのかはよくわかりません。。。

2番目のPodでも正常に書き込める

root@persistent-deployment-b9db64785-rtbk7:/persistent-volume# touch test_from_pod02

root@persistent-deployment-b9db64785-rtbk7:/persistent-volume# ls -la
total 0
drwxr-xr-x 2 root root 50 Jun 1 06:59 .
drwxr-xr-x 1 root root 53 Jun 1 06:50 ..
-rw-r--r-- 1 root root 0 Jun 1 06:26 test_from_pod
-rw-r--r-- 1 root root 0 Jun 1 06:59 test_from_pod02
root@persistent-deployment-b9db64785-rtbk7:/persistent-volume#
root@persistent-deployment-b9db64785-rtbk7:/persistent-volume# pwd
/persistent-volume


Pod をオートヒーリングしたときのPVとの関係を確認

Podの1個目を削除して、ReplicaSetによりオートヒーリングを発生させます。

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl delete pod persistent-deployment-b9db64785-7fq4z

pod "persistent-deployment-b9db64785-7fq4z" deleted

新たなPodが作成されます

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl get pods -o wide

NAME READY STATUS RESTARTS AGE IP NODE
persistent-deployment-b9db64785-rtbk7 1/1 Running 0 53m 10.244.2.28 sugi-kubernetes110-node02.localdomain
persistent-deployment-b9db64785-vfcd5 1/1 Running 0 27s 10.244.1.30 sugi-kubernetes110-node01.localdomain

オートヒーリングされたPodを確認すると、こちらでも引き続き PV を使用していることがわかります。

削除前に作っていたファイルが確認できます

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl exec -it persistent-deployment-b9db64785-vfcd5 bash

root@persistent-deployment-b9db64785-vfcd5:/# ls -la /persistent-volume/
total 0
drwxr-xr-x 2 root root 50 Jun 1 06:59 .
drwxr-xr-x 1 root root 53 Jun 1 07:43 ..
-rw-r--r-- 1 root root 0 Jun 1 06:26 test_from_pod
-rw-r--r-- 1 root root 0 Jun 1 06:59 test_from_pod02


DeploymentとPVCの関係まとめ

Deploymentで作成されたPodは全て、同一のPVを参照する動作となる。

今回はNFSをPVとして作成したため、ReadWriteAnyが許されており、複数PodからMountが出来ている。

しかし、AWSElasticBlockStoreやAWSElasticBlockStoreでは、ReadWriteManyが出来ないため、

DeploymentにPVを紐づけると、Replicaを2以上にすることは出来ないと予想出来る。

Pod に障害が発生して、オートヒーリングを実施した際にも、PV は引き続き同じものをmountすることが出来ます。


Persistent VolumeとStatefulSetの紐づけ検証


NFSサーバでPV用の領域をExport

StatefulSet として2個のPod を作成します。その前準備として、PV を2個作成するために、NFS Export を2個設定します

[root@sugi-nfs mnt]# mkdir /mnt/pv002

[root@sugi-nfs mnt]# mkdir /mnt/pv003

[root@sugi-nfs mnt]# vi /etc/exports

/mnt/pv002 *(rw,async,no_root_squash)
/mnt/pv003 *(rw,async,no_root_squash)

export point を再読み込み

[root@sugi-nfs mnt]# exportfs -ra

[root@sugi-nfs mnt]# exportfs -v
/mnt/pv002 <world>(rw,async,wdelay,hide,no_subtree_check,sec=sys,secure,no_root_squash,no_all_squash)
/mnt/pv003 <world>(rw,async,wdelay,hide,no_subtree_check,sec=sys,secure,no_root_squash,no_all_squash)


Persistent Volume の作成

cat <<'EOF' > /root/kube_yaml/persistent_volume/persistent_volume_002.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
name: pv002
spec:
capacity:
storage: 1Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
# storageClassName: slow
mountOptions:
- hard
nfs:
server: 192.168.120.230
path: /mnt/pv002
EOF

cat <<'EOF' > /root/kube_yaml/persistent_volume/persistent_volume_003.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
name: pv003
spec:
capacity:
storage: 1Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
# storageClassName: slow
mountOptions:
- hard
nfs:
server: 192.168.120.230
path: /mnt/pv003
EOF

PVを作成します

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl create -f /root/kube_yaml/persistent_volume/persistent_volume_002.yaml

persistentvolume "pv002" created
[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl create -f /root/kube_yaml/persistent_volume/persistent_volume_003.yaml
persistentvolume "pv003" created

確認します

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl get pv

NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv0001 1Gi RWO Recycle Bound default/test-claim slow 4h
pv002 1Gi RWO Recycle Available 8s
pv003 1Gi RWO Recycle Available 6s


StatefulSetの作成

StatefulSet の YAML を定義します

cat <<'EOF' > /root/kube_yaml/persistent_volume/persistent_volume_statefulset.yaml

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: persistent-stateset
spec:
serviceName: nginx-service
replicas: 2
selector:
matchLabels:
app: persistent-stateful
template:
metadata:
labels:
app: persistent-stateful
spec:
containers:
- name: nginx-container
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: pvc-volume
mountPath: /persistent-volume
volumeClaimTemplates:
- metadata:
name: pvc-volume
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 1Gi
EOF

StatefulSet を作成します

kubectl create -f /root/kube_yaml/persistent_volume/persistent_volume_statefulset.yaml

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl get statefulset -o wide

NAME DESIRED CURRENT AGE CONTAINERS IMAGES
persistent-stateset 2 2 29s nginx-container nginx

pvcが自動的に作成されています

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl get pvc -o wide

NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc-volume-persistent-stateset-0 Bound pv002 1Gi RWO 1m
pvc-volume-persistent-stateset-1 Bound pv003 1Gi RWO 51s
test-claim Bound pv0001 1Gi RWO slow 2h

PVの一覧でも、PVCに bound されていることを確認できます

Deployment とは違い、Pod ごとに PV が接続されています

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl get pv -o wide

NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv0001 1Gi RWO Recycle Bound default/test-claim slow 4h
pv002 1Gi RWO Recycle Bound default/pvc-volume-persistent-stateset-0 18m
pv003 1Gi RWO Recycle Bound default/pvc-volume-persistent-stateset-1 18m

StatefulSet の Pod も作成されています

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl get pods -o wide

NAME READY STATUS RESTARTS AGE IP NODE
persistent-stateset-0 1/1 Running 0 2m 10.244.1.32 sugi-kubernetes110-node01.localdomain
persistent-stateset-1 1/1 Running 0 2m 10.244.2.31 sugi-kubernetes110-node02.localdomain

Pod に割り当てられている PVC を確認すると、PVC が紐づけされていることがわかります

# kubectl describe pod persistent-stateset-0

snip

Volumes:
pvc-volume:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: pvc-volume-persistent-stateset-0
ReadOnly: false
default-token-q65hj:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-q65hj
Optional: false

# kubectl describe pod persistent-stateset-1

snip

Volumes:
pvc-volume:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: pvc-volume-persistent-stateset-1
ReadOnly: false
default-token-q65hj:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-q65hj
Optional: false

それぞれのPodにログインし、test file を作成します

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl exec -it persistent-stateset-0 bash

root@persistent-stateset-0:/# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 14G 3.5G 10G 26% /
tmpfs 1.9G 0 1.9G 0% /dev
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
192.168.120.230:/mnt/pv002 14G 1.5G 12G 11% /persistent-volume
/dev/mapper/cl-root 14G 3.5G 10G 26% /etc/hosts
shm 64M 0 64M 0% /dev/shm
tmpfs 1.9G 12K 1.9G 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 1.9G 0 1.9G 0% /proc/scsi
tmpfs 1.9G 0 1.9G 0% /sys/firmware
root@persistent-stateset-0:/# touch /persistent-volume/testfile-frompod-0
root@persistent-stateset-0:/# ls -la /persistent-volume/
total 0
drwxr-xr-x 2 root root 32 Jun 1 08:57 .
drwxr-xr-x 1 root root 65 Jun 1 08:48 ..
-rw-r--r-- 1 root root 0 Jun 1 08:57 testfile-frompod-0

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl exec -it persistent-stateset-1 bash

root@persistent-stateset-1:/# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 14G 4.1G 9.4G 31% /
tmpfs 1.9G 0 1.9G 0% /dev
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
192.168.120.230:/mnt/pv003 14G 1.5G 12G 11% /persistent-volume
/dev/mapper/cl-root 14G 4.1G 9.4G 31% /etc/hosts
shm 64M 0 64M 0% /dev/shm
tmpfs 1.9G 12K 1.9G 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 1.9G 0 1.9G 0% /proc/scsi
tmpfs 1.9G 0 1.9G 0% /sys/firmware
root@persistent-stateset-1:/# touch /persistent-volume/testfile-frompod-1
root@persistent-stateset-1:/# ls -la /persistent-volume/
total 0
drwxr-xr-x 2 root root 32 Jun 1 08:57 .
drwxr-xr-x 1 root root 53 Jun 1 08:48 ..
-rw-r--r-- 1 root root 0 Jun 1 08:57 testfile-frompod-1

NFSサーバを確認すると、それぞれの Export Point で、test file が作成されていることを確認できます

[root@sugi-nfs mnt]# ls -la /mnt/pv002/

total 0
drwxr-xr-x 2 root root 32 Jun 1 17:57 .
drwxr-xr-x. 5 root root 47 Jun 1 17:10 ..
-rw-r--r-- 1 root root 0 Jun 1 17:57 testfile-frompod-0
[root@sugi-nfs mnt]#
[root@sugi-nfs mnt]# ls -la /mnt/pv003/
total 0
drwxr-xr-x 2 root root 32 Jun 1 17:57 .
drwxr-xr-x. 5 root root 47 Jun 1 17:10 ..
-rw-r--r-- 1 root root 0 Jun 1 17:57 testfile-frompod-1


Pod をオートヒーリングしたときのPVとの関係を確認

Podの1個目を削除して、StatefulSet によりオートヒーリングを発生させます。

削除した直後に Pod がオートヒーリングされることを確認できます

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl delete pod persistent-stateset-0

pod "persistent-stateset-0" deleted
[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]#
[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl get pod
NAME READY STATUS RESTARTS AGE
persistent-stateset-0 0/1 Terminating 0 14m
persistent-stateset-1 1/1 Running 0 14m
[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]#
[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl get pod
NAME READY STATUS RESTARTS AGE
persistent-stateset-0 0/1 Terminating 0 14m
persistent-stateset-1 1/1 Running 0 14m
[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]#
[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl get pod
NAME READY STATUS RESTARTS AGE
persistent-stateset-0 0/1 Terminating 0 14m
persistent-stateset-1 1/1 Running 0 14m
[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]#
[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl get pod
NAME READY STATUS RESTARTS AGE
persistent-stateset-0 0/1 Pending 0 0s
persistent-stateset-1 1/1 Running 0 14m
[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]#
[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl get pod
NAME READY STATUS RESTARTS AGE
persistent-stateset-0 0/1 ContainerCreating 0 2s
persistent-stateset-1 1/1 Running 0 14m
[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]#
[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl get pod
NAME READY STATUS RESTARTS AGE
persistent-stateset-0 0/1 ContainerCreating 0 3s
persistent-stateset-1 1/1 Running 0 14m

オートヒーリングされたPodを確認すると、こちらでも引き続き PV を使用していることがわかります。

削除前に作っていたファイルが確認できます

[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl exec -it persistent-stateset-0 bash

root@persistent-stateset-0:/# ls -la /persistent-volume/
total 0
drwxr-xr-x 2 root root 32 Jun 1 08:57 .
drwxr-xr-x 1 root root 53 Jun 1 09:02 ..
-rw-r--r-- 1 root root 0 Jun 1 08:57 testfile-frompod-0


StatefulSet と PVC の関係まとめ

StatefulSet で作成された Pod は、それぞれ単一の PV をマウントしています

Deployment では、全てのPodで1個のPV をマウントしている違いがあります

Pod に障害が発生し、オートヒーリングを実施した際にも、同一のPVを引き続き mount するため、データの永続性を担保することが出来ます。


参考URL

https://kubernetes.io/docs/concepts/storage/persistent-volumes/