
이런 구조를 가지는 서비스를 하나 만드려고 한다.
지금부터 쓰이는 내용은 정확하지 않을 수 있습니다. 순전히 제 삽질을 바탕으로 작성되었습니다. 필자의 OS는 Windows 11 Pro 입니다.
내가 관련 문서를 찾아 다니면서 계속 생각했던 한 마디다.
AWS 배포 경험이 제대로 없는 상태에서 Docker며 Kubernetes며 Fargate며 굉장히 복잡한 개념들을 머리에 주입하려고 해봤지만 결국 끝까지 이해되지 않았다.
그래서 정리해보았다
이제 나의 삽질 기록이 시작된다.
쿠버네티스(k8s, Kubernetes, 또는 큐브(kube)라고도 함)는 컨테이너화된 애플리케이션을 배포, 관리, 확장할 때 수반되는 다수의 수동 프로세스를 자동화하는 오픈소스 컨테이너 오케스트레이션 플랫폼입니다.
출처
그렇다고 한다. 간단히 말해 컨테이너 관리 플랫폼이라는 말이다.
EKS는 AWS에서 관리형 쿠버네티스 클러스터를 제공하는 서비스다. EKS는 관리 서비스이기 때문에 실제로 애플리케이션이 실행되는 노드를 구성해야하는데, 이 때 Fargate나 EC2를 사용할 수 있다.
Fargate는 AWS에서 제공하는 서버리스 컴퓨팅 엔진이다.
이제 알아가보자.
GPT의 많은 도움을 받아서 단계별 과정을 배워왔다.
AWS 루트 계정과 IAM 계정이 하나씩은 있는 것으로 가정하고 시작한다.
cmd에서 아래 명령을 입력한다.
msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi
aws cli가 설치되었는지 확인하기 위해 aws --version을 입력해보면

아.
하지만 다른 cmd 창을 열고 입력해보면, 정상적으로 버전이 나올 것이다.
만약 그래도 안 나온다면, 공식 문서를 참고해서 해결해보자.
cmd에 aws configure를 입력한다.
그러면 순서대로 아래처럼 나타날텐데, IAM 계정을 만들면서 받았던 키들을 차례로 입력해주면 된다.
AWS Access Key ID [None]: ABCD1234EFGH5678IJKL
AWS Secret Access Key [None]: aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890
Default region name [None]: us-west-2
Default output format [None]: json
예시 입력은 위와 같다.
kubectl은 쿠버네티스 클러스터 관리 도구이고, eksctl은 AWS EKS에서 클러스터 생성을 위한 도구라고 한다.
쿠버네티스 공식 가이드를 참고해서 작성했다.
curl이 설치되어있는 상태라고 생각하겠다.
curl.exe -LO "https://dl.k8s.io/release/v1.32.0/bin/windows/amd64/kubectl.exe"
cmd에 위 명령어를 입력하여 kubectl을 설치할 수 있다. (버전이 달라졌을 수 있으니 공식 가이드에서 직접 링크 받기를 추천)
또는 choco를 사용해서
choco install kubernetes-cli
이런 코드로 간단히 설치할 수도 있다... 왜 더 아래에 놔둔걸까..
일단 choco를 쓰는게 더 간단하기 때문에 choco를 사용한다.
관리자 권한이 켜진 터미널로 설치해야한다.
설치 후 버전 확인으로 설치 여부를 확인한다.
kubectl version --client

