kubevirt-actions-runner
is a runner image for Actions Runner Controller (ARC) that spawns ephemeral virtual machines for jobs using KubeVirt.
- Windows and macOS jobs
- Jobs that require configuring system services
- Jobs that require stronger isolation
You need a Kubernetes cluster with Actions Runner Controller and KubeVirt installed.
First, we need to create a VirtualMachine to act as a template for the runner VMs.
kubevirt-actions-runner
will create VirtualMachineInstances from it, and the VirtualMachine itself will never be started.
Create a namespace and apply the sample template:
! kubectl get namespaces "${namespace}" && kubectl create namespace "${namespace}"
kubectl apply -f scripts/vm_template.yml -n "${namespace}"
Let's take a deeper look at this sample VirtualMachine.
Inside we mount the runner-info
volume:
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: ubuntu-jammy-vm
spec:
runStrategy: Manual
template:
spec:
domain:
devices:
filesystems:
- name: runner-info
virtiofs: {}
This runner-info
volume will be injected by kubevirt-actions-runner
, containing runner-info.json
that looks like the following:
{
"name": "runner-abcde-abcde",
"token": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"url": "https://github.com/org/repo",
"ephemeral": true,
"groups": "",
"labels": ""
}
The service account of the runner pod needs to be able to create VirtualMachineInstance
s.
An example is as follows:
apiVersion: v1
kind: ServiceAccount
metadata:
name: kubevirt-actions-runner
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: kubevirt-actions-runner
rules:
- apiGroups: ["kubevirt.io"]
resources: ["virtualmachines"]
verbs: ["get", "watch", "list"]
- apiGroups: ["kubevirt.io"]
resources: ["virtualmachineinstances"]
verbs: ["get", "watch", "list", "create", "delete"]
- apiGroups: ["cdi.kubevirt.io"]
resources: ["datavolumes"]
verbs: ["get", "watch", "list", "create", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cdi-cloner
rules:
- apiGroups: ["cdi.kubevirt.io"]
resources: ["datavolumes/source"]
verbs: ["create"]
You can configure the runner scale set using Helm.
Use the following values.yaml
:
githubConfigUrl: https://github.com/<your_enterprise/org/repo>
githubConfigSecret: ...
template:
spec:
serviceAccountName: kubevirt-actions-runner
containers:
- name: runner
image: electrocucaracha/kubevirt-actions-runner:latest
command: []
env:
- name: KUBEVIRT_VM_TEMPLATE
value: ubuntu-jammy-vm
- name: RUNNER_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
helm upgrade --create-namespace --namespace "${namespace}" \
--wait --install --values values.yml vm-self-hosted \
oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set
The lifecycle of the spawned VMI is bound to the runner pod. If one of them exits, the other will be terminated as well.