[단편] Jenkins에서 Github Actions으로 전환기

황제연·2025년 2월 4일
post-thumbnail

서론

프로젝트를 진행하면서, FE와 API 연결을 진행하기 위해 BE에서 먼저 개발 서버를 배포했습니다
처음에는 BE 수정사항이 생기면, 깃허브에서 Main branch로 Merge한 뒤
개발 서버에 SSH 접속해서 직접 서버를 재배포하는 방식으로 업데이트를 진행했습니다

하지만 수정사항이 많이 생기면서, 해당 방식으로 재배포하는 것은 많은 딜레이가 발생했고,
수정사항이 자동으로 반영되는 CI/CD 환경을 구축하기로 결정했습니다.

당시 주어진 시간이 부족했기에 빠른 구축을 위해 이전에 경험했던 Jenkins를 선택했습니다

Jenkins 환경 구축 및 문제점

하루동안 Jenkins 환경을 구축하였고, 배포 방식의 자동화가 이루어졌습니다

Jenkins을 사용한 CI/CD 아키텍처

Jenkins을 사용한 CI/CD 아키텍처는 위와 같습니다
아직 개발서버라서 트래픽이 적고,
CI/CD용 EC2 환경을 구축하면 비용이 발생하기 때문에 위와 같이 구성했습니다

Jenkins사용의 문제점

Jenkins을 사용했을 때, 아래와 같은 문제가 발생했습니다
1. Jenkins 서버를 유지하는 리소스 비용이 발생한다.
2. 플러그인 등 Jenkins 서버를 관리하는 비용이 발생한다
3. 운영 환경에서는 별도의 CI/CD 서버를 구축해야하는데, 이때 비용이 발생한다

Jenkins 서버를 유지하는 리소스 비용이 발생

별도의 CI/CD 서버를 구축해서 발생하는 비용을 줄이기 위해,
개발 서버와 CI/CD 서버를 함께 사용하거나 혹은 운영서버와 함께 사용했을 때 리소스 비용이 발생합니다

Docker 컨테이너 위에 띄운 Jenkins 서버가 어떤 작업을 하지 않는다고 하더라도
기본적으로 EC2 서버의 메모리를 사용합니다.

또한 CI/CD하는 상황이라면 그 사용량이 더 증가할 것입니다
트래픽이 발생하는 운영환경에서는 사용가능한 메모리를 확보하는 것이 중요한데,
CI/CD 서버의 존재는 이것을 방해합니다

플러그인 등 Jenkins 서버를 관리하는 비용 발생

Jenkins는 많은 플러그인을 지원합니다.

다양하게 커스텀할 수 있고, 편리하게 사용할 수 있는 장점이 있지만
플러그인들을 주기적으로 업데이트하고 관리하는 단점도 존재합니다.

또한 업데이트하는 상황에서는 CI/CD 작업을 진행하지 못할 수도 있습니다.

별도의 CI/CD 서버를 구축할 때 추가 비용 발생

앞선 1번의 문제를 해결하고자 별도의 CI/CD 서버를 구축합니다

하지만 별도의 서버를 구축하면 비용이 더 발생합니다.
EC2 서버를 하나 더 구축하면 추가 비용이 발생하는데,
현재 프로젝트 규모에서는 적합하지 않은 선택이라고 판단했습니다

다른 선택지 고민

따라서 Jenkins을 대체할 다른 CI/CD 서비스를 사용하기로 결정했습니다.

이때 선택한 서비스는 Github Actions입니다

Github Actions로 전환기

처음 Jenkins를 선택한 이유 중 하나는 비용이 무료라는 점입니다.

(Travis 비용)

Travis등 다른 선택지도 많았지만 선택적인 무료이며,
Jenkins을 대체할 선택지로는 부족했습니다

Github Actions는 Public Repo에 대해 무료로 사용할 수 있습니다.
물론 사용량 제한이 있긴 하지만, 프로젝트 규모와 다른 서비스의 한도를 비교했을 때,
가장 합리적인 선택지였습니다.

GitHub Actions의 장점

현재 프로젝트에서 GitHub Actions을 사용했을 때, 다음과 같은 장점이 존재합니다
1. Github에서 코드를 관리하고 있기 때문에 연동이 쉽다
2. 별도의 CI/CD 서버를 구축할 필요가 없다

특히 2번 장점은 Jenkins을 대체할만한 이유로 가장 적합했습니다
Jenkins가 가지고 있는 리소스/비용 문제를
Github Actions로 전환하면 걱정할 필요가 없습니다!

Github Actions Workflow작성

Jenkins의 파이프라인을 참고해서, Workflow를 작성했습니다.
Yaml 파일로 관리하기 때문에 어렵지 않게 작성했습니다.



완성한 Github Actions WorkFlow는 위와 같습니다.
Jenkins와 다르게 Github Actions는 3시간만에 모든 환경 구축을 완료했습니다!

Jenkins 파이프라인과 비교

Jenkins 파이프라인과 비교했을 때,
Github Actions Workflow에서 CI 작업은 전체 STEP이 동일하지만
각 Step마다 권한 부여, 경로 생성 등의 추가 작업이 빠져서
전체 작업량은 더 줄었습니다

하지만 CD작업은 더 늘어났는데, EC2 서버에 접속하는 과정이 추가되었기 때문입니다

