brunch

EKS 8탄-6.스토리지-EFS -6/17

EKS 8탄 - 3주차

by Master Seo

본 내용은 CloudNet 주말 스터디 내용을 참고로 작성되었습니다.

https://gasidaseo.notion.site/gasidaseo/CloudNet-Blog-c9dfa44a27ff431dafdd2edacc8a1863

계속 테스트하며 내용과 설명이 업데이트 됩니다.


목표

Pod에서 EFS 사용하기



<1> EFS 파일시스템 확인 및 EFS Controller 설치

<2> EFS 파일시스템을 다수의 파드가 사용하게 설정 - static example

<3> EFS 파일시스템을 다수의 파드가 사용하게 설정 : Dynamic

<4> 파게이트 사용해 보기

<5> EKS Persistent Volumes for Instance Store & Add NodeGroup

<6> 삭제 필수 - 화면을 유지하세요!!!




<1> EFS 파일시스템 확인 및 EFS Controller 설치


1

참고 자료

https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/efs-csi.html

https://github.com/kubernetes-sigs/aws-efs-csi-driver

https://artifacthub.io/packages/helm/aws-efs-csi-driver/aws-efs-csi-driver



2

앞에서 Cloudformation으로 efs 파일 시스템은 만들었다. eks-oneclick2.yaml file



3

내용 ?

보안 그룹 하나 추가함.


EFS

EFSSG:

Type: AWS::EC2::SecurityGroup

Properties:

VpcId: !Ref EksVPC

GroupDescription: EFS Security Group

Tags:

- Key : Name

Value : !Sub ${ClusterBaseName}-EFS

SecurityGroupIngress:

- IpProtocol: tcp

FromPort: '2049'

ToPort: '2049'

CidrIp: !Ref VpcBlock


ElasticFileSystem:

Type: AWS::EFS::FileSystem

Properties:

FileSystemTags:

- Key: Name

Value: !Sub ${ClusterBaseName}-EFS

ElasticFileSystemMountTarget0:

Type: AWS::EFS::MountTarget

Properties:

FileSystemId: !Ref ElasticFileSystem

SecurityGroups:

- !Ref EFSSG

SubnetId: !Ref PublicSubnet1

ElasticFileSystemMountTarget1:

Type: AWS::EFS::MountTarget

Properties:

FileSystemId: !Ref ElasticFileSystem

SecurityGroups:

- !Ref EFSSG

SubnetId: !Ref PublicSubnet2

ElasticFileSystemMountTarget2:

Type: AWS::EFS::MountTarget

Properties:

FileSystemId: !Ref ElasticFileSystem

SecurityGroups:

- !Ref EFSSG

SubnetId: !Ref PublicSubnet3



10 efs.png

https://dev.to/awscommunity-asean/aws-eks-with-efs-csi-driver-and-irsa-using-cdk-dgc




# EFS 정보 확인

aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text

------

fs-00fc18f0ad801703e



4

정책을 만들어야 한다. 고객 관리형 정책을 별도로 만들어야 한다. (고객이 직접 만든 정책이다.)

IRSA 설정을 해야 한다.



5

# IAM 정책 생성

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



6

# IRSA 설정

: 고객관리형 정책 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


(2분 소요)



7

# IRSA 확인

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::476286675138:role/eksctl-myeks-addon-iamserviceaccount-kube-sy-Role1-Q5FRU0E419V2



eksctl get iamserviceaccount --cluster myeks

---------

NAMESPACE NAME ROLE ARN

kube-system aws-load-balancer-controller arn:aws:iam::476286675138:role/eksctl-myeks-addon-iamserviceaccount-kube-sy-Role1-ILKQZ0MFQ6E5

kube-system ebs-csi-controller-sa arn:aws:iam::4738:role/AmazonEKS_EBS_CSI_DriverRole

kube-system efs-csi-controller-sa arn:aws:iam::47138:role/eksctl-myeks-addon-iamserviceaccount-kube-sy-Role1-Q5FRU0E419V2

