Runner controllers

  • Tier: Ultimate
  • Offering: GitLab Self-Managed, GitLab Dedicated
  • Status: Experiment

The availability of this feature is controlled by a feature flag. For more information, see the history. This feature is available for testing, but not ready for production use.

Runner controllers enable admission control for CI/CD jobs routed through the job router. When a job is about to be executed, the job router sends an admission request to connected runner controllers, which can admit or reject the job based on custom policies.

Runner controllers are on the instance-level and are applicable to jobs depending on their scoping.

Use runner controllers to:

  • Enforce custom admission policies like image allowlists, resource quotas, or security requirements.
  • Control job queuing and resource allocation for capacity management.
  • Ensure jobs meet organizational policies before execution for compliance enforcement.
  • Limit job execution based on budget or resource constraints for cost control.

Admission control workflow

When you configure runner controllers with the job router, the admission control workflow operates as follows:

  1. A runner controller connects to the job router.
  2. The controller registers itself and starts handling admission requests.
  3. When a job needs admission, the job router sends job details to connected controllers.
  4. The controller evaluates the job against custom policies.
  5. The controller sends an admission decision (admit or reject with reason).
  6. The job router proceeds with job execution or reports the rejection.

View rejection reasons

When a runner controller rejects a job, the job fails with the job_router_failure failure reason. The job details page displays a message that includes:

  • Job router information
  • Runner controller information
  • The rejection reason provided by the runner controller

Job rejection message showing runner controller rejection reason

Dry run mode logging

When a runner controller is in dry_run state, rejection decisions are not enforced but are logged as informational messages in the job router (KAS) backend logs. Use these logs to validate your controller’s behavior before you enable enforcement.

Runner controller states

Runner controllers can be in one of three states:

StateDescription
disabledThe runner controller does not receive admission requests. This is the default state.
enabledThe runner controller receives admission requests and its decisions affect job execution.
dry_runThe runner controller receives admission requests. Job router logs the decisions, but decisions are not enforced. Use this state for strategic rollouts to validate controller behavior and de-risk deployments before you enable enforcement.

Scoping

Runner controllers must be scoped to be active. A runner controller without any scope does not receive admission requests, even when its state is enabled or dry_run.

Runner controllers support two mutually exclusive scoping types:

ScopeDescription
InstanceThe runner controller evaluates jobs for all runners in the GitLab instance. This scope cannot be combined with runner scope.
RunnerThe runner controller evaluates jobs only for specific runners. You can scope a controller to one or more runners. The runner must be an instance runner.

Additional scope types (group, project) are proposed in issue 586419.

To manage runner controller scoping, see the runner controllers API.

Manage runner controllers

Runner controllers are managed through the REST API. There is no UI for managing runner controllers yet.

Prerequisites:

  • You must have administrator access to the GitLab instance.

Implement a runner controller

For a step-by-step guide, see Tutorial: Build a runner admission controller.

To implement your own runner controller, you need to:

  1. Create a runner controller in GitLab.
  2. Scope the runner controller.
  3. Obtain a runner controller token.
  4. Connect to the job router with the token.
  5. Register your controller with the job router.
  6. Handle admission requests and send decisions.

For technical specifications and protobuf definitions, see the runner controller documentation in the GitLab Agent for Kubernetes repository.