EKS – GitHub Actions를 통한 CI/CD 자동화

CI/CD 개념 이해

  • Continuous Integration (CI): 지속적 통합으로 소스코드를 Docker 이미지로 빌드
  • Continuous Deployment (CD): 지속적 배포로 이미지를 ECR에 업로드하고 Pod 재생성

배포 작업의 분류

일회성 작업 (한 번만 설정)
  • RDS 생성
  • Redis Pod/Service 생성
  • ECR Repository 생성
  • Kubernetes Secret 생성
  • Ingress 생성
  • HTTPS 인증서 생성
반복적 작업 (코드 변경 시마다)
  • Docker 이미지 빌드
  • Docker 이미지 Push
  • Pod 재생성 (새 이미지 적용)

자동화가 필요한 이유

수동 배포의 문제점
  • GitHub에서 최신 코드 Pull
  • 로컬에서 Docker 이미지 빌드
  • ECR 로그인
  • ECR에 이미지 Push
  • kubectl rollout restart 실행

실수 가능성이 높고 시간 소모적이다

자동화의 장점
  • GitHub에 코드 Push만 하면
  • GitHub Actions가 모든 작업 자동 수행
  • 실수 방지, 일관된 배포 프로세스

GitHub Actions 핵심 개념

  • Workflow: 자동화된 프로세스 전체 (YAML 파일로 정의)
  • Event: Workflow를 트리거하는 조건 (예: push, pull_request)
  • Job: 여러 step의 묶음
  • Step: 개별 작업 단위
  • Runner: Workflow를 실행하는 가상 서버
  • Action: 재사용 가능한 작업 단위

Workflow 파일 위치

프로젝트-root/
├── .github/                    ← 이 이름은 고정
│   └── workflows/              ← 이 이름도 고정
│       └── deploy.yml          ← 파일명은 자유
├── src/
└── Dockerfile

중요: .github/workflows 경로는 Github와의 약속이다. 이 경로에 YAML 파일이 있으면 GitHub가 자동으로 인식한다

Runner (실행 환경)

GitHub Actions의 가상 PC
코드 Push
    ↓
GitHub Actions가 가상 PC 생성 (Ubuntu)
    ↓
환경 설정 (kubectl, AWS CLI 등)
    ↓
이미지 빌드 및 배포
    ↓
작업 완료 후 가상 PC 삭제
  • 매번 새로운 가상 PC가 생성된다
  • GitHub이 제공하는 클라우드 환경이다
  • 개발자의 로컬 PC를 사용하지 않는다

Workflow 파일 구조 분석

deploy_order_with_k8s.yml
name: deploy order order-backend

on:
  push:
    branches:
      - main  # 본인의 브랜치명으로 변경 가능

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: checkout github
        uses: actions/checkout@v2
      
      - name: install kubectl
        uses: azure/setup-kubectl@v3
        with:
          version: "v1.25.9"
        id: install
        
      - name: configure aws
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_KEY }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET }}
          aws-region: ap-northeast-2

      - name: update cluster infomation
        run: aws eks update-kubeconfig --name my-cluster --region ap-northeast-2

      - name: Login to ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1

      - name: build and push docker image to ecr
        env:
          REGISTRY: 123456789012.dkr.ecr.ap-northeast-2.amazonaws.com
          REPOSITORY: order-backend
          IMAGE_TAG: latest
        run: |
          docker build \
          --platform linux/amd64 \
          -t $REGISTRY/$REPOSITORY:$IMAGE_TAG \
          -f ./ordersystem/Dockerfile ./ordersystem
          docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG

      - name: eks kubectl apply
        run: |
          kubectl rollout restart deployment ordersystem-backend -n hyeok

Workflow 구성 요소 상세 설명

이벤트 정의 (on)

on:
  push:
    branches:
      - main

main 브랜치에 코드가 Push 되면 Workflow 실행

다른 브랜치 예시

on:
  push:
    branches:
      - dev      # dev 브랜치로 변경 가능

