[EKS] GitOps 기반 SaaS: 실습 환경 구성 - 3. 설치
최영락님의 AWS EKS Workshop Study(AEWS) 6주차 학습 내용을 기반으로 합니다.
TL;DR
- CloudFormation 콘솔에서 스택 생성 → ~30분 후 자동으로 전체 환경 구축
- 스택 배포 중 SSM Session Manager로 EC2에 접속하면
terraform-install.log로 진행 상황을 실시간 모니터링할 수 있다 CREATE_COMPLETE= 1단계(CloudFormation) + 2단계(Terraform) 모두 완료된 상태
사전 준비
- 개인 AWS 계정 + AdministratorAccess 권한을 가진 IAM 사용자
- 참조 레포: ianychoi/eks-saas-gitops 또는 aws-samples/eks-saas-gitops
- 구현 가이드 참조
최영락님께서 AWS 워크숍 환경을 제공해 주셔서 1회차 실습을 진행했는데, 내부 구조를 더 자세히 이해하기 위해 2회차에는 개인 AWS 계정에서 직접 CloudFormation으로 배포해 보았다.
CloudFormation 스택 생성
템플릿 업로드
- AWS CloudFormation 콘솔로 이동한다


- “스택 생성” → “새 리소스 사용(표준)”을 선택한다

- “템플릿 파일 업로드”를 선택하고, 이 리포지토리의
helpers/vs-code-ec2.yaml파일을 업로드한다


스택 세부 정보 지정
“다음”을 클릭하여 스택 세부 정보를 지정한다.
스택 이름: eks-saas-gitops-vscode
파라미터 구성:
| 파라미터 | 값 | 비고 |
|---|---|---|
| EnvironmentName | eks-saas-gitops |
기본값 |
| InstanceType | t3.large |
기본값 |
| AllowedIP | 본인 공인 IP/32 | 보안을 위해 0.0.0.0/0 대신 특정 IP 사용 권장 |
| LatestAmiId | 기본값 유지 | SSM에서 최신 AL2023 AMI 자동 조회 |


AllowedIP 설정
AllowedIP는 VS Code 서버 EC2의 보안 그룹에 허용할 소스 CIDR이다. EC2 보안 그룹은 출발지를 공인 IP 기준으로 판단하므로, 사설 IP(예: 192.168.x.x, 10.x.x.x)를 넣으면 접속할 수 없다.
| 상황 | 권장 CIDR | 예시 |
|---|---|---|
| 집/개인 PC | 내 공인 IP/32 | 123.45.67.89/32 |
| 회사/VPN | 회사 egress IP 대역 | 203.0.113.0/24 |
| 테스트/단기 실습 (비권장) | 0.0.0.0/0 |
전체 오픈 |
현재 공인 IP는 터미널에서 확인할 수 있다.
curl ifconfig.me
/32는 “정확히 그 IP 하나만 허용”이라는 의미다.
스택 옵션 구성
기본값 그대로 유지하면 된다.
| 옵션 | 의미 | 실습에서 |
|---|---|---|
| 태그 | 리소스 라벨링 용도 | 불필요 (템플릿이 자동 태깅) |
| IAM 역할 | CFN이 위임받을 역할 | 비워두면 현재 사용자 권한으로 실행 |
| 스택 실패 옵션 | 실패 시 리소스 롤백 | 모든 리소스 롤백 (기본값 유지) |
| 롤백 중 삭제 | 삭제 정책 사용 | 기본값 유지 |

IAM 기능 승인 및 전송
맨 아래 “기능” 섹션의 체크박스를 반드시 체크해야 한다.
AWS CloudFormation에서 사용자 지정 이름으로 IAM 리소스를 생성할 수 있음을 승인합니다.
이 템플릿은 eks-saas-gitops-admin이라는 고정 이름의 IAM Role(+ AdministratorAccess 권한)과 InstanceProfile을 만든다. 사용자 지정 이름의 IAM 리소스를 생성하기 때문에 CAPABILITY_NAMED_IAM 승인이 필요하다.
체크하지 않으면 다음 에러로 즉시 실패한다.
Requires capabilities : [CAPABILITY_NAMED_IAM]

체크 후 “전송” 버튼을 클릭하면 스택 생성이 시작된다.


배포 진행 모니터링
CloudFormation 콘솔에서 확인
스택 이벤트 탭에서 리소스 생성 타임라인을 확인할 수 있다.





