Actions Runner Controller로 러너 스케일 세트 배포하기
Actions Runner Controller로 러너 스케일 세트 배포하기
Actions Runner Controller(ARC)로 러너 스케일 세트를 배포하고, 고급 구성 옵션을 사용해 ARC를 필요에 맞게 조정하는 방법을 알아봐요. Helm 차트를 사용해 스케일 세트를 배포하고 다양한 커스터마이징 옵션을 살펴봐요.
출처: 문서
본문
러너 스케일 세트 배포하기
러너 스케일 세트를 배포하려면 ARC가 실행 중이어야 해요. 자세한 내용은 Actions Runner Controller 시작하기를 참고하세요.
ARC의 Helm 차트를 사용하거나 필요한 매니페스트를 배포해 러너 스케일 세트를 배포할 수 있어요. ARC의 Helm 차트를 사용하는 것이 선호되는 방법으로, 특히 ARC 사용 경험이 없다면 더 그래요.
Note
- 보안 모범 사례로, 러너 팟을 운영자(operator) 팟이 있는 네임스페이스와 다른 네임스페이스에 만들어요.
- 보안 모범 사례로, Kubernetes 시크릿을 만들고 시크릿 참조를 전달해요. CLI를 통해 시크릿을 평문으로 전달하면 보안 위험이 될 수 있어요.
- 프로덕션 워크로드를 격리해서 실행할 것을 권장해요. GitHub Actions 워크플로는 임의 코드를 실행하도록 설계되었으며, 프로덕션 워크로드에 공유 Kubernetes 클러스터를 사용하면 보안 위험이 될 수 있어요.
- 컨트롤러, 리스너, 임시 러너의 로그를 수집·보존하는 방법을 구현했는지 확인해요.
-
러너 스케일 세트를 구성하려면 ARC 구성의 값을 사용해 터미널에서 다음 명령을 실행해요.
명령을 실행할 때 다음 사항을 염두에 두세요.
-
INSTALLATION_NAME값을 주의해서 업데이트해요. 설치 이름을 워크플로의runs-on값으로 사용할 수 있어요. -
NAMESPACE값을 러너 팟을 만들고 싶은 위치로 업데이트해요. -
GITHUB_CONFIG_URL값을 저장소, 조직, 또는 엔터프라이즈의 URL로 설정해요. 러너가 속하게 될 엔터티예요. -
이 예제 명령은 최신 버전의 Helm 차트를 설치해요. 특정 버전을 설치하려면 설치하려는 차트 버전과 함께
--version인자를 전달할 수 있어요. 릴리스 목록은actions-runner-controller저장소에서 찾을 수 있어요.
Note
이 예제는 초기 설정을 짧게 유지하기 위해 개인 액세스 토큰을 사용해요. 저장소 또는 조직 수준에서 러너를 등록한다면 GitHub App으로 인증할 것을 권장해요. 자세한 내용은 ARC를 GitHub API에 인증하기를 참고하세요. 엔터프라이즈 수준 러너는 개인 액세스 토큰(classic) 인증이 필요해요.
INSTALLATION_NAME="arc-runner-set" NAMESPACE="arc-runners" GITHUB_CONFIG_URL="https://github.com/<your_enterprise/org/repo>" GITHUB_PAT="<PAT>" helm install "${INSTALLATION_NAME}" \ --namespace "${NAMESPACE}" \ --create-namespace \ --set githubConfigUrl="${GITHUB_CONFIG_URL}" \ --set githubConfigSecret.github_token="${GITHUB_PAT}" \ oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set추가 Helm 구성 옵션은 ARC 저장소의
values.yaml을 참고하세요. -
-
설치를 확인하려면 터미널에서 다음 명령을 실행해요.
helm list -A다음과 비슷한 출력이 보여야 해요.
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION arc arc-systems 1 2023-04-12 11:45:59.152090536 +0000 UTC deployed gha-runner-scale-set-controller-0.4.0 0.4.0 arc-runner-set arc-systems 1 2023-04-12 11:46:13.451041354 +0000 UTC deployed gha-runner-scale-set-0.4.0 0.4.0 -
관리자(manager) 팟을 확인하려면 터미널에서 다음 명령을 실행해요.
kubectl get pods -n arc-systems설치가 성공했다면 팟이
Running상태를 보여줘요.NAME READY STATUS RESTARTS AGE arc-gha-runner-scale-set-controller-594cdc976f-m7cjs 1/1 Running 0 64s arc-runner-set-754b578d-listener 1/1 Running 0 12s
설치가 성공하지 못했다면 문제 해결 정보는 Actions Runner Controller 오류 문제 해결을 참고하세요.
고급 구성 옵션 사용하기
ARC는 여러 고급 구성 옵션을 제공해요.
러너 스케일 세트 이름 구성하기
Note
러너 스케일 세트 이름은 속한 러너 그룹 내에서 고유해요. 같은 이름으로 여러 러너 스케일 세트를 배포하려면 서로 다른 러너 그룹에 속해야 해요.
러너 스케일 세트 이름을 구성하려면 INSTALLATION_NAME을 정의하거나 values.yaml 파일의 사본에서 runnerScaleSetName 값을 설정할 수 있어요.
## The name of the runner scale set to create, which defaults to the Helm release name
runnerScaleSetName: "my-runners"
helm install 명령에 values.yaml 파일을 전달해야 해요. 자세한 내용은 Helm Install 문서를 참고하세요.
러너 대상 선택하기
러너 스케일 세트는 저장소, 조직, 또는 엔터프라이즈 수준으로 배포할 수 있어요.
러너 스케일 세트를 특정 수준에 배포하려면 values.yaml 사본의 githubConfigUrl 값을 저장소, 조직, 또는 엔터프라이즈의 URL로 설정해요.
다음 예제는 ARC가 octo-org/octo-repo에 러너를 추가하도록 구성하는 방법을 보여줘요.
githubConfigUrl: "https://github.com/octo-ent/octo-org/octo-repo"
추가 Helm 구성 옵션은 ARC 저장소의 values.yaml을 참고하세요.
인증에 GitHub App 사용하기
엔터프라이즈 수준 러너를 사용하지 않는다면 GitHub Apps를 사용해 GitHub API로 인증할 수 있어요. 자세한 내용은 ARC를 GitHub API에 인증하기를 참고하세요.
Note
디스크의 파일에 개인 키를 평문으로 노출하는 것과 관련된 보안 위험이 있으므로, Kubernetes 시크릿을 만들고 참조를 전달할 것을 권장해요.
Kubernetes 시크릿을 만들거나 values.yaml 파일에 값을 지정할 수 있어요.
옵션 1: Kubernetes 시크릿 만들기(권장)
GitHub App을 만든 후 Kubernetes 시크릿을 만들고 values.yaml 파일의 사본에서 해당 시크릿에 대한 참조를 전달해요.
Note
gha-runner-scale-set차트가 설치된 것과 같은 네임스페이스에 시크릿을 만들어요. 이 예제에서 네임스페이스는 퀵스타트 문서와 일치하도록arc-runners예요. 자세한 내용은 Actions Runner Controller 시작하기를 참고하세요.
kubectl create secret generic pre-defined-secret \
--namespace=arc-runners \
--from-literal=github_app_id=123456 \
--from-literal=github_app_installation_id=654321 \
--from-file=github_app_private_key=private-key.pem
values.yaml 파일의 사본에서 시크릿 이름을 참조로 전달해요.
githubConfigSecret: pre-defined-secret
옵션 2: values.yaml 파일에 값 지정하기
또는 values.yaml 파일의 사본에 app_id, installation_id, private_key 값을 지정할 수 있어요.
## githubConfigSecret is the Kubernetes secret to use when authenticating with GitHub API.
## You can choose to use a GitHub App or a personal access token (classic)
githubConfigSecret:
## GitHub Apps Configuration
## IDs must be strings, use quotes
github_app_id: "123456"
github_app_installation_id: "654321"
github_app_private_key: |
[REDACTED PRIVATE KEY]
추가 Helm 구성 옵션은 ARC 저장소의 values.yaml을 참고하세요.
러너 그룹으로 접근 관리하기
러너 그룹을 사용해 어떤 조직이나 저장소가 러너 스케일 세트에 접근할 수 있는지 제어할 수 있어요. 러너 그룹에 대한 자세한 내용은 그룹을 사용해 자체 호스팅 러너 접근 관리하기를 참고하세요.
러너 스케일 세트를 러너 그룹에 추가하려면 먼저 러너 그룹이 만들어져 있어야 해요. 그런 다음 values.yaml 파일의 사본에서 runnerGroup 속성을 설정해요. 다음 예제는 러너 스케일 세트를 Octo-Group 러너 그룹에 추가해요.
runnerGroup: "Octo-Group"
추가 Helm 구성 옵션은 ARC 저장소의 values.yaml을 참고하세요.
아웃바운드 프록시 구성하기
컨트롤러와 러너의 HTTP 트래픽이 아웃바운드 프록시를 통해 가도록 강제하려면 Helm 차트에서 다음 속성을 설정해요.
proxy:
http:
url: http://proxy.com:1234
credentialSecretRef: proxy-auth # a Kubernetes secret with `username` and `password` keys
https:
url: http://proxy.com:1234
credentialSecretRef: proxy-auth # a Kubernetes secret with `username` and `password` keys
noProxy:
- example.com
- example.org
ARC는 익명 또는 인증된 프록시 사용을 지원해요. 인증된 프록시를 사용한다면 credentialSecretRef 값을 Kubernetes 시크릿을 참조하도록 설정해야 해요. 다음 명령으로 프록시 자격 증명이 있는 시크릿을 만들 수 있어요.
Note
gha-runner-scale-set차트가 설치된 것과 같은 네임스페이스에 시크릿을 만들어요. 이 예제에서 네임스페이스는 퀵스타트 문서와 일치하도록arc-runners예요. 자세한 내용은 Actions Runner Controller 시작하기를 참고하세요.
kubectl create secret generic proxy-auth \
--namespace=arc-runners \
--from-literal=username=proxyUsername \
--from-literal=password=proxyPassword \
추가 Helm 구성 옵션은 ARC 저장소의 values.yaml을 참고하세요.
러너의 최대 및 최소 수 설정하기
maxRunners와 minRunners 속성은 ARC 설정을 커스터마이징할 수 있는 다양한 옵션을 제공해요.
Note
ARC는 예약된 최대 및 최소 구성을 지원하지 않아요. cron 작업이나 다른 예약 솔루션을 사용해 일정에 따라 구성을 업데이트할 수 있어요.
예제: 무제한 러너 수
maxRunners와 minRunners 속성을 둘 다 주석 처리하면 ARC는 러너 스케일 세트에 할당된 작업 수까지 확장하고, 활성 작업이 없으면 0으로 축소해요.
## maxRunners is the max number of runners the auto scaling runner set will scale up to.
# maxRunners: 0
## minRunners is the min number of idle runners. The target number of runners created will be
## calculated as a sum of minRunners and the number of jobs assigned to the scale set.
# minRunners: 0
예제: 최소 러너 수
minRunners 속성을 어떤 숫자든 설정할 수 있으며, ARC는 항상 지정된 수의 러너가 활성 상태로 러너 스케일 세트에 할당된 작업을 받을 수 있도록 해요.
## maxRunners is the max number of runners the auto scaling runner set will scale up to.
# maxRunners: 0
## minRunners is the min number of idle runners. The target number of runners created will be
## calculated as a sum of minRunners and the number of jobs assigned to the scale set.
minRunners: 20
예제: 최대 및 최소 러너 수 설정
이 구성에서 Actions Runner Controller는 최대 30개 러너로 확장하고, 작업이 완료되면 20개 러너로 축소해요.
Note
minRunners값은maxRunners가 주석 처리되어 있지 않는 한maxRunners값을 초과할 수 없어요.
## maxRunners is the max number of runners the auto scaling runner set will scale up to.
maxRunners: 30
## minRunners is the min number of idle runners. The target number of runners created will be
## calculated as a sum of minRunners and the number of jobs assigned to the scale set.
minRunners: 20
예제: 작업 큐 비우기
특정 시나리오에서 문제를 해결하거나 클러스터를 유지보수하기 위해 작업 큐를 비우고 싶을 수 있어요. 두 속성을 모두 0으로 설정하면 새 작업이 있어도 할당되어도 Actions Runner Controller가 새 러너 팟을 만들지 않아요.
## maxRunners is the max number of runners the auto scaling runner set will scale up to.
maxRunners: 0
## minRunners is the min number of idle runners. The target number of runners created will be
## calculated as a sum of minRunners and the number of jobs assigned to the scale set.
minRunners: 0
커스텀 TLS 인증서
Note
Debian배포판을 기반으로 하지 않는 커스텀 러너 이미지를 사용한다면 다음 지침은 작동하지 않아요.
일부 환경은 커스텀 인증 기관(CA)이 서명한 TLS 인증서를 필요로 해요. 커스텀 CA 인증서는 컨트롤러나 러너 컨테이너에 번들로 포함되지 않으므로, 각각의 신뢰 저장소(trust store)에 주입해야 해요.
githubServerTLS:
certificateFrom:
configMapKeyRef:
name: config-map-name
key: ca.crt
runnerMountPath: /usr/local/share/ca-certificates/
이렇게 할 때 Privacy Enhanced Mail(PEM) 형식을 사용하고 인증서 확장자가 .crt인지 확인해요. 그 외의 것은 무시돼요.
컨트롤러는 다음 작업을 실행해요.
certificateFrom에 지정된 인증서를 포함하는github-server-tls-cert볼륨을 만들어요.- 그 볼륨을
runnerMountPath/<certificate name>경로에 마운트해요. NODE_EXTRA_CA_CERTS환경 변수를 같은 경로로 설정해요.RUNNER_UPDATE_CA_CERTS환경 변수를1로 설정해요(버전2.303.0부터 이는 러너가 호스트에서 인증서를 다시 로드하도록 지시해요).
ARC는 러너 팟 템플릿에 설정된 값을 관찰하고 덮어쓰지 않아요.
추가 Helm 구성 옵션은 ARC 저장소의 values.yaml을 참고하세요.
비공개 컨테이너 레지스트리 사용하기
Warning
이 Actions Runner Controller 커스터마이징 옵션은 GitHub Support가 도와줄 수 있는 범위를 벗어날 수 있으며, 잘못 구성하면 예기치 않은 동작을 일으킬 수 있어요.
GitHub Support가 도와줄 수 있는 범위에 대한 자세한 내용은 Actions Runner Controller 지원을 참고하세요.
비공개 컨테이너 레지스트리를 사용하려면 컨트롤러 이미지와 러너 이미지를 비공개 컨테이너 레지스트리로 복사할 수 있어요. 그런 다음 해당 이미지에 대한 링크를 구성하고 imagePullPolicy와 imagePullSecrets 값을 설정해요.
컨트롤러 이미지 구성하기
values.yaml 파일의 사본을 업데이트해 image 속성을 다음과 같이 설정할 수 있어요.
image:
repository: "custom-registry.io/gha-runner-scale-set-controller"
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: "0.4.0"
imagePullSecrets:
- name: <registry-secret-name>
리스너 컨테이너는 컨트롤러에 대해 정의된 imagePullPolicy를 상속해요.
러너 이미지 구성하기
values.yaml 파일의 사본을 업데이트해 template.spec 속성을 설정해 특정 사용 사례에 맞게 러너 팟을 구성할 수 있어요.
Note
러너 컨테이너 이름은
runner여야 해요. 그렇지 않으면 GitHub에 연결하도록 제대로 구성되지 않아요.
다음은 샘플 구성이에요:
template:
spec:
containers:
- name: runner
image: "custom-registry.io/actions-runner:latest"
imagePullPolicy: Always
command: ["/home/runner/run.sh"]
imagePullSecrets:
- name: <registry-secret-name>
추가 Helm 구성 옵션은 ARC 저장소의 values.yaml을 참고하세요.
러너 팟의 팟 사양 업데이트하기
Warning
이 Actions Runner Controller 커스터마이징 옵션은 GitHub Support가 도와줄 수 있는 범위를 벗어날 수 있으며, 잘못 구성하면 예기치 않은 동작을 일으킬 수 있어요.
GitHub Support가 도와줄 수 있는 범위에 대한 자세한 내용은 Actions Runner Controller 지원을 참고하세요.
러너 팟의 PodSpec을 완전히 커스터마이징할 수 있고, 컨트롤러는 지정한 구성을 적용해요. 다음은 예제 팟 사양이에요.
template:
spec:
containers:
- name: runner
image: ghcr.io/actions/actions-runner:latest
command: ["/home/runner/run.sh"]
resources:
limits:
cpu: 500m
memory: 512Mi
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
add:
- NET_ADMIN
추가 Helm 구성 옵션은 ARC 저장소의 values.yaml을 참고하세요.
리스너 팟의 팟 사양 업데이트하기
Warning
이 Actions Runner Controller 커스터마이징 옵션은 GitHub Support가 도와줄 수 있는 범위를 벗어날 수 있으며, 잘못 구성하면 예기치 않은 동작을 일으킬 수 있어요.
GitHub Support가 도와줄 수 있는 범위에 대한 자세한 내용은 Actions Runner Controller 지원을 참고하세요.
리스너 팟의 PodSpec을 커스터마이징할 수 있고, 컨트롤러는 지정한 구성을 적용해요. 다음은 예제 팟 사양이에요.
Note
리스너 컨테이너의
listenerTemplate.spec.containers.name값을 변경하지 않는 것이 중요해요. 그렇지 않으면 지정한 구성이 새 사이드카 컨테이너에 적용돼요.
listenerTemplate:
spec:
containers:
# If you change the name of the container, the configuration will not be applied to the listener,
# and it will be treated as a sidecar container.
- name: listener
securityContext:
runAsUser: 1000
resources:
limits:
cpu: "1"
memory: 1Gi
requests:
cpu: "1"
memory: 1Gi
추가 Helm 구성 옵션은 ARC 저장소의 values.yaml을 참고하세요.
컨테이너에 Docker-in-Docker 또는 Kubernetes 모드 사용하기
Warning
이 Actions Runner Controller 커스터마이징 옵션은 GitHub Support가 도와줄 수 있는 범위를 벗어날 수 있으며, 잘못 구성하면 예기치 않은 동작을 일으킬 수 있어요.
GitHub Support가 도와줄 수 있는 범위에 대한 자세한 내용은 Actions Runner Controller 지원을 참고하세요.
컨테이너 작업과 서비스 또는 컨테이너 액션을 사용한다면 containerMode 값을 dind 또는 kubernetes로 설정해야 해요. 커스텀 컨테이너 모드를 사용하려면 containerMode를 주석 처리하거나 제거하고, 원하는 구성을 template 섹션에 추가해요. 컨테이너 모드 커스터마이징하기를 참고하세요.
- 컨테이너 작업과 서비스에 대한 자세한 내용은 컨테이너에서 작업 실행하기를 참고하세요.
- 컨테이너 액션에 대한 자세한 내용은 Docker 컨테이너 액션 만들기를 참고하세요.
Docker-in-Docker 모드 사용하기
Note
Docker-in-Docker 컨테이너는 권한 모드(privileged mode)를 필요로 해요. 자세한 내용은 Kubernetes 문서의 Pod 또는 Container에 대한 Security Context 구성하기를 참고하세요.
기본적으로
dind컨테이너는 Docker 데몬을 root로 실행하는docker:dind이미지를 사용해요. 알려진 제한 사항을 인지하고 팟을--privileged모드로 실행한다면 이 이미지를docker:dind-rootless로 교체할 수 있어요. Docker-in-Docker 구성을 커스터마이징하는 방법은 컨테이너 모드 커스터마이징하기를 참고하세요.
Docker-in-Docker 모드는 Docker 컨테이너 안에서 Docker를 실행할 수 있게 해주는 구성이에요. 이 구성에서 ARC는 생성된 각 러너 팟에 대해 다음 컨테이너를 만들어요.
init컨테이너runner컨테이너dind컨테이너
Docker-in-Docker 모드를 활성화하려면 다음과 같이 containerMode.type을 dind로 설정해요.
containerMode:
type: "dind"
template.spec은 다음 기본 구성으로 업데이트돼요.
Kubernetes >= v1.29 버전의 경우 사이드카 컨테이너가 Docker 데몬을 실행하는 데 사용돼요.
template:
spec:
initContainers:
- name: init-dind-externals
image: ghcr.io/actions/actions-runner:latest
command: ["cp", "-r", "/home/runner/externals/.", "/home/runner/tmpDir/"]
volumeMounts:
- name: dind-externals
mountPath: /home/runner/tmpDir
- name: dind
image: docker:dind
args:
- dockerd
- --host=unix:///var/run/docker.sock
- --group=$(DOCKER_GROUP_GID)
env:
- name: DOCKER_GROUP_GID
value: "123"
securityContext:
privileged: true
restartPolicy: Always
startupProbe:
exec:
command:
- docker
- info
initialDelaySeconds: 0
failureThreshold: 24
periodSeconds: 5
volumeMounts:
- name: work
mountPath: /home/runner/_work
- name: dind-sock
mountPath: /var/run
- name: dind-externals
mountPath: /home/runner/externals
containers:
- name: runner
image: ghcr.io/actions/actions-runner:latest
command: ["/home/runner/run.sh"]
env:
- name: DOCKER_HOST
value: unix:///var/run/docker.sock
- name: RUNNER_WAIT_FOR_DOCKER_IN_SECONDS
value: "120"
volumeMounts:
- name: work
mountPath: /home/runner/_work
- name: dind-sock
mountPath: /var/run
volumes:
- name: work
emptyDir: {}
- name: dind-sock
emptyDir: {}
- name: dind-externals
emptyDir: {}
Kubernetes < v1.29 버전의 경우 다음 구성이 적용돼요:
template:
spec:
initContainers:
- name: init-dind-externals
image: ghcr.io/actions/actions-runner:latest
command:
["cp", "-r", "/home/runner/externals/.", "/home/runner/tmpDir/"]
volumeMounts:
- name: dind-externals
mountPath: /home/runner/tmpDir
containers:
- name: runner
image: ghcr.io/actions/actions-runner:latest
command: ["/home/runner/run.sh"]
env:
- name: DOCKER_HOST
value: unix:///var/run/docker.sock
volumeMounts:
- name: work
mountPath: /home/runner/_work
- name: dind-sock
mountPath: /var/run
- name: dind
image: docker:dind
args:
- dockerd
- --host=unix:///var/run/docker.sock
- --group=$(DOCKER_GROUP_GID)
env:
- name: DOCKER_GROUP_GID
value: "123"
securityContext:
privileged: true
volumeMounts:
- name: work
mountPath: /home/runner/_work
- name: dind-sock
mountPath: /var/run
- name: dind-externals
mountPath: /home/runner/externals
volumes:
- name: work
emptyDir: {}
- name: dind-sock
emptyDir: {}
- name: dind-externals
emptyDir: {}
template.spec의 값은 자동으로 주입되며 재정의할 수 없어요. 이 설정을 커스터마이징하려면 containerMode.type을 설정 해제한 다음, 이 구성을 복사해 values.yaml 파일의 사본에 직접 적용해야 해요.
추가 Helm 구성 옵션은 ARC 저장소의 values.yaml을 참고하세요.
Kubernetes 모드 사용하기
Kubernetes 모드에서 ARC는 러너 컨테이너 훅을 사용해 같은 namespace에 새 팟을 만들어 서비스, 컨테이너 작업, 또는 액션을 실행해요.
사전 요구 사항
Kubernetes 모드는 러너 팟과 컨테이너 작업 팟 사이에 작업 데이터를 공유하는 두 가지 접근 방식을 지원해요. 동시 쓰기 접근이 필요한 시나리오에서 권장 옵션으로 남아 있는 영구 볼륨(persistent volumes)을 사용하거나, RWX 볼륨에 의존하지 않고 팟 사이에 작업 파일 시스템을 복원·내보내기 위해 컨테이너 수명주기 훅을 사용할 수 있어요. 수명주기 훅 접근 방식은 로컬 스토리지를 활용해 이식성과 성능을 개선하며, 공유 스토리지가 없는 클러스터에 이상적이에요.
영구 볼륨이 있는 Kubernetes 모드 구성하기
Kubernetes 모드를 사용하려면 러너 팟이 클레임할 수 있는 영구 볼륨을 만들고, 이러한 볼륨을 주문형으로 자동 프로비저닝하는 솔루션을 사용해야 해요. 테스트의 경우 OpenEBS 같은 솔루션을 사용할 수 있어요.
Kubernetes 모드를 활성화하려면 values.yaml 파일에서 containerMode.type을 kubernetes로 설정해요.
containerMode:
type: "kubernetes"
kubernetesModeWorkVolumeClaim:
accessModes: ["ReadWriteOnce"]
storageClassName: "dynamic-blob-storage"
resources:
requests:
storage: 1Gi
추가 Helm 구성 옵션은 ARC 저장소의 values.yaml을 참고하세요.
컨테이너 수명주기 훅이 있는 Kubernetes 모드 구성하기
컨테이너 수명주기 훅을 사용해 Kubernetes 모드를 활성화하려면 values.yaml 파일에서 containerMode.type을 kubernetes-novolume으로 설정해요:
containerMode:
type: "kubernetes-novolume"
Kubernetes 모드 문제 해결
Kubernetes 모드가 활성화되면 컨테이너 작업으로 구성되지 않은 워크플로는 다음과 비슷한 오류로 실패해요:
Jobs without a job container are forbidden on this runner, please add a 'container:' to your job or contact your self-hosted runner administrator.
컨테이너 작업이 없는 작업이 실행되도록 허용하려면 러너 컨테이너에서 ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER를 false로 설정해요. 이는 러너가 이 검사를 비활성화하도록 지시해요.
Warning
kubernetes또는kubernetes-novolume모드에서 컨테이너 없이 작업 실행을 허용하면 러너 팟에 Kubernetes API 서버에 대한 높은 권한(팟 생성 및 시크릿 접근 능력 포함)이 부여될 수 있어요. 이 기본값을 변경하기 전에 잠재적 보안 영향을 신중히 검토할 것을 권장해요.
template:
spec:
containers:
- name: runner
image: ghcr.io/actions/actions-runner:latest
command: ["/home/runner/run.sh"]
env:
- name: ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER
value: "false"
컨테이너 모드 커스터마이징하기
gha-runner-scale-set helm 차트의 values.yaml 파일에서 containerMode를 설정할 때 다음 값 중 하나를 사용할 수 있어요:
dind또는kubernetes
containerMode에 설정한 값에 따라 gha-runner-scale-set helm 차트의 values.yaml 파일 template 섹션에 구성이 자동으로 주입돼요.
dind구성을 참고하세요.kubernetes구성을 참고하세요.
스펙을 커스터마이징하려면 containerMode를 주석 처리하거나 제거하고, 원하는 구성을 template 섹션에 추가해요.
예제: dind-rootless 실행하기
dind-rootless를 실행하기로 결정하기 전에 알려진 제한 사항을 인지하고 있는지 확인해요.
Kubernetes >= v1.29 버전의 경우 사이드카 컨테이너가 Docker 데몬을 실행하는 데 사용돼요.
## githubConfigUrl is the GitHub url for where you want to configure runners
## ex: https://github.com/myorg/myrepo or https://github.com/myorg
githubConfigUrl: "https://github.com/actions/actions-runner-controller"
## githubConfigSecret is the k8s secrets to use when auth with GitHub API.
## You can choose to use GitHub App or a PAT token
githubConfigSecret: my-super-safe-secret
## maxRunners is the max number of runners the autoscaling runner set will scale up to.
maxRunners: 5
## minRunners is the min number of idle runners. The target number of runners created will be
## calculated as a sum of minRunners and the number of jobs assigned to the scale set.
minRunners: 0
runnerGroup: "my-custom-runner-group"
## name of the runner scale set to create. Defaults to the helm release name
runnerScaleSetName: "my-awesome-scale-set"
## template is the PodSpec for each runner Pod
## For reference: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodSpec
template:
spec:
initContainers:
- name: init-dind-externals
image: ghcr.io/actions/actions-runner:latest
command: ["cp", "-r", "/home/runner/externals/.", "/home/runner/tmpDir/"]
volumeMounts:
- name: dind-externals
mountPath: /home/runner/tmpDir
- name: init-dind-rootless
image: docker:dind-rootless
command:
- sh
- -c
- |
set -x
cp -a /etc/. /dind-etc/
echo 'runner:x:1001:1001:runner:/home/runner:/bin/ash' >> /dind-etc/passwd
echo 'runner:x:1001:' >> /dind-etc/group
echo 'runner:100000:65536' >> /dind-etc/subgid
echo 'runner:100000:65536' >> /dind-etc/subuid
chmod 755 /dind-etc;
chmod u=rwx,g=rx+s,o=rx /dind-home
chown 1001:1001 /dind-home
securityContext:
runAsUser: 0
volumeMounts:
- mountPath: /dind-etc
name: dind-etc
- mountPath: /dind-home
name: dind-home
- name: dind
image: docker:dind-rootless
args:
- dockerd
- --host=unix:///run/user/1001/docker.sock
securityContext:
privileged: true
runAsUser: 1001
runAsGroup: 1001
restartPolicy: Always
startupProbe:
exec:
command:
- docker
- info
initialDelaySeconds: 0
failureThreshold: 24
periodSeconds: 5
volumeMounts:
- name: work
mountPath: /home/runner/_work
- name: dind-sock
mountPath: /run/user/1001
- name: dind-externals
mountPath: /home/runner/externals
- name: dind-etc
mountPath: /etc
- name: dind-home
mountPath: /home/runner
containers:
- name: runner
image: ghcr.io/actions/actions-runner:latest
command: ["/home/runner/run.sh"]
env:
- name: DOCKER_HOST
value: unix:///run/user/1001/docker.sock
securityContext:
privileged: true
runAsUser: 1001
runAsGroup: 1001
volumeMounts:
- name: work
mountPath: /home/runner/_work
- name: dind-sock
mountPath: /run/user/1001
volumes:
- name: work
emptyDir: {}
- name: dind-externals
emptyDir: {}
- name: dind-sock
emptyDir: {}
- name: dind-etc
emptyDir: {}
- name: dind-home
emptyDir: {}
Kubernetes < v1.29 버전의 경우 다음 구성이 적용돼요:
## githubConfigUrl is the GitHub url for where you want to configure runners
## ex: https://github.com/myorg/myrepo or https://github.com/myorg
githubConfigUrl: "https://github.com/actions/actions-runner-controller"
## githubConfigSecret is the k8s secrets to use when auth with GitHub API.
## You can choose to use GitHub App or a PAT token
githubConfigSecret: my-super-safe-secret
## maxRunners is the max number of runners the autoscaling runner set will scale up to.
maxRunners: 5
## minRunners is the min number of idle runners. The target number of runners created will be
## calculated as a sum of minRunners and the number of jobs assigned to the scale set.
minRunners: 0
runnerGroup: "my-custom-runner-group"
## name of the runner scale set to create. Defaults to the helm release name
runnerScaleSetName: "my-awesome-scale-set"
## template is the PodSpec for each runner Pod
## For reference: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodSpec
template:
spec:
initContainers:
- name: init-dind-externals
image: ghcr.io/actions/actions-runner:latest
command: ["cp", "-r", "/home/runner/externals/.", "/home/runner/tmpDir/"]
volumeMounts:
- name: dind-externals
mountPath: /home/runner/tmpDir
- name: init-dind-rootless
image: docker:dind-rootless
command:
- sh
- -c
- |
set -x
cp -a /etc/. /dind-etc/
echo 'runner:x:1001:1001:runner:/home/runner:/bin/ash' >> /dind-etc/passwd
echo 'runner:x:1001:' >> /dind-etc/group
echo 'runner:100000:65536' >> /dind-etc/subgid
echo 'runner:100000:65536' >> /dind-etc/subuid
chmod 755 /dind-etc;
chmod u=rwx,g=rx+s,o=rx /dind-home
chown 1001:1001 /dind-home
securityContext:
runAsUser: 0
volumeMounts:
- mountPath: /dind-etc
name: dind-etc
- mountPath: /dind-home
name: dind-home
containers:
- name: runner
image: ghcr.io/actions/actions-runner:latest
command: ["/home/runner/run.sh"]
env:
- name: DOCKER_HOST
value: unix:///run/user/1001/docker.sock
securityContext:
privileged: true
runAsUser: 1001
runAsGroup: 1001
volumeMounts:
- name: work
mountPath: /home/runner/_work
- name: dind-sock
mountPath: /run/user/1001
- name: dind
image: docker:dind-rootless
args:
- dockerd
- --host=unix:///run/user/1001/docker.sock
securityContext:
privileged: true
runAsUser: 1001
runAsGroup: 1001
volumeMounts:
- name: work
mountPath: /home/runner/_work
- name: dind-sock
mountPath: /run/user/1001
- name: dind-externals
mountPath: /home/runner/externals
- name: dind-etc
mountPath: /etc
- name: dind-home
mountPath: /home/runner
volumes:
- name: work
emptyDir: {}
- name: dind-externals
emptyDir: {}
- name: dind-sock
emptyDir: {}
- name: dind-etc
emptyDir: {}
- name: dind-home
emptyDir: {}
runner-container-hooks 이해하기
러너가 컨테이너 작업, 서비스 컨테이너, 또는 Docker 액션을 사용하는 워크플로 실행을 감지하면 runner-container-hooks를 호출해 새 팟을 만들어요. 러너는 runner-container-hooks를 사용해 Kubernetes API를 호출하고 러너 팟과 같은 네임스페이스에 새 팟을 만들어요. 이 새로 생성된 팟은 컨테이너 작업, 서비스 컨테이너, 또는 Docker 액션을 실행하는 데 사용돼요. 자세한 내용은 runner-container-hooks 저장소를 참고하세요.
훅 확장 구성하기
ARC 버전 0.4.0부터 runner-container-hooks는 훅 확장을 지원해요. 이를 사용해 runner-container-hooks가 만드는 팟을 구성할 수 있어요. 예를 들어 훅 확장을 사용해 팟에 보안 컨텍스트를 설정할 수 있어요. 훅 확장을 사용하면 runner-container-hooks가 만드는 팟의 PodSpec을 업데이트하는 데 사용되는 YAML 파일을 지정할 수 있어요.
훅 확장을 구성하는 두 가지 옵션이 있어요.
- 커스텀 러너 이미지에 저장해요. 커스텀 러너 이미지의 어느 곳에든 YAML 파일에 PodSpec을 저장할 수 있어요. 자세한 내용은 Actions Runner Controller를 참고하세요.
- ConfigMap에 저장해요. PodSpec으로 구성 맵을 만들고 그 구성 맵을 러너 컨테이너에 마운트해요. 자세한 내용은 Kubernetes 문서의 ConfigMaps을 참고하세요.
Note
두 옵션 모두 러너 컨테이너 스펙에서
ACTIONS_RUNNER_CONTAINER_HOOK_TEMPLATE환경 변수를 러너 컨테이너에 마운트된 YAML 파일의 경로를 가리키도록 설정해야 해요.
예제: config map을 사용해 securityContext 설정하기
러너 팟과 같은 네임스페이스에 구성 맵을 만들어요. 예를 들어:
apiVersion: v1
kind: ConfigMap
metadata:
name: hook-extension
namespace: arc-runners
data:
content: |
metadata:
annotations:
example: "extension"
spec:
containers:
- name: "$job" # Target the job container
securityContext:
runAsUser: 1000
.metadata.labels와metadata.annotations필드는 키가 예약되지 않았다면 있는 그대로 추가돼요..metadata.name과metadata.namespace필드는 재정의할 수 없어요.- PodSpec 필드의 대부분은 지정된 템플릿에서 적용되며, Helm 차트
values.yaml파일에서 전달된 값을 재정의해요. - 추가 볼륨을 지정하면 러너가 지정한 기본 볼륨에 추가돼요.
spec.containers는 할당된 이름을 기준으로 병합돼요.- 컨테이너 이름이
$job인 경우:spec.containers.name과spec.containers.image필드는 무시돼요.spec.containers.env,spec.containers.volumeMounts,spec.containers.ports필드는 훅이 만든 기본 컨테이너 스펙에 추가돼요.- 나머지 필드는 제공된 대로 적용돼요.
- 컨테이너 이름이
$job이 아니면 필드가 있는 그대로 팟 정의에 추가돼요.
- 컨테이너 이름이
메트릭 활성화하기
Note
ARC의 메트릭은 gha-runner-scale-set-0.5.0 버전부터 사용할 수 있어요.
ARC는 러너, 작업, 워크플로 실행에 소요된 시간에 대한 메트릭을 방출할 수 있어요. 메트릭은 혼잡 식별, ARC 배포 상태 모니터링, 사용 추세 시각화, 리소스 소모 최적화 등 많은 사용 사례에 사용될 수 있어요. 메트릭은 controller-manager와 listener 팟에서 Prometheus 형식으로 방출돼요. 자세한 내용은 Prometheus 문서의 Exposition formats을 참고하세요.
ARC의 메트릭을 활성화하려면 gha-runner-scale-set-controller 차트의 values.yaml 파일에서 metrics 속성을 구성해요.
다음은 예제 구성이에요.
metrics:
controllerManagerAddr: ":8080"
listenerAddr: ":8080"
listenerEndpoint: "/metrics"
Note
metrics:객체가 제공되지 않거나 주석 처리되면 다음 플래그가 빈 값으로 controller-manager와 listener 팟에 적용돼요:--metrics-addr,--listener-metrics-addr,--listener-metrics-endpoint. 이렇게 하면 ARC의 메트릭이 비활성화돼요.
이 속성들을 구성하면 controller-manager와 listener 팟은 values.yaml 파일에서 지정한 포트에 바인딩된 listenerEndpoint를 통해 메트릭을 방출해요. 위 예제에서 엔드포인트는 /metrics이고 포트는 :8080이에요. 이 엔드포인트를 사용해 controller-manager와 listener 팟에서 메트릭을 스크래핑할 수 있어요.
메트릭을 끄려면 values.yaml 파일에서 metrics: 객체와 그 속성을 제거하거나 주석 처리해 업데이트해요.
ARC에 사용 가능한 메트릭
다음 표는 controller-manager와 listener 팟이 방출하는 메트릭을 보여줘요.
Note
controller-manager가 방출하는 메트릭은 컨트롤러 런타임과 관련되며 GitHub이 소유하지 않아요.
| Owner | Metric | Type | Description |
|---|---|---|---|
| controller-manager | gha_controller_pending_ephemeral_runners | gauge | pending 상태의 임시 러너 수 |
| controller-manager | gha_controller_running_ephemeral_runners | gauge | running 상태의 임시 러너 수 |
| controller-manager | gha_controller_failed_ephemeral_runners | gauge | failed 상태의 임시 러너 수 |
| controller-manager | gha_controller_running_listeners | gauge | running 상태의 리스너 수 |
| listener | gha_assigned_jobs | gauge | 러너 스케일 세트에 할당된 작업 수 |
| listener | gha_running_jobs | gauge | 실행 중이거나 실행 대기 중인 작업 수 |
| listener | gha_registered_runners | gauge | 러너 스케일 세트가 등록한 러너 수 |
| listener | gha_busy_runners | gauge | 현재 작업을 실행 중인 등록된 러너 수 |
| listener | gha_min_runners | gauge | 러너 스케일 세트에 대해 구성된 최소 러너 수 |
| listener | gha_max_runners | gauge | 러너 스케일 세트에 대해 구성된 최대 러너 수 |
| listener | gha_desired_runners | gauge | 러너 스케일 세트가 원하는(확장/축소 대상) 러너 수 |
| listener | gha_idle_runners | gauge | 작업을 실행하지 않는 등록된 러너 수 |
| listener | gha_started_jobs_total | counter | 리스너가 준비된 후 시작된 작업의 총 수 [1] |
| listener | gha_completed_jobs_total | counter | 리스너가 준비된 후 완료된 작업의 총 수 [1] |
| listener | gha_job_startup_duration_seconds | histogram | 워크플로 작업이 러너 스케일 세트가 소유한 러너에서 시작되기를 기다리는 데 소요된 초 수 |
| listener | gha_job_execution_duration_seconds | histogram | 러너 스케일 세트가 워크플로 작업을 실행하는 데 소요된 초 수 |
[1]: counter 타입인 리스너 메트릭은 리스너 팟이 다시 시작되면 리셋돼요.
ARC 업그레이드하기
Helm으로 CRD를 업그레이드하거나 삭제하는 것은 지원되지 않으므로, Helm을 사용해 ARC를 업그레이드할 수 없어요. 자세한 내용은 Helm 문서의 Custom Resource Definitions을 참고하세요. ARC를 최신 버전으로 업그레이드하려면 다음 단계를 완료해야 해요.
- 모든
gha-runner-scale-set설치를 제거해요. - 리소스 정리를 기다려요.
- ARC를 제거해요.
- 현재 설치된 버전에서 업그레이드된 버전으로 CRD에 변경이 있다면
actions.github.comAPI 그룹과 관련된 모든 CRD를 제거해요. - ARC를 다시 설치해요.
자세한 내용은 러너 스케일 세트 배포하기를 참고하세요.
ARC를 업그레이드하고 싶지만 가동 중지가 우려된다면, ARC를 고가용성 구성으로 배포해 러너가 항상 사용 가능하도록 할 수 있어요. 자세한 내용은 고가용성 및 자동 장애 조치를 참고하세요.
Note
커뮤니티 지원 버전의 ARC에서 GitHub 지원 버전으로 전환하는 것은 상당한 아키텍처 변화예요. GitHub 지원 버전은 ARC의 많은 구성 요소를 재설계하는 것을 포함해요. 사소한 소프트웨어 업그레이드가 아니에요. 이러한 이유로, 새 버전을 프로덕션에 배포하기 전에 프로덕션 환경과 일치하는 스테이징 환경에서 먼저 테스트할 것을 권장해요. 이렇게 하면 설정의 안정성과 신뢰성이 보장돼요.
카나리(canary) 이미지 배포하기
controller-manager 컨테이너 이미지의 카나리 릴리스를 사용해 출시 전에 기능을 테스트할 수 있어요. 카나리 이미지는 canary-SHORT_SHA 태그 형식으로 게시돼요. 자세한 내용은 Container registry의 gha-runner-scale-set-controller을 참고하세요.
Note
- 로컬 파일 시스템의 Helm 차트를 사용해야 해요.
- 릴리스된 Helm 차트는 사용할 수 없어요.
- gha-runner-scale-set-controller
values.yaml파일에서tag를canary-SHORT_SHA로 업데이트해요. gha-runner-scale-set의Chart.yaml파일에서appVersion필드를canary-SHORT_SHA로 업데이트해요.- 업데이트된 Helm 차트와
values.yaml파일을 사용해 ARC를 다시 설치해요.
고가용성 및 자동 장애 조치
ARC는 고가용성(active-active) 구성으로 배포할 수 있어요. 별도 지역에 배포된 두 개의 다른 Kubernetes 클러스터가 있다면 두 클러스터에 모두 ARC를 배포하고, 러너 스케일 세트가 같은 runnerScaleSetName을 사용하도록 구성할 수 있어요. 이렇게 하려면 각 러너 스케일 세트를 별도의 러너 그룹에 할당해야 해요. 예를 들어 한 러너 스케일 세트가 runner-group-A에 속하고 다른 러너 스케일 세트가 runner-group-B에 속하는 한, 각각 arc-runner-set으로 이름 지어진 두 개의 러너 스케일 세트를 가질 수 있어요. 러너 그룹에 러너 스케일 세트를 할당하는 방법은 그룹을 사용해 자체 호스팅 러너 접근 관리하기를 참고하세요.
두 러너 스케일 세트가 모두 온라인이면 할당된 작업은 임의로 분산돼요(할당 경쟁). 작업 할당 알고리즘을 구성할 수 없어요. 한 클러스터가 다운되면 다른 클러스터의 러너 스케일 세트는 어떤 개입이나 구성 변경 없이도 계속 정상적으로 작업을 획득해요.
조직 전반에 ARC 사용하기
Actions Runner Controller의 단일 설치로 하나 이상의 러너 스케일 세트를 구성할 수 있어요. 이 러너 스케일 세트는 저장소, 조직, 또는 엔터프라이즈에 등록할 수 있어요. 또한 러너 그룹을 사용해 이 러너 스케일 세트의 권한 경계를 제어할 수도 있어요.
모범 사례로 각 조직에 고유한 네임스페이스를 만들어요. 각 러너 그룹이나 각 러너 스케일 세트에 대한 네임스페이스를 만들 수도 있어요. 각 네임스페이스에 필요한 만큼 많은 러너 스케일 세트를 설치할 수 있어요. 이렇게 하면 최고 수준의 격리가 제공되고 보안이 개선돼요. GitHub Apps를 인증에 사용하고 각 러너 스케일 세트에 대해 세밀한 권한을 정의할 수 있어요.