리셋 되지 말자

[Github Action] Workflow State based Self-Hosted Runner AutoScaling (AWS) 본문

CI CD

[Github Action] Workflow State based Self-Hosted Runner AutoScaling (AWS)

kyeongjun-dev 2022. 11. 20. 17:27

목적

github action runner를 Self-Hosted로 구성하면, 빌드캐시 활용 등 장점이 있다. 그런데 문제는 Runner가 한번에 무조건 하나의 Job만 수행한다. 그래서 Runner가 한 개 뿐인데, 특정 시간에 Workflow가 많이 수행되어 Job이 쌓이는 문제가 있다. (Workflow는 1개 이상의 Job으로 이루어져 있다.)
이러한 점을 고려하여 Self-Hosted Runner를 동적으로 스케일링 해주면 좋겠다는 생각을 했고, 이에 걸맞는 서비스로 AWS의 AutoScaling를 선택했다. 사실 AWS말고는 사용할줄 아는 클라우드 서비스가 없기에...


기존의 구성 방법

Kubernetes 환경에서는 Action Runner Controller를 이용하여 자동으로 스케일링 해주는 솔루션이 이미 공식적으로 지원된다. 또한 Terraform을 이용해서 구성하는 방법(philips-labs/terraform-aws-github-runner)도 이미 존재한다.

그런데 Terraform으로 구성한 방법은 동작하지를 않았다... 물론 쓴이가 잘 못한 것이겠지만... 굳이 여러 서비스 들을 사용할 필요가 있는지 의문점이 들어 직접 구성해보게 되었다. philips-labs에서 제공하는 방법은 AWS만 사용이 가능하며 API Gateway, Lambda, S3, SQS 등이 사용된다.

philips-labs/terraform-aws-github-runner 구성도


AMI 이미지 만들기

먼저 Auto Scaling Group에 사용될 AMI 이미지먼저 만들어보자. 여기서도 선택사항이 두 개이다.

  1. 쌩 이미지에 모든걸 user-data로 구성 : 별도로 AMI 관리 x, AMI 스냅샷 저장 비용 지출 필요 x, Auto Scaling으로 EC2 서버가 생길 때마다 Github Action Runner 관련 파일 다운로드 필요
  2. Github Action Runner 관련 파일이 설치된 상태로 Custom AMI 이미지 생성 : 별도로 AMI 관리 o, AMI 스냅샷 저장 비용 지출 필요 o

1번의 단점은 밑줄친 요소가 제일 문제라고 생각한다. philips-labs의 terraform 구성도를 보면, S3를 사용하는 이유도 이와 같은 이유다.(Github Action Runner 관련 파일, docker 바이너리 파일을 저장해 놓은 다음 EC2 서버 생성시에 사용)

따라서 2번의 경우를 가정하여 user-data와 AMI를 적절히 이용하여 사용하도록 한다.

1. Github Personal Access Token 발급

먼저 Github REST API, Action Runner 등록에 사용할 사용자 Token을 각자 발급받는다.(링크 참고)

그리고 Repository의 Settings > Actions > Runners > New self-hosted runner로 이동한다.

 

그러면 Runner를 설치할 플랫폼(Linux 선택), 아키텍처(x64 선택)를 선택할 수 있고, 설치 방법을 확인할 수 있다.

 

2. Github Action Runner, docker, jq 패키지 설치

EC2에 가상머신을 하나 시작한 뒤, /home/ec2-user 디렉토리가 아닌 다른 디렉토리에 생성 및 docker 설치

sudo mkdir /var/lib/actions-runner && sudo chmod 755 /var/lib/actions-runner && cd /var/lib/actions-runner
curl -o actions-runner-linux-x64-2.299.1.tar.gz -L https://github.com/actions/runner/releases/download/v2.299.1/actions-runner-linux-x64-2.299.1.tar.gz
tar xzf ./actions-runner-linux-x64-2.299.1.tar.gz

sudo amazon-linux-extras install -y docker
sudo systemctl enable docker
sudo usermod -aG docker ec2-user
sudo systemctl start docker

sudo yum install -y jq

 

설치가 완료되면, 해당 가상머신을 베이스로 Image 스냅샷을 생성한다.


user-data 작성

EC2 서버가 최초 생성 및 실행될 때, 실행될 스크립트인 user-data를 작성한다.

먼저 Job이 수행될 디렉토리인 /opt/actions-runner를 생성한 뒤, curl 명령어를 이용해 Runner 등록에 필요한 토큰을 획득한 뒤 등록 후, 백그라운드로 실행시킨다. REGIST_TOKEN 획득에 사용되는 curl 명령어에는 각자에 맞는 주소와, personal access toekn 값을 넣는다.

removeActionRunner.service는 가상머신이 종료될 때, ExecStart에 명시된 removeActionRunner.sh 스크립트를 실행한다. removeActionRunner.sh는 등록된 ActionRunner를 등록 해제하도록 한다. RUNNER_TOKEN 획득에 사용되는 curl 명령어에는 각자에 맞는 주소와, personal access toekn 값을 넣는다.

user-data는 root 계정으로 실행되는데, run.sh 스크립트는 root 권한으로 실행할 수 없으므로 su - ec2-user -c 를 이용해 ec2-user 계정으로 실행한다.

#!/bin/bash
mkdir /opt/actions-runner
chown ec2-user:ec2-user /opt/actions-runner
export REGIST_TOKEN=`curl --location --request POST 'https://api.github.com/repos/<계정이름>/<repo 이름>/actions/runners/registration-token' --header 'Accept: application/vnd.github+json' --header 'Authorization: Bearer ghp_user token here' | jq -r .token`
su - ec2-user -c "/var/lib/actions-runner/config.sh --unattended --url https://github.com/<계정이름>/<repo 이름> --token $REGIST_TOKEN --labels 'ec2' --work /opt/actions-runner"
su - ec2-user -c "nohup /var/lib/actions-runner/run.sh &"

cat <<EOF > /etc/systemd/system/removeActionRunner.service
[Unit]
Description=remove action runner from github
DefaultDependencies=no
Before=shutdown.target halt.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/removeActionRunner.sh

[Install]
WantedBy=halt.target shutdown.target
EOF

systemctl enable removeActionRunner.service

cat <<EOF > /usr/local/sbin/removeActionRunner.sh
#!/bin/bash
RUNNER_TOKEN=\`curl --location --request POST 'https://api.github.com/repos/<계정이름>/<repo 이름>/actions/runners/registration-token' --header 'Accept: application/vnd.github+json' --header 'Authorization: Bearer ghp_user token here' | jq -r .token\`
su - ec2-user -c "/var/lib/actions-runner/config.sh remove --token \$RUNNER_TOKEN"
EOF

chmod 755 /usr/local/sbin/removeActionRunner.sh

Launch Template 작성 및 Auto Scaling Group에 적용

Auto Scaling Group에서 사용할 Launch Template을 EC2 대시보드에서 생성한다. AMI 이미지를 위에서 생성한(jq, docker, action runner 파일이 설치된) AMI를 선택하고, user-data에 각자에 맞게 수정한 user-data 스크립트를 넣는다.

그리고 desired, min, max 개수를 조절해가며 레파지토리에 Runner가 등록되거나 자동으로 등록 해제되는지 확인한다.

Comments