카이도스의 Tech Blog

EKS 3주차 - EKS Storage & Node 관리 본문

EKS

EKS 3주차 - EKS Storage & Node 관리

카이도스 2023. 5. 12. 17:40
728x90
반응형
CloudNet@-가시다(Gasida)님의 EKS 스터디를 기준으로 작성됩니다.

지난글 : 2023.04.26 - [EKS] - EKS 1주차 - Amzaon EKS 설치 및 기본 사용

 

EKS 1주차 - Amzaon EKS 설치 및 기본 사용

CloudNet@-가시다(Gasida)님의 EKS 스터디를 기준으로 작성됩니다. Amazon EKS 소개 - 참고링크 Amazon EKS 소개 - 링크 한글 기능 Amazon Elastic Kubernetes Service는 자체 Kubernetes 컨트롤 플레인 또는 노드를 설치,

djdakf1234.tistory.com

지난글 : 2023.05.09 - [EKS] - EKS 2주차 - EKS Networking

 

EKS 2주차 - EKS Networking

CloudNet@-가시다(Gasida)님의 EKS 스터디를 기준으로 작성됩니다. 지난글 : 2023.04.26 - [EKS] - EKS 1주차 - Amzaon EKS 설치 및 기본 사용 EKS 1주차 - Amzaon EKS 설치 및 기본 사용 CloudNet@-가시다(Gasida)님의 EKS 스

djdakf1234.tistory.com

비슷한글 : 2023.02.01 - [KOPS] - PKOS(쿠버네티스)3주차 - Ingress & Storage

 

PKOS(쿠버네티스)3주차 - Ingress & Storage

실습 환경 배포 : 노드 c5d.large 해당 셋팅값으로 CloudFormation 배포 후 실습 진행. c5d.large 의 EC2 인스턴스 스토어(임시 블록 스토리지), NVMe SSD 데이터 손실 : 기본 디스크 드라이브 오류, 인스턴스가

djdakf1234.tistory.com


0. 실습 환경 배포

0-1. Amazon EKS 윈클릭 배포 & 기본 설정(CloudFormation으로 진행함)

# YAML 파일 다운로드
curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/eks-oneclick2.yaml

# CloudFormation 스택 배포 (20~25분 소요)
# aws cloudformation deploy --template-file eks-oneclick2.yaml --stack-name myeks --parameter-overrides KeyName=<My SSH Keyname> SgIngressSshCidr=<My Home Public IP Address>/32 MyIamUserAccessKeyID=<IAM User의 액세스키> MyIamUserSecretAccessKey=<IAM User의 시크릿 키> ClusterBaseName='<eks 이름>' --region ap-northeast-2
예시) aws cloudformation deploy --template-file eks-oneclick2.yaml --stack-name myeks --parameter-overrides KeyName=PJH-aws-test SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32  MyIamUserAccessKeyID=AKIATA.... MyIamUserSecretAccessKey='SX+o7l.....' ClusterBaseName=myeks --region ap-northeast-2

# CloudFormation 스택 배포 완료 후 작업용 EC2 IP 출력
aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text
43.201.83.156

# 작업용EC2 SSH 접속
ssh -i ~/PJH-aws-test.pem ec2-user@$(aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text)

0-2. 기본 설정 및 EFS 확인

# default 네임스페이스 적용
kubectl ns default

# EFS 확인 : AWS 관리콘솔 EFS 확인해보자
#mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport <자신의 EFS FS ID>.efs.ap-northeast-2.amazonaws.com:/ /mnt/myefs
mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport fs-07932f79795ec8f70.efs.ap-northeast-2.amazonaws.com:/ /mnt/myefs
df -hT --type nfs4
Filesystem                                              Type  Size  Used Avail Use% Mounted on
fs-07932f79795ec8f70.efs.ap-northeast-2.amazonaws.com:/ nfs4  8.0E     0  8.0E   0% /mnt/myefs

mount | grep nfs4
fs-07932f79795ec8f70.efs.ap-northeast-2.amazonaws.com:/ on /mnt/myefs type nfs4 (rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,noresvport,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.1.100,local_lock=none,addr=192.168.1.77)

echo "efs file test" > /mnt/myefs/memo.txt
cat /mnt/myefs/memo.txt
efs file test

rm -f /mnt/myefs/memo.txt

# 스토리지클래스 및 CSI 노드 확인
kubectl get sc
NAME            PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
gp2 (default)   kubernetes.io/aws-ebs   Delete          WaitForFirstConsumer   false                  16m

