brunch

You can make anything
by writing

C.S.Lewis

by Master Seo May 10. 2023

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

EKS 8탄 - 3주차

본 내용은 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



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


감사합니다.


브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari