Analysis of EKS Deployment Methods & Terraform Code

안녕하십니까.
CloudNet@ 팀 'Gasida' 님이 진행하시는 스터디 내용 중,
EKS의 배포 방식의 종류와 Terraform으로 배포 시
코드의 내용에 대해 알아보는 시간을 갖도록 하겠습니다.

01. EKS 배포 방식
📌 AWS Console - 수동 생성
가장 직관적인 방법으로 클릭 기반 GUI를 통해 EKS 클러스터를 구축할 수 있습니다.

- 진입장벽이 없고 즉시 시작 가능하며, 옵션이 UI에 시각화 되어 있어 학습에 유리한 장점이 있습니다.
- 변경 이력이 없어 "언제 누가 무엇을 바꿨는지" 추적 불가하며, 자동화가 불가능합니다.
이러한 특성을 봤을 때 프로덕션 환경에서는 권장하지 않고 학습 목적이나 일회성 테스트에 적합합니다.
📌 eksctl
eks 전용 cli 도구이며, yaml 기반 선언형 구성을 아래와 같이 지원합니다.
# yaml example
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: test-cluster
region: ap-northeast-2
vpc:
id: 'vpc-06a8d5e21e1ff70fe' # VPC ID
subnets:
private:
ap-northeast-2a: { id: subnet-072828d8126d902a2 }
ap-northeast-2c: { id: subnet-0fce293e71da2551a }
managedNodeGroups:
- name: test-worker1
labels: { role: workers }
instanceType: t2.large
desiredCapacity: 1
privateNetworking: true
subnets:
- subnet-072828d8126d902a2 #서브넷 ID
iam:
withAddonPolicies:
imageBuilder: true
- name: test-worker2
labels: { role: workers }
instanceType: t2.large
desiredCapacity: 1
privateNetworking: true
subnets:
- subnet-0fce293e71da2551a #서브넷 ID
iam:
withAddonPolicies:
imageBuilder: true
iam:
withOIDC: true
# cluster create
eksctl create cluster -f test-cluster.yaml
장점 !
- EKS에 최적화된 기본값 자동 설정 됨 (IAM role, security group etc..)
- add-on 관리, node group scaling이 간단한 명령어로 가능
- yaml 파일로 버전 관리가 가능하다.
단점 !
- 상태(state) 관리 기능이 없어 drift 감지 불가
- EKS 이외 리소스(RDS, S3 등)와 함께 통합 관리가 어려움
- CloudFormation 스택을 내부적으로 생성하기 때문에 세밀한 제어가 제한됨
이런 장 단점을 비교해봤을 때 개발/스테이징 환경에 적합할 것 같습니다.
📌 AWS CDK - IaC 도구
Python/TypeScript 등 프로그래밍 언어로 인프라를 정의하며, 내부적으로 CloudFormation으로 변환됩니다.
from aws_cdk import aws_eks as eks, aws_ec2 as ec2
cluster = eks.Cluster(self, "TestCluster",
version=eks.KubernetesVersion.V1_29,
vpc=vpc,
default_capacity=0
)
cluster.add_nodegroup_capacity("ng-test",
instance_types=[ec2.InstanceType("t3.large")],
min_size=2,
max_size=5,
desired_size=3,
)
장점 !
- 프로그래밍 언어의 추상화(루프, 조건문, 클래스 상속) 활용 가능
- AWS 서비스 간 통합이 매우 간결 (IAM 정책 자동 생성 등)
단점 !
- AWS 전용 — 멀티클라우드 불가
- CDK 버전 업그레이드 시 breaking change 발생 가능
- 팀원들 모두 해당 언어가 능숙해야함.
이러한 장 단점을 비교해봤을 때 인프라와 애플리케이션 코드를 같은 레포에서 관리하고 싶을 때나
AWS Native 서비스를 이용하는 개발자 중심 팀에 어울릴 것 같습니다.
📌 CloudFormation - IaC 도구
AWS Native IaC로, YAML/JSON 템플릿을 직접 작성하는 선언형 방식입니다.
# EKS Cluster (일부 내용 발췌)
Resources:
EKSCluster:
Type: AWS::EKS::Cluster
Properties:
Name: test-cluster
Version: "1.29"
ResourcesVpcConfig:
SubnetIds: !Ref PrivateSubnetIds
SecurityGroupIds: !Ref ClusterSG
RoleArn: !GetAtt EKSClusterRole.Arn
NodeGroup:
Type: AWS::EKS::Nodegroup
Properties:
ClusterName: !Ref EKSCluster
NodegroupName: ng-test
ScalingConfig:
MinSize: 2
MaxSize: 5
DesiredSize: 3
장점 !
- AWS 완전 통합으로 drift 감지 및 롤백 지원
- Stack 단위 라이프사이클 관리 (StackSets으로 멀티 계정 배포)
- 변경 사항 미리 보기 (Change Sets) 가능.
단점 !
- YAML 템플릿이 매우 장황해짐 — EKS 풀 스택은 수백 줄
- AWS 전용 — 타 클라우드 불가
- 반복 로직이 없어 Conditions/Mappings로 우회해야 함.
AWS 전용 엔터프라이즈 환경, StackSets으로 멀티 계정(dev/staging/prod)에 동일 스택 배포가 잦은 환경에
어울리는 배포 방식인 것 같습니다.
📌 Terraform - IaC 도구
HashiCorp의 멀티클라우드 IaC 도구로, HCL(HashiCorp Configuration Language)을 사용합니다.
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 20.0"
cluster_name = "test-cluster"
cluster_version = "1.29"
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
eks_managed_node_groups = {
prod = {
instance_types = ["t3.large"]
min_size = 2
max_size = 5
desired_size = 3
}
}
tags = {
Environment = "dev"
Project = "cloudneta"
}
}
장점 !
- terraform.tfstate로 실제 인프라 상태를 추적, drift 감지 가능
- 멀티클라우드 (AWS + Azure + GCP 등) 통합 관리
- 방대한 커뮤니티 모듈 (terraform-aws-modules/eks가 업계 표준)
- Terragrunt와 조합하면 환경별(dev/prod) 설정 분리가 깔끔
단점 !
- state 파일 관리 필요 (S3 + DynamoDB lock 설정)
- CloudFormation 대비 AWS 리소스 지원이 살짝 늦을 수 있음
- provider 버전 관리 주의 필요
프로덕션 표준으로 많이 사용하는 추세이며, 멀티 계정/멀티 리전 환경에서 환경 일관성을 보장해야 할 때 최적.
저희 EKS 배포 방식은 'Terraform'을 채택하여 배포할 예정이며, Terraform에 어색하신 분들은
이전 포스팅을 먼저 읽어보시는 것을 권장드립니다.
→ Click : https://ssunghwan.tistory.com/56
02. 테스트 환경 구성
필자는 MacOS 환경에서 로컬로 실습을 진행하였음을 사전에 밝힙니다.
aws cli 설치 및 자격 증명 설정
# Install aws cli
brew install awscli
aws --version
# iam (주체) 자격 증명 설정
aws configure
AWS Access Key ID : <액세스 키 입력>
AWS Secret Access Key : <시크릿 키 입력>
Default region name : ap-northeast-2
# 확인
aws sts get-caller-identity
AWS CLI로 EC2 Key Pair 생성
# 기본 Key Pair 생성 (pem 파일 생성)
aws ec2 create-key-pair \
--key-name my-keypair \
--query 'KeyMaterial' \
--output text > my-keypair.pem
# 권한 설정
chmod 400 my-keypair.pem
# 확인
aws ec2 describe-key-pairs --key-names my-keypair
k8s 관리 필수 툴 및 유용한 툴 설치
# install kubectl
brew install kubernetes-cli
kubectl version --client=true
# install helm
brew install helm
helm version
# 유용한 툴 설치
brew install krew k9s kube-ps1 kubectx kubecolor
# kubectl 출력 시 하이라이트 처리
echo "alias k=kubectl" >> ~/.zshrc
echo "alias kubectl=kubecolor" >> ~/.zshrc
echo "compdef kubecolor=kubectl" >> ~/.zshrc
# k8s krew path : ~/.zshrc 아래 추가
export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"
Terraform install
# tfenv 설치
brew install tfenv
# 설치 가능 버전 리스트 확인
tfenv list-remote
# 테라폼 특정 버전 설치
tfenv install 1.14.6
# 테라폼 특정 버전 사용 설정
tfenv use 1.14.6
# tfenv로 설치한 버전 확인
tfenv list
# 테라폼 버전 정보 확인
terraform version
# 자동완성
terraform -install-autocomplete
## 참고 .zshrc 에 아래 추가됨
cat ~/.zshrc
autoload -U +X bashcompinit && bashcompinit
complete -o nospace -C /usr/local/bin/terraform terraform
2-1. 실습 코드 다운로드 및 EKS 배포
# 코드 다운로드
git clone https://github.com/gasida/aews.git
cd aews
tree .
# 작업 디렉터리 이동
cd 1w