// 로드 밸드밸런서 컨트롤러, EBS 컨트롤러, EFS컨트롤러 role을 가지고 있다.



8

# 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



9

# 확인

helm list -n kube-system


(masterseo@myeks:default) [root@myeks-bastion-EC2 ~]# helm list -n kube-system

NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION

aws-efs-csi-driver kube-system 1 2023-05-11 00:08:53.043865633 +0900 KST deployed aws-efs-csi-driver-2.4.3 1.5.5

aws-load-balancer-controller kube-system 1 2023-05-10 18:54:06.089972566 +0900 KST deployed aws-load-balancer-controller-1.5.2 v2.5.1

kube-ops-view kube-system 1 2023-05-10 18:55:59.745086296 +0900 KST deployed kube-ops-view-1.2.2 20.4.0



10

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-6f64dcc5dc-86nr5 3/3 Running 0 59s

efs-csi-controller-6f64dcc5dc-wjlc6 3/3 Running 0 59s

efs-csi-node-nf2c2 3/3 Running 0 59s

efs-csi-node-ngrf5 3/3 Running 0 59s

efs-csi-node-zdscq 3/3 Running 0 59s





<2> EFS 파일시스템을 다수의 파드가 사용하게 설정 - static example



1

워크셥

https://www.eksworkshop.com/docs/fundamentals/storage/efs/efs-csi-driver/



2

# 모니터링

watch 'kubectl get sc efs-sc; echo; kubectl get pv,pvc,pod'



3

# 실습 코드 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

├── claim.yaml

├── pod1.yaml

├── pod2.yaml

├── pv.yaml

└── storageclass.yaml



4

# EFS 스토리지클래스 생성 및 확인

cat storageclass.yaml | yh


kubectl apply -f storageclass.yaml

kubectl get sc efs-sc


kubectl get sc

(masterseo@myeks:default) [root@myeks-bastion-EC2 specs]# kubectl get sc

NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE

efs-sc efs.csi.aws.com Delete Immediate false 88s

gp2 (default) kubernetes.io/aws-ebs Delete WaitForFirstConsumer false 6h42m

gp3 ebs.csi.aws.com Delete WaitForFirstConsumer true 94m

local-path rancher.io/local-path Delete WaitForFirstConsumer false 4h28m




5

# PV 생성 및 확인


: volumeHandle을 자신의 EFS 파일시스템ID로 변경


EfsFsId=$(aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text)

sed -i "s/fs-00fc18f0ad801703e/$EfsFsId/g" pv.yaml

// 본인 EFS의 fs id 확인

sed -i "s/fs-00fc18f0ad801703e/$EfsFsId/g" pv.yaml



cat pv.yaml | yh


kubectl apply -f pv.yaml

kubectl get pv; kubectl describe pv



6

# PVC 생성 및 확인


cat claim.yaml | yh


kubectl apply -f claim.yaml


kubectl get pvc

--------------------

NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE

ebs-snapshot-restored-claim Bound pvc-61d66ff6-be81-4899-8d84-7e6a55fd7b35 4Gi RWO gp3 36m

efs-claim Bound efs-pv 5Gi RWX efs-sc 2s

localpath-claim Bound pvc-c37e1be5-de1a-4e4b-a7df-4984a60f6ee3 1Gi RWO local-path 4h32m



7

# 파드 생성 및 연동 ?


파드 내에 /data 데이터는 EFS를 사용

# 파드 2개 생성 됨


cat pod1.yaml pod2.yaml | yh


kubectl apply -f pod1.yaml,pod2.yaml


kubectl df-pv

PV NAME PVC NAME NAMESPACE NODE NAME POD NAME VOLUME MOUNT NAME SIZE USED AVAILABLE %USED IUSED IFREE %IUSED

pvc-61d66ff6-be81-4899-8d84-7e6a55fd7b35 ebs-snapshot-restored-claim default ip-192-168-2-38.ap-northeast-2.compute.internal app persistent-storage 3Gi 44Ki 3Gi 0.00 12 262132 0.00




8

# 파드 정보 확인 ?

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



# 공유 저장소 저장 동작 확인

