1 cat <<'EOF' > eks-cluster.yaml apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: my-eks-cluster region: ap-northeast-2 managedNodeGroups: - name: standard-nodes instanceType: c7i-flex.large minSize: 1 maxSize: 3 EOF eksctl create cluster -f eks-cluster.yaml 2 k get no 3 # 터미널 2 wa 4 mkdir 3 cd 3 cat <<'EOF' > app.py from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return "Hello from EKS (c7i-flex.large) and GitHub Actions!" if __name__ == '__main__': app.run(host='0.0.0.0', port=8080) EOF cat <<'EOF' > requirements.txt Flask==3.0.0 EOF cat <<'EOF' > Dockerfile FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY app.py . EXPOSE 8080 CMD ["python", "app.py"] EOF 5 mkdir -p k8s cat <<'EOF' > k8s/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: flask-app spec: replicas: 2 selector: matchLabels: app: flask-app template: metadata: labels: app: flask-app spec: containers: - name: flask-app image: REPLACE_ME_IMAGE_URI ports: - containerPort: 8080 EOF cat <<'EOF' > k8s/service.yaml apiVersion: v1 kind: Service metadata: name: flask-service spec: type: LoadBalancer selector: app: flask-app ports: - port: 80 targetPort: 8080 EOF 6 AWS 계정 ID (12자리 숫자)로 직접 변경해 주셔야 GitHub Actions가 정상적으로 AWS 권한을 얻을 수 있습니다. AWS 계정 ID를 확인하고 파일에 적용하는 방법은 다음과 같습니다. 1. AWS 계정 ID 확인하기 터미널에서 아래 명령어를 실행하시면 본인의 12자리 계정 ID가 바로 출력됩니다 aws sts get-caller-identity --query "Account" --output text 588752323301 -------- # 수정 mkdir -p .github/workflows cat <<'EOF' > .github/workflows/deploy.yml name: Deploy to EKS on: push: branches: [ "main" ] env: AWS_REGION: ap-northeast-2 ECR_REPOSITORY: my-flask-app EKS_CLUSTER: my-eks-cluster # OIDC 인증을 위한 권한 설정 permissions: id-token: write contents: read jobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Configure AWS credentials with OIDC uses: aws-actions/configure-aws-credentials@v4 with: # 입력해주신 AWS 계정 ID가 적용되었습니다. role-to-assume: arn:aws:iam::588752323301:role/GitHubActions_EKS_Role aws-region: ${{ env.AWS_REGION }} - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v2 - name: Build, tag, and push image to Amazon ECR env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} IMAGE_TAG: ${{ github.sha }} run: | docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG echo "IMAGE=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_ENV - name: Update kubeconfig run: aws eks update-kubeconfig --name ${{ env.EKS_CLUSTER }} --region ${{ env.AWS_REGION }} - name: Deploy to EKS run: | sed -i.bak "s|REPLACE_ME_IMAGE_URI|$IMAGE|" k8s/deployment.yaml kubectl apply -f k8s/deployment.yaml kubectl apply -f k8s/service.yaml EOF 7 # 1. Git 사용자 정보 설정 (본인의 GitHub 계정 정보로 설정합니다) git config --global user.email "topasvga1@github.com" git config --global user.name "topasvga1" # 2. 현재 폴더의 모든 파일을 Git에 추가 git add . # 3. 첫 번째 커밋 생성 (이 명령어가 성공해야 로컬에 main 브랜치가 생깁니다) git commit -m "feat: initial commit" # 4. 기본 브랜치 이름을 main으로 확정 git branch -M main # 5. 원격 저장소로 다시 푸시 git push -u origin main --------- # 원격 저장소의 변경 사항을 로컬로 가져와서 병합합니다. (rebase 방식을 사용하여 커밋 히스토리를 깔끔하게 유지합니다) git pull origin main --rebase # 정상적으로 가져왔다면 다시 푸시합니다. git push -u origin main # 로컬 코드로 원격 저장소를 강제로 덮어씁니다. git push -u origin main --force -------- 이 에러(fetch first)는 현재 작업 중인 폴더(로컬)에는 없는 파일이나 과거 기록이 GitHub(원격 저장소)에 이미 존재하기 때문에 발생합니다. 이전에 다른 폴더에서 푸시했던 실습 파일이나, 리포지토리를 처음 만들 때 생성된 README 파일 등이 남아있기 때문입니다. 새로운 폴더(3)에서 Git을 다시 초기화하고 커밋하셨기 때문에, 로컬과 GitHub의 과거 기록이 달라서 일반적인 푸시가 거절된 상태입니다. 현재 작성하신 최신 EKS 실습 코드가 가장 중요하므로, 이 코드로 GitHub 저장소를 완전히 덮어쓰는 강제 푸시(Force Push)를 진행하는 것이 가장 깔끔한 해결책입니다. 터미널에 아래 명령어를 복사하여 실행해 주세요. git push -u origin main --force topasvga1 ghp_o6KluGjdK 8 export GITHUB_ORG="topasvga1" export GITHUB_REPO="s1" export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text) export ROLE_NAME="GitHubActions_EKS_Role" export CLUSTER_NAME="my-eks-cluster" export REGION="ap-northeast-2" 9 aws iam create-open-id-connect-provider \ --url "https://token.actions.githubusercontent.com" \ --client-id-list "sts.amazonaws.com" \ --thumbprint-list "1b511abead59c6ce207077c0bf0e0043b1382612" "1c58a3a8518e8759bf075b76b750d4f2df264fcd" 10 cat < trust-policy.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::${AWS_ACCOUNT_ID}:oidc-provider/token.actions.githubusercontent.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringLike": { "token.actions.githubusercontent.com:sub": "repo:${GITHUB_ORG}/${GITHUB_REPO}:*" }, "StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" } } } ] } EOF aws iam create-role \ --role-name ${ROLE_NAME} \ --assume-role-policy-document file://trust-policy.json 11 # ECR 접근 권한 (AWS 관리형 정책) 연결 aws iam attach-role-policy \ --role-name ${ROLE_NAME} \ --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser # EKS 클러스터 조회 권한 (인라인 정책) 생성 및 연결 cat < eks-policy.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "eks:DescribeCluster", "Resource": "arn:aws:eks:${REGION}:${AWS_ACCOUNT_ID}:cluster/${CLUSTER_NAME}" } ] } EOF aws iam put-role-policy \ --role-name ${ROLE_NAME} \ --policy-name EKSAccessPolicy \ --policy-document file://eks-policy.json 12 # Access Entry 생성 aws eks create-access-entry \ --cluster-name ${CLUSTER_NAME} \ --principal-arn arn:aws:iam::${AWS_ACCOUNT_ID}:role/${ROLE_NAME} \ --type STANDARD # Cluster Admin 정책 연결 aws eks associate-access-policy \ --cluster-name ${CLUSTER_NAME} \ --principal-arn arn:aws:iam::${AWS_ACCOUNT_ID}:role/${ROLE_NAME} \ --policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy \ --access-scope type=cluster 13 ------------------------ 깃허브 동작 확인 트러블 슈팅 1 # ecr 권한 aws iam attach-role-policy \ --role-name GitHubActions_EKS_Role \ --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser 2 ecr 레포 생성 aws ecr create-repository \ --repository-name my-flask-app \ --region ap-northeast-2 \ --image-scanning-configuration scanOnPush=true 3 cat <<'EOF' >> main.tf # 1. EKS 워커 노드를 위한 IAM Role 생성 resource "aws_iam_role" "node_group_role" { name = "eks-node-group-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "ec2.amazonaws.com" } }] }) } # 2. 노드 그룹에 필요한 3가지 필수 정책 연결 resource "aws_iam_role_policy_attachment" "node_group_worker_policy" { policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy" role = aws_iam_role.node_group_role.name } resource "aws_iam_role_policy_attachment" "node_group_cni_policy" { policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy" role = aws_iam_role.node_group_role.name } resource "aws_iam_role_policy_attachment" "node_group_ecr_policy" { policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" role = aws_iam_role.node_group_role.name } EOF ---------------- 모두 삭제법 terraform destroy -auto-approve eksctl delete cluster --name my-eks-cluster (삭제후 3분후 동일 이름으로 재설치가 가능하다.2 11:59:35 [ℹ] building cluster stack "eksctl-my-eks-cluster-cluster" 2026-02-22 11:59:35 [!] 1 error(s) occurred and cluster hasn't been created properly, you may wish to check CloudFormation console 2026-02-22 11:59:35 [ℹ] to cleanup resources, run 'eksctl delete cluster --region=ap-northeast-2 --name=my-eks-cluster' 2026-02-22 11:59:35 [✖] creating CloudFormation stack "eksctl-my-eks-cluster-cluster": operation error CloudFormation: CreateStack, https response error StatusCode: 400, RequestID: bc887135-9187-4833-8533-0b6c79697db6, AlreadyExistsException: Stack [eksctl-my-eks-cluster-cluster] already exists Error: failed to create cluster "my-eks-cluster" (N/A:N/A) [root@kops-ec2 ~]#