[EKS@CloudNet] EKS by Terraform

2024. 4. 28. 02:50EKS@CloudNet

- CloudNet에서 주관하는 EKS 스터디 2기 내용입니다

- 매번 좋은 스터디를 진행해 주시는 CloudNet 팀 감사드립니다

- 잘못된 점, 업데이트된 지식, 다른 코멘트 언제나 환영입니다!

 

0. Setup

- 테라폼 설치

# tfenv 설치
brew install tfenv

# 테라폼 1.5.1 버전 설치
tfenv install 1.8.1

# 테라폼 1.5.1 버전 사용 설정 
tfenv use 1.8.1

# tfenv로 설치한 버전 확인
tfenv list

# 테라폼 버전 정보 확인
terraform version

# 자동완성
terraform -install-autocomplete

 

 

- 맥 기준 awscli/eksctl/kubectl/helm/watch/jq/tree 설치

brew install awscli eksctl kubernetes-cli helm tree jq watch

 

 

- aws 자격증명 설정

 

- default VPC 확인

aws ec2 describe-vpcs --filter 'Name=isDefault,Values=true' | jq '.Vpcs[0].VpcId'
aws ec2 describe-vpcs --filter 'Name=isDefault,Values=true' | jq

# configure region 확인
aws configure get region

# configure region 설정
aws configure set region ap-northeast-2

++DEBUG : Could not connect to the endpoint URL: "https://ec2.yes.amazonaws.com/"

처음에 aws configure 하면서 default region name 을 잘못 설정했기 때문이었다. ap-northeast-2로 재설정해 주니 정상적으로 VPC를 확인할 수 있었다

 

1. 테라폼으로 AWS EC2 배포 실습

- 우선 사용할 Amazon linux의 최신 ami id를 찾는다. ami 는 가상 머신의 운영 체제, 애플리케이션 서버 및 애플리케이션을 포함한 전체 소프트웨어 구성을 가지고 있다.

# 최신 ami id 찾기
aws ec2 describe-images --owners amazon --filters "Name=name,Values=amzn2-ami-hvm-2.0.*-x86_64-gp2" "Name=state,Values=available" --query 'Images|sort_by(@, &CreationDate)[-1].[ImageId]' --output text

# 추후 사용을 위해 AL2ID 변수에 저장
AL2ID=`aws ec2 describe-images --owners amazon --filters "Name=name,Values=amzn2-ami-hvm-2.0.*-x86_64-gp2" "Name=state,Values=available" --query 'Images|sort_by(@, &CreationDate)[-1].[ImageId]' --output text`
echo $AL2ID

 

- 다른 터미널에서 EC2 생성을 모니터링한다

export AWS_PAGER=""
while true; do aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text ; echo "------------------------------" ; sleep 1; done

 

- 테라폼 코드를 main.tf 에 작성한다

provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_instance" "example" {
  ami           = "$AL2ID"
  instance_type = "t2.micro"
}

 

- 배포를 실행한다

terraform init -> terraform plan -> terraform apply 순으로 배포한다

terraform init

# 종속관계 확인
tree .terraform

# auto plan
terraform plan

# 배포 실행
terraform apply # insert yes

 

plan을 하고 나면 Create/Update/Delete 중 해당 동작이 있는지를 알려준다

apply 를 실행하고 나면 아까 만들어놓은 모니터링 창에서 배포가 잘 되는 것을 확인할 수 있다.

- 테라폼 업데이트 및 반영

아까 만든 main.tf 파일을 수정해서 태그를 추가한다

provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_instance" "example" {
  ami           = "$AL2ID"
  instance_type = "t2.micro"

  tags = {
    Name = "aews-study"
  }

}

 

그리고 다시 Terraform plan -> terraform apply 를 실행하면 아래와 같이 ec2에 태그가 반영된 것을 볼 수 있다

 

- 리소스 삭제

terraform destroy #추가 yes 입력 필요

 

 

 

 

2. Terraform으로 EKS 배포

- 가시다님이 깃허브에 기존 cloudformation 과 동일한 내용으로 구성된 테라폼 코드를 배포해주셨다. 이 레포를 이용해서 배포를 진행한다. 배포에는 약 10분이 소요된다.

git clone https://github.com/gasida/aews-cicd.git
cd aews-cicd/4