다른 이벤트 예시

on:
  pull_request:   # Pull Request 시
  issues:         # Issue 생성 시

Job 정의

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
  • build-and-deploy: Job의 이름으로 임의로 지정이 가능하다
  • runs-on: 가상 PC의 운영체제를 정한다
사용 가능한 runs-on 옵션
  • ubuntu-latest (가장 일반적)
  • windows-latest
  • macos-latest

Step별 상세 설명

uses와 run

  • uses: 미리 만들어진 Action 사용 (actions/checkout@v2)
  • run: 직접 명령어 실행 (docker build …)

GitHub 소스코드 체크아웃

- name: checkout github
  uses: actions/checkout@v2

역할: “GitHub Repository의 소스코드를 가상 PC로 가져오기”로 git clone과 내부동작이 유사하다

kubectl 설치

- name: install kubectl
  uses: azure/setup-kubectl@v3
  with:
    version: "v1.25.9"
  id: install

역할: Kubernetes 명령어 도구 설치로 Pod 재생성을 위해 kubectl rollout restart 명령어를 실행하기 위해 필요하다

AWS 설정

- name: configure aws
  uses: aws-actions/configure-aws-credentials@v1
  with:
    aws-access-key-id: ${{ secrets.AWS_KEY }}
    aws-secret-access-key: ${{ secrets.AWS_SECRET }}
    aws-region: ap-northeast-2

역할: AWS CLI 설치와 AWS 계정 인증 설정을 한다

Secret 참조
  • ${{ secrets.AWS_KEY }}: GitHub Secret에 저장된 값 참조
  • 소스코드에 민감 정보가 노출되지 않는다

EKS 클러스터 연결

- name: update cluster infomation
  run: aws eks update-kubeconfig --name my-cluster --region ap-northeast-2

역할: kubectl이 EKS 클러스터에 접근할 수 있도록 설정한다
클러스터 이름 변경: my-cluster를 본인의 클러스터 이름으로 변경

ECR 로그인

- name: Login to ECR
  id: login-ecr
  uses: aws-actions/amazon-ecr-login@v1

역할: Docker 이미지를 ECR에 Push하기 위한 인증

Docker 이미지 빌드 및 Push

- name: build and push docker image to ecr
  env:
    REGISTRY: 123456789012.dkr.ecr.ap-northeast-2.amazonaws.com
    REPOSITORY: order-backend
    IMAGE_TAG: latest
  run: |
    docker build \
    --platform linux/amd64 \
    -t $REGISTRY/$REPOSITORY:$IMAGE_TAG \
    -f ./ordersystem/Dockerfile ./ordersystem
    docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG
  • REGISTRY: ECR URI로 ECR Repository 주소 (본인 것으로 변경 필수)
  • REPOSITORY: order-backend는 ECR Repository 이름
  • IMAGE_TAG: latest는 이미지 태그
명령어 분석
docker build \
  --platform linux/amd64 \          # ARM(M1 Mac) 호환성 해결
  -t $REGISTRY/$REPOSITORY:$IMAGE_TAG \  # 이미지 이름
  -f ./ordersystem/Dockerfile \     # Dockerfile 위치
  ./ordersystem                     # 빌드 컨텍스트
Workflow는 항상 프로젝트 루트에서 실행되므로
  • -f 옵션으로 Dockerfile 경로 명시 필수
  • 빌드 컨텍스트 경로도 명시 필수
로컬 VS GitHub Actions
  • 로컬
    • 실행 위치: ordersystem/폴더내부
    • 명령어: docker build -t … .
  • GitHub Actions
    • 실행 위치: 프로젝트 루트
    • 명령어: docker build -t … -f ./ordersystem/Dockerfile ./ordersystem

Pod 재생성

- name: eks kubectl apply
  run: |
    kubectl rollout restart deployment ordersystem-backend -n hyeok

역할: ECR에 새 이미지가 올라갔으므로 Pod를 재시작하여 새 이미지를 Pull

