Cloudnet AWES 3주차 스터디를 진행하며 정리한 글입니다.
지난 시간에는 쿠버네티스에서 사용하는 스토리지에 대해 알아보았습니다.
이번 시간에는 AWS EKS에서 다양한 종류의 CSI Driver를 활용하여 AWS의 스토리지를 사용하는 방법에 대해 알아보겠습니다.
우선 AWS 환경에 대표적인 스토리지를 알아보겠습니다.
AWS 스토리지
AWS EBS (AWS Elastic Block Storage)
- AWS 블록 스토리지로, EC2에서 디스크처럼 연결하여 사용하는 블록 스토리지입니다.
- EC2 특정 노드에 종속 되어서 여러 노드에서 공유가 불가능하고, ReadWriteOnce(RWO) 모드만 지원하여 하나의 Pod에서만 접근이 가능합니다. AZ가 제한되어 하나의 AZ 내에서만 접근 가능합니다
- 높은 IOPS와 낮은 지연 시간 제공하여 성능이 좋습니다.
- 스냅샷을 통해 백업이 가능합니다.
AWS EFS (AWS File System)
- NFS 기반 AWS 확장 가능한 네트워크 파일 시스템입니다.
- 다중 AZ를 지원하여 여러 노드에서 동시에 마운트 가능합니다.
- 사전 할당 필요 없이 자동 확장이 가능합니다.
- 파일 단위 공유가 가능합니다.
- EBS보다 높은 지연 시간으로 비교적 낮은 성능을 가집니다.
AWS S3 (Simple Storage Service)
- AWS 오브젝트 스토리지입니다. (파일 단위 저장, 계층적 디렉토리 X)
- 전 세계에서 접근 가능하고, 무제한 확장 가능합니다.
- EBS, EFS보다 저렴합니다.
- REST API 기반 접근을 합니다. (POSIX 파일 시스템 아님)
CSI Driver
지난 포스팅에서 CSI란 쿠버네티스를 비롯한 컨테이너 오케이스트레이션 도구와 다양한 스토리지 백엔드를 연결하는 표준 인터페이스라고 소개했었는데요.

이러한 CSI 표준을 구현한 스토리지 프로바이더 (Storage Provider) 플러그인이 CSI Driver입니다.
CSI Driver는 스토리지 종류 별로 AWS EBS, AWS EFS, Ceph, NFS 등 다양한 스토리지를 지원하고, 쿠버네티스에서 스토리지 프로비저닝, 볼륨 연결, 마운트, 스냅샷 등의 기능을 제공합니다.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs-sc
provisioner: ebs.csi.aws.com # <- CSI Driver
volumeBindingMode: WaitForFirstConsumer
parameters:
type: gp3
CSI Driver의 동작 과정
- 사용자가 PersistentVolumeClaim (PVC) 를 생성
- PVC가 StorageClass와 연결되어 있으면, Kubernetes가 CSI Driver에게 볼륨을 생성하라고 요청
- CSI Controller가 스토리지 백엔드(EBS, EFS 등)에 볼륨을 생성
CSI Driver의 주요 컴포넌트
- CSI Controller Plugin : 볼륨 생성, 삭제, 노드에 Attach, Detach
- CSI Node Plugin : 볼륨을 해당 노드에 Mount, Unmount
AWS EBS Controller
EKS에서 EBS를 스토리지로 사용하기 위해서는 EBS CSI Driver 설치가 필요합니다.
AWS EBS Controller의 역할
1. 동적 볼륨 생성
- PVC를 요청하면 자동으로 EBS 볼륨 생성
- StorageClass에 정의된 volumeBindingMode를 기반으로 볼륨 프로비저닝
2. 볼륨 연결 및 해제
- EBS 볼륨을 특정 노드 (워커 노드 EC2)에 연결, 분리
3. 스냅샷 생성 및 복원
- EBS 볼륨의 스냅샷 생성하고 새로운 볼륨으로 복구 가능
AWS EBS CSI Driver 구성 요소
AWS EBS CSI Driver는 크게 2개 구성요소가 있습니다.