# Keypair 저장
export TF_VAR_KeyName='my_keypair'
echo $TF_VAR_KeyName

terraform init
terraform plan

terraform apply -auto-approve

 

 

++DEBUG: creating CloudWatch Logs Log Group (/aws/eks/myeks/cluster): operation error CloudWatch Logs: CreateLogGroup, https response error StatusCode: 400, RequestID: cf0a427e-ee38-45fe-b6a0-a097d80d8c7b, ResourceAlreadyExistsException: The specified log group already exists

만든 적도 없는 CloudWatch 에서 에러가 뜨니까 조금 당황했는데 에러내용을 자세히 보니 동일한 이름의 로그그룹이 cloudwatch 에 이미 만들어져 있다는 것이었다. 그래서 웹콘솔로 CloudWatch에 들어가보니

 

내가 만든 기억도 없는 로그그룹이 만들어져 있었다. 클릭해서 들어가 보니

생성 시간 28일 전 ㅋㅋㅋㅋㅋ 언젠가 실습에서 만들었다가 지워지지 않은 녀석이 그대로 남아있었나 보다.

 

 

++DEBUG: 계속해서 꽃피는 애로사항

Error: creating IAM Policy (myeksExternalDNSPolicy): operation error IAM: CreatePolicy, https response error StatusCode: 409, RequestID: f1ff6e54-3112-48c9-b803-aaa2547278ac, EntityAlreadyExists: A policy called myeksExternalDNSPolicy already exists. Duplicate names are not allowed.

 

-> IAM 정책-고객 관리형 정책에 들어가서 테라폼실습 때 만들어진 것으로 추정되는 정책을 일일이 시간 확인해서 손으로 지움 

 

 

creating KMS Alias (alias/eks/myeks): AlreadyExistsException: An alias with the name arn:aws:kms:ap-northeast-2:484533150835:alias/eks/myeks already exists

 

-> 이것도 유사하게 KMS(Key Management Service) 에 들어가서 키를 싹 지워버리고 싶었는데 삭제 대기기간이 있어서, 다시 확인해보니 alias 때문이었어서 eks/myeks 이름 달고 있는 태그의 alias 를 지워줌 (맨 밑의 eks/myeks 만 살아 있는 것)

 

 

이 모든 일의 원흉은 

1. 미상의 로그그룹 존재(로 인한 배포 실패)

2. 1. 에서 배포 실패를 terraform destory 로 제대로 지우지 않고 그냥 로컬 파일만 지우고 다시 깔았던 것

이었다. 배포 실패시에도 꼭 terraform destroy 로 제대로 복구하고 재시도 하자!

 

 

- 우여곡절 끝에 배포에 성공했다.

# 테라폼 정보 확인
terraform state list

aws console 에서도 배포된 리소스를 확인할 수 있다

 

 

 

3. 두 번째 EKS 클러스터 배포: 코드 재사용 검증

- 똑같은 코드를 긁어다가 새 폴더를 만들고 배포하는데, 옵션들 다르게 줘서 배포한다

# 위 레포 폴더 4를 복사해서 새 폴더(5) 를 만듦
cd ..
mkdir 5
cd 5
cp ../4/*.tf .
ls

# 코드 재사용 배포
terraform init
terraform apply -auto-approve -var=ClusterBaseName=myeks2 -var=KubernetesVersion="1.28"

 

- 배포가 성공하는 것을 확인하고 나서 클러스터 이름을 업데이트 해준다

CLUSTER_NAME2=myeks2
aws eks update-kubeconfig --region ap-northeast-2 --name $CLUSTER_NAME2 --kubeconfig ./myeks2config

 

 

- 재사용 되어서 배포가 다시 잘되었음을 확인할 수 있다

 

 

자원 삭제

# 1st cluster
terraform destroy -auto-approve

# 2nd cluster
terraform destroy -auto-approve -var=ClusterBaseName=myeks2 -var=KubernetesVersion="1.28"

 

 

8주간의 EKS 스터디를 진행하면서 많이 성장했고, 간단한 EKS 클러스터는 직접 구성할 수 있으리라는 자신감이 생겼다.

동시에 아직 갈 길이 먼 것도 느꼈다.

가시다님과 CloudNet 팀원분들, 그리고 끝까지 과제 해내느라 애쓰신 2기 분들 모두 감사하고 고생많으셨습니다!!