GitHub Actions self-hosted runnerとvclusterを使って、Kubernetesクラスタ上で隔離されたCI環境を構築する実験
簡単に言うと、これをやりたい。
まずは、Kubernetes上でself-hosted runnerを動かすために何を使うかを検討。
一番スターのついてるこれでよさそう。
kindをセットアップ
$ kind create cluster
cert-managerをセットアップ
$ curl -fsL https://github.com/jetstack/cert-manager/releases/latest/download/cert-manager.yaml | kubectl apply -f -
actions-runner-controllerをセットアップ
$ kubectl apply -f https://github.com/actions-runner-controller/actions-runner-controller/releases/download/v0.20.3/actions-runner-controller.yaml
認証はGitHub Appを使う方法とPATを使う方法があるらしい。
今回はPATを利用。repoのfull権限を付与する。
生成したPATでシークレットリソースを作成。
$ kubectl create secret generic controller-manager \
-n actions-runner-system \
--from-literal=github_token=${GITHUB_TOKEN}
テスト用のリポジトリを作成
Runnerリソースを作成
apiVersion: actions.summerwind.dev/v1alpha1
kind: Runner
metadata:
name: example-runner
namespace: default
spec:
repository: zoetrope/vcluster-runner-test
env: []
runner podが動作していることを確認
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
example-runner 2/2 Running 0 10m
GitHubのリポジトリを開いて、settings→actions→runnersをみるとexample-runnerが登録されていることが確認できる。
GitHub ActionsのWorkflowを作成。
PRを作成してみると、Runner Podでチェックアウト処理が実行されました。
name: CI
on:
pull_request:
push:
branches:
- 'main'
jobs:
test:
name: test
runs-on: [ self-hosted, linux ]
steps:
- name: Checkout
uses: actions/checkout@v2
とりあえずこれで準備OK。
Runnerの中でkubectlを叩きたいので、以下のようなRunnerのコンテナイメージを用意する。
FROM summerwind/actions-runner:latest
LABEL org.opencontainers.image.source https://github.com/zoetrope/vcluster-runner-test
RUN sudo curl -sfSL "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" -o /usr/local/bin/kubectl && \
sudo chmod +x /usr/local/bin/kubectl
ghcr.ioに突っ込んでおく。
$ docker build -t ghcr.io/zoetrope/actions-runner:v0.1.0 .
$ docker push ghcr.io/zoetrope/actions-runner:v0.1.0
vclusterで仮想クラスタを立てます。
$ vcluster --version
vcluster version 0.4.3
$ vcluster create test-cluster
以前のスクラップを参考にしつつ
values.yamlを用意する。
syncer:
extraArgs:
- --out-kube-config-server=https://test-cluster
- --tls-san=test-cluster
仮想クラスタを作り直し
$ vcluster delete test-cluster
$ vcluster create test-cluster --extra-values=./values.yaml
仮想clusterにアクセスするためのSecretリソースが生成されているので、それをRunnerから参照します。
apiVersion: actions.summerwind.dev/v1alpha1
kind: Runner
metadata:
name: example-runner
namespace: default
spec:
repository: zoetrope/vcluster-runner-test
image: ghcr.io/zoetrope/actions-runner:v0.1.0
env: []
volumeMounts:
- mountPath: /etc/kubernetes
name: kubeconfig
readOnly: true
volumes:
- name: kubeconfig
secret:
defaultMode: 420
secretName: vc-test-cluster
これで、Runner Podから仮想クラスタにアクセスできるはずです。
ではこれを使って、CIから仮想クラスタ上にPodをデプロイしてみます。
適当なマニフェストを用意
apiVersion: v1
kind: Pod
metadata:
name: sample
namespace: default
spec:
containers:
- name: ubuntu
image: ubuntu:20.04
command: ["/usr/bin/sleep", "infinity"]
CIからkubectlを叩く処理を書いてみます。
name: CI
on:
pull_request:
push:
branches:
- 'main'
jobs:
test:
name: test
runs-on: [ self-hosted, linux ]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Deploy Pod
run: |
kubectl --kubeconfig=/etc/kubernetes/config apply -f ./pod.yaml
kubectl --kubeconfig=/etc/kubernetes/config wait --for=condition=ready pod sample
ばっちり動きました。
次は、仮想クラスタ上でArgo CDを入れてみます。
まずはRunner Podにargocdコマンドを追加。
FROM summerwind/actions-runner:latest
LABEL org.opencontainers.image.source https://github.com/zoetrope/vcluster-runner-test
RUN sudo curl -sfSL "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" -o /usr/local/bin/kubectl && \
sudo chmod +x /usr/local/bin/kubectl && \
sudo curl -sfSL https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64 -o /usr/local/bin/argocd && \
sudo chmod +x /usr/local/bin/argocd
次に仮想クラスタにArgo CDをデプロイ
$ kubectl exec -it example-runner bash
$ kubectl create namespace argocd
$ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
そして、CIではこんな感じのテストを実行する。
name: CI
on:
pull_request:
push:
branches:
- 'main'
jobs:
test:
name: test
runs-on: [ self-hosted, linux ]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Deploy Application
run: |
ARGOCD_PASSWORD=$(kubectl get secrets -n argocd argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d)
argocd login argocd-server-x-argocd-x-test-cluster --insecure --username admin --password ${ARGOCD_PASSWORD}
argocd app create test --repo https://github.com/zoetrope/vcluster-runner-test.git --path manifests --dest-namespace default --dest-server https://kubernetes.default.svc --directory-recurse
argocd app sync test
実行結果もバッチリ。
実用に向けての課題
- テスト実行のたびにvclusterを作り直す仕組みが欲しい。
- ホスト側のクラスタが提供している機能(カスタムリソース)を、仮想クラスタ内でも使いたい。
- 仮想クラスタ上のPodから、ホストクラスタ上のサービスへのアクセスを制限するためのNetworkPolicyが必要。