EBS CSI controller
- PVC 요청 시 EBS 볼륨 동적 생성/삭제
- EBS 볼륨을 EC2 노드에 Attach/Detach
- Kubernetes 컨트롤 플레인 노드에서 작동 / EKS의 경우에는 kube-system 네임스페이스에서 동작
EBS CSI Node
- EBS 볼륨을 Pod에 마운트 및 언마운트
- Pod가 생성되면 볼륨을 마운트하고, 삭제되면 언마운트
- 각 워커 노드에서 실행되며 kubelet과 상호작용
AWS API를 호출하면서 AWS 스토리지를 관리하는 CSI-Controller와 kubelet과 상호작용하면서 AWS스토리지를 pod에 마운트하는 CSI-Node가 있습니다.
이 때, EBS는 블록 스토리지 이미로, 하나의 노드에서만 마운트가 가능하여, 한 번에 하나의 EC2 인스턴스에만 attach가 가능합니다. 따라서 ReadWriteOnce만 지원됩니다. (=즉, 한 개의 Pod만 볼륨을 마운트 할 수 있습니다.)
또한, EBBS는 하나의 가용 영역에 물리적으로 배치 되기 때문에, 동일한 AZ에 있는 인스턴스에만 연결이 가능합니다.
이제 실제로, Pod가 EBS 볼륨을 사용하도록 실습을 진행해보겠습니다.
aws-ebs-csi-driver 전체 버전 정보와 기본 설치 버전(True) 정보 확인합니다.
❯ aws eks describe-addon-versions \
--addon-name aws-ebs-csi-driver \
--kubernetes-version 1.31 \
--query "addons[].addonVersions[].[addonVersion, compatibilities[].defaultVersion]" \
--output text
v1.39.0-eksbuild.1
True
v1.38.1-eksbuild.2
False
v1.38.1-eksbuild.1
False
v1.37.0-eksbuild.2
False
v1.37.0-eksbuild.1
False
v1.36.0-eksbuild.2
False
v1.36.0-eksbuild.1
False
v1.35.0-eksbuild.2
False
v1.35.0-eksbuild.1
False
v1.34.0-eksbuild.1
False
v1.33.0-eksbuild.1
False
v1.32.0-eksbuild.1
False
v1.31.0-eksbuild.1
False
v1.30.0-eksbuild.1
False
v1.29.1-eksbuild.1
False
ISRA 설정(AmazonEBSCSIDriverPolicy)을 사용하고 ISRA를 확인합니다.
AmazonEKS_EBS_CSI_DriverRole이라는 IAM 역할을 생성하고, AmazonEBSCSIDriverPolicy 정책을 해당 IAM 역할에 부여합니다. ebs-csi-controller-sa 서비스 계정이 EBS API를 호출할 수 있도록 설정합니다.
++ 이때 ISRA란 무엇일까요?
IAM Service Role for Amazone EKS의 약자로, EKS 클러스터에서 특정 서비스가 AWS 리소스에 안전하게 접근할 수 있도록 IAM 역할을 부여하는 방식입니다.
IAM 역할을 쿠버네티스 ServiceAccount와 연결하여 AWS 리소스에 대한 권한을 제어하는 기능입니다.
Kubernetes Service Account
- K8s 클러스터 내부에서 Pod와 API 서버가 상화작용하는데 작용
- Pod가 Kubernetes API를 호출할 때 해당 SA권한 사용
IAM Service Account (ISRA)
- AWS IAM 역할을 K8s Service Account에 연결하여 AWS 리소스에 안전하게 접근할 수 있도록 하는 기능
- Pod가 AWS API를 안정하게 호출할 수 있도록 역할을 부여하는 방식
❯ eksctl create iamserviceaccount \
--name ebs-csi-controller-sa \ # 서비스 계정 이름 (K8s에서 사용할 이름)
--namespace kube-system \
--cluster ${CLUSTER_NAME} \
--attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \ # AWS 관리형 정책 연결
--approve \ # 즉시 적용
--role-only \ # IAM Role만 생성하고, K8s 서비스 계정을 따로 있음
--role-name AmazonEKS_EBS_CSI_DriverRole # IAM 역할 지정
❯ eksctl get iamserviceaccount --cluster ${CLUSTER_NAME}
NAMESPACE NAME ROLE ARN
kube-system aws-load-balancer-controller arn:aws:iam::941377114730:role/eksctl-myeks-addon-iamserviceaccount-kube-sys-Role1-yq8VPD5xPBny
kube-system ebs-csi-controller-sa arn:aws:iam::941377114730:role/AmazonEKS_EBS_CSI_DriverRole
❯ kubectl get sa -A | grep ebs
Amazon EBS CSI driver addon 배포합니다.
❯ export ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
❯ eksctl create addon --name aws-ebs-csi-driver --cluster ${CLUSTER_NAME} --service-account-role-arn arn:aws:iam::${ACCOUNT_ID}:role/AmazonEKS_EBS_CSI_DriverRole --force
❯ kubectl get sa -n kube-system ebs-csi-controller-sa -o yaml | head -5
apiVersion: v1
automountServiceAccountToken: true
kind: ServiceAccount
metadata:
annotations:
❯ eksctl get addon --cluster ${CLUSTER_NAME}
NAME VERSION STATUS ISSUES IAMROLE UPDATE AVAILABLE CONFIGURATION VALUES POD IDENTITY ASSOCIATION ROLES
aws-ebs-csi-driver v1.39.0-eksbuild.1 ACTIVE 0 arn:aws:iam::941377114730:role/AmazonEKS_EBS_CSI_DriverRole
coredns v1.11.4-eksbuild.2 ACTIVE 0
kube-proxy v1.31.3-eksbuild.2 ACTIVE 0
metrics-server v0.7.2-eksbuild.2 ACTIVE 0
vpc-cni v1.19.2-eksbuild.5 ACTIVE 0 arn:aws:iam::941377114730:role/eksctl-myeks-addon-vpc-cni-Role1-cSbYmEhHAYbN enableNetworkPolicy: "true"
❯ kubectl get deploy,ds -l=app.kubernetes.io/name=aws-ebs-csi-driver -n kube-system
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ebs-csi-controller 2/2 2 2 5m50s
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/ebs-csi-node 3 3 3 3 3 kubernetes.io/os=linux 5m50s
daemonset.apps/ebs-csi-node-windows 0 0 0 0 0 kubernetes.io/os=windows 5m51s
❯ kubectl get pod -n kube-system -l app.kubernetes.io/component=csi-driver
NAME READY STATUS RESTARTS AGE
ebs-csi-controller-7f8f8cb84-9v5mq 6/6 Running 0 5m39s
ebs-csi-controller-7f8f8cb84-hnkzb 6/6 Running 0 5m39s
ebs-csi-node-5zjzp 3/3 Running 0 5m39s
ebs-csi-node-bnxtr 3/3 Running 0 5m39s
ebs-csi-node-llzph 3/3 Running 0 5m39s
# ebs-csi-controller에 컨테이너 6개가 배포됩니다.
❯ kubectl get pod -n kube-system -l app=ebs-csi-controller -o jsonpath='{.items[0].spec.containers[*].name}' ; echo
ebs-plugin csi-provisioner csi-attacher csi-snapshotter csi-resizer liveness-probe
# csinode 확인
❯ kubectl api-resources | grep -i csi
csidrivers storage.k8s.io/v1 false CSIDriver
csinodes storage.k8s.io/v1 false CSINode
csistoragecapacities storage.k8s.io/v1 true CSIStorageCapacity
❯ kubectl get csinodes
NAME DRIVERS AGE
ip-192-168-1-115.ap-northeast-2.compute.internal 1 11h
ip-192-168-2-36.ap-northeast-2.compute.internal 1 11h
ip-192-168-3-152.ap-northeast-2.compute.internal 1 11h
❯ kubectl describe csinodes
Name: ip-192-168-1-115.ap-northeast-2.compute.internal
Labels: <none>
Annotations: storage.alpha.kubernetes.io/migrated-plugins:
kubernetes.io/aws-ebs,kubernetes.io/azure-disk,kubernetes.io/azure-file,kubernetes.io/cinder,kubernetes.io/gce-pd,kubernetes.io/portworx-v...
CreationTimestamp: Sat, 22 Feb 2025 13:57:49 +0900
Spec:
Drivers:
ebs.csi.aws.com:
Node ID: i-02bd989c032cbc389
Allocatables:
Count: 25
Topology Keys: [kubernetes.io/os topology.ebs.csi.aws.com/zone topology.kubernetes.io/zone]
❯ kubectl get csidrivers
NAME ATTACHREQUIRED PODINFOONMOUNT STORAGECAPACITY TOKENREQUESTS REQUIRESREPUBLISH MODES AGE
ebs.csi.aws.com true false false <unset> false Persistent 9m9s
efs.csi.aws.com false false false <unset> false Persistent 12
❯ kubectl describe csidrivers ebs.csi.aws.com
Name: ebs.csi.aws.com
Namespace:
Labels: app.kubernetes.io/component=csi-driver
app.kubernetes.io/managed-by=EKS
app.kubernetes.io/name=aws-ebs-csi-driver
app.kubernetes.io/version=1.39.0
Annotations: <none>
API Version: storage.k8s.io/v1
Kind: CSIDriver
Metadata:
Creation Timestamp: 2025-02-22T16:43:58Z
Resource Version: 144190
UID: b167e9ee-470a-4b1a-86fc-a04633ee8ea1
Spec:
Attach Required: true
Fs Group Policy: ReadWriteOnceWithFSType
Pod Info On Mount: false
Requires Republish: false
Se Linux Mount: false
Storage Capacity: false
Volume Lifecycle Modes:
Persistent
Events: <none>
EBS CSI Driver를 추가하였으므로, 이제 EKS에 EBS 볼륨을 동적으로 생성하고 관리할 수 있습니다.
예제로 PVC/PV를 사용하여 워드프레스 배포해보는 실습을 진행해보겠습니다.
https://kubernetes.io/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/
Example: Deploying WordPress and MySQL with Persistent Volumes
This tutorial shows you how to deploy a WordPress site and a MySQL database using Minikube. Both applications use PersistentVolumes and PersistentVolumeClaims to store data. A PersistentVolume (PV) is a piece of storage in the cluster that has been manuall
kubernetes.io
# 사용하고 싶은 비밀번호 추가
❯ cat <<EOF >./kustomization.yaml
secretGenerator:
- name: mysql-pass
literals:
- password=hellouz818
EOF
❯ curl -LO https://k8s.io/examples/application/wordpress/mysql-deployment.yaml
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 162 100 162 0 0 560 0 --:--:-- --:--:-- --:--:-- 591
100 1442 100 1442 0 0 2035 0 --:--:-- --:--:-- --:--:-- 15673
❯ curl -LO https://k8s.io/examples/application/wordpress/wordpress-deployment.yaml
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 162 100 162 0 0 759 0 --:--:-- --:--:-- --:--:-- 778
100 1341 100 1341 0 0 1778 0 --:--:-- --:--:-- --:--:-- 0
# 다만 EBS를 볼륨으로 쓰고자 PVC에 storageclass 추가
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
labels:
app: wordpress
spec:
accessModes:
- ReadWriteOnce
storageClassName: gp2
resources:
requests:
storage: 20Gi
❯ kubectl apply -k ./ 11s ○ myeks 03:03:54
secret/mysql-pass-k7bm2d8695 created
service/wordpress created
service/wordpress-mysql created
persistentvolumeclaim/mysql-pv-claim created
persistentvolumeclaim/wp-pv-claim created
deployment.apps/wordpress created
deployment.apps/wordpress-mysql created
하지만 워드프레스 접속은 Ingress(ALB, group 활용) - Service(ClusterIP)로 설정하는 경우에는 추가적인 설정이 더 필요합니다.
우선, Service 타입은 ClusterIP로 변경하고 ALB를 Ingress로 사용하기 위해 AWS Load Balancer Controller를 배포해야합니다.
❯ helm repo add eks https://aws.github.io/eks-charts
❯ helm repo update
❯ helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n kube-system \
--set clusterName=myeks \
--set serviceAccount.create=false \
--set serviceAccount.name=aws-load-balancer-controller
NAME: aws-load-balancer-controller
LAST DEPLOYED: Sun Feb 23 03:15:34 2025
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
AWS Load Balancer controller installed!
# 배포한 설정
apiVersion: v1
kind: Service
metadata:
name: wordpress
labels:
app: wordpress
spec:
ports:
- port: 80
selector:
app: wordpress
tier: frontend
type: ClusterIP
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wp-pv-claim
labels:
app: wordpress
spec:
accessModes:
- ReadWriteOnce
storageClassName: gp2
resources:
requests:
storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress
labels:
app: wordpress
spec:
selector:
matchLabels:
app: wordpress
tier: frontend
strategy:
type: Recreate
template:
metadata:
labels:
app: wordpress
tier: frontend
spec:
containers:
- image: wordpress:6.2.1-apache
name: wordpress
env:
- name: WORDPRESS_DB_HOST
value: wordpress-mysql
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-pass
key: password
- name: WORDPRESS_DB_USER
value: wordpress
ports:
- containerPort: 80
name: wordpress
volumeMounts:
- name: wordpress-persistent-storage
mountPath: /var/www/html
volumes:
- name: wordpress-persistent-storage
persistentVolumeClaim:
claimName: wp-pv-claim
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: wordpress-ingress
namespace: default
annotations:
alb.ingress.kubernetes.io/certificate-arn: arn:~~
alb.ingress.kubernetes.io/group.name: study
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":443}]'
alb.ingress.kubernetes.io/load-balancer-name: myeks-ingress-alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/ssl-redirect: "443"
alb.ingress.kubernetes.io/success-codes: 200-399
alb.ingress.kubernetes.io/target-type: ip
spec:
ingressClassName: alb
rules:
- host: wordpress.hellouz818.com # 사전에 구입한 도메인
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: wordpress
port:
number: 80
++ 참고) EBS 볼륨 확인 명령어
실습하였을 때 EBS를 볼륨으로 사용하고 있는 것을 볼 수 있습니다.
# 워커 노드 EBS 볼륨 확인
❯ aws ec2 describe-volumes --filters Name=tag:Name,Values=$CLUSTER_NAME-ng1-Node --output table
--------------------------------------------------------------
| DescribeVolumes |
+------------------------------------------------------------+
|| Volumes ||
|+---------------------+------------------------------------+|
|| AvailabilityZone | ap-northeast-2a ||
|| CreateTime | 2025-02-22T04:57:06.422000+00:00 ||
|| Encrypted | False ||
|| Iops | 3000 ||
|| MultiAttachEnabled | False ||
|| Size | 120 ||
|| SnapshotId | snap-09234f0993e1a70d3 ||
|| State | in-use ||
|| Throughput | 125 ||
|| VolumeId | vol-06d41d88a511ce918 ||
|| VolumeType | gp3 ||
|+---------------------+------------------------------------+|
||| Attachments |||
||+------------------------+-------------------------------+||
||| AttachTime | 2025-02-22T04:57:06+00:00 |||
||| DeleteOnTermination | True |||
||| Device | /dev/xvda |||
||| InstanceId | i-02bd989c032cbc389 |||
||| State | attached |||
||| VolumeId | vol-06d41d88a511ce918 |||
||+------------------------+-------------------------------+||
||| Operator |||
||+------------------------------+-------------------------+||
||| Managed | False |||
||+------------------------------+-------------------------+||
||| Tags |||
||+------------------------------------+-------------------+||
||| Key | Value |||
||+------------------------------------+-------------------+||
||| alpha.eksctl.io/nodegroup-type | managed |||
||| Name | myeks-ng1-Node |||
||| alpha.eksctl.io/nodegroup-name | ng1 |||
||| eks:nodegroup-name | ng1 |||
||| eks:cluster-name | myeks |||
--------------------------------------------------------------
# 워커 노드에서 파드에 추가한 EBS 볼륨 확인 (워드프레스 실습 전)
❯ aws ec2 describe-volumes --filters Name=tag:ebs.csi.aws.com/cluster,Values=true --output table
-----------------
|DescribeVolumes|
+---------------+
# 워커 노드에서 파드에 추가한 EBS 볼륨 확인 (워드프레스 실습 후)
-----------------------------------------------------------------------------------------------------------
| DescribeVolumes |
+---------------------------------------------------------------------------------------------------------+
|| Volumes ||
|+--------------------------------------+----------------------------------------------------------------+|
|| AvailabilityZone | ap-northeast-2c ||
|| CreateTime | 2025-02-22T18:06:53.448000+00:00 ||
|| Encrypted | False ||
|| Iops | 100 ||
|| MultiAttachEnabled | False ||
|| Size | 20 ||
|| SnapshotId | ||
|| State | in-use ||
|| VolumeId | vol-0172e8f746fc14ca9 ||
|| VolumeType | gp2 ||
|+--------------------------------------+----------------------------------------------------------------+|
||| Attachments |||
||+--------------------------------------------+--------------------------------------------------------+||
||| AttachTime | 2025-02-22T18:06:57+00:00 |||
||| DeleteOnTermination | False |||
||| Device | /dev/xvdaa |||
||| InstanceId | i-05491bd445d37f0f3 |||
||| State | attached |||
||| VolumeId | vol-0172e8f746fc14ca9 |||
||+--------------------------------------------+--------------------------------------------------------+||
||| Operator |||
||+-------------------------------------------------------+---------------------------------------------+||
||| Managed | False |||
||+-------------------------------------------------------+---------------------------------------------+||
||| Tags |||
||+------------------------------------------+----------------------------------------------------------+||
||| Key | Value |||
||+------------------------------------------+----------------------------------------------------------+||
||| CSIVolumeName | pvc-f81bce58-7c94-463f-a2e9-e5d32d09c3e5 |||
||| KubernetesCluster | myeks |||
||| Name | myeks-dynamic-pvc-f81bce58-7c94-463f-a2e9-e5d32d09c3e5 |||
||| ebs.csi.aws.com/cluster | true |||
||| kubernetes.io/cluster/myeks | owned |||
||| kubernetes.io/created-for/pvc/namespace | default |||
||| kubernetes.io/created-for/pv/name | pvc-f81bce58-7c94-463f-a2e9-e5d32d09c3e5 |||
||| kubernetes.io/created-for/pvc/name | mysql-pv-claim |||
||+------------------------------------------+----------------------------------------------------------+||

