Self-hosted action runner란?
GitHub Actions는 코드 변경을 자동으로 감지하여 빌드, 테스트, 배포 등의 작업을 수행할 수 있는 강력한 CI/CD 플랫폼입니다. 기본적으로 GitHub에서는 자체적으로 관리되는 호스티드 러너(Hosted Runner)를 제공하며, 사용자는 별도의 설정 없이 워크플로를 실행할 수 있습니다.
하지만 때로는 GitHub에서 제공하는 러너로는 한계가 있을 수 있습니다. 이럴 때 사용하는 것이 바로 self-hosted Action Runner입니다. Self-hosted runner는 GitHub Actions 워크플로를 실행할 수 있는 러너를 사용자가 직접 운영하는 방식으로, GitHub에서 제공하는 러너와 동일한 기능을 제공하면서도 다음과 같은 이점이 있습니다
- 비용 절감: GitHub의 호스티드 러너는 사용량에 따라 비용이 발생하지만, self-hosted runner는 자체 인프라를 활용하므로 요금을 줄일 수 있습니다.
- 높은 유연성: 필요에 따라 원하는 도구, 라이브러리, 하드웨어(GPU 등)를 설치해 커스텀 환경을 구성할 수 있습니다.
- 직접 제어 가능: runner의 리소스, 보안 정책, 확장 전략 등을 사용자가 직접 관리할 수 있습니다.
이번 실습에서는 Kubernetes 환경에 self-hosted runner를 구축하고, GitHub의 Private Repository에 코드가 수정될 때마다 자동으로 Docker 이미지를 빌드한 뒤, DockerHub의 Repository에 Push 하는 파이프라인을 구성해 보겠습니다. 이 실습을 통해 self-hosted runner의 구성 방법은 물론, 이를 활용한 실질적인 CI 자동화 사례를 직접 체험할 수 있도록 이번 문서를 작성하였습니다.
실습 환경 구성
minikube cluster 생성
필자는 개인 개발 환경에서 Minikube를 사용하고 있어, 아래와 같이 Kubernetes 클러스터를 생성하였습니다.
만약 이미 사용 중인 Kubernetes 클러스터가 있다면, 이 단계는 생략하셔도 괜찮습니다.
# node 2대, CPU 2core, Memory 2GB
# CRI는 containerd, CNI는 cilium으로 구성하였습니다.
minikube start -p=runner-profile --nodes 2 \
--container-runtime=containerd --cni=cilium \
--cpus=2 --memory=2048MB \
--addons=metrics-server
cert-manager 설치
actions-runner-controller는 인증서 발급을 위해 cert-manager를 사용하므로, 먼저 cert-manager를 설치해야 합니다.
간단히 소개하자면, cert-manager는 Kubernetes 환경에서 TLS 인증서를 자동으로 발급하고 갱신해주는 오픈소스 도구입니다.
Let’s Encrypt와 같은 외부 CA(Certificate Authority)와 연동하여 인증서를 관리하며, Kubernetes 리소스와 통합되어 동작합니다.
이를 통해 사용자는 복잡한 인증서 관리를 수동으로 하지 않아도 되고, 보다 쉽게 안전한 HTTPS 연결을 구성할 수 있습니다.
# cert-manager Helm repository 추가
helm repo add cert-manager https://charts.jetstack.io
helm repo update
# cert-manager 설치
# installCRDs=true 옵션을 주지 않으면 CRD가 설치되지 않음
# CRD가 설치되지 않으면 actions-runner-controller가 정상적으로 동작하지 않음
helm install my-cert-manager cert-manager/cert-manager \
--namespace cert-manager --create-namespace \
--set installCRDs=true
Kubernetes에 action runner 설치
이제는 이번 문서 실습의 주제인 kubernetes에 action runner를 설치해보겠습니다.
actions-runner-controller는 GitHub Actions Runner를 Kubernetes 클러스터에서 관리할 수 있도록 도와주는 Helm 차트입니다. 이 차트를 사용하면 GitHub Actions Runner를 Kubernetes 클러스터에 쉽게 배포하고 관리할 수 있습니다. actions-runner-controller는 GitHub API와 상호작용하여 Runner의 상태를 모니터링하고, 필요한 경우 자동으로 스케일링 및 업데이트를 수행합니다.
# actions-runner-controller Helm repository 추가
helm repo add actions-runner-controller https://actions-runner-controller.github.io/actions-runner-controller
helm repo update
# action-runner-controller 설치
helm upgrade --install actions-runner-controller actions-runner-controller/actions-runner-controller \
--namespace actions-runner-system --create-namespace \
--set githubWebhookServer.enabled=false \
--set syncPeriod=1m \
--set authSecret.create=true \
--set authSecret.github_token=ghp_나의깃헙토큰
"나의깃헙토큰" 위치에 GitHub Repo에 접근하기 위해 Read, Write 권한을 가진 토큰 값을 넣습니다.
RunnerDeployment 생성
kubectl apply -f - <<EOF
apiVersion: actions.summerwind.dev/v1alpha1
kind: RunnerDeployment
metadata:
name: self-hosted-runner
namespace: actions-runner-system
spec:
replicas: 1
template:
spec:
repository: 깃헙유저명/깃헙레포명
EOF
"깃헙유저명/깃헙레포명" 본인 환경의 GitHub Repo명을 입력합니다.
Workflow 실습 진행
필자는 개인 GitHub Private Repository를 구성하여 실습을 진행하였습니다. "myapp"라는 이름의 Repository를 생성하고, 간단한 코드와 Dockerfile을 작성하였지만 이번 문서의 주제는 GitHub Action Self-hosted Runner 구축이므로, 코드 내용과 Dockerfile 내용은 생략하였습니다.
GitHub Repo Secret 생성
Action Runner가 코드를 가져와 Docker 이미지를 빌드하고, 이를 DockerHub에 Push 하려면 GitHub Token과 DockerHub Token이 필요합니다. 하지만 이러한 민감한 값은 workflow 파일 내에 직접 작성하면 보안상 문제가 발생할 수 있습니다. 따라서 GitHub에서는 Repository의 Secrets 기능을 제공하며, 토큰과 같은 민감한 정보를 안전하게 저장하고 워크플로에서 참조할 수 있도록 하고 있습니다.
아래 경로를 따라 이동하여 DOCKER_USERNAME, DOCKER_TOKEN, GH_TOKEN과 같은 필요한 이름으로 Secret을 생성하면 됩니다. 이렇게 등록한 값은 GitHub Actions 워크플로에서 ${{ secrets.DOCKER_TOKEN }} 형태로 안전하게 사용할 수 있습니다.
GitHub Repo >> Settings >> Secrets and variables >> Actions >> New repository secret
Workflow 작성
GitHub Repo(myapp)에 workflow를 작성합니다.
.github/workflows/myrunner.yml
name: Seft-Hosted CI
on:
push:
branches: [ "**" ]
pull_request:
branches: [ main, develop ]
jobs:
build:
# self-hosted 러너에서 실행하도록 설정
runs-on: self-hosted
env:
IMAGE_REPO: standard2hsw/myapp
steps:
# 코드 체크아웃
- name: Checkout code
uses: actions/checkout@v2
# DockerHub 로그인
- name: DockerHub Login
run: |
echo "${{ secrets.DOCKER_TOKEN }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
# 브랜치명을 이용한 이미지 태그 생성
# main branch는 latest로 설정하고 나머지 branch는 branch명으로 태그를 생성합니다.
- name: Determine image tag
id: vars
run: |
BRANCH_NAME=${GITHUB_REF#refs/heads/}
SAFE_BRANCH_NAME=$(echo $BRANCH_NAME | sed 's#[^a-zA-Z0-9_.-]#-#g')
if [ "$BRANCH_NAME" = "main" ]; then
echo "tag=latest" >> $GITHUB_OUTPUT
else
echo "tag=$SAFE_BRANCH_NAME" >> $GITHUB_OUTPUT
fi
# 이미지 빌드
- name: Build Docker image
run: |
docker build --platform linux/amd64 -t ${{ env.IMAGE_REPO }}:${{ steps.vars.outputs.tag }} .
# 이미지 푸시
- name: Push Docker image
run: |
docker push ${{ env.IMAGE_REPO }}:${{ steps.vars.outputs.tag }}
runs-on에 반드시 self-hosted를 입력해야 self hosted runner로 동작합니다.
RunnerDeployment 생성하기
kubectl apply -f - <<EOF
apiVersion: actions.summerwind.dev/v1alpha1
kind: RunnerDeployment
metadata:
name: self-hosted-runner
namespace: actions-runner-system
spec:
replicas: 1
template:
spec:
repository: stdhsw/myapp
EOF
지금까지 실습을 잘 진행하셨다면 Self hosted runner가 정상적으로 동작하였는지 다음 위치에서 확인할 수 있습니다.
GitHub Repo >> Actions >> 해당 워크플로우 선택 >> Jobs 선택을 진행하시면 각각의 Job에서 Step별로 확인할 수 있습니다.
Set up job을 선택하여 보시면 어떤 Runner가 선택되어 동작되었는지 확인할 수 있습니다.
마지막으로 Hosted runner VS Self hosted runner
저는 개인적으로 절대적인 정답은 없다고 생각합니다. 따라서 Hosted Runner와 Self-hosted Runner의 장단점을 잘 비교하고, 각자의 환경과 목적에 맞는 최적의 선택을 하는 것이 중요합니다.
아래 표는 두 러너의 특성을 비교한 내용입니다. 표를 참고하셔서 여러분의 개발 환경에 가장 잘 맞는 러너를 선택하시기 바랍니다.
항목 | GitHub Hosted Runner | Self-hosted Runner |
인프라 제공 | GitHub에서 자동으로 VM 제공 | 사용자가 직접 서버/VM/Kubernetes 구성 |
비용 | 일정 사용량 이후 과금됨 | GitHub에는 무료, 인프라 비용은 사용자 부담 |
환경 커스터마이징 | 제한적 (사전 설치된 도구만 사용 가능) | 원하는 도구, 라이브러리, 하드웨어 설정 가능 |
실행 속도 | 동시 job 수 제한 시 대기 가능성 있음 | 러너 수 확장으로 빠르게 실행 가능 |
보안 | GitHub 클라우드에서만 실행 | 사내망, VPC 등 폐쇄 환경에서도 사용 가능 |
'DevOps' 카테고리의 다른 글
[Kubernetes] Pod Resource CPU 0.5 설정과 CFS 관계 (0) | 2025.04.27 |
---|---|
[Helm] helm hook 사용법 (0) | 2025.04.26 |
[Terraform] 기본 개념과 기본 사용법 (0) | 2025.04.22 |
[CI/CD] GitHub Action을 이용한 CI 설정하기 (0) | 2025.04.19 |
[CI/CD] ArgoCD를 이용한 Application 배포 자동화 (0) | 2025.04.12 |