1. Amazon EKS 원클릭 배포
이번 실습은 3장의 실습을 위한 기본 인프라 환경과 Amazon EKS 클러스터 배포에 대해 CloudFormation을 통해 원클릭 배포를 수행하는 가이드입니다.
Amazon EKS 원클릭 배포를 통해 실습 구성의 시간 절약과 함께 각 실습의 목표 학습 내용만 집중할 수 있을 것입니다.
1.1. CloudFormation 스택 생성
해당 링크를 클릭하면 AWS CloudFormation 페이지로 연결되며, 파라미터를 입력 후 스택을 생성합니다.
Note: AWS 관리 콘솔에 로그인 할때 IAM 사용자 계정으로 진행합니다.
[관리 콘솔] CloudFormation 파라미터 설정
- 스택 생성 페이지에서
다음
버튼을 클릭합니다. - 스택 이름은 [myeks]로 입력합니다.
- KeyName은 [각자의 키페어]를 선택합니다.
- MyIAMUserAccessKeyID는 [각자의 액세스 키 ID 값]을 입력합니다.
- MyIAMUserSecretAccessKey는 [각자의 시크릿 액세스 키 값]을 입력합니다.
- SgIngressSshCidr는 [각자의 PC의 퍼블릭 IP 주소/32]로 입력합니다.
- 나머지 파라미터는 기본 값을 유지하고
다음
버튼을 클릭합니다.
Warning: 설정을 마치고 약 20분 정도 대기 시간이 흐른 뒤 기본 인프라 환경과 Amazon EKS 클러스터 생성이 완료됩니다. 반드시 해당 대기 시간이 지난 후 다음 작업을 수행합니다.
1.2. CloudFormation 스택 생성 확인
Amazon EKS 원클릭 배포를 수행하면 AWS CloudFormation 스택 5개가 생성됩니다.
CloudFormation 스택 정보
- myeks: 기본 인프라 생성을 정의한 스택
- eksctl-myeks-cluster: eks 클러스터 생성을 정의한 스택
- eksctl-myeks-addon-vpc-cni: vpc cni를 위한 IAM 역할을 정의한 스택
- eksctl-myeks-nodegroup-ng1: eks 클러스터의 관리형 노드 그룹을 정의한 스택
- eksctl-myeks-addon-iamserviceaccount-kube-system-aws-load-balancer-controller: aws load balancer controller를 위한 IRSA를 정의한 스택
Note: myeks 스택의 출력 탭에서 관리용 인스턴스의 퍼블릭 IP 주소를 확인할 수 있습니다.
2. Amazon EKS 원클릭 배포 정보 확인
AWS CloudFormation 스택의 출력 탭에서 eksctlhost의 퍼블릭 IP를 확인합니다.
해당 IP로 EKS 관리용 인스턴스(myeks-bastion-EC2
)에 SSH로 접속하고 아래 명령어를 통해 정보를 확인합니다.
2.1. 기본 정보 확인
Amazon EKS 원클릭으로 배포된 기본 정보와 설정을 진행합니다.
Default Namespace로 적용
1
2
// Default Namespace로 위치 변경
kubectl ns default
노드의 프라이빗 IP 변수 선언
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 3대의 워커노드의 Private IP 주소 변수 저장
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})
// 3대의 워커노드의 Private IP 주소 전역 변수로 선언 및 확인
echo "export N1=$N1" >> /etc/profile
echo "export N2=$N2" >> /etc/profile
echo "export N3=$N3" >> /etc/profile
echo $N1, $N2, $N3
작업용 인스턴스에서 노드로 보안 그룹 설정
1
2
3
4
5
// 노드 보안 그룹 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
노드에 Tool 설치
1
2
3
4
5
6
// 노드 1, 2, 3에 유용한 Tool 설치
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
EFS 마운트 확인
1
2
3
4
5
6
7
8
9
10
11
// NFS4로 마운트 된 디스크 확인
df -hT --type nfs4
mount | grep nfs4
// EFS에 파일 생성, 확인, 삭제
echo "efs file test" > /mnt/myefs/memo.txt
cat /mnt/myefs/memo.txt
rm -f /mnt/myefs/memo.txt
만약 마운트가 되지 않는다면..
EFS 마운트
1
2
3
4
5
// EFS 파일 시스템 ID 변수 지정
EFS_ID=$(aws efs describe-file-systems --query "FileSystems[?Name=='myeks-EFS'].[FileSystemId]" --output text); echo $EFS_ID
// 작업용 인스턴스에 EFS 마운트
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
Default StorageClass 확인
1
2
3
4
// Default StorageClass 확인 (gp2)
kubectl get sc
kubectl get sc gp2 -o yaml | yh
2.2. AWS LB Controller, ExternalDNS, kube-ops-view 설치
2장에서 실습한 AWS Load Balancer Controller, ExternalDNS, kube-ops-view를 설치합니다.
AWS Load Balancer Controller 설치
1
2
3
4
5
6
7
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 설치
1
2
3
4
5
6
7
8
9
MyDomain=<자신의 도메인>
MyDnsHostedZoneId=$(aws route53 list-hosted-zones-by-name --dns-name "${MyDomain}." --query "HostedZones[0].Id" --output text)
echo $MyDomain, $MyDnsHostedZoneId
curl -s -O https://raw.githubusercontent.com/cloudneta/cnaeblab/master/_data/externaldns.yaml
MyDomain=$MyDomain MyDnsHostedZoneId=$MyDnsHostedZoneId envsubst < externaldns.yaml | kubectl apply -f -
kube-ops-view 설치
1
2
3
4
5
6
7
8
9
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"
설치 정보 확인
1
2
3
4
5
6
7
8
// 이미지 정보 확인
kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" | tr -s '[[:space:]]' '\n' | sort | uniq -c
// Add-On 정보 확인
eksctl get addon --cluster $CLUSTER_NAME
// IRSA 확인
eksctl get iamserviceaccount --cluster $CLUSTER_NAME
3. 기본 스토리지 실습
Amazon EKS 환경에서 기본 스토리지 실습을 진행합니다.
실습 단계는 1. 임시 파일 시스템, 2. emptyDir 볼륨, 3. local-path-provisioner 입니다.
3.1. 임시 파일 시스템 구성
컨테이너 내부에 구성되는 임시 파일 시스템을 구성하고 검증합니다.
파드 배포
1
2
3
4
5
6
// 파드 배포 - 10초 간격으로 date 명령을 입력하고 /home/pod-out.txt 파일에 저장
curl -s -O https://raw.githubusercontent.com/cloudneta/cnaeblab/master/_data/temporary-fs.yaml
cat temporary-fs.yaml | yh
kubectl apply -f temporary-fs.yaml
모니터링 - 저장된 파일 확인
1
2
// 신규 터미널 생성
kubectl exec busybox -- tail -f /home/pod-out.txt
busybox 컨테이너 프로세스 강제 종료
1
2
// 컨테이너에서 프로세스를 강제로 종료
kubectl exec busybox -c busybox -- kill -s SIGINT 1
실습 종료 후 파드 삭제
1
kubectl delete pod busybox
3.2. emptyDir 구성
파드 내부에 구성되는 emptyDir 볼륨을 구성하고 검증합니다.
파드 배포
1
2
3
4
5
6
7
8
9
10
// 파드 배포 - 10초 간격으로 date 명령을 입력하고 /mount/1-out.txt, 2-out.txt 파일에 저장
// 컨테이너 2대 생성 - emptyDir 볼륨 마운트
curl -s -O https://raw.githubusercontent.com/cloudneta/cnaeblab/master/_data/emptydir.yaml
cat emptydir.yaml | yh
kubectl apply -f emptydir.yaml
// busybox 파드에서 컨테이너 생성 확인
kubectl get pod busybox -o jsonpath='{.spec.containers[*].name}' ; echo
모니터링 - 저장된 파일 확인
1
2
// 신규 터미널 생성
kubectl exec busybox -- tail -f /mount/1-out.txt
busybox1 컨테이너 프로세스 강제 종료
1
2
// 컨테이너에서 프로세스를 강제로 종료
kubectl exec busybox -c busybox1 -- kill -s SIGINT 1
파드 삭제 후 재생성
1
2
3
4
5
6
7
8
9
// 파드 삭제 후 재생성
kubectl delete pod busybox
kubectl apply -f emptydir.yaml
// 저장된 파일 다시 확인
kubectl exec busybox -- tail -f /mount/1-out.txt
kubectl exec busybox -- tail -f /mount/2-out.txt
실습 종료 후 파드 삭제
1
kubectl delete pod busybox
3.3. local-path-provisioner 구성
PV와 PVC가 구성되는 영구 볼륨 환경에서 동적 프로비저닝을 구성합니다.
이때 외부 스토리지가 아닌 노드 내 경로로 local-path를 구성하고 검증합니다.
local-path-provisioner 설치 및 확인
local-path-provisioner 링크
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// local-path-provisioner 배포
curl -s -O https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml
cat local-path-storage.yaml | yh
kubectl apply -f local-path-storage.yaml
// local-path-provisioner 확인
kubectl get-all -n local-path-storage
kubectl get pod -n local-path-storage -owide
kubectl describe cm -n local-path-storage local-path-config
kubectl get sc
kubectl get sc local-path -o yaml | yh
모니터링 - 저장된 파일 확인
1
2
// 신규 터미널 생성 - pod, pv, pvc 모니터링
watch -d kubectl get pod,pv,pvc
PVC 생성
1
2
3
4
5
6
7
8
curl -s -O https://raw.githubusercontent.com/cloudneta/cnaeblab/master/_data/localpath-pvc.yaml
cat localpath-pvc.yaml | yh
kubectl apply -f localpath-pvc.yaml
// PVC 정보 확인
kubectl describe pvc
파드 생성
1
2
3
4
5
curl -s -O https://raw.githubusercontent.com/cloudneta/cnaeblab/master/_data/localpath-pod.yaml
cat localpath-pod.yaml | yh
kubectl apply -f localpath-pod.yaml
PV 정보 확인 및 변수 선언
1
2
3
4
5
6
7
8
9
10
11
12
13
// PV 정보 확인
kubectl describe pv
// PV가 마운팅할 노드 IP를 변수 지정
NODE_PV=$(kubectl describe pv | grep 'Term 0' | cut -b 50-62 | sed 's/[.|a-z]//g' | sed 's/-/./g')
echo $NODE_PV
// PV 이름 확인
kubectl get pvc localpath-claim -o jsonpath='{.spec.volumeName}' ; echo
// PV 이름 변수 지정
LP_PVC_NAME=$(kubectl get pvc localpath-claim -o jsonpath='{.spec.volumeName}')
생성된 파일 확인
1
2
3
4
5
6
7
8
// 파드에서 out.txt 파일 내용 확인
kubectl exec -it app -- tail -f /data/out.txt
// 노드에서 PV 경로 확인
ssh ec2-user@$NODE_PV tree /opt/local-path-provisioner
// 노드에서 out.txt 파일 내용 확인
ssh ec2-user@$NODE_PV tail -f /opt/local-path-provisioner/${LP_PVC_NAME}_default_localpath-claim/out.txt
파드 삭제 후 데이터 유지 확인
1
2
3
4
5
6
7
8
// 파드 삭제
kubectl delete pod app
// 노드에서 PV 경로 확인
ssh ec2-user@$NODE_PV tree /opt/local-path-provisioner
// 노드에서 out.txt 파일 내용 확인
ssh ec2-user@$NODE_PV tail -f /opt/local-path-provisioner/${LP_PVC_NAME}_default_localpath-claim/out.txt
파드 재 생성 후 데이터 유지 확인
1
2
3
4
5
6
7
8
// 파드 재생성
kubectl apply -f localpath-pod.yaml
// 파드에서 out.txt 파일 내용 확인 (Head)
kubectl exec -it app -- head /data/out.txt
// 파드에서 out.txt 파일 내용 확인 (Tail)
kubectl exec -it app -- tail -f /data/out.txt
실습 종료 후 파드와 PVC 삭제
1
2
3
4
5
6
7
8
// 파드 삭제
kubectl delete pod app
// PVC 삭제
kubectl delete pvc localpath-claim
// 노드에서 PV 경로 확인
ssh ec2-user@$NODE_PV tree /opt/local-path-provisioner
4. 실습 환경 삭제
Amazon EKS 원클릭을 통해 배포된 모든 자원을 삭제합니다.
Amazon EKS 원클릭 배포의 삭제
1
2
3
4
5
6
// kube-ops-view 삭제
helm uninstall -n kube-system kube-ops-view
// Amazon EKS 원클릭 배포의 삭제
eksctl delete cluster --name $CLUSTER_NAME \
&& aws cloudformation delete-stack --stack-name $CLUSTER_NAME
Warning: Amazon EKS 원클릭 배포의 삭제는 약 15분 정도 소요됩니다. 삭제가 완료될 때 까지 SSH 연결 세션을 유지합니다.
Warning: 만약에 CloudFormation 스택이 삭제되지 않는다면 수동으로 VPC(myeks-VPC )를 삭제 후 CloudFormation 스택을 다시 삭제해 주세요.
여기까지 3장의 Amazon EKS 원클릭 배포와 기본 스토리지 실습을 마칩니다.
수고하셨습니다 :)