배포하는 동안 시간이 오래 걸리므로 (15분 내외) 배포 진행 후, Terraform 코드를 살펴보겠습니다.
# 변수 지정
aws ec2 describe-key-pairs --query "KeyPairs[].KeyName" --output text
export TF_VAR_KeyName=$(aws ec2 describe-key-pairs --query "KeyPairs[].KeyName" --output text)
export TF_VAR_ssh_access_cidr=$(curl -s ipinfo.io/ip)/32
echo $TF_VAR_KeyName $TF_VAR_ssh_access_cidr
# 배포 : 12분 정도 소요
terraform init
terraform plan
nohup sh -c "terraform apply -auto-approve" > create.log 2>&1 &
tail -f create.log
03. Terraform 코드 분석
각 tf 파일 별로 중요하게 생각되는 부분들만 간단하게 리뷰를 하도록 하겠습니다.
📌 vpc.tf

AWS 모듈을 표준화해서 관리하는 Terraform 공식 커뮤니티 조직에서 가져온 "vpc" 이름의 모듈입니다.
이 "vpc" 모듈 하나가 수 십개의 리소스를 대신 생성해주는 역할을 하고 있습니다.
즉, 모듈 없이 .tf 파일을 작성하려면 수 십줄이 넘어갑니다 (생성하고자 하는 리소스들을 모두 작성)
vpc cidr 및 azs, subnets 등 모두 var.tf에서 변수 처리되어 값을 호출하는 형태로 되어 있습니다.
Public 에서 사용하므로 NAT Gateway를 생성하지 않고, 노드에 Public IP를 자동 할당하는 변수를 사용함.
- enable_dns_support = true → AWS DNS 서버(169.254.169.253)를 사용 가능하도록
- enable_dns_hostnames = true → 퍼블릭 IP를 가진 인스턴스에 DNS 호스트네임 자동 부여
- enable_nat_gateway = flase → NAT 생성 X
- map_public_ip-on_launch = true → 노드에 Public IP 자동 할당.
vpc.tf 에서 알아볼 수 있는 내용은 아래와 같습니다.
- vpc 1개 생성
- Public subets 생성
- Internet Gateway 생성
- Private Subnetes 사용 안함.
📌 var.tf
아래 사진을 참고해본다면, 각 .tf 파일에서 사용할 변수들을 선언하는 파일인 것 같습니다.
실제 값을 담는 게 아니라 "이 모듈은 어떤 입력을 받을 수 있는가"를 정의하는 인터페이스 역할입니다.


