스터디

EKS 스터디 3주차 (Storage)

엔지니어-여리 2023. 5. 22. 14:03
반응형

 

안녕하세요. 이번에는 지난 주에 진행했던 EKS 스터디 3주차 내용인 스토리지에 관하여 얘기하고자 합니다.

 

실습 환경 준비

가시다님이 제공해주시는 실습 자료:  Link

- Console에서 cloudformation을 배포하시는 경우에 AccessKey, SecretKey, Bastion노드에 SSH 접근할 IP Cidr를 주의해서 입력해주시기 바랍니다.

 

지난 번과 다르게 중복된 내용은 최대한 생략하고, 새로운 내용 위주로 정리해보도록 하겠습니다. 

### 기본 설정 ###

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

# (옵션) context 이름 변경
NICK=yeoli # 자신의 닉네임으로 변경하세요.
kubectl ctx
kubectl config rename-context eks-study-poc@myeks.ap-northeast-2.eksctl.io $NICK@myeks

# EFS 확인 : AWS 관리콘솔 EFS 확인해보자
mkdir -p /mnt/myefs # EFS 마운트를 위한 경로를 생성합니다.
EFS_ID=`aws efs describe-file-systems --query 'FileSystems[*].FileSystemId' --output text` # AWS CLI를 통해 EFS ID를 호출하여, 변수에 할당합니다.
mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport $EFS_ID.efs.ap-northeast-2.amazonaws.com:/ /mnt/myefs
df -hT --type nfs4 #마운트가 잘 되었는지 확인해봅시다.
mount | grep nfs4
echo "efs file test" > /mnt/myefs/memo.txt
cat /mnt/myefs/memo.txt
rm -f /mnt/myefs/memo.txt

# 스토리지클래스 및 CSI 노드 확인
kubectl get sc  #sc(storage class) 목록을 호출합니다. 
kubectl get sc gp2 -o yaml | yh #
kubectl get csinodes

# 노드 정보 확인
kubectl get node --label-columns=node.kubernetes.io/instance-type,eks.amazonaws.com/capacityType,topology.kubernetes.io/zone
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

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


# 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=<자신의 도메인>
MyDnzHostedZoneId=$(aws route53 list-hosted-zones-by-name --dns-name "${MyDomain}." --query "HostedZones[0].Id" --output text)
echo $MyDomain, $MyDnzHostedZoneId
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=1.5"

 

스토리지의 이해

 

쿠버네티스에서 동작하는 어플리케이션(application)을 상태로 분류하면 두 가지 유형이 있습니다.

stateless application

- (파드 내부의 데이터는)파드가 정지될 때 데이터가 유실될 수 있음

- 어플리케이션의 워크로드는 중단, 실행시 저장소 의존성을 고려해야함

stateful application

- 쿠버네티스에서 상태 저장 애플리케이션을 실행하려면 세 가지 간단한 스토리지 요구 사항을 준수해야 합니다.

  1. 스토리지는 포드의 수명 주기에 의존해서는 안 됩니다.
  2. 스토리지는 Kubernetes 클러스터의 모든 포드 및 노드에서 사용할 수 있어야 합니다.
  3. 스토리지는 충돌이나 애플리케이션 오류에 관계없이 가용성이 높아야 합니다.

 

실습

kube-ops-view 구성 및 hostPath

 

먼저 EFS를 인스턴스에 마운트 해줍니다.

 

gp2 스토리지 클래스 정보를 확인합니다.

노드 정보와 할당된 EC2 Instance Profile을 확인합니다.

 

 

Helm을 이용해 로드밸런서 컨트롤러도 설치해줍니다.

MyDomain을 설정해줍니다. (Route53에 호스트존을 미리 생성하셔야합니다.)

helm을 통해 kube-ops-view를 구축해줍니다.

kube-ops-view 접속 주소를 출력합니다.

 

 

kube-ops-view 링크로 접속시, 쿠버네티스의 정보(노드, 파드, 하드웨어)를 실시간으로 확인할 수 있습니다.

 

 

볼륨 최대 제한을 확인할 수 있습니다.

 

emptyDir

기본 컨테이너의 저장소를 활용하는 경우, 파드를 삭제하면 파드에 포함된 컨테이너의 저장소도 삭제됩니다.

아래 busybox 예제는, 10초마다 현재시간을 파일에 저장하는 컨테이너입니다.