주의사항
  • Deployment 이름 (ordersystem-backend)은 depl_svc.yml의 이름과 일치해야 함
  • Namespace (hyeok)도 본인의 네임스페이스로 변경

GitHub Secret 설정

Secret이 필요한 이유

# 문제 상황
aws-access-key-id: AKIAIOSFODNN7EXAMPLE  # 노출 위험

# 해결
aws-access-key-id: ${{ secrets.AWS_KEY }}  # 안전

Secret 등록 방법

GitHub Repository → Settings → Secrets and variables → Actions → New repository secret 클릭
Secret 추가 및 입력
IAM에서 확인
  • AWS Console → IAM → 사용자
  • 본인 사용자 선택 → 보안 자격 증명 탭
  • 엑세스 키 생성 (없는 경우)

배포 실습

Git 초기화 (신규 프로젝트인 경우)

# 프로젝트 루트에서 실행
git init

기존 .git 제거

다른 Repository에서 클론한 경우나 필요한 경우

# 기존 .git 폴더 삭제
rm -rf .git

# 새로 초기화
git init

GitHub Repository 연결

# Repository 추가
git remote add origin https://github.com/your-username/your-repo.git

# 브랜치를 main으로 변경
git checkout -b main

# 확인
git branch

Workflow 파일 수정

수정해야 할 부분
# 1. 브랜치 이름 확인
on:
  push:
    branches:
      - main  # 본인의 브랜치명

# 2. ECR URI 변경
env:
  REGISTRY: 123456789012.dkr.ecr.ap-northeast-2.amazonaws.com  # 본인 ECR URI

# 3. Dockerfile 경로 확인
run: |
  docker build \
  -f ./ordersystem/Dockerfile ./ordersystem  # 본인 프로젝트 경로

# 4. Namespace 변경
kubectl rollout restart deployment ordersystem-backend -n hyeok  # 본인 namespace

첫 배포 실행

# 1. 모든 파일 추가
git add .

# 2. 커밋
git commit -m "CI/CD 자동화 테스트"

# 3. Push
git push origin main
GitHub Actions 확인
  • GitHub Repository → Actions 탭
  • 실행 중인 Workflow 확인 (빙글빙글 돌아가는 아이콘)
  • Workflow 클릭하여 각 Step 로그 확인

배포 (Pod 상태) 확인

kubectl get pods -n hyeok

# 예상 결과
NAME                                   READY   STATUS    RESTARTS   AGE
ordersystem-backend-56975q86qq-2q7qq   1/1     Running   0          77s
ordersystem-backend-56975q86qq-qqqqq   1/1     Running   0          51s

AGE가 짧으면 새로 생성된 Pod이다

코드 변경 및 자동 배포 테스트

코드 수정

@RestController
public class HealthController {
    @GetMapping("/health")
    public String healthCheck() {
        return "ok2";  // ok1 → ok2로 변경
    }
}

배포

git add .
git commit -m "health check 응답 변경"
git push origin main

자동화 프로세스

코드 Push
    ↓
GitHub Actions 자동 트리거
    ↓
├─ 소스코드 체크아웃
├─ kubectl 설치
├─ AWS 설정
├─ 클러스터 연결
├─ ECR 로그인
├─ 이미지 빌드 (변경된 코드 포함)
├─ ECR Push
└─ Pod 재생성 (새 이미지로)
    ↓
배포 완료

변경 사항 확인

ECR 확인
  • AWS Console → ECR → Repository
  • 새 이미지가 ‘latest’ 태그로 Push 됨
  • 이전 이미지는 태그가 제거됨
API 테스트
GET https://server.hyeok9244.shop/health
→ 응답: "ok2" (변경된 값)

트러블 슈팅

문제 1: Actions 실행 안됨

증상: Push 했는데 Actions 탭에 아무것도 안 나타나는 경우로 Workflow 파일 경로 오류이거나 브랜치 이름이 불일치한 경우이다

# 경로 확인
ls .github/workflows/