kubectl get sc gp2 -o yaml | yh
kubectl get csinodes
NAME                                               DRIVERS   AGE
ip-192-168-1-217.ap-northeast-2.compute.internal   0         5m50s
ip-192-168-2-218.ap-northeast-2.compute.internal   0         5m57s
ip-192-168-3-183.ap-northeast-2.compute.internal   0         5m58s

# 노드 정보 확인
kubectl get node --label-columns=node.kubernetes.io/instance-type,eks.amazonaws.com/capacityType,topology.kubernetes.io/zone
NAME                                               STATUS   ROLES    AGE     VERSION                INSTANCE-TYPE   CAPACITYTYPE   ZONE
ip-192-168-1-217.ap-northeast-2.compute.internal   Ready    <none>   6m33s   v1.24.11-eks-a59e1f0   t3.medium       ON_DEMAND      ap-northeast-2a
ip-192-168-2-218.ap-northeast-2.compute.internal   Ready    <none>   6m40s   v1.24.11-eks-a59e1f0   t3.medium       ON_DEMAND      ap-northeast-2b
ip-192-168-3-183.ap-northeast-2.compute.internal   Ready    <none>   6m41s   v1.24.11-eks-a59e1f0   t3.medium       ON_DEMAND      ap-northeast-2c

eksctl get iamidentitymapping --cluster myeks

# 노드 IP 확인 및 PrivateIP 변수 지정
N1=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2a -o jsonpath={.items[0].status.addresses[0].address})
N2=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2b -o jsonpath={.items[0].status.addresses[0].address})
N3=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2c -o jsonpath={.items[0].status.addresses[0].address})
echo "export N1=$N1" >> /etc/profile
echo "export N2=$N2" >> /etc/profile
echo "export N3=$N3" >> /etc/profile
echo $N1, $N2, $N3
192.168.1.217, 192.168.2.218, 192.168.3.183

# 노드 보안그룹 ID 확인
NGSGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=*ng1* --query "SecurityGroups[*].[GroupId]" --output text)
aws ec2 authorize-security-group-ingress --group-id $NGSGID --protocol '-1' --cidr 192.168.1.100/32

# 워커 노드 SSH 접속
ssh ec2-user@$N1 hostname
ssh ec2-user@$N2 hostname
ssh ec2-user@$N3 hostname

# 노드에 툴 설치
ssh ec2-user@$N1 sudo yum install links tree jq tcpdump sysstat -y
ssh ec2-user@$N2 sudo yum install links tree jq tcpdump sysstat -y
ssh ec2-user@$N3 sudo yum install links tree jq tcpdump sysstat -y

0-3. AWS LB/ExternalDNS, kube-ops-view 설치

# AWS LB 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=$CLUSTER_NAME \
  --set serviceAccount.create=false --set serviceAccount.name=aws-load-balancer-controller

# ExternalDNS
MyDomain=<자신의 도메인>
MyDomain=pjhtest.click
MyDnzHostedZoneId=$(aws route53 list-hosted-zones-by-name --dns-name "${MyDomain}." --query "HostedZones[0].Id" --output text)
echo $MyDomain, $MyDnzHostedZoneId
pjhtest.click, /hostedzone/Z0834.....
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/aews/externaldns.yaml
MyDomain=$MyDomain MyDnzHostedZoneId=$MyDnzHostedZoneId envsubst < externaldns.yaml | kubectl apply -f -

# kube-ops-view
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set env.TZ="Asia/Seoul" --namespace kube-system
kubectl patch svc -n kube-system kube-ops-view -p '{"spec":{"type":"LoadBalancer"}}'
kubectl annotate service kube-ops-view -n kube-system "external-dns.alpha.kubernetes.io/hostname=kubeopsview.$MyDomain"
echo -e "Kube Ops View URL = http://kubeopsview.$MyDomain:8080/#scale=2"
Kube Ops View URL = http://kubeopsview.pjhtest.click:8080/#scale=2


0-4. 설치 정보 확인

# 이미지 정보 확인
kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" | tr -s '[[:space:]]' '\n' | sort | uniq -c
      3 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/amazon-k8s-cni:v1.12.6-eksbuild.2
      2 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/coredns:v1.9.3-eksbuild.3
      3 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/kube-proxy:v1.24.10-minimal-eksbuild.2
      1 hjacobs/kube-ops-view:20.4.0
      2 public.ecr.aws/eks/aws-load-balancer-controller:v2.5.1
      1 registry.k8s.io/external-dns/external-dns:v0.13.4
      
# eksctl 설치/업데이트 addon 확인
eksctl get addon --cluster $CLUSTER_NAME							

# IRSA 확인
eksctl get iamserviceaccount --cluster $CLUSTER_NAME
NAMESPACE	NAME				ROLE ARN

 


1. 스토리지 이해 - 링크

