DevOps - 透過 Helm Chart 建立你自己的 GitHub Action Runner
Preface
在 DevOps - 從 GitHub Actions 初探 CI/CD | Shawn Hsu 裡面有提到,你可以使用自架的 local runner 執行你的 GitHub Action
原因不外乎是因為 private repo 沒辦法免費的使用 GitHub 提供的 runner
所以你可以選擇自己架設一個 runner,這樣就可以免費的使用了
本文會記錄如何使用 Helm Chart 建立 local runner 以及中間遇到的困難點
在開始之前
既然是要使用 Helm Chart,那就必須要確保 Helm 以及 Kubernetes 都正確的安裝
Install Helm 以及 Install k3d
Token Setup
為了使 GitHub API 能夠正確的存取 Action Runner Controller,你需要設定正確的 token
Personal Access Token
可以使用傳統的 PAT 來設定
- 針對 repo 等級的 runner 要給
repo
的權限 - org 等級的 runner 要給
admin:org
的權限
這種做法如果是在公司使用會有難度,因為 PAT 是綁定在個人帳號上的
所以可以嘗試使用 GitHub App 來取代
GitHub App
你可以使用 GitHub App 來取代 Personal Access Token
GitHub App 可以把它想像成是一個擁有權限的機器人,你可以透過它來存取 GitHub API
以我們的例子來說,就是可以透過 GitHub App 來存取 Action Runner Controller
Setup Permission
建立一個 GitHub App 之後,找到 permission 設定頁面
設定 repository 的 administration 的權限
如果是要設定 organization 的 runner 就不用設定 repository 的權限,直接設定 organization 的權限即可
設定 organization 的 self hosted runner 的權限
Prepare Kubernetes Secret
操作介面取得以下
- App ID
- 在 GitHub App 設定頁面,有一個
App ID
的數字
- 在 GitHub App 設定頁面,有一個
- Private Key
- 介面上產一把 private key
- App Installation ID
- 在 GitHub App 安裝頁面,觀察 URL 就可以得到
1
https://github.com/organizations/ORGANIZATION/settings/installations/INSTALLATION_ID
- 在 GitHub App 安裝頁面,觀察 URL 就可以得到
要讓 ARC 能夠正確存取 GitHub API,你需要把這些資訊放到 Kubernetes 的 secret 裡面
1
2
3
4
5
6
$ kubectl create namespace arc-runners
$ kubectl create secret generic arc-secrets \
--namespace=arc-runners \
--from-literal=github_app_id=123456 \
--from-literal=github_app_installation_id=654321 \
--from-literal=github_app_private_key='-----BEGIN RSA PRIVATE KEY-----********'
Install Local Runner
GitHub 其實幫你把這個包的很好了,你可以簡單地透過 Helm Chart 安裝
總共就兩個步驟,Action Runner Controller 跟 Action Runner 即可
雖然官方文件寫,希望你可以將 controller 以及 runner 分開到不同的 namespace
但是這個實際上會有問題,所以還是放在一起,以本文來說就是arc-runners
Action Runner Controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ kubectl create namespace arc-runners
$ helm install arc \
--namespace "arc-runners" \
oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller
Pulled: ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller:0.9.3
Digest: sha256:4fda46fd8c4e08fe2e3d47340573f98d7a9eeb4c3a474b0e2b08057ab24d50a9
NAME: arc
LAST DEPLOYED: Wed Oct 2 01:19:15 2024
NAMESPACE: arc-runners
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Thank you for installing gha-runner-scale-set-controller.
Your release is named arc.
如果你要重新安裝,記得要
$ helm uninstall arc -n arc-runners
先把舊的刪掉
驗證一下 controller 有沒有正常跑起來
1
2
3
$ kubectl get pods -n arc-runners
NAME READY STATUS RESTARTS AGE
arc-gha-rs-controller-5f79dc8687-l6cbd 1/1 Running 0 48s
Action Runner
worker 的建立方式也一樣是用 Helm Chart
但是這裡有兩種方法,你可以用 Personal Access Token 或者是 GitHub App 來建立
PAT 的做法就只是將 credential 塞進去就可以了
1
2
3
4
5
6
$ kubectl create namespace arc-runner
$ helm install "self-hosted" \
--namespace "arc-runner" \
--set githubConfigUrl="https://github.com/ORGANIZATION" \
--set githubConfigSecret.github_token="PERSONAL_ACCESS_TOKEN" \
oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set
至於說 GitHub App 的方式稍早我們有建立了一組 secret arc-secrets
,所以這裡就可以直接使用
1
2
3
4
5
6
$ kubectl create namespace arc-runner
$ helm install "self-hosted" \
--namespace "arc-runner" \
--set githubConfigUrl="https://github.com/ORGANIZATION" \
--set githubConfigSecret="arc-secrets" \
oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set
安裝好大概會長這樣
1
2
3
4
5
6
7
8
9
10
11
12
Pulled: ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set:0.9.3
Digest: sha256:ec6acc8503fe1140e7371656b2142c42be67741d93222de7af63e167f825e531
NAME: self-hosted
LAST DEPLOYED: Thu Oct 3 07:14:06 2024
NAMESPACE: arc-runner
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Thank you for installing gha-runner-scale-set.
Your release is named self-hosted.
用 $ helm list -A
看有沒有正確安裝 release 上去
以及使用 $ kubectl
指令確認,理論上會有兩個 pod 啟動,一個是 controller 一個是 listener
注意到 listener 必須要啟動你的 action 才會成功被觸發
你也可以觀察 runner pod 的狀態,每一次 trigger 都會有一個 pod 被啟動
所以不同的 action 之間是使用獨立的 pod 來執行的
我們 deploy 的 helm chart 都是 scale set
gha-runner-scale-set-controller
以及gha-runner-scale-set
Input ‘submodules’ not supported when falling back to download using the GitHub REST API
當你都設定完成之後,實際執行 GitHub Action 的時候,checkout 會遇到這個錯誤
1
2
Error: Input 'submodules' not supported when falling back to download using the GitHub REST API.
To create a local Git repository instead, add Git 2.18 or higher to the PATH.
根據所述 Git version must 2.18 or higher??!!
When Git 2.18 or higher is not in the path, it falls back to the REST API to download the tarball.
所以即使沒有 Git 2.18 以上,也應該可以正常運作
double check 你的上述的權限是否有正確的設定
在 repository not found 中其實一直有人反應
從 2020 年開始到文章撰寫的期間都還是一直有狀況
或者是還有一個可能性
runner 沒有讀到你的 secret 資料
在 Runner Scale Set: “No gha-rs-controller deployment found” when rendering Helm chart 裡面有人有遇到跟我一樣的問題
具體上來說都是碰到 service account 無法讀取 secret 的問題
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2024-01-05T23:53:24Z ERROR Reconciler error
{
"controller": "autoscalingrunnerset",
"controllerGroup": "actions.github.com",
"controllerKind": "AutoscalingRunnerSet",
"AutoscalingRunnerSet": {
"name":"arc-controller",
"namespace":"arc-systems"
},
"namespace": "arc-systems",
"name": "arc-controller",
"reconcileID": "84ec6789-7f67-430f-98aa-df8f35f18b7a",
"error": "failed to find GitHub config secret: secrets 'arc-controller-gha-rs-github-secret' is forbidden: User 'system:serviceaccount:arc-runners:arc-gha-rs-controller' cannot get resource 'secrets' in API group '' in the namespace 'arc-systems'"
}
根據它提供的解法,我們只需要在 values.yaml 裡面加入以下的設定即可
1
2
3
controllerServiceAccount:
namespace: arc-runners
name: arc-controller-gha-rs-controller
其中 namespace 就是 Helm Chart 安裝的 namespace,arc-controller
是 Helm Release 的名稱
也因為如此,在安裝 Action Runner 的時候,也要加上這個設定
你可以嘗試把所有東西放在 values.yaml 裡面然後在 install 會比較簡潔
1
2
3
4
5
githubConfigUrl: https://github.com/ORGANIZATION
githubConfigSecret: arc-secrets
controllerServiceAccount:
namespace: arc-runners
name: arc-controller-gha-rs-controller
1
2
3
4
$ helm install "self-hosted" \
--namespace "arc-runner" \
--values "values.yaml" \
oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set
Customize Runner Image
當好不容易成功執行起來之後,我遇到了一些工具沒有安裝的問題
像是 make
, ssh
之類的
好在你其實可以把 runner image 替換成你自己的 image
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
FROM mcr.microsoft.com/dotnet/runtime-deps:6.0 AS build
# Replace value with the latest runner release version
# source: https://github.com/actions/runner/releases
# ex: 2.303.0
ARG RUNNER_VERSION="2.320.0"
ARG TARGETARCH
# Replace value with the latest runner-container-hooks release version
# source: https://github.com/actions/runner-container-hooks/releases
# ex: 0.3.1
ARG RUNNER_CONTAINER_HOOKS_VERSION="0.6.1"
ARG DOCKER_VERSION=27.1.1
ARG BUILDX_VERSION=0.16.2
ENV DEBIAN_FRONTEND=noninteractive
ENV RUNNER_MANUALLY_TRAP_SIG=1
ENV ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT=1
WORKDIR /home/runner
RUN apt update -y && apt install curl unzip -y
RUN export RUNNER_ARCH=${TARGETARCH} \
&& if [ "$RUNNER_ARCH" = "amd64" ]; then export RUNNER_ARCH=x64 ; fi \
&& curl -f -L -o runner.tar.gz https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-${RUNNER_ARCH}-${RUNNER_VERSION}.tar.gz \
&& tar xzf ./runner.tar.gz \
&& rm runner.tar.gz
RUN curl -f -L -o runner-container-hooks.zip https://github.com/actions/runner-container-hooks/releases/download/v${RUNNER_CONTAINER_HOOKS_VERSION}/actions-runner-hooks-k8s-${RUNNER_CONTAINER_HOOKS_VERSION}.zip \
&& unzip ./runner-container-hooks.zip -d ./k8s \
&& rm runner-container-hooks.zip
RUN export RUNNER_ARCH=${TARGETARCH} \
&& if [ "$RUNNER_ARCH" = "amd64" ]; then export DOCKER_ARCH=x86_64 ; fi \
&& if [ "$RUNNER_ARCH" = "arm64" ]; then export DOCKER_ARCH=aarch64 ; fi \
&& curl -fLo docker.tgz https://download.docker.com/linux/static/stable/${DOCKER_ARCH}/docker-${DOCKER_VERSION}.tgz \
&& tar zxvf docker.tgz \
&& rm -rf docker.tgz \
&& mkdir -p /usr/local/lib/docker/cli-plugins
RUN curl -fLo /usr/local/lib/docker/cli-plugins/docker-buildx \
"https://github.com/docker/buildx/releases/download/v${BUILDX_VERSION}/buildx-v${BUILDX_VERSION}.linux-${TARGETARCH}" \
&& chmod +x /usr/local/lib/docker/cli-plugins/docker-buildx
FROM mcr.microsoft.com/dotnet/runtime-deps:6.0 AS final
WORKDIR /home/runner
RUN adduser --disabled-password --gecos "" --uid 1001 runner \
&& groupadd docker --gid 123 \
&& usermod -aG sudo runner \
&& usermod -aG docker runner \
&& echo "%sudo ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers \
&& echo "Defaults env_keep += \"DEBIAN_FRONTEND\"" >> /etc/sudoers
COPY --from=build /home/runner /home/runner
COPY --from=build /usr/local/lib/docker/cli-plugins/docker-buildx /usr/local/lib/docker/cli-plugins/docker-buildx
RUN apt update -y && apt install ssh build-essential git -y
RUN chown -R runner /home/runner
RUN install -o root -g root -m 755 docker/* /usr/bin/ && rm -rf docker
USER runner
你也可以手動 build
$ docker build -t ambersun1234/arc-runner:latest -f Dockerfile .
runner base image 有兩個大要求,就是必須要有 actions/runner 以及 actions/runner-container-hooks 兩者的 binary 在 /home/runner
底下
所以前半的 multi-stage build 就是在做這件事情
後面的部分就是安裝一些我需要的工具,像是 ssh
, build-essential
, git
之類的
然後要設定 runner user 用以執行
Docker in Docker
然後如果你的 action 需要執行 build image 之類的事情
你需要開啟 Docker in Docker mode
上面的 Dockerfile 我們有安裝了
docker
以及docker-buildx
透過設定 values.yaml(往下看有完整範例)
1
2
containerMode:
type: "dind
Install
基本上你可以參考 Creating your own runner image 進行魔改就可以了
但是呢,這篇沒跟你講怎麼用
根據 Configuring the runner image,你一樣要進行修改,在 values.yaml 裡面修改 template spec 的 image
所以你的 Action Runner 的設定就會變這樣
1
2
3
4
5
6
7
8
9
10
11
12
13
14
githubConfigUrl: https://github.com/ORGANIZATION
githubConfigSecret: arc-secrets
containerMode:
type: "dind"
template:
spec:
containers:
- name: runner
image: "ambersun1234/arc-runner"
imagePullPolicy: Always
command: ["/home/runner/run.sh"]
controllerServiceAccount:
namespace: arc-runners
name: arc-controller-gha-rs-controller
上述 values.yaml 啟用了 Docker in Docker mode
設定了 runner image 為ambersun1234/arc-runner
config secret 以及 config url
你可以根據你的需要適當的進行微調
安裝也一樣
1
2
3
4
$ helm install "self-hosted" \
--namespace "arc-runner" \
--values "values.yaml" \
oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set
針對上述的 customize image 我有編一份放在 ambersun1234/arc-runner
有 linux/amd64
跟 linux/arm64
兩個版本,你可以直接使用
References
- Quickstart for Actions Runner Controller
- Authenticating to the GitHub API
- About creating GitHub Apps
- repository not found
- Git version must 2.18 or higher??!!
- Runner Scale Set: “No gha-rs-controller deployment found” when rendering Helm chart
- Creating your own runner image
- Configuring the runner image
- Using Docker-in-Docker mode
Leave a comment