GitHub Actions Self-hosted Runner (actions-runner-controller) を minikube で実行する


## はじめに

Qiita 株式会社 アドベントカレンダー 10 日目は インフラからアプリケーションまでなんでもやっている @mziyut が担当します。
最近は、共通の基盤開発を行うグループの 1 人として、Qiita 株式会社が持つインフラすべてを安定した状態で提供できるよう見直しを行いつつ、開発者全員の生産性を上げるべく様々な活動を行っています。

https://qiita.com/advent-calendar/2021/qiita

Qiita 株式会社では、CI/CD サービスに CircleCI, GitHub Actions, Travis CI など目的や用途別に様々利用していました。
サービスの特性や特徴など比較した結果、現時点では GitHub Actions に集約していくことを決定しました。
ただ、サービスの進化とともに、最適なサービスを利用することが出来るようにしていきたいとも考えています。

比較を行った際に、actions-runner-controller を minikube で実行し簡単に動作など確認を行いました。その内容を本記事にまとめます。

## GitHub Actions Self-hosted Runner について

GitHub Actions の利用が広がっている中、GitHub Actions が提供するマシンだと力不足であったり、クレデンシャルを外部サービスに置きたくないなど様々な理由で実行環境を時前で用意する方も多いはず。

今回は、GitHub Actions Self-hosted Runner を k8s で実行できる
actions-runner-controller を検証のため minikube で実行してみたので動かすまでのメモを記載します。

https://github.com/actions-runner-controller/actions-runner-controller

## 実行環境

```console
% minikube version
minikube version: v1.23.2
commit: 0a0ad764652082477c00d51d2475284b5d39ceed
```

## 事前準備

minikube で利用できる の メモリ, CPU をなるべく増やしておきましょう。
(標準ままでも動きますが若干の力不足感があった)

メモリ, CPU 数の変更は以下記事を参考にしていただけると :pray:

https://qiita.com/loftkun/items/7400d5ae0e7b1fb7d26e

https://qiita.com/loftkun/items/41ecde082778254de79a

## actions-runner-controller を実行する

### minikube を立ち上げる

`minikube start` を実行し minikube を実行します。
初回起動時には必要なイメージ等が download されます

```bash
minikube start
```

### cert-manager を用意する

actions-runner-controller を動かすには cert-manager が必要です。

https://cert-manager.io/docs/installation/

上記 URL から、実行中の k8s バージョンにあった cert-manager を apply してください

```console
$ kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.5.3/cert-manager.yaml
customresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/challenges.acme.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/clusterissuers.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/issuers.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/orders.acme.cert-manager.io created
namespace/cert-manager created
serviceaccount/cert-manager-cainjector created
serviceaccount/cert-manager created
serviceaccount/cert-manager-webhook created
clusterrole.rbac.authorization.k8s.io/cert-manager-cainjector created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-issuers created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-clusterissuers created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-certificates created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-orders created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-challenges created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-ingress-shim created
clusterrole.rbac.authorization.k8s.io/cert-manager-view created
clusterrole.rbac.authorization.k8s.io/cert-manager-edit created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-approve:cert-manager-io created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-certificatesigningrequests created
clusterrole.rbac.authorization.k8s.io/cert-manager-webhook:subjectaccessreviews created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-cainjector created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-issuers created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-clusterissuers created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-certificates created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-orders created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-challenges created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-ingress-shim created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-approve:cert-manager-io created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-certificatesigningrequests created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-webhook:subjectaccessreviews created
role.rbac.authorization.k8s.io/cert-manager-cainjector:leaderelection created
role.rbac.authorization.k8s.io/cert-manager:leaderelection created
role.rbac.authorization.k8s.io/cert-manager-webhook:dynamic-serving created
rolebinding.rbac.authorization.k8s.io/cert-manager-cainjector:leaderelection created
rolebinding.rbac.authorization.k8s.io/cert-manager:leaderelection created
rolebinding.rbac.authorization.k8s.io/cert-manager-webhook:dynamic-serving created
service/cert-manager created
service/cert-manager-webhook created
deployment.apps/cert-manager-cainjector created
deployment.apps/cert-manager created
deployment.apps/cert-manager-webhook created
mutatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created
validatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created
```

### カスタムリソースを反映

README に記載されている カスタムリソースを反映します
カスタムリソースについては以下を参照してください

https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/

k8s のバージョン等を確認しリリースバージョンは適切なものを選択してください

```bash
kubectl apply -f https://github.com/actions-runner-controller/actions-runner-controller/releases/download/$ACTIONS_RUNNER_CONTROLLER_VERSION/actions-runner-controller.yaml
```