1-1 배경 소개

  • 파드 내부의 데이터는 파드가 정지되면 모두 삭제됨 → 즉, 파드가 모두 상태가 없는(Stateless) 애플리케이션이였음! : Temporary filesystem, Volume - 링크

  • 데이터베이스(파드)처럼 데이터 보존이 필요 == 상태가 있는(Stateful) 애플리케이션 : PV & PVC
    → 로컬 볼륨(hostPath) ⇒ 퍼시스턴트 볼륨(Persistent Volume, PV) - 어느 노드에서도 연결하여 사용 가능, 예시) NFS,
    AWS EBS, Ceph 등

  • 파드가 생성될 때 자동으로 볼륨을 마운트하여 파드에 연결하는 기능을 동적 프로비저닝(Dynamic Provisioning)이라고 함

  • 퍼시스턴트 볼륨의 사용이 끝났을 때 해당 볼륨은 어떻게 초기화할 것인지 별도로 설정할 수 있는데, 쿠버네티스는 이를
    Reclaim Policy(반횐 정책) 라고 부릅니다.
  • Reclaim Policy(반환 정책) 에는 크게 Retain(보존), Delete(삭제, 즉 EBS 볼륨도 삭제됨), Recycle 방식등이 있습니다. - 링크

1-2 스토리지 소개 - 링크

 

Volume

emptyDir, hostPath, PV/PVC

kubetm.github.io


1-3 CSI  (Container Storage Intrerface)

  • CSI Driver 배경 : Kubernetes source code 내부에 존재하는 AWS EBS provisione는 당연히 Kubernetes release lifecycle을 따라서 배포되므로, provisioner 신규 기능을 사용하기 위해서는 Kubernetes version을 업그레이드해야 하는 제약 사항이 있습니다. 따라서, Kubernetes 개발자는 Kubernetes 내부에 내장된 provisioner (in-tree)를 모두 삭제하고, 별도의 controller Pod을 통해 동적 provisioning을 사용할 수 있도록 만들었습니다. 이것이 바로 CSI (Container Storage Interface) driver 입니다.
  • CSI 를 사용하면, K8S 의 공통화된 CSI 인터페이스를 통해 다양한 프로바이더를 사용할 수 있다.

  • 일반적인 CSI driver의 구조입니다. AWS EBS CSI driver 역시 아래와 같은 구조를 가지는데, 오른쪽 StatefulSet 또는 Deployment로 배포된 controller Pod이 AWS API를 사용하여 실제 EBS volume을 생성하는 역할을 합니다. 왼쪽 DaemonSet으로 배포된 node Pod은 AWS API를 사용하여 Kubernetes node (EC2 instance)에 EBS volume을 attach 해줍니다.

* etcd : key:value 형태의 데이터를 저장하는 스토리지입니다. etcd가 다운된다면 Kubernetes 클러스터는 제대로 동작하지 못하게 되므로 높은 신뢰성을 제공해야 합니다.  - 링크

1-4 Node-specific Volume Limits(노드 별 볼륨 제한) - 링크

  • AWS EC2 Type에 따라 볼륨 최대 제한 : 25개 ~ 39개
# 확인
kubectl describe node | grep Allocatable: -A1
Allocatable:
  attachable-volumes-aws-ebs:  25
  • KUBE_MAX_PD_VOLS 환경 변수의 값을 설정한 후, 스케줄러를 재시작하여 이러한 한도를 변경 가능

1-5 기본 컨테이너 환경의 임시 파일시스템 사용

# 파드 배포
# date 명령어로 현재 시간을 10초 간격으로 /home/pod-out.txt 파일에 저장
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/date-busybox-pod.yaml
cat date-busybox-pod.yaml | yh
kubectl apply -f date-busybox-pod.yaml

# 파일 확인
kubectl get pod
NAME      READY   STATUS    RESTARTS   AGE
busybox   1/1     Running   0          26s

kubectl exec busybox -- tail -f /home/pod-out.txt
Mon May 15 08:32:50 UTC 2023
Mon May 15 08:33:00 UTC 2023
...

# 파드 삭제 후 다시 생성 후 파일 정보 확인 > 이전 기록이 보존되어 있는지?
kubectl delete pod busybox
kubectl apply -f date-busybox-pod.yaml
kubectl exec busybox -- tail -f /home/pod-out.txt
Mon May 15 08:33:57 UTC 2023
.....

# 실습 완료 후 삭제
kubectl delete pod busybox

1-6 호스트 Path 를 사용하는 PV/PVC : local-path-provisioner 스트리지 클래스 배포 - 링크

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