tree /mnt/myefs



9

# 작업용EC2에서도 마운트 되어 있다. 확인

tail -f /mnt/myefs/out1.txt


# 작업용EC2에서도 확인

kubectl exec -ti app1 -- tail -f /data/out1.txt

kubectl exec -ti app2 -- tail -f /data/out2.txt


// 모두 EFS에 저장 된다.


10

스테틱 방식으로 실습 한것이다.


11

# 쿠버네티스 리소스 삭제

kubectl delete pod app1 app2

kubectl delete pvc efs-claim && kubectl delete pv efs-pv && kubectl delete sc efs-sc




<3> EFS 파일시스템을 다수의 파드가 사용하게 설정 : Dynamic



1

# 모니터링

watch 'kubectl get sc efs-sc; echo; kubectl get pv,pvc,pod'



2

다이나믹은 파게이트는 지원 안함.



3

# EFS 스토리지클래스 생성 및 확인

curl -s -O https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/storageclass.yaml


cat storageclass.yaml | yh


sed -i "s/fs-00fc18f0ad801703e/$EfsFsId/g" storageclass.yaml

kubectl apply -f storageclass.yaml

kubectl get sc efs-sc



4

# PVC/파드 생성 및 확인


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

kubectl apply -f pod.yaml

kubectl get pvc,pv,pod


# PVC/PV 생성 로그 확인

kubectl logs -n kube-system -l app=efs-csi-controller -c csi-provisioner -f



5

# 파드 정보 확인

kubectl exec -it efs-app -- 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



6

# 공유 저장소 저장 동작 확인

tree /mnt/myefs # 작업용EC2에서 확인

kubectl exec efs-app -- bash -c "cat data/out"


7

콘솔에서 확인하자

EFS -> 엑세스 포인트에 정보가 나온다.









<4> 파게이트 사용해 보기


https://kschoi728.tistory.com/86



1

프라이빗 서브넷에서 NATGW 생성

Pod가 프라이빗 서브넷에서 사용하는 경우 NAT를 생성해야 한다.

CF로 NATGW 만들어지고, 라우팅 정보가 추가 된다.



2

# 변수 지정

PrivateSubnetRouteTable=$(aws ec2 describe-route-tables --filters Name=tag:Name,Values=$CLUSTER_NAME-PrivateSubnetRouteTable --query 'RouteTables[0].RouteTableId' --output text)


# NATGW 생성, Private 라우팅 정보 추가

curl -s -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/natgw.yaml


sed -i "s/<PublicSubnet1>/$PrivateSubnet1/g" natgw.yaml

sed -i "s/<PrivateSubnetRouteTable>/$PrivateSubnetRouteTable/g" natgw.yaml


cat natgw.yaml



3

aws cloudformation deploy --template-file natgw.yaml --stack-name $CLUSTER_NAME-natgw






<5> EKS Persistent Volumes for Instance Store & Add NodeGroup


1

클러스터는 기존 것을 유지한다.

신규 노드 그룹 ng2 생성한다 - Blog :

서버는 1대로 생성한다.



c5d.large 의 EC2 인스턴스 스토어(임시 블록 스토리지) 설정 작업

https://aws.amazon.com/ko/blogs/containers/eks-persistent-volumes-for-instance-store/

https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/InstanceStorage.html



2

인스턴스 스토어는 EC2 스토리지(EBS) 정보에 출력되지는 않는다



3

# 인스턴스 스토어 볼륨이 있는 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 |

...


# 신규 노드 그룹 생성

eksctl create nodegroup --help


eksctl create nodegroup -c $CLUSTER_NAME -r $AWS_DEFAULT_REGION --subnet-ids "$PubSubnet1","$PubSubnet2","$PubSubnet3" --ssh-access \

-n ng2 -t c5d.large -N 1 -m 1 -M 1 --node-volume-size=30 --node-labels disk=nvme --max-pods-per-node 100 --dry-run > myng2.yaml


(20분 걸림)



4

cat <<EOT > nvme.yaml

preBootstrapCommands:

- |

