Github Actions(Self-Hosted Runner)를 이용한 ECR, ECS 배포 자동화하기 (3)

저번에 적은 "Github Actions를 이용한 ECR, ECS 배포 자동화 (2)" 글이 마지막이 될 줄 알았으나... 실제 운영 중 비용과 배포 시간 문제를 겪으면서 GitHub Actions의 Self-Hosted Runner를 도입하게 되었습니다.

이번 글에서는 Self-Hosted Runner를 선택한 이유와 연결 방법에 대해 정리해보겠습니다. (이전 글은 아래 링크를 참고해주세요!)

 

Github Actions를 이용한 ECR, ECS 배포 자동화하기 (2)

이전 글에서는 ECR, ECS, Github Actions에 대해서 설명했습니다. 이번에는 실제 코드를 확인하면서 GitHub Actions를 활용한 CI/CD 파이프라인을 알아보겠습니다.CI/CD 파이프라인에서는 AWS CodeBuild를 이용

itcodeheaven.tistory.com

Self-Hosted Runner란?

Github Actions Self-Hosted Runner

Self-hosted Runner는 GitHub Actions 워크플로에서 작업을 실행할 환경을 사용자가 직접 지정할 수 있는 기능입니다. 기본적으로 GitHub Actions는 GitHub에서 제공하는 Runner를 사용하지만, 필요에 따라 사용자는 Self-Hosted Runner를 이용해 실행 환경을 지정할 수 있습니다.

자세한 정보는 아래 링크에서 확인하실 수 있습니다.

 

자체 호스트형 실행기 정보 - GitHub Docs

자체 실행기를 호스트하고 GitHub Actions 워크플로에서 작업을 실행하는 데 사용되는 환경을 사용자 지정할 수 있습니다.

docs.github.com

필요한 이유!

GitHub Actions에서는 VPC 내부 Private Subnet에 직접 접근이 불가능!

프로젝트를 진행하면서 AWS RDS를 Private Subnet에 배치했는데, GitHub Actions에서 빌드할 때 데이터베이스에 접근할 수 없는 문제가 발생했습니다.

이러한 오류가 발생한 이유는 GitHub Actions가 AWS 외부 서비스이기 때문에 VPC 내부 Private Subnet에 직접 접근할 수 없기 때문입니다. 이러한 이유들 때문에 아래 사진처럼 CI/CD 파이프라인에서 지속적인 오류가 발생했습니다.

DataSource 오류 : 데이터베이스에 직접 접근이 불가능...

따라서 코드 테스트가 가능하면서도 AWS Private Subnet에 위치한 RDS에 접근할 수 있는 환경을 구축해야 했습니다

방법 1. CodeBuild를 이용한 CI/CD 파이프라인 구성

첫번째로 고려한 방법은 AWS CodeBuild를 이용해, 저희 팀에서 사용하고 있는 VPC 내부 Subnet을 지정하여 해당 Subnet에서 Build 파일을 생성해 배포하는 것이었습니다.

그러나 CodeBuild에 VPC 설정을 지정하면 인터넷 접근이 불가능해지는 문제가 발생했습니다. Codebuild를 이용해 Github Actions에서 정의한 워크플로우를 진행하려면 Github에 올라온 파일들을 읽을 수 있게 Internet Access가 필요한데, Codebuild에서 VPC 설정을 건들이는 순간 인터넷 Access가 불가능해졌습니다.

출처 : Stack Overflow

이유를 찾아보니 CodeBuild에서는 Public Ip 주소를 할당할 수 없기 때문에 외부 통신을 하려면 별도로 NAT Gateway를 붙여야 했습니다.

그런데 NAT Gateway를 이용하게 되면 서울 리전 기준으로 1시간당 약 0.059달러, 하루 약 1.42달러, 한 달 약 42.48달러가 발생하게 됩니다. 이러한 비용적인 문제 때문에 단순히 Github Actions를 위해 NAT Gateway를 추가하는 것은 비용적으로 아깝다고 생각하게 되었습니다. 

방법2. Self-Hosted Runners를 이용 (채택)

Self-Hosted runner 이용 시 이점

그래서 찾아본 다른 방법으로는 Public Subnet에 위치한 AWS EC2 인스턴스를 Self-hosted Runner로 운영하기로 결정했습니다.