# 확인
kubectl get-all -n local-path-storage
kubectl get pod -n local-path-storage -owide
NAME                                      READY   STATUS    RESTARTS   AGE   IP              NODE                                               NOMINATED NODE   READINESS GATES
local-path-provisioner-759f6bd7c9-dtdpc   1/1     Running   0          19s   192.168.2.104   ip-192-168-2-218.ap-northeast-2.compute.internal   <none>           <none>

kubectl describe cm -n local-path-storage local-path-config
kubectl get sc
kubectl get sc local-path
NAME         PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
local-path   rancher.io/local-path   Delete          WaitForFirstConsumer   false                  61s
  • PV/PVC 를 사용하는 파드 생성
# PVC 생성
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/localpath1.yaml
cat localpath1.yaml | yh
kubectl apply -f localpath1.yaml

# PVC 확인
kubectl get pvc
kubectl describe pvc

# 파드 생성
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/localpath2.yaml
cat localpath2.yaml | yh
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: localpath-claim
      
kubectl apply -f localpath2.yaml

# 파드 확인
kubectl get pod,pv,pvc
NAME      READY   STATUS    RESTARTS   AGE
pod/app   1/1     Running   0          2m51s

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                     STORAGECLASS   REASON   AGE
persistentvolume/pvc-5a7525c4-4829-49f5-8cd6-a7306e93a0e2   1Gi        RWO            Delete           Bound    default/localpath-claim   local-path              2m43s

NAME                                    STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/localpath-claim   Bound    pvc-5a7525c4-4829-49f5-8cd6-a7306e93a0e2   1Gi        RWO            local-path     3m47s

kubectl describe pv    # Node Affinity 확인
kubectl exec -it app -- tail -f /data/out.txt
Sun Jan 29 05:13:45 UTC 2023
... 

# 워커노드 중 현재 파드가 배포되어 있다만, 아래 경로에 out.txt 파일 존재 확인
ssh ec2-user@$N1 tree /opt/local-path-provisioner
/opt/local-path-provisioner
└── pvc-5a7525c4-4829-49f5-8cd6-a7306e93a0e2_default_localpath-claim
    └── out.txt

# 해당 워커노드 자체에서 out.txt 파일 확인 : 아래 굵은 부분은 각자 실습 환경에 따라 다름
ssh ec2-user@$N1 tail -f /opt/local-path-provisioner/pvc-5a7525c4-4829-49f5-8cd6-a7306e93a0e2_default_localpath-claim/out.txt
Mon May 15 08:39:39 UTC 2023
Mon May 15 08:39:44 UTC 2023
...
  • 파드 삭제 후 재생성해서 데이터 유지되는지 확인
# 파드 삭제 후 PV/PVC 확인
kubectl delete pod app
kubectl get pod,pv,pvc
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                     STORAGECLASS   REASON   AGE
persistentvolume/pvc-5a7525c4-4829-49f5-8cd6-a7306e93a0e2   1Gi        RWO            Delete           Bound    default/localpath-claim   local-path              3m37s

NAME                                    STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/localpath-claim   Bound    pvc-5a7525c4-4829-49f5-8cd6-a7306e93a0e2   1Gi        RWO            local-path     4m41s

ssh ec2-user@$N1 tree /opt/local-path-provisioner
/opt/local-path-provisioner
└── pvc-5a7525c4-4829-49f5-8cd6-a7306e93a0e2_default_localpath-claim
    └── out.txt

# 파드 다시 실행
kubectl apply -f localpath2.yaml
 
# 확인
kubectl exec -it app -- head /data/out.txt
Mon May 15 08:38:14 UTC 2023
Mon May 15 08:38:19 UTC 2023
....

kubectl exec -it app -- tail -f /data/out.txt
Mon May 15 08:43:54 UTC 2023
Mon May 15 08:43:59 UTC 2023
....
  • 다음 실습을 위해서 파드와 PVC 삭제
PV/PVC 자세히 이해해보기 - 링크
# 파드와 PVC 삭제 
kubectl delete pod app
kubectl get pv,pvc
kubectl delete pvc localpath-claim

# 확인
kubectl get pv
ssh ec2-user@$N1 tree /opt/local-path-provisioner
0 directories, 0 files

2. AWS EBS Controller - 링크

 

EKS 스터디 - 3주차 1편 - EKS가 AWS스토리지를 다루는 원리

3주차 1편에서는 EKS가 어떻게 AWS스토리지를 사용할 수 있으며, 사용 예제를 소개합니다. EKS가 AWS스토리지를 사용하는 원리 쿠버네티스에서는 다양한 스토리지 연계를 위해 CSI 인터페이스를 제

malwareanalysis.tistory.com

