CloudNet@ Team Study/EKS Workshop 4th Cohort

Analysis of EKS Deployment Methods & Terraform Code

"Everything about infra" 2026. 3. 16. 20:45

 

안녕하십니까.

 

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

1w 디렉토리에서 terraform init, plan 및 apply 실행

 

배포하는 동안 시간이 오래 걸리므로 (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