이렇게 잘 뜨는 것을 볼 수 있다.
다음은 eksctl을 설치한다.
eksctl은 eksctl 설치 가이드를 참고했다.
깃허브 페이지에서 설명해준 대로 git bash를 사용해서 설치했다.
# for ARM systems, set ARCH to: `arm64`, `armv6` or `armv7`
ARCH=amd64
PLATFORM=windows_$ARCH
curl -sLO "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_$PLATFORM.zip"
# (Optional) Verify checksum
curl -sL "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_checksums.txt" | grep $PLATFORM | sha256sum --check
unzip eksctl_$PLATFORM.zip -d $HOME/bin
rm eksctl_$PLATFORM.zip
위 명령어 더미를 통째로 붙여넣으면 전부 설치가 완료된다.
설치가 완료되었는지 확인하기 위해서는
eksctl version 명령어를 입력해보면 된다.
그런데 cmd에서는 버전이 안 나오는 문제가 있었다.
이는 환경변수 세팅이 되어있지 않아서 생기는 문제로, 환경변수 PATH를 수정해주면 된다.
Path 필드에 들어가서
C:\Users\<Your-Username>\bin
이걸 추가해주면 된다. 당연히 <Your-username> 자리는 사용자명으로 바꿔줘야 한다.
이제 AWS EKS에서 Fargate를 사용할 수 있는 클러스터를 생성해야 한다.
eksctl create cluster \
--name <cluster-name> \
--region <region> \
--fargate
이렇게 명령어를 입력해주면 된다.

아.
이건 IAM 계정 권한 문제로 오류가 난 것으로 추정된다.
IAM 계정 대시보드에서 인라인 정책 추가를 선택하고
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"eks:DescribeClusterVersions",
"eks:CreateCluster",
"eks:DescribeCluster",
"eks:ListClusters",
"eks:UpdateClusterConfig",
"eks:UpdateClusterVersion",
"eks:DeleteCluster"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"iam:ListInstanceProfiles",
"iam:GetInstanceProfile",
"iam:ListRolePolicies",
"iam:GetRolePolicy",
"iam:GetRole"
],
"Resource": "*"
}
]
}
위와 같이 json 코드를 추가한다.
다시 시도하면

아.
또 에러가 난다. 이번에도 권한 문제다.
IAM 대시보드에 다시 가서, 이번에는 AWSCloudFormationFullAccess 권한을 추가해준다.
다시 시도하면,

ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
아니 진짜로 좀 화가 나기 시작했다.
IAM 대시보드에서
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:CreateRole",
"iam:TagRole",
"iam:AttachRolePolicy",
"iam:PutRolePolicy",
"iam:UpdateAssumeRolePolicy",
"iam:ListRoles",
"iam:GetRole",
"iam:ListRolePolicies",
"iam:GetRolePolicy"
],
"Resource": "*"
}
]
}
위 코드를 추가해준다.
계속 이 짓거리를 반복하다가 성공 한 뒤에 돌아오기로 마음을 바꿨습니다. 아래는 클러스터 생성에 성공했을 때의 IAM 권한들입니다.
진짜 뻘짓이었던게 있다.

권한은 이렇게 추가해주면 되는데,
EKS 커스텀 권한에서 굉장히 많이 막혔었다.
근데, 아주 간단하게 모든걸 해결할 수 있었다.
{
"Effect": "Allow",
"Action": [
"eks:*"
],
"Resource": "*"
},
아니 그냥 이러면 되는거였다.
왜 일일이 추가하고 있었던건지 참...
AWS의 CloudFormation 대시보드를 확인하면서 진행해주면 좋다.
결국에는 클러스터 생성이 성공적으로 완료되었다. 지금은 오전 5시 47분이다. ㅋㅋㅋ 6시간동안 삽질했다.
kubectl get nodes 명령어를 통해서 클러스터가 제대로 생성됐는지 확인할 수 있다.
eksctl create fargateprofile \
--cluster <cluster-name> \
--name <fargate-profile-name> \
--namespace default
위 명령어를 입력해주면
2025-01-25 12:32:31 [ℹ] created Fargate profile "<fargate-profile-name>" on EKS cluster "<cluster-name>"
이렇게 잘 생성된 것을 볼 수 있다.
이제 우리 Flask 앱을 컨테이너화시켜줄 Dockerfile을 만들어주어야 한다.
일단 내 Flask 서버의 폴더 구조는 위와 같다.
main.py를 실행하면 서버가 돌아가는 형식이다.
GPT의 도움을 받아서 Dockerfile을 만들었다.
FROM python:3.13.1-slim
WORKDIR /
COPY . .
RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 8000
CMD ["python", "main.py"]
이렇게 구성된다.
docker build -t <image-name>:<version> <path>
위 명령어를 입력하면 빌드가 시작되는데, 추천하는 것은 requirements.txt에 들어있는 버전 부분을 전부 지워버리는 것이다. 버전들이 충돌하면서 자꾸 오류가 나는데 그냥 다 지워버리고 도커한테 맡기면 알아서 잘 해준다.
이미지를 만들고 나서 도커 앱에 들어가 보면