2-1 Volume (ebs-csi-controller) : EBS CSI driver 동작 : 볼륨 생성 및 파드에 볼륨 연결 - 링크

  • persistentvolume, persistentvolumeclaim의 accessModes는 ReadWriteOnce로 설정해야 합니다 - Why? 
  • EBS스토리지 기본 설정이 동일 AZ에 있는 EC2 인스턴스(에 배포된 파드)에 연결해야 합니다 - Why? 파드 스케줄링 방안은?


2-2 설치 : Amazon EBS CSI driver as an Amazon EKS add-on - 링크 Parameters

# 아래는 aws-ebs-csi-driver 전체 버전 정보와 기본 설치 버전(True) 정보 확인
aws eks describe-addon-versions \
    --addon-name aws-ebs-csi-driver \
    --kubernetes-version 1.24 \
    --query "addons[].addonVersions[].[addonVersion, compatibilities[].defaultVersion]" \
    --output text
v1.18.0-eksbuild.1
Tru
v1.17.0-eksbuild.1
False
...

# ISRA 설정 : AWS관리형 정책 AmazonEBSCSIDriverPolicy 사용
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

# ISRA 확인
kubectl get sa -n kube-system ebs-csi-controller-sa -o yaml | head -5
eksctl get iamserviceaccount --cluster myeks

# 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

# 확인
eksctl get addon --cluster ${CLUSTER_NAME}
kubectl get deploy,ds -l=app.kubernetes.io/name=aws-ebs-csi-driver -n kube-system
kubectl get pod -n kube-system -l 'app in (ebs-csi-controller,ebs-csi-node)'
kubectl get pod -n kube-system -l app.kubernetes.io/component=csi-driver

# 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

# csinodes 확인
kubectl get csinodes
NAME                                               DRIVERS   AGE
ip-192-168-1-217.ap-northeast-2.compute.internal   1         35m
ip-192-168-2-218.ap-northeast-2.compute.internal   1         35m
ip-192-168-3-183.ap-northeast-2.compute.internal   1         35m

# gp3 스토리지 클래스 생성
kubectl get sc
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
kubectl apply -f gp3-sc.yaml
kubectl get sc
NAME            PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
gp2 (default)   kubernetes.io/aws-ebs   Delete          WaitForFirstConsumer   false                  46m
gp3             ebs.csi.aws.com         Delete          WaitForFirstConsumer   true                   6s
local-path      rancher.io/local-path   Delete          WaitForFirstConsumer   false                  17m

kubectl describe sc gp3 | grep Parameters
Parameters:            allowAutoIOPSPerGBIncrease=true,encrypted=true,type=gp3
  • AWS EBS 스토리지 클래스 파라미터 - 링크
 

스토리지 클래스

이 문서는 쿠버네티스의 스토리지클래스의 개념을 설명한다. 볼륨과 퍼시스턴트 볼륨에 익숙해지는 것을 권장한다. 소개 스토리지클래스는 관리자가 제공하는 스토리지의 "classes"를 설명할 수

kubernetes.io


2-3 설치

# 워커노드의 EBS 볼륨 확인 : tag(키/값) 필터링 - 링크
aws ec2 describe-volumes --filters Name=tag:Name,Values=$CLUSTER_NAME-ng1-Node --output table
aws ec2 describe-volumes --filters Name=tag:Name,Values=$CLUSTER_NAME-ng1-Node --query "Volumes[*].Attachments" | jq
aws ec2 describe-volumes --filters Name=tag:Name,Values=$CLUSTER_NAME-ng1-Node --query "Volumes[*].{ID:VolumeId,Tag:Tags}" | jq
aws ec2 describe-volumes --filters Name=tag:Name,Values=$CLUSTER_NAME-ng1-Node --query "Volumes[].[VolumeId, VolumeType, Attachments[].[InstanceId, State][]][]" | jq
aws ec2 describe-volumes --filters Name=tag:Name,Values=$CLUSTER_NAME-ng1-Node --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 <<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
kubectl get pvc,pv
NAME                              STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/ebs-claim   Pending                                      gp3            20s

# 파드 생성
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

# PVC, 파드 확인
kubectl get pvc,pv,pod
NAME                              STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/ebs-claim   Bound    pvc-ec97ab62-b4f6-413d-9b9d-dfd601f526de   4Gi        RWO            gp3            95s

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE
persistentvolume/pvc-ec97ab62-b4f6-413d-9b9d-dfd601f526de   4Gi        RWO            Delete           Bound    default/ebs-claim   gp3                     11s

NAME      READY   STATUS    RESTARTS   AGE
pod/app   1/1     Running   0          15s