AWS EFS Controller
EKS에서 EFS를 스토리지로 사용하기 위해서는 EFS CSI Driver 설치가 필요합니다.
AWS CSI driver의 동작 원리는 EBS CSI driver와 유사합니다.

aws-efs-csi-driver 전체 버전 정보와 기본 설치 버전(True) 정보 확인합니다.
ISRA 설정(AmazonEFSCSIDriverPolicy)을 사용하고 ISRA를 확인합니다.
AmazonEKS_EFS_CSI_DriverRole이라는 IAM 역할을 생성하고, AmazonEFSCSIDriverPolicy 정책을 해당 IAM 역할에 부여합니다. efs-csi-controller-sa 서비스 계정이 EFS API를 호출할 수 있도록 설정합니다.
# EFS 정보 확인
❯ aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text
fs-067eb7f3b3ee1b039
# 아래는 aws-efs-csi-driver 전체 버전 정보와 기본 설치 버전(True) 정보 확인
❯ aws eks describe-addon-versions \
--addon-name aws-efs-csi-driver \
--kubernetes-version 1.31 \
--query "addons[].addonVersions[].[addonVersion, compatibilities[].defaultVersion]" \
--output text
v2.1.4-eksbuild.1
True
v2.1.3-eksbuild.1
False
v2.1.2-eksbuild.1
False
v2.1.1-eksbuild.1
False
v2.1.0-eksbuild.1
False
v2.0.9-eksbuild.1
False
v2.0.8-eksbuild.1
False
v2.0.7-eksbuild.1
False
v2.0.6-eksbuild.2
False
v2.0.6-eksbuild.1
False
v2.0.5-eksbuild.1
False
v2.0.4-eksbuild.1
False
v2.0.3-eksbuild.1
False
v2.0.2-eksbuild.1
False
v2.0.1-eksbuild.1
False
v2.0.0-eksbuild.1
False
v1.7.7-eksbuild.1
False
v1.7.6-eksbuild.2
False
v1.7.6-eksbuild.1
# ISRA 설정 : 고객관리형 정책 AmazonEKS_EFS_CSI_Driver_Policy 사용
❯ eksctl create iamserviceaccount \
--name efs-csi-controller-sa \
--namespace kube-system \
--cluster ${CLUSTER_NAME} \
--attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEFSCSIDriverPolicy \
--approve \
--role-only \
--role-name AmazonEKS_EFS_CSI_DriverRole
# ISRA 확인
❯ eksctl get iamserviceaccount --cluster ${CLUSTER_NAME}
NAMESPACE NAME ROLE ARN
kube-system aws-load-balancer-controller arn:aws:iam::941377114730:role/eksctl-myeks-addon-iamserviceaccount-kube-sys-Role1-yq8VPD5xPBny
kube-system ebs-csi-controller-sa arn:aws:iam::941377114730:role/AmazonEKS_EBS_CSI_DriverRole
kube-system efs-csi-controller-sa arn:aws:iam::941377114730:role/AmazonEKS_EFS_CSI_DriverRole
Amazon EFS CSI driver addon 배포합니다.
# Amazon EFS CSI driver addon 배포(설치)
❯ export ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
❯ eksctl create addon --name aws-efs-csi-driver --cluster ${CLUSTER_NAME} --service-account-role-arn arn:aws:iam::${ACCOUNT_ID}:role/AmazonEKS_EFS_CSI_DriverRole --force
❯ kubectl get sa -n kube-system efs-csi-controller-sa -o yaml | head -5
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::941377114730:role/AmazonEKS_EFS_CSI_DriverRole
❯ eksctl get addon --cluster ${CLUSTER_NAME}
NAME VERSION STATUS ISSUES IAMROLE UPDATE AVAILABLE CONFIGURATION VALUES POD IDENTITY ASSOCIATION ROLES
aws-ebs-csi-driver v1.39.0-eksbuild.1 ACTIVE 0 arn:aws:iam::941377114730:role/AmazonEKS_EBS_CSI_DriverRole
aws-efs-csi-driver v2.1.4-eksbuild.1 ACTIVE 0 arn:aws:iam::941377114730:role/AmazonEKS_EFS_CSI_DriverRole
coredns v1.11.4-eksbuild.2 ACTIVE 0
kube-proxy v1.31.3-eksbuild.2 ACTIVE 0
metrics-server v0.7.2-eksbuild.2 ACTIVE 0
vpc-cni v1.19.2-eksbuild.5 ACTIVE 0 arn:aws:iam::941377114730:role/eksctl-myeks-addon-vpc-cni-Role1-cSbYmEhHAYbN enableNetworkPolicy: "true"
❯ kubectl get pod -n kube-system -l "app.kubernetes.io/name=aws-efs-csi-driver,app.kubernetes.io/instance=aws-efs-csi-driver"
NAME READY STATUS RESTARTS AGE
efs-csi-controller-64fc4bc65d-2ksl9 3/3 Running 0 2m50s
efs-csi-controller-64fc4bc65d-sllvp 3/3 Running 0 2m50s
efs-csi-node-2bh7z 3/3 Running 0 2m50s
efs-csi-node-8cbv8 3/3 Running 0 2m50s
efs-csi-node-8qld7 3/3 Running 0 2m50s
❯ kubectl get pod -n kube-system -l app=efs-csi-controller -o jsonpath='{.items[0].spec.containers[*].name}' ; echo
efs-plugin csi-provisioner liveness-probe
AWS → EFS → 파일 시스템 : 네트워크 확인

