Skip to content

electrocucaracha/kubevirt-actions-runner

Repository files navigation

Kubevirt Actions Runner

License GitHub Super-Linter

visitors Scc Code Badge Scc COCOMO Badge

Overview

kubevirt-actions-runner is a custom GitHub Actions runner image designed for use with the Actions Runner Controller (ARC). This runner provisions ephemeral virtual machines (VMs) using KubeVirt, extending the flexibility and security of your CI/CD workflows.

This is particularly useful for validating scenarios that are not supported by default GitHub-hosted runners, such as:

  • Running Windows or macOS jobs
  • Custom environments that require specific kernel modules or system services
  • Jobs requiring strong isolation from the host system

Key Features

  • Ephemeral VM creation: Launch a fresh VM for every job and destroy it after completion
  • Increased isolation: Ideal for untrusted code or complex system configurations
  • Custom system-level configuration support
  • Easily integrates with ARC and Kubernetes-native tooling

Prerequisites

To use this project, ensure you have the following installed:

Quick Start Guide

1. Create VirtualMachine template

This template will be used to spawn VMs on-demand for each GitHub job. The base VirtualMachine will never be started; instead, clones of it will be launched as VirtualMachineInstances.

# Create namespace if it doesn't exist
! kubectl get namespace "${namespace}" && kubectl create namespace "${namespace}"

# Apply the VM template
kubectl apply -f scripts/vm_template.yml -n "${namespace}"

Example snippet from vm_template.yml:

apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: ubuntu-jammy-vm
spec:
  runStrategy: Manual
  template:
    spec:
      domain:
        devices:
          filesystems:
            - name: runner-info
              virtiofs: {}

The runner-info volume is mounted at runtime and contains metadata required by the GitHub Actions runner, e.g.:

{
  "name": "runner-abcde-abcde",
  "token": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
  "url": "https://github.com/org/repo",
  "ephemeral": true,
  "groups": "",
  "labels": ""
}

2. Configure RBAC for KubeVirt Access

The service account used by the runner pods must be granted permissions to manage KubeVirt VMs.

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"]

3. Deploy the Runner scale set

Use Helm to install the GitHub Actions runner scale set.

Create a values.yml file:

githubConfigUrl: https://github.com/<your_enterprise/org/repo>
githubConfigSecret: <your_github_secret>

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

Install using Helm:

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

Architecture Diagram

flowchart TD
  subgraph GitHub
    A[GitHub Job Triggered]
  end

  subgraph Kubernetes Cluster
    B[Actions Runner Controller]
    C[Create kubevirt-actions-runner Pod]
    E[Mount runner-info.json]
    F[Create VirtualMachineInstance from Template]
    G[Boot VirtualMachineInstance]
  end

  subgraph Virtual Machine
    H[Runner fetches GitHub job metadata]
    I[Execute Job Steps]
    J[Job Completion]
  end

  subgraph Teardown
    K[Cleanup: Terminate VMI & Runner Pod]
  end

  A --> B --> C --> E --> F --> G --> H --> I --> J --> K
Loading

Limitations

  • macOS support: macOS virtualization is not supported via KubeVirt due to licensing constraints.
  • Long job durations: Boot time of VMs may increase total runtime.
  • Persistent state: Not designed for workflows requiring persisted state between jobs.

Contributing

Contributions are welcome! Please open issues or submit PRs to help improve this project.

Presentations

KCD Guadalajara 2025 – Migrating GitHub Actions with Nested Virtualization to the Cloud-Native Ecosystem

This project was presented at Kubernetes Community Days (KCD) Guadalajara 2025, showcasing how to extend GitHub Actions with KubeVirt and nested virtualization to support custom and complex CI/CD workflows in Kubernetes.

The presentation walks through:

  • Challenges with standard GitHub-hosted runners
  • Benefits of using KubeVirt for GitHub Actions runners
  • Live demo deploying and running jobs inside ephemeral VMs
  • Lessons learned and architectural considerations

About

GitHub self-host actions project for creation of Kubevirt runners

Topics

Resources

Stars

Watchers

Forks

Packages