콘솔 타임라인에서 주목할 점은 WaitCondition 막대가 전체 길이의 80% 이상을 차지한다는 것이다. 이 구간이 install.sh → Terraform 실행 시간에 해당한다. CFN 타임라인에는 EC2, VPC, SG 등 CloudFormation이 직접 만든 리소스만 보인다. EKS, Flux, Gitea, ECR 등은 EC2 내부에서 Terraform이 생성한 것이므로, CloudFormation은 그 존재를 알지 못하고 WaitCondition 신호만 기다리는 상태다.
참고: tracking-stack
CloudFormation 콘솔에
tracking-stack-<랜덤>이름의 스택이 자동으로 나타날 수 있다. 이는 AWS가 내부 추적 용도로 자동 생성하는 스택으로,EmptyResource하나만 포함되어 있다. 과금 없음, 실습 환경에 영향 없음 → 무시하면 된다.
![]()
터미널에서 실시간 모니터링
SSM Session Manager로 EC2에 접속하면, Terraform의 진행 상황을 실시간으로 확인할 수 있다.
# SSM 인스턴스 확인
aws ssm describe-instance-information \
--query "InstanceInformationList[*].{InstanceId:InstanceId, Status:PingStatus, OS:PlatformName}" \
--output text
# SSM으로 접속
export MYINSTANCE=i-0abc1234def56789
aws ssm start-session --target $MYINSTANCE
# 접속 후 root로 전환
sudo su -
# Terraform 설치 로그 실시간 확인
tail -f /home/ec2-user/environment/terraform-install.log
# install.sh 프로세스 확인
ps -ef | grep install.sh
주의: SSM Status가 Online이라는 것은 SSM Agent가 정상 체크인 중이라는 뜻일 뿐,
install.sh는 아직 진행 중일 수 있다.
terraform-install.log 주요 단계
tail -f 로그를 보면 다음과 같은 단계를 거친다.
1. VPC + EKS 클러스터 생성: 가장 오래 걸리는 구간이다.
module.vpc.aws_nat_gateway.this[0]: Still creating... [00m10s elapsed]
module.eks.aws_eks_cluster.this[0]: Still creating... [00m10s elapsed]
...
module.eks.aws_eks_cluster.this[0]: Still creating... [07m30s elapsed]
2. Gitea 서버 생성
module.gitea.aws_instance.gitea: Creation complete after 13s [id=i-0abc1234def56789]
3. IRSA(IAM Roles for Service Accounts) 역할 생성: Karpenter, Argo Workflows, Argo Events, LB Controller, TF Controller 등의 IAM Role을 생성한다.
4. setup-repos 스크립트 실행: payments, consumer, producer 세 저장소를 Gitea에 생성하고 초기 코드를 푸시한다.
setup-repos 로그 발췌
null_resource.execute_setup_repos_script: Creating...
null_resource.execute_setup_repos_script (local-exec): Executing: ["/bin/sh" "-c" "bash ./setup-repos.sh"]
null_resource.execute_setup_repos_script (local-exec): Getting configuration from Terraform outputs...
null_resource.execute_setup_repos_script (local-exec): Getting Gitea token from SSM Parameter Store...
null_resource.execute_setup_repos_script (local-exec): Getting ECR repository URLs from Terraform outputs...
null_resource.execute_setup_repos_script (local-exec): Processing payments...
null_resource.execute_setup_repos_script (local-exec): Creating repository for payments...
null_resource.execute_setup_repos_script (local-exec): ECR URL for payments: 123456789012.dkr.ecr.ap-northeast-2.amazonaws.com/payments
null_resource.execute_setup_repos_script (local-exec): Preparing payments code...
null_resource.execute_setup_repos_script (local-exec): Pushing payments code to Gitea...
null_resource.execute_setup_repos_script (local-exec): payments setup complete
null_resource.execute_setup_repos_script (local-exec): Processing consumer...
null_resource.execute_setup_repos_script (local-exec): Creating repository for consumer...
null_resource.execute_setup_repos_script (local-exec): consumer setup complete
null_resource.execute_setup_repos_script (local-exec): Processing producer...
null_resource.execute_setup_repos_script (local-exec): Creating repository for producer...
null_resource.execute_setup_repos_script (local-exec): producer setup complete
null_resource.execute_setup_repos_script (local-exec): All repositories have been set up successfully
null_resource.execute_setup_repos_script: Creation complete after 24s
5. Flux v2 설치: Flux Operator Helm chart를 설치하고 FluxInstance CRD를 적용한다.
Flux 설치 로그 발췌
module.flux_v2.helm_release.flux2-operator: Creating...
module.flux_v2.kubernetes_secret.flux_system: Creating...
module.flux_v2.kubernetes_secret.flux_system: Creation complete after 1s
module.flux_v2.helm_release.flux2-operator: Creation complete after 24s [id=flux-operator]
module.flux_v2.local_file.flux_instance_manifest: Creation complete after 0s
module.flux_v2.null_resource.apply_flux_instance: Creating...
module.flux_v2.null_resource.apply_flux_instance (local-exec): Waiting for Flux CRDs to be available...
module.flux_v2.null_resource.apply_flux_instance (local-exec): customresourcedefinition.apiextensions.k8s.io/fluxinstances.fluxcd.controlplane.io condition met
module.flux_v2.null_resource.apply_flux_instance (local-exec): Applying FluxInstance manifest...
module.flux_v2.null_resource.apply_flux_instance (local-exec): fluxinstance.fluxcd.controlplane.io/flux created
module.flux_v2.null_resource.apply_flux_instance: Creation complete after 2s
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
6. 최종 terraform apply: 실패한 Helm release 정리 후, 나머지 리소스(EBS CSI IRSA, EKS addon 등)를 생성한다.
최종 apply 로그 발췌
Deleting failed Helm releases in the flux-system namespace...
► deleting helmrelease karpenter in flux-system namespace
✔ helmrelease deleted
► deleting helmrelease kubecost in flux-system namespace
✔ helmrelease deleted
► deleting helmrelease metrics-server in flux-system namespace
✔ helmrelease deleted
Reconciling source git 'flux-system' in the flux-system namespace...
✔ fetched revision refs/heads/main@sha1:b792d408...
Applying remaining Terraform resources...
Apply complete! Resources: 2 added, 1 changed, 0 destroyed.
All Terraform resources created successfully.
==============================
Flux Setup Complete!
==============================
You can now check the status of Flux with:
kubectl get pods -n flux-system
==============================
7. 설치 완료 및 Gitea repo clone: 모든 인프라가 생성된 후, eks-saas-gitops 저장소를 로컬에 clone한다.
==============================
Infrastructure Installation Complete!
==============================
Gitea URL: http://xx.xx.xx.xx:3000
Gitea Admin Username: admin
Gitea Admin Password: ********
Your EKS cluster has been configured.
==============================
Cloning Gitea repositories...
Repository cloning completed successfully!
배포 완료 확인
CREATE_COMPLETE의 의미
CloudFormation 콘솔에서 스택 상태가 CREATE_COMPLETE로 전환되었다면, 다음이 모두 완료된 것이다.
- VS Code EC2 부팅 완료
- code-server 실행 중 (8080 포트)
install.sh의 Terraform이 전부 성공적으로 apply됨- EKS 클러스터, Gitea, Flux, ECR 등 모두 배포됨
gitops-gitea-repo까지 로컬에 clone 완료
이렇게 동작하는 이유는 이전 포스트에서 분석한 WaitCondition 때문이다.
WaitCondition.DependsOn: SSMBootstrapAssociation
WaitCondition.Timeout: 2000 # ~33분
CloudFormation은 EC2 내부의 install.sh가 Terraform으로 모든 리소스를 생성하고, curl -X PUT '{"Status":"SUCCESS"...}' 신호를 보내야만 WaitCondition 리소스를 “생성 완료”로 인정한다. 그래야 스택 전체가 CREATE_COMPLETE로 전이된다.
반대로, install.sh가 중간에 실패하면 FAILURE 신호가 전송되어 스택은 CREATE_FAILED가 되고, 아예 신호가 오지 않으면 33분 후 타임아웃으로 CREATE_FAILED가 된다. 따라서 CREATE_COMPLETE = “2단계까지 전부 성공”을 보장하는 지표다.
Outputs 확인

CloudFormation 콘솔의 “출력” 탭에서 다음을 확인할 수 있다.
| 키 | 값 |
|---|---|
| VsCodeIdeUrl | VS Code 웹 접속 URL |
| VsCodePassword | SSM Parameter Store 콘솔 링크 |
정리
- 전체 소요 시간: ~30분 (대부분 Terraform의 EKS 클러스터 생성에 소요)
- 모니터링 핵심:
tail -f /home/ec2-user/environment/terraform-install.log CREATE_COMPLETE확인 후 바로 VS Code(http://<EC2 Public DNS>:8080)에 접속하여 실습을 시작할 수 있다
댓글남기기