이 내용은 CloudNet@ 에서 진행하는 쿠버네티스 실무 실습 스터디에 대한 연재글입니다.
스터디에서 사용하는 교재는 24단계 실습으로 정복하는 쿠버네티스 입니다.
본 2주차에는 교재의 제 2부 전체 내용 중 상반기 부분을 살펴보고 있습니다. 전체 컨텍스트를 이해하시려면 교재를 참고하시기를 추천드립니다.
쿠버네티스를 클라우드 환경에서 사용하고자 하는 것 자체가 이미 하기 사항들에 대한 기본적인 이해와 준비사항을 요합니다.
이번 연재글에서는 개념에 대한 상세한 추가설명은 가급적 없이 작성하려 합니다. 다만 제가 공부하며 기본적으로 알아야겠다 싶은 연재글에 대해 대신 소개드립니다.
쿠버네티스 스토리지를 이해하기 위해 볼륨 스토리지, 파일 스토리지, 오브젝트 스토리지에 대한 그림을 소개합니다. 이해에 도움이 되시길 바랍니다.
주의! 비용이 많이 발생할 수 있으니, 빠르게 실습 후 종료하시기를 권장드립니다.
t3.medium
c5d.large
t3.small
아래 커맨드를 통해 배포하여 주십시오.
주의! 비용이 많이 발생할 수 있으니, 빠르게 실습 후 종료하시기를 권장드립니다.
워커노드 (c5d.large
) 의 EC2 인스턴스 스토어(임시 블록 스토리지) 설정작업이 필요합니다.
임시 블록 스토리지 내의 데이터는 관련 인스턴스의 수명기간 동안만 지속됩니다. 인스턴스 재부팅의 경우에는 데이터가 유지되지만, 아래의 경우 데이터가 사라집니다.
이런 연유로 중요한 장기 데이터는 S3, Amazon EBS, Amazon EFS 와 같은 데이터 스토리지를 이용하는 것이 필요합니다. 대표적인 데이터 스토리지인 EBS 볼륨과 인스턴스 볼륨의 차이를 살펴봅시다[^1]:
인스턴스 볼륨을 마운트하고 사용하는 방안에 대해 알아보겠습니다.
아래 예제에서는 인스턴스 스토어 볼륨을 설정하고, 이를 확인하는 방법을 소개합니다.
# default NS 진입
kubectl ns default
# 인스턴스 스토어 볼륨이 있는 c5 모든 타입의 스토리지 크기
aws ec2 describe-instance-types \
--filters "Name=instance-type,Values=c5*" "Name=instance-storage-supported,Values=true" \
--query "InstanceTypes[].[InstanceType, InstanceStorageInfo.TotalSizeInGB]" \
--output table
--------------------------
| DescribeInstanceTypes |
+---------------+--------+
| c5d.large | 50 |
| c5d.12xlarge | 1800 |
...
# 워커 노드 Public IP 확인
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value}" --filters Name=instance-state-name,Values=running --output table
# 워커 노드 Public IP 변수 지정
W1PIP=<워커 노드 1 Public IP>
W2PIP=<워커 노드 2 Public IP>
W1PIP=3.38.212.122
W2PIP=43.201.99.109
echo "export W1PIP=$W1PIP" >> /etc/profile
echo "export W2PIP=$W2PIP" >> /etc/profile
# 워커 노드 스토리지 확인 : NVMe SSD 인스턴스 스토어 볼륨 확인
ssh -i ~/.ssh/id_rsa ubuntu@$W1PIP sudo apt install -y nvme-cli
ssh -i ~/.ssh/id_rsa ubuntu@$W2PIP sudo apt install -y nvme-cli
ssh -i ~/.ssh/id_rsa ubuntu@$W1PIP sudo nvme list
ssh -i ~/.ssh/id_rsa ubuntu@$W2PIP sudo nvme list
ssh -i ~/.ssh/id_rsa ubuntu@$W1PIP lsblk -e 7 -d
ssh -i ~/.ssh/id_rsa ubuntu@$W2PIP lsblk -e 7
ssh -i ~/.ssh/id_rsa ubuntu@$W1PIP df -hT -t ext4
ssh -i ~/.ssh/id_rsa ubuntu@$W2PIP df -hT -t ext4
ssh -i ~/.ssh/id_rsa ubuntu@$W1PIP lspci | grep Non-Volatile
00:04.0 Non-Volatile memory controller: Amazon.com, Inc. Device 8061
00:1f.0 Non-Volatile memory controller: Amazon.com, Inc. NVMe SSD Controller
# 파일시스템 생성 및 /data 마운트
ssh -i ~/.ssh/id_rsa ubuntu@$W1PIP sudo mkfs -t xfs /dev/nvme1n1
ssh -i ~/.ssh/id_rsa ubuntu@$W2PIP sudo mkfs -t xfs /dev/nvme1n1
ssh -i ~/.ssh/id_rsa ubuntu@$W1PIP sudo mkdir /data
ssh -i ~/.ssh/id_rsa ubuntu@$W2PIP sudo mkdir /data
ssh -i ~/.ssh/id_rsa ubuntu@$W1PIP sudo mount /dev/nvme1n1 /data
ssh -i ~/.ssh/id_rsa ubuntu@$W2PIP sudo mount /dev/nvme1n1 /data
ssh -i ~/.ssh/id_rsa ubuntu@$W1PIP df -hT -t ext4 -t xfs
ssh -i ~/.ssh/id_rsa ubuntu@$W2PIP df -hT -t ext4 -t xfs
참고 2 인스턴스 스토어는 스토리지 정보에 출력되지 않습니다.
컨테이너 환경에서는 별도의 설정을 하지 않으면, 데이터는 호스트 노드의 임시 디스크(Ephemeral disk)에 보관됩니다. 이는 컨테이너 삭제 시 사라집니다. 이를 Stateless 애플리케이션이라고도 합니다. 말 그대로 관리하고있는 상태(또는 데이터)가 없기 때문입니다. 이를 해결하려면 영구 볼륨 이라는 리소스로 관리해야 합니다. 관리를 진행하는 애플리케이션은 Stateful 애플리케이션입니다.
Ephemeral disk 및 Node의 특정 경로를 매핑하는 기능도 있습니다.
이는 각각 emptyDir
와 hostPath
라고 일컫습니다.
이에 대한 간략한 예시는 해당 링크 를 참고하여 주십시오.
당연하겠지만, Ephemeral disk나 Node의 경로를 매핑한다면 특정 노드의 상태에 영속적인 데이터의 상태가 좌우됩니다. 그리고, 쿠버네티스의 모든 리소스는 cattle과 같아, 별도의 제약을 두지 않으면 항상 stateful하다곤 할 수 없습니다. 이를 통해 스토리지 HA 구성에 제약이 생깁니다.
스토리지의 보다 기민하고 상세한 관리를 위해, 용어를 정리하고 진행하도록 합시다. 쿠버네티스에서는 볼륨을 구성하는 주요 리소스로 아래 세 가지가 있습니다.
PersistentVolume
, 영구 볼륨)PersistentVolumeClaim
, 영구 볼륨 요청자)StorageCla2s
)상기 내용들은 아래와 같은 그림[^3]들으로 이루어집니다.
하기의 Status, Policy 및 외부 네트워크의 액세스 모드 등은
데이터 스토리지는 AWS를 사용한다면 블록 스토리지/파일 스토리지/객체 스토리지 를 사용할 수 있습니다.
Dynamic Provisioning
)이라고 합니다.Reclaim Policy
라고 부릅니다.Reclaim Policy
에는 크게 Retain(보존), Delete(삭제, 즉 EBS 볼륨도 삭제됨), CSI는 CNI와 같이, 컨테이너의 스토리지를 관리하기 위한 일련의 인터페이스 입니다. 보다 상세히 말하자면, 쿠버네티스가 컨테이너화된 워크로드에 임의의 스토리지 시스템을 노출할 수 있게 해주는 개방형 표준 API입니다. 즉 CSI 를 사용함으로서 쿠버네티스 의 공통화된 CSI 인터페이스를 통해 다양한 프로바이더를 사용할 수 있게 됩니다.
아래 그림은 일반적인 CSI driver의 구조입니다. 일례로 AWS EBS CSI driver 역시 아래와 같은 구조를 가집니다.
이번 절에서는 AWS의 EBS 컨트롤러에 대해 살펴보도록 하겠습니다. 기본적인 블록 스토리지를 쿠버네티스 클러스터에서 어떤 식으로 관리할 수 있을까요? 아래의 도식을 통해 살펴봅시다.
kOps를 통해 배포한 클러스터의 스토리지 클래스, PVC, 파드 확인을 통한 배포현황을 살펴봅시다.
# kOps 설치 시 기본 배포됨
kubectl get pod -n kube-system -l app.kubernetes.io/instance=aws-ebs-csi-driver
# 스토리지 클래스 확인
kubectl get sc kops-csi-1-21 kops-ssd-1-17
kubectl describe sc kops-csi-1-21 | grep Parameters
Parameters: encrypted=true,type=gp3
kubectl describe sc kops-ssd-1-17 | grep Parameters
Parameters: encrypted=true,type=gp2
# 워커노드의 EBS 볼륨 확인 : tag(키/값) 필터링 - 링크
aws ec2 describe-volumes --filters Name=tag:k8s.io/role/node,Values=1 --output table
aws ec2 describe-volumes --filters Name=tag:k8s.io/role/node,Values=1 --query "Volumes[*].Attachments" | jq
aws ec2 describe-volumes --filters Name=tag:k8s.io/role/node,Values=1 --query "Volumes[*].Attachments[*].State" | jq
aws ec2 describe-volumes --filters Name=tag:k8s.io/role/node,Values=1 --query "Volumes[*].Attachments[*].State" --output text
aws ec2 describe-volumes --filters Name=tag:k8s.io/role/node,Values=1 --query "Volumes[*].Attachments[].State" --output text
aws ec2 describe-volumes --filters Name=tag:k8s.io/role/node,Values=1 --query "Volumes[*].Attachments[?State=='attached'].VolumeId[]" | jq
aws ec2 describe-volumes --filters Name=tag:k8s.io/role/node,Values=1 --query "Volumes[*].Attachments[?State=='attached'].VolumeId[]" --output text
aws ec2 describe-volumes --filters Name=tag:k8s.io/role/node,Values=1 --query "Volumes[*].Attachments[?State=='attached'].InstanceId[]" | jq
aws ec2 describe-volumes --filters Name=tag:k8s.io/role/node,Values=1 --query "Volumes[*].{ID:VolumeId,Tag:Tags}" | jq
aws ec2 describe-volumes --filters Name=tag:k8s.io/role/node,Values=1 --query "Volumes[].[VolumeId, VolumeType]" | jq
aws ec2 describe-volumes --filters Name=tag:k8s.io/role/node,Values=1 --query "Volumes[].[VolumeId, VolumeType, Attachments[].[InstanceId, State]]" | jq
aws ec2 describe-volumes --filters Name=tag:k8s.io/role/node,Values=1 --query "Volumes[].[VolumeId, VolumeType, Attachments[].[InstanceId, State][]][]" | jq
aws ec2 describe-volumes --filters Name=tag:k8s.io/role/node,Values=1 --query "Volumes[].{VolumeId: VolumeId, VolumeType: VolumeType, InstanceId: Attachments[0].InstanceId, State: Attachments[0].State}" | jq
# 워커노드에서 파드에 추가한 EBS 볼륨 확인
aws ec2 describe-volumes --filters Name=tag:ebs.csi.aws.com/cluster,Values=true --output table
aws ec2 describe-volumes --filters Name=tag:ebs.csi.aws.com/cluster,Values=true --query "Volumes[*].{ID:VolumeId,Tag:Tags}" | jq
aws ec2 describe-volumes --filters Name=tag:ebs.csi.aws.com/cluster,Values=true --query "Volumes[].{VolumeId: VolumeId, VolumeType: VolumeType, InstanceId: Attachments[0].InstanceId, State: Attachments[0].State}" | jq
# 워커노드에서 파드에 추가한 EBS 볼륨 모니터링
while true; do aws ec2 describe-volumes --filters Name=tag:ebs.csi.aws.com/cluster,Values=true --query "Volumes[].{VolumeId: VolumeId, VolumeType: VolumeType, InstanceId: Attachments[0].InstanceId, State: Attachments[0].State}" --output text; date; sleep 1; done
# PVC 생성
cat ~/pkos/3/awsebs-pvc.yaml | yh
kubectl apply -f ~/pkos/3/awsebs-pvc.yaml
# 파드 생성
cat ~/pkos/3/awsebs-pod.yaml | yh
kubectl apply -f ~/pkos/3/awsebs-pod.yaml
# PVC, 파드 확인
kubectl get pvc,pv,pod
kubectl df-pv
# 추가된 EBS 볼륨 상세 정보 확인
aws ec2 describe-volumes --volume-ids $(kubectl get pv -o jsonpath="{.items[0].spec.csi.volumeHandle}") | jq
# 파일 내용 추가 저장 확인
kubectl exec app -- tail -f /data/out.txt
# 파드 내에서 볼륨 정보 확인
kubectl exec -it app -- sh -c 'df -hT --type=ext4'
Filesystem Type Size Used Avail Use% Mounted on
/dev/nvme1n1 ext4 3.9G 16M 3.8G 1% /data
/dev/root ext4 124G 4.9G 120G 4% /etc/hosts
이어서, 볼륨을 증가하는 테스트를 진행해봅시다.
# 현재 pv 의 이름을 기준하여 4G > 10G 로 증가 : .spec.resources.requests.storage의 4Gi 를 10Gi로 변경
kubectl edit pvc ebs-claim
kubectl get pvc ebs-claim -o jsonpath={.spec.resources.requests.storage} ; echo
kubectl get pvc ebs-claim -o jsonpath={.status.capacity.storage} ; echo
kubectl patch pvc ebs-claim -p '{"spec":{"resources":{"requests":{"storage":"10Gi"}}}}'
kubectl patch pvc ebs-claim -p '{"status":{"capacity":{"storage":"10Gi"}}}' # status 는 바로 위 커멘드 적용 후 EBS 10Gi 확장 후 알아서 10Gi 반영됨
# 확인 : 볼륨 용량 수정 반영이 되어야 되니, 수치 반영이 조금 느릴수 있다
kubectl exec -it app -- sh -c 'df -hT --type=ext4'
kubectl df-pv
aws ec2 describe-volumes --volume-ids $(kubectl get pv -o jsonpath="{.items[0].spec.csi.volumeHandle}") | jq
아래 커맨드를 입력하여 실습 01 내용을 정리합시다.
kubectl delete pod app & kubectl delete pvc ebs-claim
영속적 데이터에 대해 스냅샷을 찍고 얼마든지 상태를 돌아갈 수 있다면 안전한 서비스를 운영함에 있어 큰 도움이 될 것입니다.
AWS에서는 VolumeSnapShot
컨트롤러를 사용하여 이를 수행할 수 있습니다.
아래 커맨드를 통해 스냅샷 컨트롤러를 설치해 봅시다.
# kOps 클러스터 편집
kops edit cluster
-----
spec:
snapshotController:
enabled: true
certManager: # 이미 설치됨
enabled: true # 이미 설치됨
-----
# 업데이트 적용
kops update cluster --yes && sleep 3 && kops rolling-update cluster
# 확인 >> 배포 시 3분 정도 소요됨
watch kubectl get pod -n kube-system
kubectl get crd | grep volumesnapshot
volumesnapshotclasses.snapshot.storage.k8s.io 2022-07-19T13:45:26Z
volumesnapshotcontents.snapshot.storage.k8s.io 2022-07-19T13:45:26Z
volumesnapshots.snapshot.storage.k8s.io 2022-07-19T13:45:26Z
# vsclass 생성
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-ebs-csi-driver/master/examples/kubernetes/snapshot/manifests/classes/snapshotclass.yaml
kubectl get volumesnapshotclass
NAME DRIVER DELETIONPOLICY AGE
csi-aws-vsc ebs.csi.aws.com Delete 6s
그렇다면, PVC와 파드를 만들고 VolumeSnapShot을 만들어서 스냅샷 생성을 확인 후 장애를 내봅시다!!!!!
# PVC 생성
kubectl apply -f ~/pkos/3/awsebs-pvc.yaml
# 파드 생성
kubectl apply -f ~/pkos/3/awsebs-pod.yaml
# VolumeSnapshot 생성 : Create a VolumeSnapshot referencing the PersistentVolumeClaim name
cat ~/pkos/3/ebs-volume-snapshot.yaml | yh
kubectl apply -f ~/pkos/3/ebs-volume-snapshot.yaml
# 파일 내용 추가 저장 확인
kubectl exec app -- tail -f /data/out.txt
# VolumeSnapshot 확인
kubectl get volumesnapshot
NAME READYTOUSE SOURCEPVC SOURCESNAPSHOTCONTENT RESTORESIZE SNAPSHOTCLASS SNAPSHOTCONTENT CREATIONTIME AGE
ebs-volume-snapshot true ebs-claim 4Gi csi-aws-vsc snapcontent-5881b167-2375-4aa7-b0ad-c5d305cc0aaf 90s 91s
kubectl get volumesnapshot ebs-volume-snapshot -o jsonpath={.status.boundVolumeSnapshotContentName}
snapcontent-5881b167-2375-4aa7-b0ad-c5d305cc0aaf
kubectl describe volumesnapshot.snapshot.storage.k8s.io ebs-volume-snapshot
# AWS EBS 스냅샷 확인
aws ec2 describe-snapshots --owner-ids self | jq
aws ec2 describe-snapshots --owner-ids self --query 'Snapshots[]' --output table
# app & pvc 제거 : 강제로 장애 재현
kubectl delete pod app && kubectl delete pvc ebs-claim
하지만 필요한 서비스들을 구동한다면, 스냅샷을 통해 복구할 수 있습니다.
# 스냅샷에서 PVC 로 복원
cat ~/pkos/3/ebs-snapshot-restored-claim.yaml | yh
**kubectl apply -f ~/pkos/3/ebs-snapshot-restored-claim.yaml**
# 확인
kubectl get pvc,pv
# 파드 생성
cat ~/pkos/3/ebs-snapshot-restored-pod.yaml | yh
**kubectl apply -f ~/pkos/3/ebs-snapshot-restored-pod.yaml**
# 파일 내용 저장 확인 : 파드 삭제 전까지의 저장 기록이 남아 있다. 이후 파드 재생성 후 기록도 잘 저장되고 있다
**kubectl exec app -- cat /data/out.txt**
...
Sat Dec 24 15:12:24 UTC 2022
Sat Dec 24 15:12:24 UTC 2022
Sat Dec 24 15:24:23 UTC 2022
Sat Dec 24 15:24:23 UTC 2022
...
아래 커맨드를 입력하여 실습 02 내용을 정리합시다.
# 삭제
kubectl delete pod app && kubectl delete pvc ebs-snapshot-restored-claim && kubectl delete volumesnapshots ebs-volume-snapshot
그렇다면, 다수의 파드가 공유하는 파일 시스템은 어떻게 운영하면 좋을까요? 이럴 때 파일 스토리지를 사용합니다. 파일 스토리지의 대표적인 예로 NFS, SMB 등이 있겠습니다. 파일 스토리지를 쿠버네티스 클러스터에서 활용하기 위한 예시를 실행해봅시다.
EFS 확인 및 적절한 IAM 정책 생성 후 EFS 컨트롤러를 helm으로 설치해봅시다. (드라이버에 대한 설명
# EFS 정보 확인
aws efs describe-file-systems
while true; do aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text; date; sleep 1; done
# IAM 정책 생성
curl -s -o iam-policy-example.json 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
# EC2 instance profiles 에 IAM Policy 추가(attach)
aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AmazonEKS_EFS_CSI_Driver_Policy --role-name masters.$KOPS_CLUSTER_NAME
aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AmazonEKS_EFS_CSI_Driver_Policy --role-name nodes.$KOPS_CLUSTER_NAME
# EFS Controller 설치
helm repo add aws-efs-csi-driver https://kubernetes-sigs.github.io/aws-efs-csi-driver/
helm repo update
helm install my-aws-efs-csi-driver aws-efs-csi-driver/aws-efs-csi-driver --version 2.4.0 --set replicaCount=1 --namespace kube-system
# 확인
helm list -n kube-system
kubectl get pod -n kube-system -l "app.kubernetes.io/name=aws-efs-csi-driver,app.kubernetes.io/instance=my-aws-efs-csi-driver"
본격적으로 EFS 파일 시스템을 설치하고 마운트 타겟을 생성해봅시다. (참고링크)
# kops가 동작하는 vpc id 출력
aws ec2 describe-vpcs --query 'Vpcs[?Tags[?Key==`Name`]|[?Value==`<각자 자신의 클러스터 이름 직접 입력>`]].VpcId' --output text
aws ec2 describe-vpcs --query 'Vpcs[?Tags[?Key==`Name`]|[?Value==`gasida.link`]].VpcId' --output text
vpc-03f5bf92f0fa78a86
# kops가 동작하는 vpc id 출력 변수 입력
VPCID=$(aws ec2 describe-vpcs --query 'Vpcs[?Tags[?Key==`Name`]|[?Value==`gasida.link`]].VpcId' --output text)
# kops가 동작하는 vpc id의 CIDR 정보 변수 입력
CIDR=$(aws ec2 describe-vpcs --vpc-ids $VPCID --query "Vpcs[].CidrBlock" --output text)
# kops가 동작하는 vpc id의 CIDR 대역에서 EFS 통신(TCP 2049)을 허용하는 인바운드 보안 그룹 생성
SGID=$(aws ec2 create-security-group --group-name MyEfsSg --description "My EFS security group" --vpc-id $VPCID --output text)
aws ec2 authorize-security-group-ingress --group-id $SGID --protocol tcp --port 2049 --cidr $CIDR
# EFS 파일 시스템 생성
EfsFsId=$(aws efs create-file-system --performance-mode generalPurpose --query 'FileSystemId' --output text)
echo $EfsFsId
echo "export EfsFsId=$EfsFsId" >> /etc/profile
# kops가 동작하는 서브넷 정보 출력
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$VPCID" --query 'Subnets[*].{SubnetId: SubnetId,AvailabilityZone: AvailabilityZone,CidrBlock: CidrBlock}' --output table
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$VPCID" --query 'Subnets[*].{SubnetId: SubnetId,AvailabilityZone: AvailabilityZone,CidrBlock: CidrBlock}' --output text
ap-northeast-2c 172.30.64.0/19 subnet-06fab272fad989708
ap-northeast-2a 172.30.32.0/19 subnet-0aa58f0ab7856f391
# kops가 동작하는 서브넷ID를 변수에 지정
SUB1=<바로 위 서브넷 ID중 하나를 입력>
SUB2=<바로 위 서브넷 ID중 나머지 입력>
SUB1=subnet-0aa58f0ab7856f391
SUB2=subnet-06fab272fad989708
# efs mount target 생성
aws efs create-mount-target --file-system-id $EfsFsId --subnet-id $SUB1 --security-groups $SGID
aws efs create-mount-target --file-system-id $EfsFsId --subnet-id $SUB2 --security-groups $SGID
# EFS 확인
aws efs describe-file-systems --output text
aws efs describe-file-systems --output table
echo $EfsFsId
EFS 스토리지클래스와 PV생성 및 확인 후 PVC 생성을 확인하여 본격적인 EFS 파일시스템 공유를 실습해봅시다. (참고링크)
# 모니터링
watch 'kubectl get sc efs-sc; echo; kubectl get pv,pvc,pod'
# 실습 코드 clone
git clone https://github.com/kubernetes-sigs/aws-efs-csi-driver.git /root/efs-csi
cd /root/efs-csi/examples/kubernetes/multiple_pods/specs && tree
# EFS 스토리지클래스 생성 및 확인
cat storageclass.yaml | yh
kubectl apply -f storageclass.yaml
kubectl get sc efs-sc
# PV 생성 및 확인 : volumeHandle을 자신의 EFS 파일시스템ID로 변경
sed -i "s/fs-4af69aab/$EfsFsId/g" pv.yaml
cat pv.yaml | yh
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-05699d3c12ef609e2
kubectl apply -f pv.yaml
kubectl get pv
# PVC 생성 및 확인
cat claim.yaml | yh
kubectl apply -f claim.yaml
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
efs-claim Bound efs-pv 5Gi RWX efs-sc 2m14s
# 파드 생성 및 연동 : 파드 내에 /data 데이터는 EFS를 사용
cat pod1.yaml pod2.yaml | yh
kubectl apply -f pod1.yaml,pod2.yaml
kubectl df-pv
# 파드 정보 확인 : PV에 5Gi 와 파드 내에서 확인한 NFS4 볼륨 크리 8.0E의 차이는 무엇? 파드에 6Gi 이상 저장 가능한가?
kubectl get pods
kubectl exec -ti app1 -- sh -c "df -hT -t nfs4"
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
# 공유 저장소 저장 동작 확인
kubectl exec -ti app1 -- tail -f /data/out1.txt
kubectl exec -ti app2 -- tail -f /data/out2.txt
실습 완료 후 쿠버네티스 리소스 및 EFS를 삭제합니다.
# 쿠버네티스 리소스 삭제
kubectl delete pod app1 app2
kubectl delete pvc efs-claim && kubectl delete pv efs-pv && kubectl delete sc efs-sc
# EFS 삭제
## efs mount target 삭제 : 아래 출력된 mount target id 값으로 삭제
aws efs describe-mount-targets --file-system-id $EfsFsId --query 'MountTargets[].MountTargetId' --output text
fsmt-0e9f23f8c90cf6b36 fsmt-077cc300899d131af
aws efs delete-mount-target --mount-target-id <value>
aws efs delete-mount-target --mount-target-id fsmt-0e9f23f8c90cf6b36
aws efs delete-mount-target --mount-target-id fsmt-077cc300899d131af
## EFS 파일 시스템 삭제 : 위 mlunt target 삭제(1~2분정도소요) 완료 후 삭제가 가능하다
aws efs delete-file-system --file-system-id $EfsFsId
앞서 마운트 시 살펴본 EFS Access point를 통해, Dynamic Provisioning 또한 가능합니다. (참고링크 GitHub)
스토리지 클래스의 YAML 파일을 살펴봅시다.
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: efs-sc
provisioner: efs.csi.aws.com
mountOptions:
- tls
parameters:
provisioningMode: efs-ap
fileSystemId: fs-92107410
directoryPerms: "700"
gidRangeStart: "1000"
gidRangeEnd: "2000"
basePath: "/dynamic_provisioning"
provisioningMode
- The type of volume to be provisioned by efs. Currently, only access point based provisioning is supported efs-ap
.fileSystemId
- The file system under which Access Point is created.directoryPerms
- Directory Permissions of the root directory created by Access Point.gidRangeStart
(Optional) - Starting range of Posix Group ID to be applied onto the root directory of the access point. Default value is 50000
.gidRangeEnd
(Optional) - Ending range of Posix Group ID. Default value is 7000000
.basePath
(Optional) - Path on the file system under which access point root directory is created. If path is not provided, access points root directory are created under the root of the file system.프로비저닝 모드 값과, 기존의 옵션값 및 옵셔널값을 함께 수정한다면 필요에 따라 지속적으로 PV를 프로비저닝 요청할 수 있습니다.
추가로, 이 링크 의 2.3.2
Dynamic Provisioning을 함께 읽어보십시오.
aws ec2 delete-security-group --group-id <MyEfsSg의 보안그룹ID>
kops delete cluster --yes && aws cloudformation delete-stack --stack-name mykops
제 2장 (2) 에서는 쿠버네티스 스토리지에 대해 살펴보았습니다.
이번 장에서는 아래 내용을 반드시 기억하셨으면 좋겠습니다.
이것으로 제 2장 파트 2까지, 2장을 마칩니다. 긴 글 읽어주셔서 감사합니다.
[^1]: 출처 : https://cloud.google.com/blog/topics/developers-practitioners/map-storage-options-google-cloud
[^2]: 이 링크에 설명되어있습니다.
[^3]: 출처: https://blog.mayadata.io/kubernetes-storage-basics-pv-pvc-and-storageclass