var.tf에서 알아볼 수 있는 내용은 아래와 같습니다.
- vpc.tf가 var.VpcBlock, var.public_subnet_blocks 등을 참조 → VPC, 서브넷, IGW 등이 생성됨
- eks.tf가 var.ClusterBaseName, var.WorkerNodeCount 등을 참조 → EKS Cluster, NodeGroup, Security Group 등이 생성됨.
📌 eks.tf
크게 세 개의 Block으로 구성되어 있습니다.
provider block
# AWS 공급자: 지정된 리전에서 AWS 리소스를 설정
provider "aws" {
region = var.TargetRegion
}
이 루트 모듈 전체(vpc.tf 포함)에서 사용할 AWS 리전을 지정합니다.
provider는 보통 루트 모듈에 한 번만 선언하면 모든 .tf 파일에 적용됩니다.
Security Group block

- var.tf를 참조 했을 때 'myeks-node-group-sg' 라는 이름으로 노드 그룹의 SG가 생성됨.
- SG의 인바운드 규칙에 내 IP에 대한 all 허용 규칙이 추가.
EKS Module block
terraform-aws-modules/eks/aws ~> 21.0 모듈을 호출해서 내부적으로 수십 개의 리소스를 생성합니다.
(내부에서 처리되는 리소스 생성들은 'terraform init' 후 'terraform plan' 에서 확인이 가능합니다)

- Cluster Name, K8s version, managed node group 등 var.tf을 참조해서 값을 가져옴.
- enable_cluster_creator_admin_permission = true → terraform apply를 실행하는 IAM 자격증명 사용자에게 EKS Cluster-admin 권한을 자동으로 부여하는 옵션 (없으면 kubectl 명령 불가)
- endpoint_public_access = true → 퍼블릭 망에서 kubectl 호출 가능.
- User-data를 입력하여 노드 인스턴스 시작 시 입력된 스크립트를 실행하여 인스턴스에 적용시킴.
# add-on
addons = {
coredns = {
most_recent = true
}
kube-proxy = {
most_recent = true
}
vpc-cni = {
most_recent = true
before_compute = true
}
}
tags = {
Environment = "cloudneta-lab"
Terraform = "true"
}
}
- 노드에 필요한 coredns, kube-proxy, cni 애드온을 활성화 시키는 옵션.
결론적으로는, 아래와 같은 흐름으로 정리하시면 될 것 같습니다.
var.tf 에서 변수를 정의 → vpc.tf 에서 vpc 및 subnets 생성 → eks.tf 에서 SG, EKS Cluster, NodeGroup 생성.
1w 디렉토리의 vpc.tf , var.tf , eks.tf 파일을 분석하면 아래와 같이 정리할 수 있습니다.

긴 글 읽어주셔서 감사합니다.
꼭 실습을 해본 후에 아래 명령어를 입력하여 과금이 되지 않도록 리소스를 삭제해주세요!
terraform destory -auto-approve