今回は `v0.20.0` を利用します。

```console
$ kubectl apply -f https://github.com/actions-runner-controller/actions-runner-controller/releases/download/v0.20.0/actions-runner-controller.yaml
namespace/actions-runner-system created
customresourcedefinition.apiextensions.k8s.io/horizontalrunnerautoscalers.actions.summerwind.dev created
customresourcedefinition.apiextensions.k8s.io/runnerdeployments.actions.summerwind.dev created
customresourcedefinition.apiextensions.k8s.io/runnerreplicasets.actions.summerwind.dev created
customresourcedefinition.apiextensions.k8s.io/runners.actions.summerwind.dev created
customresourcedefinition.apiextensions.k8s.io/runnersets.actions.summerwind.dev created
role.rbac.authorization.k8s.io/leader-election-role created
clusterrole.rbac.authorization.k8s.io/manager-role created
clusterrole.rbac.authorization.k8s.io/proxy-role created
rolebinding.rbac.authorization.k8s.io/leader-election-rolebinding created
clusterrolebinding.rbac.authorization.k8s.io/manager-rolebinding created
clusterrolebinding.rbac.authorization.k8s.io/proxy-rolebinding created
service/controller-manager-metrics-service created
service/webhook-service created
deployment.apps/controller-manager created
certificate.cert-manager.io/serving-cert created
issuer.cert-manager.io/selfsigned-issuer created
mutatingwebhookconfiguration.admissionregistration.k8s.io/mutating-webhook-configuration created
validatingwebhookconfiguration.admissionregistration.k8s.io/validating-webhook-configuration created
```

### GitHub API の認証方法を設定する

actions-runner-controller には "GitHub App" と "PAT (Personal access tokens)" を用いる方法があります

今回は、簡単な検証だったため "PAT" を選択しました。

"GitHub App" と "PAT" それぞれ向き不向きがあるため、本導入時には "GitHub App" を利用することを検討しています。

#### PAT で必要な権限について

Organization Runners を PAT 経由で操作/利用する場合は、以下権限をもった Token を発行してください

- repo Full control of private repositories
- workflow Update GitHub Action workflows
- admin:org Full control of orgs and teams, read and write org projects
- admin:public_key Full control of user public keys
- admin:repo_hook Full control of repository hooks
- admin:org_hook Full control of organization hooks
- notifications Access notifications

`Enterprise` 環境での実行など環境によってはさらに追加の権限が必要になる場合があります。

https://github.com/actions-runner-controller/actions-runner-controller#deploying-using-pat-authentication

#### 作成した PAT を 定義します

以下コマンドで 作成した PAT を k8s から参照できるよう定義してください。

```bash
kubectl create secret generic controller-manager \
    -n actions-runner-system \
    --from-literal=github_token=${GITHUB_TOKEN}
```

### Runner を実行する

Runner には `Runner` と `RunnerDeployment` の 2 種類あり、こちらも環境によって適切な Runner 定義を使用してください。
特別な理由がない限り、複数 Runner をコントロールできる `RunnerDeployment` を利用することをお勧めします。

以下サンプルは `replicas` を 4 台用意する k8s の `RunnerDeployment` 定義です。

```yml:runner.yaml
apiVersion: actions.summerwind.dev/v1alpha1
kind: RunnerDeployment
metadata:
  name: minikube-test-runner
spec:
  replicas: 4
  template:
    spec:
      organization: your-org-name # Org名を指定してください
      env:
      - name: RUNNER_FEATURE_FLAG_EPHEMERAL
        value: "true"
```

ここまで実行すると GitHub 上から登録された Runner を確認できるようになります。
それぞれの workflow 定義の中で 今回作成した runner を選択すると job の実行を確認できるようになると思います。

## まとめ

簡単になりますが、 GitHub Actions Self-hosted Runner を actions-runner-controller を minikube で実行するところまで確認しました。
actions-runner-controller はただ実行するだけでなく、 job の実行状態に応じて runner 数を増減する機能もあります。
詳細については README に細かく記載されているため 是非試してみてください。

## 最後に

Qiita 株式会社では一緒に働く仲間を探しています。
この記事には、一部しか記載できていないため もっと詳しく知りたいと思った方は ▼ からカジュアル面談など申請いただけますと :pray:

https://meety.net/articles/t2--h6croouig1ma

https://corp.qiita.com/jobs/

Qiita Advent Calendar 2021 の 11 日目は、 @fussy113 が担当します :xmas-tree: