이번 주는 EKS에서 Storage 관련 내용과 노드 그룹을 추가하는 방법을 알아봤습니다.
EKS Storage
EKS에서는 Amazon CSI driver를 통해 스토리지 볼륨을 생성하고 관리합니다. 먼저 CSI에 대해 알아보겠습니다.
CSI(Container Storage Interface)
CSI는 storage 벤더가 여러 컨테이너 오케스트레이션 시스템에서 동작하는 플러그인을 개발하기 위한 표준(인터페이스)을 정의합니다.
다음과 같은 API를 정의합니다. (참고)
- 볼륨의 동적 프로비저닝 및 해제
- 노드에 볼륨 부착 및 해제 / mount 및 umount
- 볼륨 스냅샷 생성 및 삭제
- 스냅샷으로부터 신규 볼륨 생성 등
CSI driver
CSI 표준을 따라 구현하여 실제 스토리지 시스템과 kubernetes이 함께 작동하도록 설정합니다.
Amazon CSI driver
AWS의 스토리지 종류(EBS, EFS, FSX 등)에 따라 CSI driver를 각각 제공합니다.
CSI driver의 구성 요소는 아래와 같습니다.
csi-controller는 api server에 볼륨 관련 요청이 있는지 확인하고 AWS API를 호출하는 역할을 합니다.
csi-node는 각 노드에서 실행되며, 실제 볼륨을 Pod에 마운트 하는 역할을 합니다.
이제 AWS에서 주로 사용하는 CSI driver에 대해 알아보겠습니다.
Amazon EBS CSI driver
EBS를 pv의 볼륨으로 사용하기 위해 설치하는 driver입니다.
EBS를 사용하기 때문에 동시에 하나의 노드에만 마운트가 가능하고, AZ도 고려를 해야 합니다.
EKS add-on을 통해 설치가 가능하며, driver에서 사용하는 service account에 AmazonEBSCSIDriverPolicy
정책이 필요합니다.
해당 정책은 AWS managed 정책이며 볼륨 생성/삭제, snapshot 생성/삭제, 볼륨 attach/detach 등의 권한이 포함되어 있습니다.
Amazon EFS CSI driver
EFS를 pv의 볼륨으로 사용하기 위해 설치하는 driver입니다.
여러 pod에서 하나의 볼륨 공유가 필요할 때 사용할 수 있습니다. 하지만 테스트를 통해 성능 확인 후 사용이 필요합니다.
helm이나 별도의 manifest를 사용해서 설치할 수 있습니다.
별도의 IAM 정책을 만들고 driver에서 사용하는 service account에 연결을 해야 합니다.
해당 정책은 주로 AmazonEKS_EFS_CSI_Driver_Policy
라는 이름으로 생성하지만 사용자 관리 정책이기 때문에 이름 변경이 가능합니다. 또한, access point 생성/삭제 등의 권한을 갖습니다.
권한을 통해 유추할 수 있지만, EFS CSI driver는 access point는 생성할 수 있지만 EFS 생성에 대한 권한은 갖고 있지 않습니다. 따라서 EFS를 미리 생성할 필요가 있습니다.
EKS의 Storage Class
Storage Class는 클러스터 내에서 동적으로 볼륨을 생성할 때 사용합니다.
이는 pvc 생성 시 pv를 자동으로 생성할 때 사용하는 개념입니다.
storage class에는 이름과 provisioner 정보가 포함됩니다.
EKS에는 기본적으로 gp2 storage class가 생성됩니다. 추가로 필요한 storege class(gp3 등)는 직접 생성이 필요합니다.
기타
주로 사용하는 pv, pvc 같은 스토리지 오브젝트 외에 볼륨의 snapshot을 만들 때 사용하는 오브젝트도 있습니다.
두 오브젝트 모두 api 그룹(snapshot.storage.k8s.io/v1)을 통해 제공됩니다. 참고로 pv, pvc는 core api 그룹에 포함되어 있습니다.
- VolumeSnapshot
- 사용 중인 pvc의 볼륨에 대해서 snapshot을 생성 요청
- VolumeSnapshot 생성 시 실제 snapshot인 VolumeSnapshotContent가 생성되고 두 오브젝트는 pvc와 pv의 관계와 유사함
- VolumeSnapshot은 이미 만들어진 VolumeSnapshotContent를 사용할 수도 있고 동적으로 생성 후에 사용할 수도 있음
- VolumeSnapshot 삭제 시 VolumeSnapshotContent 삭제 여부도 정책에 설정할 수 있음
- VolumeSnapshotClass
- Storage Class와 유사하게 snapshot을 생성할 때 속성을 지정하는 역할
실습
이번 주부터는 AWS loadbalancer controller가 포함된 yaml 파일을 활용하여 클러스터를 생성합니다.
노드에서 사용할 수 있는 볼륨 수 확인
노드의 describe 결과에서 Allocatable 아래 설정된 값을 보면 해당 노드에 생성할 수 있는 pod, 부착할 수 있는 볼륨의 수 등을 확인할 수 있습니다.
$ k describe no | grep Allocatable -A7
Allocatable:
attachable-volumes-aws-ebs: 25
cpu: 1930m
ephemeral-storage: 27905944324
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 3388364Ki
pods: 17
...
EBS CSI driver 설치 및 예제
EBS CSI driver를 설치해보겠습니다.
# IRSA 설정
eksctl create iamserviceaccount \
--name ebs-csi-controller-sa \
--namespace kube-system \
--cluster ${CLUSTER_NAME} \
--attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \
--approve \
--role-only \
--role-name AmazonEKS_EBS_CSI_DriverRole
# Amazon EBS CSI driver addon 추가
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
# IRSA 확인
k get sa -n kube-system ebs-csi-controller-sa -o yaml | head -5
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::xxxxxxxxxxxx:role/AmazonEKS_EBS_CSI_DriverRole
# EBS CSI pod 확인
k get po -n kube-system | grep -i csi
ebs-csi-controller-67658f895c-8bpkf 6/6 Running 0 3m31s
ebs-csi-controller-67658f895c-jlnjn 6/6 Running 0 3m31s
ebs-csi-node-b7bvd 3/3 Running 0 3m31s
ebs-csi-node-fkqgc 3/3 Running 0 3m31s
ebs-csi-node-tqft2 3/3 Running 0 3m31s
# EKS Addon 현황 확인
$ eksctl get addon --cluster ${CLUSTER_NAME}
2023-05-08 20:27:14 [ℹ] Kubernetes version "1.24" in use by cluster "myeks"
2023-05-08 20:27:14 [ℹ] getting all addons
2023-05-08 20:27:16 [ℹ] to see issues for an addon run `eksctl get addon --name <addon-name> --cluster <cluster-name>`
NAME VERSION STATUS ISSUES IAMROLE UPDATE AVAILABLE CONFIGURATION VALUES
aws-ebs-csi-driver v1.18.0-eksbuild.1 ACTIVE 0 arn:aws:iam::xxxxxxxxxxxx:role/AmazonEKS_EBS_CSI_DriverRole
coredns v1.9.3-eksbuild.3 ACTIVE 0
kube-proxy v1.24.10-eksbuild.2 ACTIVE 0
vpc-cni v1.12.6-eksbuild.1 ACTIVE 0 arn:aws:iam::xxxxxxxxxxxx:role/eksctl-myeks-addon-vpc-cni-Role1-1H4JLKF6W7LU1
클러스터 내 Storage Class를 확인하면 gp2를 볼 수 있습니다.
k get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
gp2 (default) kubernetes.io/aws-ebs Delete WaitForFirstConsumer false 36m
최신 볼륨 타입을 사용하기 위해 gp3 Storage Class를 추가하겠습니다.
$ cat <<EOT > gp3-sc.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: gp3
allowVolumeExpansion: true
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
parameters:
type: gp3
allowAutoIOPSPerGBIncrease: 'true'
encrypted: 'true'
#fsType: ext4 # 기본값이 ext4 이며 xfs 등 변경 가능 >> 단 스냅샷 경우 ext4를 기본으로하여 동작하여 xfs 사용 시 문제가 될 수 있음 - 테스트해보자
EOT
allowVolumeExpansion 옵션을 true로 설정했기 때문에 자동으로 볼륨 증설이 가능합니다.
$ kubectl apply -f gp3-sc.yaml
$ k get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
gp2 (default) kubernetes.io/aws-ebs Delete WaitForFirstConsumer false 39m
gp3 ebs.csi.aws.com Delete WaitForFirstConsumer true 18s
이제 pvc를 생성해서 pod에 연결해보겠습니다.
먼저 pvc를 생성합니다.
$ cat <<EOT > awsebs-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ebs-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 4Gi
storageClassName: gp3
EOT
$ kubectl apply -f awsebs-pvc.yaml
$ k get pvc,pv
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/ebs-claim Pending gp3 32s
pvc를 생성한 후에 pvc, pv를 조회하면 pv는 아직 생성되지 않은 것을 볼 수 있습니다.
이제 pod에 pvc를 연결해보겠습니다.
$ cat <<EOT > awsebs-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
terminationGracePeriodSeconds: 3
containers:
- name: app
image: centos
command: ["/bin/sh"]
args: ["-c", "while true; do echo \$(date -u) >> /data/out.txt; sleep 5; done"]
volumeMounts:
- name: persistent-storage
mountPath: /data
volumes:
- name: persistent-storage
persistentVolumeClaim:
claimName: ebs-claim
EOT
$ kubectl apply -f awsebs-pod.yaml
다시 객체들을 조회 해보겠습니다.
pv가 동적으로 생성된 것을 확인할 수 있습니다.
$ kubectl get pvc,pv,pod
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/ebs-claim Bound pvc-2cc56fdc-83b7-48cb-8020-90cce998f4af 4Gi RWO gp3 3m4s
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/pvc-2cc56fdc-83b7-48cb-8020-90cce998f4af 4Gi RWO Delete Bound default/ebs-claim gp3 46s
NAME READY STATUS RESTARTS AGE
pod/app 1/1 Running 0 50s
$ kubectl get VolumeAttachment
NAME ATTACHER PV NODE ATTACHED AGE
csi-f7c3e8530a92fd0c9ddcce17d7eca88254e983a3f1924bf93e2c7561555df271 ebs.csi.aws.com pvc-2cc56fdc-83b7-48cb-8020-90cce998f4af ip-192-168-3-73.ap-northeast-2.compute.internal true 62s
pv가 동적으로 생성된 것을 확인할 수 있습니다. 생성된 pv를 자세히 보면 Node Affinity가 자동으로 설정된 것을 볼 수 있습니다.
EBS는 같은 AZ에 실행 중인 EC2와 연결할 수 있기 때문에 해당 설정이 필요합니다.
$ kubectl get pv -o yaml
...
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: topology.ebs.csi.aws.com/zone
operator: In
values:
- ap-northeast-2c
persistentVolumeReclaimPolicy: Delete
storageClassName: gp3
volumeMode: Filesystem
status:
phase: Bound
...
실제 pod는 ap-northeast-2c AZ에 있는 노드에서 실행중인 것을 알 수 있습니다.
$ k get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
app 1/1 Running 0 6m44s 192.168.3.214 ip-192-168-3-73.ap-northeast-2.compute.internal <none> <none>
$ kubectl get node --label-columns=topology.ebs.csi.aws.com/zone,topology.kubernetes.io/zone
NAME STATUS ROLES AGE VERSION ZONE ZONE
ip-192-168-1-148.ap-northeast-2.compute.internal Ready <none> 42m v1.24.11-eks-a59e1f0 ap-northeast-2a ap-northeast-2a
ip-192-168-2-67.ap-northeast-2.compute.internal Ready <none> 42m v1.24.11-eks-a59e1f0 ap-northeast-2b ap-northeast-2b
ip-192-168-3-73.ap-northeast-2.compute.internal Ready <none> 42m v1.24.11-eks-a59e1f0 ap-northeast-2c ap-northeast-2c
볼륨 snapshot 생성 및 복구
이번에는 pv로 사용 중인 EBS 볼륨의 snapshot을 생성하기 위해 관련 구성 요소를 설치해보겠습니다.
# Install Snapshot CRDs
$ curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml
$ curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml
$ curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml
$ kubectl apply -f snapshot.storage.k8s.io_volumesnapshots.yaml,snapshot.storage.k8s.io_volumesnapshotclasses.yaml,snapshot.storage.k8s.io_volumesnapshotcontents.yaml
$ kubectl get crd | grep snapshot
volumesnapshotclasses.snapshot.storage.k8s.io 2023-05-08T11:48:24Z
volumesnapshotcontents.snapshot.storage.k8s.io 2023-05-08T11:48:24Z
volumesnapshots.snapshot.storage.k8s.io 2023-05-08T11:48:23Zkubectl api-resources | grep snapshot
$ kubectl api-resources | grep snapshot
volumesnapshotclasses vsclass,vsclasses snapshot.storage.k8s.io/v1 false VolumeSnapshotClass
volumesnapshotcontents vsc,vscs snapshot.storage.k8s.io/v1 false VolumeSnapshotContent
volumesnapshots vs snapshot.storage.k8s.io/v1 true VolumeSnapshot
# Install Common Snapshot Controller
$ curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/rbac-snapshot-controller.yaml
$ curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/setup-snapshot-controller.yaml
$ kubectl apply -f rbac-snapshot-controller.yaml,setup-snapshot-controller.yaml
$ kubectl get deploy -n kube-system snapshot-controller
NAME READY UP-TO-DATE AVAILABLE AGE
snapshot-controller 2/2 2 2 82s
$ kubectl get pod -n kube-system -l app=snapshot-controller
NAME READY STATUS RESTARTS AGE
snapshot-controller-76494bf6c9-4bkwj 1/1 Running 0 98s
snapshot-controller-76494bf6c9-lth8k 1/1 Running 0 98s
# Install Snapshotclass
$ curl -s -O https://raw.githubusercontent.com/kubernetes-sigs/aws-ebs-csi-driver/master/examples/kubernetes/snapshot/manifests/classes/snapshotclass.yaml
$ kubectl apply -f snapshotclass.yaml
$ kubectl get vsclass
NAME DRIVER DELETIONPOLICY AGE
csi-aws-vsc ebs.csi.aws.com Delete 30s
설치 과정을 보면 앞서 살펴본 VolumeSnapshot, VolumeSnapshotClass 등을 생성하는 것을 알 수 있습니다.
이제 snapshot을 생성하고 테스트 해보겠습니다.
앞서 만들어둔 pod에서 /data/out.txt 파일에 시간을 기록하고 있습니다. 해당 볼륨을 snapshot으로 복구했을 때 동일한 데이터가 있는지 확인해보겠습니다.
kubectl exec app -- tail -f /data/out.txt
Mon May 8 11:52:04 UTC 2023
Mon May 8 11:52:09 UTC 2023
Mon May 8 11:52:14 UTC 2023
Mon May 8 11:52:19 UTC 2023
Mon May 8 11:52:24 UTC 2023
Mon May 8 11:52:29 UTC 2023
Mon May 8 11:52:34 UTC 2023
Mon May 8 11:52:39 UTC 2023
Mon May 8 11:52:44 UTC 2023
Mon May 8 11:52:49 UTC 2023
Mon May 8 11:52:54 UTC 2023
먼저 ebs-volume-snapshot.yaml 라는 파일을 작성합니다.
앞에서 생성한 pvc(ebs-claim)와 volumeSnapshotClass(csi-aws-vsc)를 입력하고 VolumeSnapshot을 생성합니다.
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: ebs-volume-snapshot
spec:
volumeSnapshotClassName: csi-aws-vsc
source:
persistentVolumeClaimName: ebs-claim
volumesnapshot과 volumesnapshotcontents가 생성된 것을 볼 수 있습니다.
$ kubectl get volumesnapshot
NAME READYTOUSE SOURCEPVC SOURCESNAPSHOTCONTENT RESTORESIZE SNAPSHOTCLASS SNAPSHOTCONTENT CREATIONTIME AGE
ebs-volume-snapshot true ebs-claim 4Gi csi-aws-vsc snapcontent-2eaab85c-ce5f-4270-b32b-23a7ce61eae7 2m44s 2m44s
$ kubectl get volumesnapshotcontents
NAME READYTOUSE RESTORESIZE DELETIONPOLICY DRIVER VOLUMESNAPSHOTCLASS VOLUMESNAPSHOT VOLUMESNAPSHOTNAMESPACE AGE
snapcontent-2eaab85c-ce5f-4270-b32b-23a7ce61eae7 true 4294967296 Delete ebs.csi.aws.com csi-aws-vsc ebs-volume-snapshot default 2m48s
실제 AWS 볼륨 snapshot이 생성됐는지 확인해보겠습니다.
aws ec2 describe-snapshots --owner-ids self --query 'Snapshots[]' --output table
-----------------------------------------------------------------------------------------------------
| DescribeSnapshots |
+-------------+-------------------------------------------------------------------------------------+
| Description| Created by AWS EBS CSI driver for volume vol-0545776c5686066d6 |
| Encrypted | True |
| KmsKeyId | arn:aws:kms:ap-northeast-2:xxxxxxxxxxx:key/b270e6dd-9226-46ac-8e69-68729a56795a |
| OwnerId | 738740507565 |
| Progress | 100% |
| SnapshotId | snap-03b511aeff38a0e57 |
| StartTime | 2023-05-08T11:55:58.794000+00:00 |
| State | completed |
| StorageTier| standard |
| VolumeId | vol-0545776c5686066d6 |
| VolumeSize | 4 |
+-------------+-------------------------------------------------------------------------------------+
|| Tags ||
|+-------------------------------+-----------------------------------------------------------------+|
|| Key | Value ||
|+-------------------------------+-----------------------------------------------------------------+|
|| ebs.csi.aws.com/cluster | true ||
|| CSIVolumeSnapshotName | snapshot-2eaab85c-ce5f-4270-b32b-23a7ce61eae7 ||
|| kubernetes.io/cluster/myeks | owned ||
|| Name | myeks-dynamic-snapshot-2eaab85c-ce5f-4270-b32b-23a7ce61eae7 ||
|+-------------------------------+-----------------------------------------------------------------+|
이제 pod와 pvc를 삭제해보겠습니다.
$ kubectl delete pod app && kubectl delete pvc ebs-claim
$ kubectl get pvc,pv
No resources found
그 다음에 snapshot을 통해서 pvc를 복구해보겠습니다.
dataSource에 전에 생성한 snapshot 이름을 입력합니다.
$ cat <<EOT > ebs-snapshot-restored-claim.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ebs-snapshot-restored-claim
spec:
storageClassName: gp3
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 4Gi
dataSource:
name: ebs-volume-snapshot
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
EOT
$ kubectl apply -f ebs-snapshot-restored-claim.yaml
$ kubectl get pvc,pv
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/ebs-snapshot-restored-claim Pending gp3 2m3s
아직 pv는 생성되지 않았고, 이제 복구된 pvc가 연결된 pod를 만들어 보겠습니다.
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: centos
command: ["/bin/sh"]
args: ["-c", "while true; do echo $(date -u) >> /data/out.txt; sleep 5; done"]
volumeMounts:
- name: persistent-storage
mountPath: /data
volumes:
- name: persistent-storage
persistentVolumeClaim:
claimName: ebs-snapshot-restored-claim
pod 생성 후에 pv가 생성된 것을 볼 수 있습니다.
$ kubectl get pvc,pv,pod
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/ebs-snapshot-restored-claim Bound pvc-ce3c5e51-0267-4ef6-8cdb-62e229ac95d6 4Gi RWO gp3 3m56s
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/pvc-ce3c5e51-0267-4ef6-8cdb-62e229ac95d6 4Gi RWO Delete Bound default/ebs-snapshot-restored-claim gp3 17s
NAME READY STATUS RESTARTS AGE
pod/app 1/1 Running 0 21s
이제 pod의 /data/out.txt 파일에 이전 데이터가 남아있는지 확인해보겠습니다.
$ kubectl exec app -- cat /data/out.txt
Mon May 8 11:51:49 UTC 2023
Mon May 8 11:51:54 UTC 2023
Mon May 8 11:51:59 UTC 2023
Mon May 8 11:52:04 UTC 2023
Mon May 8 11:52:09 UTC 2023
Mon May 8 11:52:14 UTC 2023
Mon May 8 11:52:19 UTC 2023
Mon May 8 11:52:24 UTC 2023
Mon May 8 11:52:29 UTC 2023
Mon May 8 11:52:34 UTC 2023
Mon May 8 11:52:39 UTC 2023
Mon May 8 11:52:44 UTC 2023
Mon May 8 11:52:49 UTC 2023
Mon May 8 11:52:54 UTC 2023
Mon May 8 11:52:59 UTC 2023
...
pod 삭제 이전 시간의 데이터가 남아있는 것을 확인할 수 있습니다.
EFS CSI driver 설치 및 예제
이번에는 EFS CSI driver를 설치해보겠습니다.
먼저 IAM Policy를 생성합니다.
$ curl -s -O https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/docs/iam-policy-example.json
$ aws iam create-policy --policy-name AmazonEKS_EFS_CSI_Driver_Policy --policy-document file://iam-policy-example.json
그 다음 IRSA를 설정하고 EFS CSI driver를 설치합니다.
# 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::${ACCOUNT_ID}:policy/AmazonEKS_EFS_CSI_Driver_Policy \
--approve
# EFS Controller 설치
$ helm repo add aws-efs-csi-driver https://kubernetes-sigs.github.io/aws-efs-csi-driver/
$ helm repo update
$ helm upgrade -i aws-efs-csi-driver aws-efs-csi-driver/aws-efs-csi-driver \
--namespace kube-system \
--set image.repository=602401143452.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/eks/aws-efs-csi-driver \
--set controller.serviceAccount.create=false \
--set controller.serviceAccount.name=efs-csi-controller-sa
# 확인
$ kubectl get sa -n kube-system efs-csi-controller-sa -o yaml | head -5
$ eksctl get iamserviceaccount --cluster myeks
$ helm list -n kube-system
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
aws-efs-csi-driver kube-system 1 2023-05-08 21:27:12.256768144 +0900 KST deployed aws-efs-csi-driver-2.4.1 1.5.4
$ 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-64d67ffcdd-2xx2x 3/3 Running 0 24m
efs-csi-controller-64d67ffcdd-h8czl 3/3 Running 0 24m
efs-csi-node-4pr42 3/3 Running 0 24m
efs-csi-node-7x8dt 3/3 Running 0 24m
efs-csi-node-gj626 3/3 Running 0 24m
현재 상태에서는 EFS 자체 id를 사용하거나 access point를 생성한 뒤 해당 id를 통해서 pv를 먼저 만들어주어야 pvc가 정상적으로 볼륨과 binding될 수 있습니다.
동적으로 EFS pv를 만들기 위해서는 Storage Class를 추가로 생성해야합니다.
$ curl -s -O https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/storageclass.yaml
$ cat storageclass.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: efs-sc
provisioner: efs.csi.aws.com
parameters:
provisioningMode: efs-ap
fileSystemId: fs-92107410
directoryPerms: "700"
gidRangeStart: "1000" # optional
gidRangeEnd: "2000" # optional
basePath: "/dynamic_provisioning" # optional
$ sed -i "s/fs-92107410/$EfsFsId/g" storageclass.yaml
$ kubectl apply -f storageclass.yaml
$ kubectl get sc efs-sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
efs-sc efs.csi.aws.com Delete Immediate false 3s
이 때 먼저 생성해 둔 EFS id를 입력해야 합니다.
이제 EFS를 사용하는 pod를 만들어 보겠습니다.
$ curl -s -O https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/pod.yaml
$ cat pod.yaml | yh
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: efs-claim
spec:
accessModes:
- ReadWriteMany
storageClassName: efs-sc
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: Pod
metadata:
name: efs-app
spec:
containers:
- name: app
image: centos
command: ["/bin/sh"]
args: ["-c", "while true; do echo $(date -u) >> /data/out; sleep 5; done"]
volumeMounts:
- name: persistent-storage
mountPath: /data
volumes:
- name: persistent-storage
persistentVolumeClaim:
claimName: efs-claim
$ kubectl apply -f pod.yaml
$ kubectl get pvc,pv,pod
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/efs-claim Bound pvc-0ee5efeb-75c9-475c-9d0e-09e3fb32b364 5Gi RWX efs-sc 19s
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/pvc-0ee5efeb-75c9-475c-9d0e-09e3fb32b364 5Gi RWX Delete Bound default/efs-claim efs-sc 19s
NAME READY STATUS RESTARTS AGE
pod/app 1/1 Running 0 59m
pod/efs-app 1/1 Running 0 45s
이후 EFS의 access point를 확인하면 pvc이름 기반의 path로 새로운 access point가 생성된 것을 확인할 수 있습니다.
또한, 자동으로 생성된 pv를 확인하면 EBS를 사용하는 pv와 다르게 nodeAffinity 설정이 없는 것을 확인할 수 있습니다.
이상으로 3주차 내용을 마무리하겠습니다.
추가로 생각해 볼 만한 것
주기적으로 snapshot을 생성하는 방법
1) AWS Backup 이용하여 ebs 볼륨 백업
- 백업 스케쥴링 및 백업본 관리가 쉬움
- tag 기반 백업을 위해서 pv에 custom tag 추가 필요 (pv에 tag 추가하기)
- 클러스터 객체인 VolumeSnapshot은 사용하지 못하고, 백업된 EBS로 PV를 만든 후에 PVC와 연결이 필요함
2) snapshot scheduler 설치 후 사용
- snapshot은 kubectl 명령어로 생성이 불가하고 yaml 파일을 생성한 뒤 apply를 해야 하는데, 백업본 보관일 지정이나 백업을 하기 위한 pod 세팅이 번거로워 보였음
- snapshot scheduler라는 비슷한 이름으로 다양한 프로젝트가 있는 것으로 보임 (실습)
참고 문서
'Kubernetes > EKS Study' 카테고리의 다른 글
[5주차] EKS Autoscaling (0) | 2023.05.24 |
---|---|
[4주차] EKS Observability (0) | 2023.05.21 |
EKS에서 볼륨 snapscheduler 설치하기 (0) | 2023.05.09 |
EKS에서 pvc로 생성한 ebs에 태그 추가하기 (0) | 2023.05.09 |
[2주차] EKS Networking (0) | 2023.05.01 |