kubectl get VolumeAttachment
NAME                                                                   ATTACHER          PV                                         NODE                                               ATTACHED   AGE
csi-a34b0bca7da1a1c9d6647183284fec2884ba39906929e6a5782debd03089f82c   ebs.csi.aws.com   pvc-ec97ab62-b4f6-413d-9b9d-dfd601f526de   ip-192-168-1-217.ap-northeast-2.compute.internal   true       25s

# 추가된 EBS 볼륨 상세 정보 확인 
aws ec2 describe-volumes --volume-ids $(kubectl get pv -o jsonpath="{.items[0].spec.csi.volumeHandle}") | jq

# PV 상세 확인 : nodeAffinity 내용의 의미는?
kubectl get pv -o yaml | yh
...
    nodeAffinity:
      required:
        nodeSelectorTerms:
        - matchExpressions:
          - key: topology.ebs.csi.aws.com/zone
            operator: In
            values:
            - ap-northeast-2a
...

kubectl get node --label-columns=topology.ebs.csi.aws.com/zone,topology.kubernetes.io/zone
kubectl describe node | more

# 파일 내용 추가 저장 확인
kubectl exec app -- tail -f /data/out.txt

# 아래 명령어는 확인까지 다소 시간이 소요됨
kubectl df-pv
PV NAME                                   PVC NAME   NAMESPACE  NODE NAME                                         POD NAME  VOLUME MOUNT NAME   SIZE  USED  AVAILABLE  %USED  IUSED  IFREE   %IUSED 
 pvc-ec97ab62-b4f6-413d-9b9d-dfd601f526de  ebs-claim  default    ip-192-168-1-217.ap-northeast-2.compute.internal  app       persistent-storage  3Gi   28Ki  3Gi        0.00   12     262132  0.00   

## 파드 내에서 볼륨 정보 확인
kubectl exec -it app -- sh -c 'df -hT --type=overlay'
Filesystem     Type     Size  Used Avail Use% Mounted on
overlay        overlay   30G  3.8G   27G  13% /

kubectl exec -it app -- sh -c 'df -hT --type=ext4'
Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/nvme1n1   ext4  3.8G   28K  3.8G   1% /data
  • 볼륨 증가 - 링크 ⇒ 늘릴수는 있어도 줄일수는 없다! - 링크
# 현재 pv 의 이름을 기준하여 4G > 10G 로 증가 : .spec.resources.requests.storage의 4Gi 를 10Gi로 변경
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'
Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/nvme1n1   ext4  9.8G   28K  9.7G   1% /data

kubectl df-pv
PV NAME                                   PVC NAME   NAMESPACE  NODE NAME                                         POD NAME  VOLUME MOUNT NAME   SIZE  USED  AVAILABLE  %USED  IUSED  IFREE   %IUSED 
 pvc-ec97ab62-b4f6-413d-9b9d-dfd601f526de  ebs-claim  default    ip-192-168-1-217.ap-northeast-2.compute.internal  app       persistent-storage  9Gi   28Ki  9Gi        0.00   12     655348  0.00  
 
aws ec2 describe-volumes --volume-ids $(kubectl get pv -o jsonpath="{.items[0].spec.csi.volumeHandle}") | jq
  • 삭제
kubectl delete pod app & kubectl delete pvc ebs-claim

3. AWS Volume SnapShots Controller

3-1 Volumesnapshots 컨트롤러 설치 - 링크 VolumeSnapshot example Blog

# (참고) EBS CSI Driver에 snapshots 기능 포함 될 것으로 보임
kubectl describe pod -n kube-system -l app=ebs-csi-controller

# 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-15T09:03:30Z
volumesnapshotcontents.snapshot.storage.k8s.io   2023-05-15T09:03:30Z
volumesnapshots.snapshot.storage.k8s.io          2023-05-15T09:03:30Z

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            0           9s

kubectl get pod -n kube-system -l app=snapshot-controller
NAME                                   READY   STATUS    RESTARTS   AGE
snapshot-controller-76494bf6c9-565bp   1/1     Running   0          21s
snapshot-controller-76494bf6c9-g8tvl   1/1     Running   0          21s

# 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 # 혹은 volumesnapshotclasses

 

3-2 사용 example Blog

  • 테스트 PVC 파드 생성
# PVC 생성
kubectl apply -f awsebs-pvc.yaml

# 파드 생성
kubectl apply -f awsebs-pod.yaml

# 파일 내용 추가 저장 확인
kubectl exec app -- tail -f /data/out.txt
Mon May 15 09:08:06 UTC 2023
Mon May 15 09:08:11 UTC 2023
....

# VolumeSnapshot 생성 : Create a VolumeSnapshot referencing the PersistentVolumeClaim name >> EBS 스냅샷 확인
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/ebs-volume-snapshot.yaml
cat ebs-volume-snapshot.yaml | yh
kubectl apply -f ebs-volume-snapshot.yaml

