CI/CD 맛보기 - Github Action

dj-yang·2024년 2월 23일
0

CI/CD

목록 보기
1/2
post-thumbnail

요즘 내가 가고 싶은 회사들은 백엔드 개발자에게 구조에 대한 요구사항이 계속 있는 것 같다. API 공장이나 기획자로서의 롤을 주로 경험했던 전 회사를 다닌 나로서는 상당히 아쉽고 시간 있을 때 공부를 안한 것이 후회되기도 했다.

그래도 이미 지난 일인데 뭐.. 이제부터 열심히 해볼 생각이다. 그래서 사이드를 시작하기도 했다.


CI/CD의 정의를 보면 아래와 같다.

CI/CD는 지속적 통합(Continuous Integration) 및 지속적 제공/배포(Continuous Delivery/Deployment)를 의미하며, 소프트웨어 개발 라이프사이클을 간소화하고 가속화하는 것을 목표로 합니다.
지속적 통합(CI)은 코드 변경 사항을 공유 소스 코드 리포지토리에 자동으로 자주 통합하는 사례를 나타냅니다. 지속적 제공 및/또는 배포(CD)는 코드 변경 사항의 통합, 테스트, 제공을 나타내는 프로세스로, 두 가지 부분으로 구성됩니다. 지속적 제공에는 자동 프로덕션 배포 기능이 없는 반면, 지속적 배포는 업데이트를 프로덕션 환경에 자동으로 릴리스합니다.

간단하게 말하면 예전에는 휴먼 리소스가 들어갔던 부분인 배포 과정과 테스트 과정을 자동화 시키는 것이라고 이해했다.

예전에 CI/CD 파이프 라인이라고 쓴 포스팅은 제대로 된 것이 아니였네..

아무것도 모르는 나로써는 우선 자동 배포화를 시도해볼 생각으로 인터넷 서칭을 시작했다.

Github Action

먼저, 가장 쉽게 접근할 수 있는 Github에서 제공해주는 Action에 관심이 갔다. 예전에 간단하게 사용을 해봤었고 내가 생각하는 규모에서는 이 정도면 충분하다고 생각했다.

github action에서는 원하는 이벤트 트리거(pr, merge) 등을 이용해 원하는 동작을 사전에 지시할 수 있었고, 내가 선택한 방식은 github이 직접 내가 구성한 서버에 ssh를 이용한 접속을 진행하여 변경된 코드 사항을 pull하고 웹 서버와 미들웨어를 재시작하는 방법이다.

github action은 내가 push하는 코드에 .github/workflows 디렉토리에 yml로 되는 스크립트를 작성하면 github 컴퓨터가 해당 스크립트를 그대로 실행시키는 방식을 사용했다.

구성했던 스크립트는 아래와 같다.

name: dev branch auto ci process script

on: # 아래 job을 실행시킬 상황
  push:
    branches: [ develop ]