처음 생성시 10:50분이 출력되는 것을 확인할 수 있습니다.

 

파드를 삭제한 다음 (`kubectl delete pod busybox`)

새롭게 파드를 배포한 다음, 파일 내용을 확인해보면 좀 전에 출력된 내용이 사라진 것을 (삭제된) 확인할 수 있습니다.

 

hostPath

 

hostPath를 사용하는 스토리지 클래스를 구성해줍니다.

스토리지 클래스 목록을 출력합니다.

이번에도 동일하게 파드를 배포해줍니다.

emptyDir과 같이 현재 시간이 출력되네요.

노드와 파드의 어떤 경로가 연결(binding)되어 있는지 확인할 수 있습니다.

결론적으로 hostPath는 emptyDir에 비해서 파드 의존성을 해결할 수 있지만, 노드 의존성은 해결할 수 없습니다. 

이후에는, EBS와 EFS을 활용하여 파드 의존성, 노드 의존성을 고려한 PV를 구성해보고 실제로 테스트해보겠습니다.

 

 

EBS Controller

 

EBS CSI 드라이버를 구성하기 위해 IRSA를 만들어줍니다.

 

잘 생성되었는지 확인해줍니다.

 

이제 EBS csi driver 애드온을 설치해줍니다.

 

gp3 스토리지 클래스 배포해줍니다.

 

PVC를 생성해줍니다.

 

파드의 컨테이너가 PV를 잘 붙여서 작동하는 지 확인할 수 있습니다.

물론 파드나 노드가 삭제된 다음에 다시 어플리케이션이 작동하더라도 PV에 저장된 내용은 유지됩니다.

 

Console에서 PV(EBS)가 생성된 것도 확인할 수 있구요.  

간단하게 명령어 한 줄로 동적으로 EBS 볼륨을 증가시킬 수 있습니다.

 

3. Volume Snapshot

 

혹시나, 신입 개발자가 PV를 날리면 어떻게 될까요 ?

EBS는 Snapshot을 만들고, 스냅샷으로부터 EBS 볼륨을 복원할 수 있습니다. 혹은 장기보관할 수 있습니다.

 

snapshot CRD를 먼저 다운로드 받고 설치해줍니다.

EBS Snapshot Controller를 설치해줍니다.

 

앱을 배포합니다.  (일정 시간마다 현재시간을 출력하여 파일에 저장하는 앱)

 

파드내 파일 내용이 정상적으로 작성되는 지 확인합니다. (위)

파드가 정상적으로 실행중인 것을 확인하고 (아래)

 

볼륨 스냅샷을 생성합니다.

 

스냅샷에 대해 정보를 출력합니다.

 

장애를 재현하기 위해, 파드와 PVC, PV를 삭제해줍니다.

 

스냅샷을 PVC로 복원해줍니다.

 

앱을 재배포해서 PV 내 파일의 내용이 유지되었는지 확인합니다.

 

EBS Snapshot Controller 실습이 끝났으니 리소스를 삭제합니다.

 

EFS Controller

IAM 정책을 생성, IRSA를 생성해줍니다.

 

Helm을 사용하여 efs-csi-driver를 설치해줍니다.

 

efs-csi-driver가 잘 설치되어있는지도 확인해줍니다.

 

스토리지 클래스, PV, PVC, Pod를 다운로드 받고 배포 해줍니다.

 

하단 좌측(app1), 하단 우측 (app2)을 보면 동일한 데이터가 기록되고 있음을 확인할 수 있습니다.

 

실습이 끝났으니 리소스를 삭제해줍니다.

 

3주차 정리를 시작하고 차일피일 미루다보니 더뎌졌네요. 

도커를 사용할 때는 생각해보지 않았던 문제를 쿠버네티스를 배우면서 해결책을 찾았고, AWS의 서비스를 활용해서 해결방법을 찾은것이 머리를 시원하게 해주는 것 같아 즐겁습니다.

EBS, EFS를 활용하지 않고 온프레미스에서 사용가능한 방법도 찾아보면 좋을 것 같네요.

 

도전과제는 7주차까지 정리가 마무리 된 다음에 다시 1주차 도전과제부터 하나씩 진행하면서 시리즈물로 연재하겠습니다.

 

EKS 스터디 3주차 내용 정리를 읽어주셔서 감사합니다.

반응형