はじめに
EKSのPodでNFSやEFSを静的マウントする際に、StorageClassやcsi-driverが必要だったかうる覚えだったので実際に検証を行い、その結果をまとめました。
結論
- NFS: 静的マウントの場合、StorageClassとcsi-driverは無くてもできる
- EFS: 静的マウントかつサブネットに紐づくマウントターゲットの場合、StorageClassとcsi-driverは無くてもできる
ただし、障害時の挙動や運用面を考慮すると、efs-csi-driverは使った方がいい。
検証環境
- EKS v1.31
- EKS managed workerタイプでEC2を2台
- addon
- coredns
- eks-pod-identity-agent
- kube-proxy
- vpc-cni
NFSマウントの検証
事前準備
- EC2でNFSサーバーを作成
- 以下のuserdataでNFSサーバーをセットアップ
yum update -y
yum install -y nfs-utils
mkdir -p /mnt/nfs_share
chmod 777 /mnt/nfs_share
echo "/mnt/nfs_share *(rw,sync,no_root_squash)" >> /etc/exports
systemctl enable nfs-server
systemctl start nfs-server
exportfs -a
- NFS起動確認と確認用ファイルの作成
sudo systemctl status nfs
echo nfs > /mnt/nfs_share/index.html
動作検証
- 以下のマニフェストでPV、PVC、Podを作成
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
nfs:
path: /mnt/nfs_share
server: 10.0.1.172 # NFS EC2のIPアドレス
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
volumeName: nfs
---
apiVersion: v1
kind: Pod
metadata:
name: nfs-nginx
labels:
type: nfs
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: type
operator: In
values:
- nfs
topologyKey: "kubernetes.io/hostname"
containers:
- name: nfs-nginx
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: nginx-volume
volumes:
- name: nginx-volume
persistentVolumeClaim:
claimName: nfs
---
apiVersion: v1
kind: Pod
metadata:
name: nfs-nginx-2
labels:
type: nfs
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: type
operator: In
values:
- nfs
topologyKey: "kubernetes.io/hostname"
containers:
- name: nfs-nginx-2
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: nginx-volume
volumes:
- name: nginx-volume
persistentVolumeClaim:
claimName: nfs
- リソースの状態確認
$ kubectl get pod,pv,pvc
NAME READY STATUS RESTARTS AGE
pod/nfs-nginx 1/1 Running 0 9s
pod/nfs-nginx-2 1/1 Running 0 9s
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
persistentvolume/nfs 5Gi RWO Retain Bound default/nfs <unset> 9s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
persistentvolumeclaim/nfs Bound nfs 5Gi RWO <unset> 9s
- マウントしたファイルの確認と修正
$ kubectl exec -it nfs-nginx -- cat /usr/share/nginx/html/index.html
nfs
$ kubectl exec -it nfs-nginx-2 -- cat /usr/share/nginx/html/index.html
nfs
$ kubectl exec -it nfs-nginx -- bash -c "echo NFS > /usr/share/nginx/html/index.html"
$ kubectl exec -it nfs-nginx -- cat /usr/share/nginx/html/index.html
NFS
$ kubectl exec -it nfs-nginx-2 -- cat /usr/share/nginx/html/index.html
NFS
EFSマウントの検証
事前準備
- EFSファイルシステムを作成(マウントターゲットはサブネットごとに作成)
- NFSのEC2でマウントと確認用ファイルの作成
sudo su -
mkdir -p /mnt/efs_share
chmod 777 /mnt/efs_share
mount -t nfs fs-08b7e137f5e8809a0.efs.ap-northeast-2.amazonaws.com:/ /mnt/efs_share
echo efs > /mnt/efs_share/index.html
cat /mnt/efs_share/index.html
umount /mnt/efs_share
動作検証
- 以下のマニフェストでPV、PVC、Podを作成
apiVersion: v1
kind: PersistentVolume
metadata:
name: efs
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
nfs:
path: /
server: fs-08b7e137f5e8809a0.efs.ap-northeast-2.amazonaws.com
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: efs
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
volumeName: efs
---
apiVersion: v1
kind: Pod
metadata:
name: efs-nginx
labels:
type: efs
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: type
operator: In
values:
- efs
topologyKey: "kubernetes.io/hostname"
containers:
- name: efs-nginx
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: nginx-volume
volumes:
- name: nginx-volume
persistentVolumeClaim:
claimName: efs
---
apiVersion: v1
kind: Pod
metadata:
name: efs-nginx-2
labels:
type: efs
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: type
operator: In
values:
- efs
topologyKey: "kubernetes.io/hostname"
containers:
- name: efs-nginx-2
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: nginx-volume
volumes:
- name: nginx-volume
persistentVolumeClaim:
claimName: efs
- リソースの状態確認
$ kubectl get pod,pv,pvc
NAME READY STATUS RESTARTS AGE
pod/efs-nginx 1/1 Running 0 9s
pod/efs-nginx-2 1/1 Running 0 9s
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
persistentvolume/efs 5Gi RWO Retain Bound default/efs <unset> 10s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
persistentvolumeclaim/efs Bound efs 5Gi RWO <unset> 10s
- マウントしたファイルの確認と修正
$ kubectl exec -it efs-nginx -- cat /usr/share/nginx/html/index.html
efs
$ kubectl exec -it efs-nginx-2 -- cat /usr/share/nginx/html/index.html
efs
$ kubectl exec -it efs-nginx -- bash -c "echo EFS > /usr/share/nginx/html/index.html"
$ kubectl exec -it efs-nginx -- cat /usr/share/nginx/html/index.html
EFS
$ kubectl exec -it efs-nginx-2 -- cat /usr/share/nginx/html/index.html
EFS
障害時の挙動
セキュリティグループの変更
NFS/EFSともにセキュリティグループのインバウンド許可を削除すると:
- Podは Running 状態を維持
- Podからボリュームが見えなくなる
- インバウンドを元に戻すとPodからボリュームが再び見えるようになる
※ nfs-csi-driver および efs-csi-driver を使用した場合も同様の挙動
NFSのEC2を停止
- Podは Running 状態を維持
- Podからボリュームが見えなくなる
- EC2を起動するとPodからボリュームが再び見えるようになる
※ nfs-csi-driver を使用した場合も同様の挙動
EFSマウントターゲットの消失
- Podがマウントしている状態でEFSのマウントターゲットを1つ削除
- 削除したマウントターゲットと同じAZのノード上で動くPodでEFSが見えなくなる
$ kubectl exec -it efs-nginx -- cat /usr/share/nginx/html/index.html
efs
$ kubectl exec -it efs-nginx-2 -- cat /usr/share/nginx/html/index.html
# このまま応答なし
- マウントターゲットを再作成しても状況は変わらない
- Podを削除しようとしても削除できない
- ノードを削除すればPodも消える
※ efs-csi-driver を使用した場合:
- マウントターゲットを再作成すれば時間はかかるが再接続できるようになる
まとめ
静的マウントの場合、NFSとEFSともにStorageClassやcsi-driverなしでもマウント可能です。ただし、障害時の挙動や運用面を考慮すると、csi-driverを使用した方が良さそうです。特にEFSの場合、マウントターゲットの障害時にefs-csi-driverを使用することで、より柔軟な対応が可能になります。