이렇게 이미지 탭에서 확인해볼 수 있는데, 액션의 run 버튼을 누르면 컨테이너가 실행된다.
이 때 외부에서 접속할 때 사용할 포트와 환경변수를 설정해주면 된다.
컨테이너를 실행한 모습
잘 된다.
IAM 대시보드에 가서 AmazonEC2ContainerRegistryFullAccess 권한을 추가해준 뒤,
aws ecr create-repository --repository-name <repository-name>
이 명령어를 입력해보면, 잘 생성이 될 것이다.
생성 후에는,
aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <ecr uri>
이 명령어를 이용해서 로그인을 해줄 수 있다.
Login Succeeded 가 뜨면 성공.

ECR 페이지에 직접 가서 푸시 명령을 보면 고민하지 않고 바로 복붙으로 푸시할 수 있다.
다음은 쿠버네티스 매니페스트 파일을 작성해야한다.
프로젝트 폴더에 k8s라는 새로운 폴더 하나를 생성한 뒤 deployment.yaml과 service.yaml을 생성한다.
<deployment.yaml>
apiVersion: apps/v1
kind: Deployment
metadata:
name: <app name>
spec:
replicas: 1
selector:
matchLabels:
app: <app name>
template:
metadata:
labels:
app: <app name>
spec:
containers:
- name: <app name>
image: docker push <ECR-URI>:<tag>
ports:
- containerPort: 5000
<service.yaml>
apiVersion: v1
kind: Service
metadata:
name: <service name>
spec:
type: LoadBalancer
selector:
app: <app name>
ports:
- protocol: TCP
port: 80
targetPort: 5000
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
그 뒤 위의 명령어를 입력하면 (경로 잘 맞춰서) 된다.
드디어 마지막 스텝에 도달했다.
깃허브 레포지토리의 루트 디렉토리에 .github 폴더를 생성한다.
그 안에는 workflows라는 폴더를 만들고, deploy.yaml 파일을 생성한다.
name: Deploy to EKS
on:
push:
branches:
- generator
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v3
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-2
- name: Install kubectl
run: |
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
- name: Login to Amazon ECR
uses: aws-actions/amazon-ecr-login@v2
- name: Build, tag, and push Docker image
env:
IMAGE_URI: <ECR-URI>
run: |
docker build -t $IMAGE_URI -f <path>/Dockerfile generator
docker push $IMAGE_URI
- name: Set up kubeconfig
run: |
mkdir -p ~/.kube
echo "${{ secrets.KUBECONFIG }}" | base64 -d > ~/.kube/config
chmod 600 ~/.kube/config
- name: Deploy to Kubernetes
run: |
kubectl apply -f <path>/k8s/deployment.yaml
kubectl apply -f <path>/k8s/service.yaml
- name: Cleanup
run: rm -f ~/.kube/config
이렇게 구성하면 된다.
다음은 깃허브 레포지토리 설정에 들어가서 Secret 값을 추가해줘야 한다.
세 가지를 추가할건데, 각각 access key id, secret access key, 그리고 base64로 인코딩된 kube config 파일이다.
앞의 두 개는 잘 알고 있을테고, kube config 파일은 어떻게 하면 되냐면,
cat ~/.kube/config | base64
이 명령어를 git bash 에서 입력하면 된다.
잔뜩 문자열이 출력되는데, 그걸 복사해서 value로 붙인다.
이제 generator 브랜치에 push 할 때마다 EKS로 자동 배포가 진행된다.
근데 요금이 심상치 않다.
찾아보니 월 148달러씩 나간다고 한다 ㅋㅋㅋㅋㅋ.
바로 다 삭제하고 EC2로 이사할 예정