Jenkins는 서버 내부에서 CI 작업을 진행하기 때문에, 내부에서 바로 CD작업을 진행할 수 있습니다

하지만 Github Actions는 서버 외부에서 CI작업 후,
내부에 접속해서 CD 작업을 하기 때문에 작업이 더 추가되었습니다

Github Actions사용했을 때 불편한점

Github Actions을 사용했을 때, 다음과 같은 불편한 점이 존재했습니다

  • EC2에 접속하기 위해, IP설정 작업이 필요하다

만약 Docker를 사용하지 않는다면 CI과정에서 Build한 결과물을 저장하는 작업도 필요한데
다행히 Docker hub를 이용해서 해당 문제를 해결했습니다.

EC2 IP 설정 문제 해결방법

Github Actions에서 EC2에 접속하도록 허용하려면 IP 인바운드 접속을 허용해야합니다
이때, Github Actions는 유동 IP이며, 사용자가 직접 알만한 방법이 없기 때문에
보통은 EC2 IP를 Public하게 바꾸도록 설정합니다

하지만 현재 프로젝트의 BE서버는 FE와 개발자 외에는 보안상 위험하기 때문에 접속하면 안 됩니다.
또한 SSH 접속을 Public하게 여는 것 자체부터 보안 공격에 취약한 환경을 조성하는 것이므로 선택하면 안됩니다.

따라서 Github Actions에 별도의 설정을 추가해서 해결했습니다.

      - name: Add GitHub-Action IP
        run: |
          aws ec2 authorize-security-group-ingress \
              --group-id ${{ secrets.SECURITY_GROUP_ID }} \
              --protocol tcp \
              --port 22 \
              --cidr ${{ steps.ip.outputs.ipv4 }}/32
    
...
          
      - name: Remove GitHub-Action IP
        run: |
          aws ec2 revoke-security-group-ingress \
              --group-id ${{ secrets.SECURITY_GROUP_ID }} \
              --protocol tcp \
              --port 22 \
              --cidr ${{ steps.ip.outputs.ipv4 }}/32

현재 Github Actions의 IP를 EC2 VPC 인바운드 설정에 추가하고, SSH 접속후 작업을 완료한뒤
다시 인바운드 설정에서 해당 IP를 삭제하도록 설정했습니다

이제 EC2 IP를 Public하게 바꿀 필요없이 Github Actions을 사용할 수 있습니다!

CI/CD 작업 시간 비교

위 사진은 Jenkins의 CI/CD 작업 시간입니다

위 사진은 Github Actions의 CI/CD 작업 시간입니다

전반적으로 두 CI/CD 작업시간의 차이가 크지 않은 것을 확인할 수 있습니다
관리/운영 비용을 줄이면서, 성능상 큰 차이가 나지 않는 Github Actions으로 전환이 완료되었습니다!

Docker Build 트러블 슈팅

문제 발생

#0 building with "default" instance using docker driver

#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 38B done
#1 DONE 0.0s
Dockerfile:1
--------------------
 1 | >>>
 2 |
--------------------
ERROR: failed to solve: file with no instructions

DockerFile을 Secret영역에 업로드 했는데 해당 파일을 사용하지 못하고,
자체적으로 Default DockerFile을 만드는 문제가 발생했습니다

Yaml 파일을 Secret 영역이나 Env영역에 업로드하는 방식으로 사용해왔기 때문에,
DockerFile도 동일하게 사용하는 줄 알았습니다

문제 해결

DockerFile은 Yaml파일과 동일한 영역에서 사용하지 않습니다.
Github Branch의 Root 영역에 DockerFile을 업로드해서 사용해야합니다

Github Actions을 사용한 다른 프로젝트를 보면 DockerFile을 꼭 Root폴더에 배치합니다
이때는 왜 이렇게 사용하는지 이해할 수 없었는데,
Github Actions을 직접 사용하고 나서야 그 이유를 알았습니다!

DockerFile을 위와같이 업로드하였고, 문제가 해결되었습니다!

변경된 CI/CD 아키텍처

위와같이 Jenkins에서 Github Actions로 CI/CD 아키텍처를 변경했습니다!

마무리

사실 Github Actions으로의 전환에 부정적인 입장이었습니다.
이전 프로젝트에서 Jenkins을 처음 사용할 때, 꽤 많은 시간이 발생했습니다.
따라서 '전환 비용을 감수하면서 Github Actions으로 전환하는게 맞을까?'에 대한 고민을 많이 하게되었습니다

또한 해결법을 찾기 전까지 Github Actions을 사용하려면
반드시 EC2 IP를 Public하게 변경해야한다고 잘못 알고 있었기 때문에 전환에 부정적인 입장이었습니다

하지만 3시간만에 전환해서 생각보다 전환비용이 크지 않았고,
EC2 IP 문제도 내부 코드로 쉽게 해결가능한 문제였습니다.

전환을 완료한 지금에서는 정말 잘한 선택이라고 생각합니다.
문제도 해결하면서 Github Actions를 사용하는 방법에 대해서도 학습했기 때문입니다.

앞으로는 프로젝트 규모에 따라 CI/CD 서비스를 선택해서 사용할 것입니다
작은 규모고 Github에서 코드를 관리한다면 Github Actions를,
별도의 CI/CD 서버를 구축할 정도로 규모가 큰 프로젝트라면 Jenkins를 사용할 것입니다.

참고

profile
Software Developer

0개의 댓글