# VolumeSnapshot 확인
kubectl get volumesnapshot
kubectl get volumesnapshot ebs-volume-snapshot -o jsonpath={.status.boundVolumeSnapshotContentName} ; echo
kubectl describe volumesnapshot.snapshot.storage.k8s.io ebs-volume-snapshot
kubectl get volumesnapshotcontents

# VolumeSnapshot ID 확인 
kubectl get volumesnapshotcontents -o jsonpath='{.items[*].status.snapshotHandle}' ; echo
snap-068ba661405f51dba

# 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 로 복원
kubectl get pvc,pv
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
cat ebs-snapshot-restored-claim.yaml | yh
kubectl apply -f ebs-snapshot-restored-claim.yaml

# 확인
kubectl get pvc,pv

# 파드 생성
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/ebs-snapshot-restored-pod.yaml
cat ebs-snapshot-restored-pod.yaml | yh
kubectl apply -f ebs-snapshot-restored-pod.yaml

# 파일 내용 저장 확인 : 파드 삭제 전까지의 저장 기록이 남아 있다. 이후 파드 재생성 후 기록도 잘 저장되고 있다
kubectl exec app -- cat /data/out.txt


# 삭제
kubectl delete pod app && kubectl delete pvc ebs-snapshot-restored-claim && kubectl delete volumesnapshots ebs-volume-snapshot

참고링크 : Velero 백업 - 링크 / 볼륨 snapscheduler : 정기적인 반복 스냅샷 생성 - 링크1, 링크2, 링크3


4. AWS EFS Controller

4-1 EFS 파일시스템 확인 및 EFS Controller 설치 - 링크 Github Helm

# EFS 정보 확인 
aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text
fs-07932f79795ec8f70

# 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

# 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

# ISRA 확인
kubectl get sa -n kube-system efs-csi-controller-sa -o yaml | head -5
eksctl get iamserviceaccount --cluster myeks

# 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

# 확인
helm list -n kube-system
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-v2l66   3/3     Running   0          18s
efs-csi-controller-6f64dcc5dc-vf24n   3/3     Running   0          18s
efs-csi-node-4f28d                    3/3     Running   0          18s
efs-csi-node-72jsd                    3/3     Running   0          18s
efs-csi-node-qhsgw                    3/3     Running   0          18s
  • AWS → EFS → 파일 시스템 : 네트워크 → 탑재 대상 ID 확인


4-2 EFS 파일시스템을 다수의 파드가 사용하게 설정 : Add empty StorageClasses from static example - Workshop 링크

# 모니터링
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
.
├── claim.yaml
├── pod1.yaml
├── pod2.yaml
├── pv.yaml
└── storageclass.yaml

0 directories, 5 files

# EFS 스토리지클래스 생성 및 확인
cat storageclass.yaml | yh
kubectl apply -f storageclass.yaml
kubectl get sc efs-sc

# PV 생성 및 확인 : volumeHandle을 자신의 EFS 파일시스템ID로 변경
EfsFsId=$(aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text)
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-07932f79795ec8f70
    
kubectl apply -f pv.yaml
kubectl get pv; kubectl describe 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         1s

# 파드 생성 및 연동 : 파드 내에 /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

# 공유 저장소 저장 동작 확인
tree /mnt/myefs              # 작업용EC2에서 확인
/mnt/myefs
├── out1.txt
└── out2.txt

0 directories, 2 files

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
  • 실습 완료 후 삭제
# 쿠버네티스 리소스 삭제
kubectl delete pod app1 app2 
kubectl delete pvc efs-claim && kubectl delete pv efs-pv && kubectl delete sc efs-sc

4-3 EFS 파일시스템을 다수의 파드가 사용하게 설정 : Dynamic provisioning using EFSFargate node는 현재 미지원 - Workshop

# 모니터링
watch 'kubectl get sc efs-sc; echo; kubectl get pv,pvc,pod'

# 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
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata: 
  name: efs-sc
provisioner: efs.csi.aws.com
parameters: 
  provisioningMode: efs-ap
  fileSystemId: fs-07932f79795ec8f70
  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                  9s

# 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
---
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-1980ca28-6efc-443f-9f93-bfb5c603bb10   5Gi        RWX            efs-sc         17s

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE
persistentvolume/pvc-1980ca28-6efc-443f-9f93-bfb5c603bb10   5Gi        RWX            Delete           Bound    default/efs-claim   efs-sc                  16s

NAME          READY   STATUS    RESTARTS   AGE
pod/efs-app   1/1     Running   0          17s

# PVC/PV 생성 로그 확인
kubectl logs -n kube-system -l app=efs-csi-controller -c csi-provisioner -f