jobs:
  deploy:
    name: deploy
    runs-on: ubuntu-20.04

    steps:
      - name: Get Github Actions IP
        id: ip
        uses: haythem/public-ip@v1.2

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-east-1

      - name: Add Github Actions IP to Security group
        run: |
          aws ec2 authorize-security-group-ingress --group-id ${{ secrets.AWS_SG_ID }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32

      - name: excuting remote ssh commands
        uses: appleboy/ssh-action@v0.1.6 # ssh 접속하는 오픈소스
        with:
          host: ${{ secrets.REMOTE_IP }} # 인스턴스 IP
          username: ${{ secrets.REMOTE_USER }} # 우분투 아이디
          key: ${{ secrets.REMOTE_PRIVATE_KEY }} # ec2 instance pem key
          port: ${{ secrets.REMOTE_SSH_PORT }} # 접속포트
          script: | # 실행할 스크립트
          	{{app directory로 이동}}
            git pull origin develop
            poetry shell
            alembic upgrade head
            sudo service nginx restart
            sudo systemctl restart {{service file name}}

      - name: Remove Github Actions IP From Security Group
        run: |
          aws ec2 revoke-security-group-ingress --group-id ${{ secrets.AWS_SG_ID }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32

on : 이벤트를 트리거 시킬 상황을 뜻한다. 나는 push 이벤트가 발생할 때 스크립트를 실행시켜달라고 했는데, 그 중에서 develop branch에 push를 할 경우에만 실행할 수 있도록 선언했다.

job : on에서 설정한 조건이 충족될 때 진행해야하는 작업을 뜻한다. step option을 통해 여러 개의 동작을 한번 지시할 수 있다.

runs-on : 해당 명령어를 실행시킬 서버의 환경을 뜻한다. 나는 제일 익숙한 ubuntu로 선택했다.

step : 작업의 절차, 실제로 절차대로 작성한 스크립트를 위에서부터 차례대로 실행한다.

작성한 스텝을 순서대로 설명하면 아래와 같다.
1. github action의 컴퓨터 ip 확인 : 내 서버에 접속을 하기 위해서는 보안 그룹에 해당 컴퓨터가 접속할 수 있게 만들어줘야하고 적절한 컴퓨터인지 확인을 ip를 통해서 진행한다.
2. AWS 관련 권한 확보 : AWS에 설정을 변경하거나 그외 필요한 작업을 하기 위해 권한을 얻었다.
3. 보안 그룹에 IP 추가 : 1번에서 확보한 IP를 내 서버 보안그룹에 추가했다.
4. AWS SERVER에 접속 : SSH를 통해 내가 원하는 서버에 접속을 했고, Script 옵션을 통해 명령어를 실행했다.
5. 보안 그룹에서 IP 제거 : 필요한 작업을 진행한 후 IP를 제거해 보안의 안전성을 높혔다.


한계점 및 피드백

위와 같이 구성했지만 몇 가지 한계점과 바로 팀원이 피드백이 들어왔다.

  • 배포 주체 관련 피드백
    개인적으로 이야기를 듣고 일리가 있는 말이라고 여겼다. AWS를 서버로 사용하기 때문에 AWS 자체에서 문제가 발생하는 부분에 대해서는 어쩔 수 없지만, 적어도 Github에서 문제가 있을 때 Dependency를 최소화하는 방향성이 맞다고 생각했고, 자동 배포 중에 Github Action으로 비중을 최소화 시키는 것이 올바른 방향성이라고 생각했다.

  • 오류 대응
    스크립트를 보면 디비 변경 또한 진행하고 있다. 하지만 만약, 디비가 변경 후에 코드에 문제가 생겼다면 DB 자체의 변경은 이루어졌지만 나머지 환경이나 코드가 최신화가 안되어 제대로 된 서비스가 제공되지 않을 수 있다고 판단했다. 깃헙 액션은 정말 시킨 것에 대해 수행만 할 뿐 문제가 발생했을 때 해결법에 대한 부분이 존재하지 않았다.

지금 당장에 생각나는 방법으로는 1번 배포 주체를 AWS 서비스 로 변경한다. 팀원이 Code Deploy를 추천해줬고 찾아보니 적절한 서비스라고 판단했다. 배포 실행 자체는 Github Action 진행하더라도 배포 과정 자체는 Code Deploy의 프로세스를 따르는 방식으로 수정하는 것이 좋다고 판단했다.

오류에 대한 대응을 위해 version을 넣는 것이 좋겠다고 판단했고, versioning을 하려면 몇 가지 고민 사항이 있었다.
1. DB 문제 : versioning을 효율적으로 하기 위해 서버 컴퓨터 자체를 새로 파는 형식을 사용하는 것으로 알고 있다. 이와 같은 방식으로 진행해야 서비스가 중간에 끊기는 현상 없이 사용자 입장에서 24시간 서비스가 구동되는 것으로 보이기 때문이다. 하지만, 우리는 돈의 절약을 위해 EC2 인스턴스에 직접 디비를 설치하여 사용하고 있었다. (좋지 못한 방법이라는 건 알지만..가난한 백수의 삶이다) 따라서 서버가 변경된다면 디비 내의 데이터도 같이 옮겨줘야 하는 것도 고려해줘야 했다.
2. 환경 설정 : 새로운 서버가 생성될 때마다 환경세팅을 해주는 부담도 있었다. 단순하게 같은 서버를 만들면 된다면 상관없었지만 개발 환경에 따라 이마저도 요구사항이 달라질 수 있다고 판단했다. 그래서 docker와 같은 container를 사용하는 것이 맞다고 생각했다.

위의 고려 사항을 생각해보고 우선 local에서 docker를 사용한 이미지를 생성하는 방식으로 변경을 해보는 포스팅을 진행해보려고 한다.

fin.

profile
비전공자가 고통받으며 개발합니다

0개의 댓글