# 브랜치 확인
git branch

# Workflow 파일의 브랜치 설정 확인
on:
  push:
    branches:
      - main  # 현재 브랜치와 일치해야 함

문제 2: AWS 인증 실패

증상: Error: The security token included in the request is invalid으로 원인은 GitHub Secret의 AWS 키가 잘못 된 경우

  • GitHub → Settings → Secrets and variables 확인
  • AWS_KEY, AWS_SECRET 값 재확인
  • IAM에서 새 엑세스 키 생성 후 재등록

문제 3: Docker 빌드 실패

증상 1: no match for platform in manifest으로 원인은 ARM(M1 Mac)아키텍처 문제이다

docker build \
  --platform linux/amd64 \  # 이 줄 추가
  -t $REGISTRY/$REPOSITORY:$IMAGE_TAG \

배포가 2개가 된 이유는 .github/workflow의 디렉터리에 yml 파일이 2개였기 때문이다 (처음에는 몰랐다)

증상 2: failed to solve: openjdk:17-jdk… Error: Process completed with exit code 1.

Dockerfile

# 필요프로그램 설치
# FROM openjdk:17-jdk-alpine as stage1 에러의 원인
FROM eclipse-temurin:17-jdk-jammy as stage1 # 변경

문제 4: kubectl 명령어 실패

증상: error: You must be logged in to the server으로 클러스터 이름의 오류가 원인이다

run: aws eks update-kubeconfig --name my-cluster  # 실제 클러스터 이름으로 변경
클러스터 이름 확인
aws eks list-clusters --region ap-northeast-2

로그 확인 방법

  • Repository → Actions
  • 실패한 Workflow 클릭
  • 실패한 Step 클릭
  • 상세 에러 로그 확인

Pod 로그 (배포 후)

kubectl logs -f <pod-name> -n hyeok

CI/CD 흐름 정리

[개발자]
  소스코드 수정
      ↓
  git push origin main
      ↓
[GitHub Actions - 가상 PC]
  ├─ 1. 소스코드 체크아웃 (git clone)
  ├─ 2. kubectl 설치
  ├─ 3. AWS CLI 설치 및 인증
  ├─ 4. EKS 클러스터 연결
  ├─ 5. ECR 로그인
  ├─ 6. Docker 이미지 빌드
  ├─ 7. ECR에 이미지 Push
  └─ 8. Pod 재생성 (rollout restart)
      ↓
[Kubernetes]
  새 이미지로 Pod 재생성
  (무중단 롤링 업데이트)
      ↓
[완료]
  사용자는 새 버전 사용

반복 작업 vs 일회성 작업

매 배포마다 실행 (자동화)
  • 소스코드 체크아웃
  • 환경 설정 (kubectl, AWS CLI)
  • 이미지 빌드
  • ECR Push
  • Pod 재생성
한 번만 실행 (수동)
  • Github Secret 등록
  • Workflow 파일 작성
  • ECR Repository 생성
  • EKS 클러스터 생성
  • Deployment, Service, Ingress 생성

실무 팁

브랜치 전략

# 개발 환경
on:
  push:
    branches:
      - dev

# 프로덕션 환경
on:
  push:
    branches:
      - main

팀 협업 시

  • dev 브랜치: 개발 서버 자동 배포
  • main 브랜치: 운영 서버 자동 배포
  • Pull Request: 코드 리뷰 후 Merge

이미지 태그 전략

IMAGE_TAG: latest # 현재 방식

IMAGE_TAG: ${{ github.sha }}  # Git commit SHA 사용

장점으로는 각 배포마다 고유한 이미지 태그가 생성되고 롤백이 수비다

슬랙 알람 추가 (선택 사항)

- name: Slack Notification
  uses: 8398a7/action-slack@v3
  with:
    status: ${{ job.status }}
    webhook_url: ${{ secrets.SLACK_WEBHOOK }}

출처 – eks를 활용한 spring 운영서버 배포(feat. devops의 모든것)