kuranto #
Caution
Kuranto is at an early stage of development, and implements an experimental feature of the Forgejo Runner, use at your own risks.
kuranto implements Forgejo Runner v13's experimental
plugin.v1alpha.BackendPlugin gRPC interface. It creates one Kubernetes Pod
per Actions job and executes workflow commands using the Kubernetes
pods/exec subresource.
The Forgejo plugin protocol is alpha. This implementation currently targets Forgejo Runner
v13.2.0.
Execution model #
kuranto runs as a container alongside the Forgejo Runner in one pod. The
runner talks to kuranto through its gRPC plugin interface. When picking
up jobs, the runner instructs the plugin to execute it; kuranto then
creates job pods in its configured namespace.
A job pod is:
- a
jobcontainer using the label's image, or the workflow's configured image; - an
emptyDirmounted on/sharedfor ephemeral storage during job execution, and a writable/tmp; - optional service containers as sidecars, reachable by their service name
on
127.0.0.1
Service port mappings are unsupported by Kuranto. Because service containers share the job Pod's network, services are reached on the ports they listen on; Kuranto does not publish or translate workflow host/container port mappings. A service definition with ports will be rejected.
The job pod has no access to the Kubernetes cluster, and empty service account is mounted, which has no permissions at all.
Configuration #
The plugin reads these environment variables:
| Variable | Required | Default | Purpose |
|---|---|---|---|
KURANTO_KUBERNETES_NAMESPACE |
yes | — | Dedicated namespace in which it may create job Pods. |
KURANTO_LISTEN_ADDR |
no | 0.0.0.0:50051 |
gRPC listener. |
KURANTO_LOG_LEVEL |
no | info |
Minimum log level: trace, debug, info, warn, or error. |
KURANTO_DEFAULT_JOB_IMAGE |
no | data.forgejo.org/oci/node:lts |
Used if the runner sends no image. |
KURANTO_JOB_SERVICE_ACCOUNT |
no | none | Service account assigned to generated job Pods. It should have no Kubernetes RBAC by default. |
KURANTO_JOB_NODE_SELECTOR |
no | none | JSON object mapping node label names to string values for every generated job Pod's nodeSelector. |
KURANTO_JOB_AFFINITY |
no | none | JSON object using Kubernetes' native affinity structure for every generated job Pod. Supports node affinity and Pod affinity/anti-affinity. |
KURANTO_JOB_TOLERATIONS |
no | none | JSON array of Kubernetes toleration objects for every generated job Pod. |
KURANTO_JOB_CPU_REQUEST |
no | none | CPU request for each generated primary job container, for example 250m. |
KURANTO_JOB_MEMORY_REQUEST |
no | none | Memory request for each generated primary job container, for example 512Mi. |
KURANTO_JOB_CPU_LIMIT |
no | none | CPU limit for each generated primary job container, for example 1. |
KURANTO_JOB_MEMORY_LIMIT |
no | none | Memory limit for each generated primary job container, for example 1Gi. |
KURANTO_SERVICE_CPU_REQUEST |
no | none | CPU request for each generated service container, for example 100m. |
KURANTO_SERVICE_MEMORY_REQUEST |
no | none | Memory request for each generated service container, for example 128Mi. |
KURANTO_SERVICE_CPU_LIMIT |
no | none | CPU limit for each generated service container, for example 500m. |
KURANTO_SERVICE_MEMORY_LIMIT |
no | none | Memory limit for each generated service container, for example 512Mi. |
KURANTO_POD_CPU_REQUEST |
no | none | CPU request for the generated Pod, for example 1. Requires Kubernetes 1.34 or later. |
KURANTO_POD_MEMORY_REQUEST |
no | none | Memory request for the generated Pod, for example 2Gi. Requires Kubernetes 1.34 or later. |
KURANTO_POD_CPU_LIMIT |
no | none | CPU limit for the generated Pod, for example 2. Requires Kubernetes 1.34 or later. |
KURANTO_POD_MEMORY_LIMIT |
no | none | Memory limit for the generated Pod, for example 4Gi. Requires Kubernetes 1.34 or later. |
KURANTO_MAX_ENVIRONMENT_TIMEOUT_SECONDS |
no | 10800 |
Upper bound for a job Pod's activeDeadlineSeconds. |
Resource values use Kubernetes quantity syntax. Each request and limit is optional and omitted when unset. Job settings apply to the primary job container; service settings apply to every service container. Pod settings populate Pod-level resources and require Kubernetes 1.34 or later, where PodLevelResources is enabled by default. When a pod CPU or memory limit is set, the sum of that resource's job and service container limits must not exceed it.
Set KURANTO_LOG_LEVEL=debug to enable detailed Kuranto logs.
Job scheduling #
By default, job pods are scheduled as regular pods without any particular constraints.
Using the variables described above, you can configure nodeSelector, affinity,
and tolerations. These will be set on the pods created for jobs, and will influence
how they are scheduled in the cluster.
See the Helm scheduling examples or the manual JSON configuration for more details on this.
Installation #
For a quick start with Helm, check out the getting started documentation.
For manual deployment, see these instructions.
Development #
This repository provides two main ways of provisioning a development environment:
- Nix
- Mise
Nix #
You need to have flakes enabled in your Nix installation.
If you have direnv, just run direnv allow to load everything you need to work on Kuranto.
Otherwise, just run nix develop.
Mise #
Run mise trust and mise install to get all the tools and the Rust toolchain.
Develop #
You can run unit tests using:
cargo test --lib --bins
End-to-end tests require KinD (provided by Nix or Mise), and can be run using:
./scripts/e2e.sh
- Rust 93%
- Shell 6%
- Nix <1%
- Docker <1%