EC2는 t2.small 인스턴스 타입을 선택했으며, 시간당 약 0.023달러로 NAT Gateway 비용의 약 3분의 1 수준입니다. 여기에 Public IP를 할당해도 추가 비용이 시간당 약 0.005달러로, 전체 비용이 NAT Gateway의 절반 수준에 불과했습니다. 

또한 비용 절감뿐만 아니라 배포 시간도 개선되었습니다. CodeBuild를 이용했을 때는 평균 9~10분 정도 소요되었지만, Self-hosted Runner를 사용한 GitHub Actions에서는 평균 5분 정도의 시간만 소요되었습니다.

이러한 이유들로 기존의 AWS CodeBuild를 이용한 CI/CD 파이프라인에서 Github Actions Self-Hosted Runner를 이용한 CI/CD 파이프라인으로 전환하기로 결정했습니다.

Self-Hosted Runner 등록 방법 

1. EC2 인스턴스 생성

EC2 인스턴스 생성!

EC2 인스턴스를 하나 생성합니다. 저희 프로젝트의 경우에는 운영체제로는 Ubuntu를 이용했고, 인스턴스 타입으로는 t2.small을 이용했습니다.

인스턴스 생성시 주의해야할 점은 EC2 인스턴스를 생성할 때는 Public IP 할당 옵션이 설정되어 있어야 합니다. 러너가 GitHub 서버와 통신하기 위해서는 외부 네트워크 접근이 가능해야 하기 때문입니다. 

2. EC2에 Github Actions에 runner 설정에 추가

Self Hosted Runner를 적용하고 싶은 깃허브 레포지토리에 Actions에 Runners로 접속한 후 New Self-Hosted Runner 버튼을 누릅니다.

Repository -> Settings -> Actions -> Runners로 접속 후 New Self Hosted runner 누르기

해당 버튼을 누르게 되면 아래처럼 운영체제를 선택하는 칸과 명령어들이 보일텐데, 저희 프로젝트에서는 EC2 타입이 Ubuntu라고 했으므로 Linux 버튼을 누르고 아래에 있는 명령어들을 차례대로 적어주시면 됩니다.

해당 명령어를 EC2에 접속해서 차례대로 해주면 됩니다.

특히 ./config.sh --url ~ 명령어 실행 시 아래와 같은 설정 과정이 진행됩니다.

러너 설정 화면

(1) 그룹 설정

  • Runner 그룹을 설정하는 입력창이 뜹니다. 개인 사용자라면 별도 입력 없이 Enter를 눌러 Default 그룹을 사용하면 됩니다.

(2) Runner 이름 설정

  • 기본값으로 EC2 컴퓨터명이 자동 입력됩니다. 변경을 원한다면 원하는 이름을 직접 입력할 수 있습니다. Runner 이름은 설정 후 수정이 불가능하므로 신중하게 결정해야 합니다. 

(3) 라벨(Label) 설정

  • Runner에 기본적으로 적용될 라벨을 추가할 수 있습니다. 입력 없이 Enter를 누르면 기본 라벨만 설정됩니다.
    라벨은 이후에도 추가/수정이 가능합니다.

이후에 추가적으로 작업 폴더 명을 입력할 수 있는 단계가 있는데 저는 값을 입력하지 않고 Enter를 눌러 기본값인 _work 폴더를 이용했습니다. 작업 폴더명 까지의 작업이 완료 되었다면 Runner 설정이 완료됩니다

3. Github Actions 성공적으로 실행 되는지 확인

Runner 설정이 완료되었다면 마지막으로 ./run.sh 커맨드를 치면 Github Actions Self Hosted Runner를 사용할 수 있습니다. 만약에 터미널을 종료하더라도 Runner 프로세스가 백그라운드에서 실행될 수 있도록 하고 싶으면 nohup ./run.sh & 커맨드를 사용하시면 됩니다.

Runner 프로세스를 잘 실행했다면, GitHub Actions 워크플로우 파일(.yml)에서 runs-on 옵션을 self-hosted로 설정하면 모든 설정이 완료되었습니다.

jobs:
  build:
    runs-on: self-hosted  #이 부분에 Runner에게 부여된 라벨(Label)을 적어주면 됩니다.  
    steps:
      ...

이제 워크플로우를 실행했을 때 방금 설정한 EC2 인스턴스의 Self-Hosted Runner에서 작업이 실행되는 것을 확인할 수 있습니다!