카테고리 없음

Github Action을 이용한 CI/CD 구축

동성만능크리너 2024. 10. 8. 20:55

AWS에 애플리케이션을 띄워서 운용을 해야하는 과제를 하면서 Github Action을 이용한 CI/CD 과정을 간단하게 정리한 글

 

1.CI/CD란?

CI : Continuous Integration(지속가능한 통합) : 개발자들이 작업한 코드가 예를 들어 main 브랜치에 push, merge 됐을 때 서버에서 자동으로 빌드, 테스트를 해주는 과정. 

CD : Continuous Deployment(지속가능한 배포) : CI로 빌드, 테스트가 통과됐을 때, 운영중인 서버에 새로 통합된 코드를 자동으로 배포해주는 과정 

 

2.왜 Github Action을 사용하였는지?

 1) Github에서 제공하는 서비스이기 때문에 Github Repository에서 push, merge 됐을 때 자동으로 작업을 시작하게 하기 쉽다. 

 

 2) 커뮤니티에서 제공하는 템플릿으로 더 편하게 시작할 수 있다. 예를 들어 지금 사용하고 있는 gradle같은 경우에도 이미 빌드,테스트, 종속성 그래프를 체크하는 CI 템플릿을 제공해주기 때문에 쉽게 접근할 수 있다. 

 

3) public repository에 대해 무료이기 때문에, 학습하는 입장에서 부담없이 사용할 수 있다.

 

3. 어떤 과정으로 진행되는지?

 

나같은 경우에는 이런 방식으로 진행되게 파이프라인을 구성했다. Github Action IP를 AWS 보안규칙에 허용했다가 풀었다가 해주는 이유는 SSH 22번 포트를 아무 IP나 다 허용해주는 건 위험하다고 생각해서 찾아보다가 어떤 귀인분께서 정리해주신 글을 보고 이 방법을 선택하게 되었다.

https://makethree.tistory.com/19

 

AWS EC2 인스턴스 인바운드 IP 제한 상태에서 Github Action 배포

AWS EC2 인스턴스 인바운드 보안 설정 상태에서 Github Action 배포 자동화하기 일단 먼저 인스턴스를 만드는 방법이 궁금하신 분들은 AWS 프리티어 인스턴스 만들기 에 자세하고 쉽게 설명해놨으니

makethree.tistory.com

 

혹시나 참고가 될까 싶어서 올리는 github action yaml 설정

더보기
name: Java CI with Gradle

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  build:

    runs-on: ubuntu-latest
    permissions:
      contents: read

    # DB 관련 환경 변수와 JWT Secret 설정
    env:
      DB_URL:  ${{ secrets.DB_URL }}
      DB_USERNAME:  ${{ secrets.DB_USERNAME }}
      DB_PASSWORD:  ${{ secrets.DB_PASSWORD }}
      JWT_SECRET_KEY:  ${{ secrets.JWT_SECRET_KEY }}  
      AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
      AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }}

    steps:
    - uses: actions/checkout@v4
    - name: Set up JDK 22
      uses: actions/setup-java@v4
      with:
        java-version: '22'
        distribution: 'temurin'

    # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies.
    # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
    - name: Setup Gradle
      uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0

    - name: Build with Gradle Wrapper
      run: ./gradlew build

    #Docker Hub 로그인
    - name:  Log in to Docker Hub
      uses:  docker/login-action@v2
      with:
        username:  ${{ secrets.DOCKER_USERNAME }}
        password:  ${{ secrets.DOCKER_PASSWORD }}

    # Docker 이미지 빌드
    - name: Build the Docker image
      run: docker build -t ${{ secrets.DOCKER_USERNAME }}/spring-plus:latest .

    # Docker Hub에 이미지 푸시
    - name: Push the Docker image
      run: docker push ${{ secrets.DOCKER_USERNAME }}/spring-plus:latest

    #깃허브 액션 IP 가져오기
    - name:  Get Github action IP
      id:  ip
      uses:  haythem/public-ip@v1.3

    #AWS credentials
    - name:  Configure AWS credentials
      uses:  aws-actions/configure-aws-credentials@v4.0.2
      with:
         aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 
         aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 
         aws-region: ${{ secrets.AWS_DEFAULT_REGION }}

    # 깃허브 액션 IP 보안규칙에 추가
    - name:  Add Github Actions IP to Security group
      run:  |
         aws ec2 authorize-security-group-ingress --group-name ${{ secrets.AWS_SG_NAME }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32

    # EC2에서 이미지 Pull, 컨테이너 실행
    - name:  Deploy to AWS EC2
      uses:  appleboy/ssh-action@v1.1.0
      with:
        host:  ${{ secrets.HOST }}
        username:  ubuntu
        key:  ${{ secrets.RSA_KEY }}
        script:  |
          docker pull ${{ secrets.DOCKER_USERNAME }}/spring-plus:latest
          docker stop spring-plus || true
          docker rm spring-plus || true
          docker run --env-file .env -d --name spring-plus -p 8080:8080 ${{ secrets.DOCKER_USERNAME }}/spring-plus:latest

     # 깃허브 액션 IP 보안규칙에서 제거
    - name: Remove Github Actions IP from security group
      run: |
        aws ec2 revoke-security-group-ingress --group-name ${{ secrets.AWS_SG_NAME }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32