# Install Tools

yum install nvme-cli links tree jq tcpdump sysstat -y


# Filesystem & Mount

mkfs -t xfs /dev/nvme1n1

mkdir /data

mount /dev/nvme1n1 /data


# Get disk UUID

uuid=\$(blkid -o value -s UUID mount /dev/nvme1n1 /data)


# Mount the disk during a reboot

echo /dev/nvme1n1 /data xfs defaults,noatime 0 2 >> /etc/fstab

EOT


sed -i -n -e '/volumeType/r nvme.yaml' -e '1,$p' myng2.yaml


eksctl create nodegroup -f myng2.yaml



인스턴스 스토어 볼륨을 가지고 있다.

임시 스토리지 - 속도가 빠르다.



5

# 노드 보안그룹 ID 확인

NG2SGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=*ng2* --query "SecurityGroups[*].[GroupId]" --output text)


aws ec2 authorize-security-group-ingress --group-id $NG2SGID --protocol '-1' --cidr 192.168.1.100/32



6

# 워커 노드 SSH 접속

N4=192.168.3.160

ssh ec2-user@$N4 hostname


# 확인

ssh ec2-user@$N4 sudo nvme list

// 인스턴스 스토어 확인 = 휘발성이다.


ssh ec2-user@$N4 sudo lsblk -e 7 -d

// 용량 확인


ssh ec2-user@$N4 sudo df -hT -t xfs

// 파일 시스템 확인


ssh ec2-user@$N4 sudo tree /data

ssh ec2-user@$N4 sudo cat /etc/fstab



7

# (옵션) max-pod 확인


kubectl describe node -l disk=nvme | grep Allocatable: -A7


Allocatable:

attachable-volumes-aws-ebs: 25

cpu: 1930m

ephemeral-storage: 27905944324

hugepages-1Gi: 0

hugepages-2Mi: 0

memory: 3097552Ki

pods: 100



8

# (옵션) kubelet 데몬 파라미터 확인 ?

버그 ?

--max-pods=29 --max-pods=100



ssh ec2-user@$N4 sudo ps -ef | grep kubelet

root 2972 1 0 16:03 ? 00:00:09 /usr/bin/kubelet --config /etc/kubernetes/kubelet/kubelet-config.json --kubeconfig /var/lib/kubelet/kubeconfig --



9

스토리지 클래스 재생성


# 기존 삭제

#curl -s -O https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml

kubectl delete -f local-path-storage.yaml


#

sed -i 's/opt/data/g' local-path-storage.yaml

kubectl apply -f local-path-storage.yaml



# 모니터링

watch 'kubectl get pod -owide;echo;kubectl get pv,pvc'


ssh ec2-user@$N4 iostat -xmdz 1 -p nvme1n1



# 측정 : Read

#curl -s -O https://raw.githubusercontent.com/wikibook/kubepractice/main/ch10/fio-read.fio

kubestr fio -f fio-read.fio -s local-path --size 10G --nodeselector disk=nvme

// nodeselector 사용.







<6> 삭제 필수 - 아래 화면을 유지하세요!!!


# 삭제

(20분 걸림)


helm uninstall -n kube-system kube-ops-view


aws cloudformation delete-stack --stack-name eksctl-$CLUSTER_NAME-addon-iamserviceaccount-kube-system-efs-csi-controller-sa


aws cloudformation delete-stack --stack-name eksctl-$CLUSTER_NAME-addon-iamserviceaccount-kube-system-ebs-csi-controller-sa


aws cloudformation delete-stack --stack-name eksctl-$CLUSTER_NAME-addon-iamserviceaccount-kube-system-aws-load-balancer-controller



eksctl delete cluster --name $CLUSTER_NAME && aws cloudformation delete-stack --stack-name $CLUSTER_NAME





화면을 닫으면 리소스가 삭제되지 않습니다.





다음

https://brunch.co.kr/@topasvga/3239




https://brunch.co.kr/@topasvga/3217


감사합니다.


매거진의 이전글EKS 8탄-5. 스토리지-EBS-5/17