EFS 파일 시스템을 파드가 사용할 수 있도록 설정하겠습니다.
[root@operator-host ~]# git clone https://github.com/kubernetes-sigs/aws-efs-csi-driver.git /root/efs-csi
Cloning into '/root/efs-csi'...
remote: Enumerating objects: 30760, done.
remote: Counting objects: 100% (5451/5451), done.
remote: Compressing objects: 100% (1512/1512), done.
remote: Total 30760 (delta 4230), reused 4145 (delta 3902), pack-reused 25309 (from 3)
Receiving objects: 100% (30760/30760), 28.56 MiB | 11.23 MiB/s, done.
Resolving deltas: 100% (16621/16621), done.
[root@operator-host ~]# cd /root/efs-csi/examples/kubernetes/multiple_pods/specs && tree
.
├── claim.yaml
├── pod1.yaml
├── pod2.yaml
├── pv.yaml
└── storageclass.yaml
0 directories, 5 files
# aws configure 이후
# EFS 스토리지클래스 생성 및 확인
(admin:N/A) [root@operator-host specs]# cat storageclass.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: efs-sc
provisioner: efs.csi.aws.com
(admin:N/A) [root@operator-host specs]# kubectl apply -f storageclass.yaml
storageclass.storage.k8s.io/efs-sc created
(admin:N/A) [root@operator-host specs]# kubectl get sc efs-sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
efs-sc efs.csi.aws.com Delete Immediate false 10s
# PV 생성 및 확인 : volumeHandle을 자신의 EFS 파일시스템ID로 변경
(admin:N/A) [root@operator-host specs]# EfsFsId=$(aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text)
(admin:N/A) [root@operator-host specs]# ls
claim.yaml pod1.yaml pod2.yaml pv.yaml storageclass.yaml
(admin:N/A) [root@operator-host specs]# sed -i "s/fs-4af69aab/$EfsFsId/g" pv.yaml
(admin:N/A) [root@operator-host specs]# cat pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: efs-pv
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: efs-sc
csi:
driver: efs.csi.aws.com
volumeHandle: fs-067eb7f3b3ee1b039
(admin:N/A) [root@operator-host specs]# kubectl apply -f pv.yaml
persistentvolume/efs-pv created
(admin:N/A) [root@operator-host specs]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
efs-pv 5Gi RWX Retain Available efs-sc <unset> 12s
pvc-a80f7150-3023-48b0-af32-02b7e365aafe 20Gi RWO Delete Bound default/wp-pv-claim gp2 <unset> 107m
pvc-f81bce58-7c94-463f-a2e9-e5d32d09c3e5 20Gi RWO Delete Bound default/mysql-pv-claim gp2 <unset> 107m
# PVC 생성 및 확인
(admin:N/A) [root@operator-host specs]# cat claim.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: efs-claim
spec:
accessModes:
- ReadWriteMany
storageClassName: efs-sc
resources:
requests:
storage: 5Gi
(admin:N/A) [root@operator-host specs]# kubectl apply -f claim.yaml
persistentvolumeclaim/efs-claim created
(admin:N/A) [root@operator-host specs]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
efs-claim Bound efs-pv 5Gi RWX efs-sc <unset> 15s
mysql-pv-claim Bound pvc-f81bce58-7c94-463f-a2e9-e5d32d09c3e5 20Gi RWO gp2 <unset> 108m
wp-pv-claim Bound pvc-a80f7150-3023-48b0-af32-02b7e365aafe 20Gi RWO gp2 <unset> 108m
실제 EFS를 볼륨으로 사용하는 Pod를 생성해보도록 하겠습니다.
(admin:N/A) [root@operator-host specs]# cat pod1.yaml pod2.yaml
apiVersion: v1
kind: Pod
metadata:
name: app1
spec:
containers:
- name: app1
image: busybox
command: ["/bin/sh"]
args: ["-c", "while true; do echo $(date -u) >> /data/out1.txt; sleep 5; done"]
volumeMounts:
- name: persistent-storage
mountPath: /data
volumes:
- name: persistent-storage
persistentVolumeClaim:
claimName: efs-claim
apiVersion: v1
kind: Pod
metadata:
name: app2
spec:
containers:
- name: app2
image: busybox
command: ["/bin/sh"]
args: ["-c", "while true; do echo $(date -u) >> /data/out2.txt; sleep 5; done"]
volumeMounts:
- name: persistent-storage
mountPath: /data
volumes:
- name: persistent-storage
persistentVolumeClaim:
claimName: efs-claim
(admin:N/A) [root@operator-host specs]# kubectl apply -f pod1.yaml,pod2.yaml
pod/app1 created
pod/app2 created
(admin:N/A) [root@operator-host specs]# kubectl get pods
NAME READY STATUS RESTARTS AGE
app1 1/1 Running 0 49s
app2 1/1 Running 0 49s
wordpress-84d786f98-xmdv8 1/1 Running 0 110m
wordpress-mysql-987f4c89f-rr7pw 1/1 Running 0 110m
(admin:N/A) [root@operator-host specs]# kubectl exec -ti app1 -- sh -c "df -hT -t nfs4"
Filesystem Type Size Used Available Use% Mounted on
127.0.0.1:/ nfs4 8.0E 0 8.0E 0% /data
(admin:N/A) [root@operator-host specs]# kubectl exec -ti app2 -- sh -c "df -hT -t nfs4"
Filesystem Type Size Used Available Use% Mounted on
127.0.0.1:/ nfs4 8.0E 0 8.0E 0% /data
(admin:N/A) [root@operator-host specs]# tree /mnt/myefs
/mnt/myefs [error opening dir]
0 directories, 0 files
(admin:N/A) [root@operator-host specs]# tail -f /mnt/myefs/out1.txt
tail: cannot open ‘/mnt/myefs/out1.txt’ for reading: No such file or directory
tail: no files remaining
(admin:N/A) [root@operator-host specs]# tail -f /mnt/myefs/out2.txt
tail: cannot open ‘/mnt/myefs/out2.txt’ for reading: No such file or directory
tail: no files remaining
(admin:N/A) [root@operator-host specs]# kubectl exec -ti app1 -- tail -f /data/out1.txt
Sat Feb 22 19:57:47 UTC 2025
Sat Feb 22 19:57:52 UTC 2025
Sat Feb 22 19:57:57 UTC 2025
Sat Feb 22 19:58:02 UTC 2025
Sat Feb 22 19:58:07 UTC 2025
Sat Feb 22 19:58:12 UTC 2025
Sat Feb 22 19:58:17 UTC 2025
Sat Feb 22 19:58:22 UTC 2025
Sat Feb 22 19:58:27 UTC 2025
Sat Feb 22 19:58:32 UTC 2025
^Ccommand terminated with exit code 130
(admin:N/A) [root@operator-host specs]# kubectl exec -ti app2 -- tail -f /data/out2.txt
Sat Feb 22 19:57:52 UTC 2025
Sat Feb 22 19:57:57 UTC 2025
Sat Feb 22 19:58:02 UTC 2025
Sat Feb 22 19:58:07 UTC 2025
Sat Feb 22 19:58:12 UTC 2025
Sat Feb 22 19:58:17 UTC 2025
Sat Feb 22 19:58:22 UTC 2025
Sat Feb 22 19:58:27 UTC 2025
Sat Feb 22 19:58:32 UTC 2025
Sat Feb 22 19:58:38 UTC 2025
^Ccommand terminated with exit code 130
++) PV는 5Gi로 설정했는데 df -hT -t nfs4는 8.0E(엑사바이트)로 보일까요?
EFS는 블록 스토리지가 아니라 네트워크 파일 시스템입니다.
EBS와 같이 스토리지 크기를 미리 정하지 않고, EFS는 자동 확장 되기 때문에 고정된 크기를 가지지 않습니다. 따라서 efs-pv의 5Gi 설정은 쿠버네티스 리소스 관리 목적일 뿐(PVC 매칭을 위한 설정값), 실제 용량 제한이 아닙니다.
++) df -hT에서 8.0E가 나오는 이유는 무엇일까요?
AWS는 EFS를 무제한 확장 가능하도록 설계했기 때문입니다.
NFS 마운트 시 df -hT 명령어가 무한한 공간을 제공한다고 인식했기 때문에 8.0E로 표시되는 것입니다.
따라서 EFS에서 사용량을 직접 확인하려면 aws efs describe-file-systems 또는 du -sh 명령어 사용하여 마운트한 상태에서 디렉터리 사용량을 조회하는 것이 좋습니다.
'스터디 > AEWS' 카테고리의 다른 글
| [AEWS] 4주차 CloudWatch를 활용한 EKS 모니터링 - Container Insights 활용하기 (0) | 2025.03.02 |
|---|---|
| [AEWS] 4주차 EKS 로깅 (컨트롤 플레인, 데이터 플레인) (0) | 2025.03.02 |
| [AEWS] 3주차 쿠버네티스 스토리지 이해하기 (emptyDir, hostPath, PV, PVC, storageClass, CSI) (0) | 2025.02.22 |
| [AEWS] 2주차 EKS VPC CNI를 통한 파드 간 통신 (작성중) (0) | 2025.02.16 |
| [AEWS] 2주차 EKS 노드 최대 파드 생성 갯수 (0) | 2025.02.16 |