# 파드 정보 확인
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

# 공유 저장소 저장 동작 확인
tree /mnt/myefs              # 작업용EC2에서 확인
/mnt/myefs
├── dynamic_provisioning
│   └── pvc-1980ca28-6efc-443f-9f93-bfb5c603bb10
│       └── out
├── out1.txt
└── out2.txt

kubectl exec efs-app -- bash -c "cat data/out"
Mon May 15 09:23:32 UTC 2023
Mon May 15 09:23:37 UTC 2023
Mon May 15 09:23:42 UTC 2023
....
  • EFS → 액세스 포인트 확인

  • 실습 완료 후 삭제
# 쿠버네티스 리소스 삭제
kubectl delete -f pod.yaml
kubectl delete -f storageclass.yaml

5. AWS Fargate - 링크1, 링크2

스킵


6. EKS Persistent Volumes for Instance Store & Add NodeGroup

6-1 신규 노드 그룹 ng2 생성 - Blog : c5d.large 의 EC2 인스턴스 스토어(임시 블록 스토리지)
설정 작업- 링크 , NVMe SSD - 링크

  • 데이터 손실 : 기본 디스크 드라이브 오류, 인스턴스가 중지됨, 인스턴스가 최대 절전 모드로 전환됨, 인스턴스가 종료

  • 인스턴스 스토어는 EC2 스토리지(EBS) 정보에 출력되지는 않는다
# 인스턴스 스토어 볼륨이 있는 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

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

# 노드 보안그룹 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

# 워커 노드 SSH 접속
N4=192.168.1.116
ssh ec2-user@$N4 hostname

# 확인
ssh ec2-user@$N4 sudo nvme list
Node             SN                   Model                                    Namespace Usage                      Format           FW Rev  
---------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1     vol0ccc888359a5ddd75 Amazon Elastic Block Store               1          32.21  GB /  32.21  GB    512   B +  0 B   1.0     
/dev/nvme1n1     AWSE81A9A472F9635207 Amazon EC2 NVMe Instance Storage         1          50.00  GB /  50.00  GB    512   B +  0 B   0

ssh ec2-user@$N4 sudo lsblk -e 7 -d
NAME    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
nvme0n1 259:0    0   30G  0 disk 
nvme1n1 259:1    0 46.6G  0 disk /data

ssh ec2-user@$N4 sudo df -hT -t xfs
Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/nvme0n1p1 xfs    30G  3.3G   27G  11% /
/dev/nvme1n1   xfs    47G  365M   47G   1% /data

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

# (옵션) 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:                      3068880Ki
  pods:                        100

# (옵션) kubelet 데몬 파라미터 확인 : --max-pods=29 --max-pods=100
ssh ec2-user@$N4 sudo ps -ef | grep kubelet
root      2979     1  1 09:31 ?        00:00:03 /usr/bin/kubelet --config /etc/kubernetes/kubelet/kubelet-config.json --kubeconfig /var/lib/kubelet/kubeconfig --container-runtime-endpoint unix:///run/containerd/containerd.sock --image-credential-provider-config /etc/eks/image-credential-provider/config.json --image-credential-provider-bin-dir /etc/eks/image-credential-provider --node-ip=192.168.1.116 --pod-infra-container-image=602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/pause:3.5 --v=2 --cloud-provider=aws --container-runtime=remote --node-labels=eks.amazonaws.com/sourceLaunchTemplateVersion=1,alpha.eksctl.io/cluster-name=myeks,alpha.eksctl.io/nodegroup-name=ng2,disk=nvme,eks.amazonaws.com/nodegroup-image=ami-02ddbc7e7f404a16a,eks.amazonaws.com/capacityType=ON_DEMAND,eks.amazonaws.com/nodegroup=ng2,eks.amazonaws.com/sourceLaunchTemplateId=lt-0480288b9c96d575c --max-pods=29 --max-pods=100
  • 스토리지 클래스 재생성
# 기존 삭제
#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
...
  • 삭제
# 
kubectl delete -f local-path-storage.yaml

# 노드그룹 삭제
eksctl delete nodegroup -c $CLUSTER_NAME -n ng2

(실습 완료 후) 자원 삭제

  • 공통 : AWS CloudFormation 에 IRSA 스택 삭제
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
728x90
반응형

'EKS' 카테고리의 다른 글

EKS CloudFormation  (0) 2024.03.03
5주차 - EKS Autoscaling  (0) 2023.05.30
EKS 4주차 - EKS Observability  (0) 2023.05.16
EKS 2주차 - EKS Networking  (0) 2023.05.09
EKS 1주차 - Amzaon EKS 설치 및 기본 사용  (0) 2023.04.26
Comments