ARC — 쿠버네티스 위의 GitHub Actions 셀프호스트 러너

CI·CD3분조회

GitHub Actions 러너를 self-hosted 로 EC2 에 띄워 쓰다가 ARC(Actions Runner Controller)로 옮겼습니다. self-hosted 러너는 개수가 고정이라 job 이 몰리면 대기가 생깁니다. ARC 는 job 이 올 때 파드를 만들고 끝나면 지웁니다.

통신 방향 — K8s에서 GitHub으로 나가는 단방향

GitHub 이 클러스터로 들어오는 게 아니라, 클러스터 안의 Controller 가 GitHub API 를 폴링합니다.

ARC Controller (K8s Pod)
  └── GitHub API polling (아웃바운드만)
        ├── job 없음 → 대기
        └── job 감지 → Runner Pod 생성 → job 실행 → Pod 자동 삭제

방향이 나가는 쪽 하나라서 클러스터가 내부망에 있어도 됩니다. 아웃바운드 443만 열리면 동작합니다. GitHub 에서 들어오는 인바운드를 뚫을 필요가 없습니다.

그래서 GitHub App 을 만들 때 webhook 을 끕니다. webhook 은 GitHub 이 이쪽으로 이벤트를 밀어주는 방식인데 ARC 는 폴링이라 안 씁니다.

runs-on 값 ↔ RunnerSet 이름 매칭

워크플로의 runs-on 에 적는 값이 등록된 RunnerSet 이름과 같아야 job 이 그쪽으로 갑니다.

runs-on: test-runner-set

이름은 설치할 때 runnerScaleSetName 으로 정하고 GitHub 에 자동 등록됩니다. 수동으로 러너를 등록하는 절차가 없습니다.

설치하며 막힌 곳 — Secret 네임스페이스부터

Secret이 다른 네임스페이스에 있었습니다.

ERROR: failed to get kubernetes secret: "arc-runners/arc-github-secret"

Secret 을 arc-systems 에 만들었는데 RunnerSet 은 arc-runners 에서 찾고 있었습니다. Secret 은 RunnerSet 과 같은 네임스페이스에 있어야 합니다.

조직명이 틀렸습니다.

ERROR: 404 Not Found POST
https://api.github.com/orgs/{조직명}/actions/runners/registration-token

githubConfigUrl 의 조직명이 실제와 안 맞으면 등록 토큰 발급이 404 입니다. helm get values 로 현재 설정을 확인하고 고쳤습니다.

job이 Queued에서 안 넘어갔습니다. 러너 파드가 안 뜨는 경우입니다. 하나는 runs-on 값이 RunnerSet 이름과 안 맞는 것. 다른 하나는 Controller 와 GitHub 사이 상태가 어긋난 것으로, 간헐적으로 생기는 알려진 이슈입니다. Controller 를 재시작하면 풀립니다.

kubectl rollout restart deployment/arc-gha-rs-controller -n arc-systems

러너 파드가 Pending에서 바로 Terminating으로 죽었습니다. Karpenter 나 Cluster Autoscaler 로 노드를 새로 띄우는 환경에서 나옵니다. 노드가 뜨는 시간보다 Controller 의 타임아웃이 짧으면, 파드가 스케줄되기 전에 Controller 가 먼저 지웁니다.

minRunners 로 러너 파드를 최소 하나 항상 유지하면 완화됩니다. 노드가 새로 뜨기를 기다리지 않고 대기 중인 러너가 job 을 바로 받습니다.

남은 것

minRunners 로 하나를 상시 유지하면 그 파드는 job 이 없어도 노드를 차지합니다. 노드를 새로 띄우는 지연과 상시 파드의 비용은 맞바꾸는 관계라, job 이 얼마나 자주 오는지에 따라 값을 정하는 게 맞습니다.

  1. 불러오는 중