Kubernetes executor

  • Tier : Free, Premium, Ultimate
  • Offering : GitLab.com, GitLab Self-Managed, GitLab Dedicated

Use the Kubernetes executor to use Kubernetes clusters for your builds. The executor calls the Kubernetes cluster API and creates a pod for each GitLab CI job.

The Kubernetes executor divides the build into multiple steps:

  1. Prepare : Create the Pod against the Kubernetes Cluster. This creates the containers required for the build and services to run.
  2. Pre-build : Clone, restore cache, and download artifacts from previous stages. This step runs on a special container as part of the pod.
  3. Build : User build.
  4. Post-build : Create cache, upload artifacts to GitLab. This step also uses the special container as part of the pod.

How the runner creates Kubernetes pods

The following diagram shows the interaction between a GitLab instance and a runner hosted on a Kubernetes cluster. The runner calls the Kubernetes API to create pods on the cluster.

The pod consists of the following containers for each service defined in the .gitlab-ci.yml or config.toml files:

  • A build container defined as build .
  • A helper container defined as helper .
  • A services containers defined as svc-X , where X is [0-9]+ .

Services and containers run in the same Kubernetes pod and share the same localhost address. The following restrictions apply:

  • The services are accessible through their DNS names. If you use an older version, you must use localhost .
  • You cannot use several services that use the same port. For example, you cannot have two mysql services at the same time.
sequenceDiagram
    participant G as GitLab instance
    participant R as Runner on Kubernetes cluster
    participant Kube as Kubernetes API
    participant P as POD
    R->>+G: Get a CI job.
        G-->R: ;
    Note over R,G: POST /api/v4/jobs/request
    G->>+R: CI job data.
    R-->>-Kube: Create a POD to run the CI job.
    Note over R,Kube: POST to Kube API
    P->>+P: Execute job.
    Note over P: CI build job = Prepare + Pre-build + Build + Post-build
    P->>+G: Job logs

The interaction in the diagram is valid for any Kubernetes cluster. For example, turnkey solutions hosted on the major public cloud providers, or self-managed Kubernetes installations.

Connect to the Kubernetes API

Use the following options to connect to the Kubernetes API. The user account provided must have permission to create, list, and attach to Pods in the specified namespace.

Option Description
host Optional Kubernetes API server host URL (auto-discovery attempted if not specified).
cert_file Optional Kubernetes API server user auth certificate.
key_file Optional Kubernetes API server user auth private key.
ca_file Optional Kubernetes API server ca certificate.

If you’re running GitLab Runner in the Kubernetes cluster, omit these fields so that the GitLab Runner auto-discovers the Kubernetes API.

If you’re running GitLab Runner externally to the Cluster, these settings ensure that GitLab Runner has access to the Kubernetes API on the cluster.

Set the bearer token for Kubernetes API calls

To set the bearer token for API calls to create pods, use the KUBERNETES_BEARER_TOKEN variable. This allows project owners to use project secret variables to specify a bearer token.

When specifying the bearer token, you must set the Host configuration setting.

variables:
  KUBERNETES_BEARER_TOKEN: thebearertokenfromanothernamespace

Configure runner API permissions

To configure permissions for the core API group, update the values.yml file for GitLab Runner Helm charts.

You can either:

  • Set rbac.create to true .
  • Specify a service account serviceAccount.name: <service_account_name> with the following permissions in the values.yml file.
Resource Verb (Optional Feature/Config Flags)
events list ( print_pod_warning_events=true ), watch ( FF_PRINT_POD_EVENTS=true )
namespaces create ( kubernetes.NamespacePerJob=true ), delete ( kubernetes.NamespacePerJob=true )
pods create, delete, get, list ( using Informers ), watch ( using Informers , FF_KUBERNETES_HONOR_ENTRYPOINT=true , FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY=false )
pods/attach create ( FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY=false ), delete ( FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY=false ), get ( FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY=false ), patch ( FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY=false )
pods/exec create, delete, get, patch
pods/log get ( FF_KUBERNETES_HONOR_ENTRYPOINT=true , FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY=false , FF_WAIT_FOR_POD_TO_BE_REACHABLE=true ), list ( FF_KUBERNETES_HONOR_ENTRYPOINT=true , FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY=false )
secrets create, delete, get, update
serviceaccounts get
services create, get

You can use the following YAML role definition to create a role with the required permissions.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: gitlab-runner
  namespace: default
rules:
- apiGroups: [""]
  resources: ["events"]
  verbs:
  - "list" # Required when `print_pod_warning_events=true`
  - "watch" # Required when `FF_PRINT_POD_EVENTS=true`
- apiGroups: [""]
  resources: ["namespaces"]
  verbs:
  - "create" # Required when `kubernetes.NamespacePerJob=true`
  - "delete" # Required when `kubernetes.NamespacePerJob=true`
- apiGroups: [""]
  resources




    
: ["pods"]
  verbs:
  - "create"
  - "delete"
  - "get"
  - "list" # Required when using Informers (https://docs.gitlab.com/runner/executors/kubernetes/#informers)
  - "watch" # Required when `FF_KUBERNETES_HONOR_ENTRYPOINT=true`, `FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY=false`, using Informers (https://docs.gitlab.com/runner/executors/kubernetes/#informers)
- apiGroups: [""]
  resources: ["pods/attach"]
  verbs:
  - "create" # Required when `FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY=false`
  - "delete" # Required when `FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY=false`
  - "get" # Required when `FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY=false`
  - "patch" # Required when `FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY=false`
- apiGroups: [""]
  resources: ["pods/exec"]
  verbs:
  - "create"
  - "delete"
  - "get"
  - "patch"
- apiGroups: [""]
  resources: ["pods/log"]
  verbs:
  - "get" # Required when `FF_KUBERNETES_HONOR_ENTRYPOINT=true`, `FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY=false`, `FF_WAIT_FOR_POD_TO_BE_REACHABLE=true`
  - "list" # Required when `FF_KUBERNETES_HONOR_ENTRYPOINT=true`, `FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY=false`
- apiGroups: [""]
  resources: ["secrets"]
  verbs:
  - "create"
  - "delete"
  - "get"
  - "update"
- apiGroups: [""]
  resources: ["serviceaccounts"]
  verbs:
  - "get"
- apiGroups: [""]
  resources: ["services"]
  verbs:
  - "create"
  - "get"

Informers

In GitLab Runner 17.9.0 and later, a Kubernetes informer tracks build pod changes. This helps the executor detect the changes more quickly.

The informer requires list and watch permissions for pods . When the executor starts the build, it checks the Kubernetes API for the permissions. If all permissions are granted, the executor uses an informer. If any permission is missing, GitLab Runner logs a warning. The build continues and uses the previous mechanism to track the build pod’s status and changes.

Configuration settings

Use the following settings in the config.toml file to configure the Kubernetes executor.

CPU requests and limits

Setting Description
cpu_limit The CPU allocation given to build containers.
cpu_limit_overwrite_max_allowed The maximum amount that the CPU allocation can be written to for build containers. When empty, it disables the CPU limit overwrite feature.
cpu_request The CPU allocation requested for build containers.
cpu_request_overwrite_max_allowed The maximum amount that the CPU allocation request can be written to for build containers. When empty, it disables the CPU request overwrite feature.
helper_cpu_limit The CPU allocation given to build helper containers.
helper_cpu_limit_overwrite_max_allowed The maximum amount that the CPU allocation can be written to for helper containers. When empty, it disables the CPU limit overwrite feature.
helper_cpu_request The CPU allocation requested for build helper containers.
helper_cpu_request_overwrite_max_allowed The maximum amount that the CPU allocation request can be written to for helper containers. When empty, it disables the CPU request overwrite feature.
service_cpu_limit The CPU allocation given to build service containers.
service_cpu_limit_overwrite_max_allowed The maximum amount that the CPU allocation can be written to for service containers. When empty, it disables the CPU limit overwrite feature.
service_cpu_request The CPU allocation requested for build service containers.
service_cpu_request_overwrite_max_allowed The maximum amount that the CPU allocation request can be written to for service containers. When empty, it disables the CPU request overwrite feature.

Memory requests and limits

Setting Description
memory_limit The amount of memory allocated to build containers.
memory_limit_overwrite_max_allowed The maximum amount that the memory allocation can be written to for build containers. When empty, it disables the memory limit overwrite feature.
memory_request The amount of memory requested from build containers.
memory_request_overwrite_max_allowed The maximum amount that the memory allocation request can be written to for build containers. When empty, it disables the memory request overwrite feature.
helper_memory_limit The amount of memory allocated to build helper containers.
helper_memory_limit_overwrite_max_allowed The maximum amount that the memory allocation can be written to for helper containers. When empty, it disables the memory limit overwrite feature.
helper_memory_request The amount of memory requested for build helper containers.
helper_memory_request_overwrite_max_allowed The maximum amount that the memory allocation request can be written to for helper containers. When empty, it disables the memory request overwrite feature.
service_memory_limit The amount of memory allocated to build service containers.
service_memory_limit_overwrite_max_allowed The maximum amount that the memory allocation can be written to for service containers. When empty, it disables the memory limit overwrite feature.
service_memory_request The amount of memory requested for build service containers.
service_memory_request_overwrite_max_allowed The maximum amount that the memory allocation request can be written to for service containers. When empty, it disables the memory request overwrite feature.

Helper container memory sizing recommendations

For optimal performance, set helper container memory limits based on your workload requirements:

  • Workloads with caching and artifact generation : Minimum 250 MiB
  • Basic workloads without cache/artifacts : Might work with lower limits (128-200 MiB)

Basic configuration example:

[[runners]]
  executor = "kubernetes"
  [runners.kubernetes]
    helper_memory_limit = "250Mi"
    helper_memory_request = "250Mi"
    helper_memory_limit_overwrite_max_allowed = "1Gi"

Job-specific memory overrides:

Use the KUBERNETES_HELPER_MEMORY_LIMIT variable to adjust memory for specific jobs without requiring administrator changes:

job_with_higher_helper_memory_limit:
  variables:
    KUBERNETES_HELPER_MEMORY_LIMIT: "512Mi"
  script:

This approach allows developers to optimize resource usage per job while maintaining cluster-wide limits through helper_memory_limit_overwrite_max_allowed .

Storage requests and limits

Setting Description
ephemeral_storage_limit The ephemeral storage limit for build containers.
ephemeral_storage_limit_overwrite_max_allowed The maximum amount that the ephemeral storage limit for build containers can be overwritten. When empty, it disables the ephemeral storage limit overwrite feature.
ephemeral_storage_request The ephemeral storage request given to build containers.
ephemeral_storage_request_overwrite_max_allowed The maximum amount that the ephemeral storage request can be overwritten by for build containers. When empty, it disables the ephemeral storage request overwrite feature.
helper_ephemeral_storage_limit The ephemeral storage limit given to helper containers.
helper_ephemeral_storage_limit_overwrite_max_allowed The maximum amount that the ephemeral storage limit can be overwritten by for helper containers. When empty, it disables the ephemeral storage request overwrite feature.
helper_ephemeral_storage_request The ephemeral storage request given to helper containers.
helper_ephemeral_storage_request_overwrite_max_allowed The maximum amount that the ephemeral storage request can be overwritten by for helper containers. When empty, it disables the ephemeral storage request overwrite feature.
service_ephemeral_storage_limit The ephemeral storage limit given to service containers.
service_ephemeral_storage_limit_overwrite_max_allowed The maximum amount that the ephemeral storage limit can be overwritten by for service containers. When empty, it disables the ephemeral storage request overwrite feature.
service_ephemeral_storage_request The ephemeral storage request given to service containers.
service_ephemeral_storage_request_overwrite_max_allowed The maximum amount that the ephemeral storage request can be overwritten by for service containers. When empty, it disables the ephemeral storage request overwrite feature.

Other config.toml settings

Setting Description
affinity Specify affinity rules that determine which node runs the build. Read more about using affinity .
allow_privilege_escalation Run all containers with the allowPrivilegeEscalation flag enabled. When empty, it does not define the allowPrivilegeEscalation flag in the container SecurityContext and allows Kubernetes to use the default privilege escalation behavior.
allowed_images Wildcard list of images that can be specified in .gitlab-ci.yml . If not present all images are allowed (equivalent to ["*/*:*"] ). View details .
allowed_pull_policies List of pull policies that can be specified in the .gitlab-ci.yml file or the config.toml file.
allowed_services Wildcard list of services that can be specified in .gitlab-ci.yml . If not present all images are allowed (equivalent to ["*/*:*"] ). View details .
automount_service_account_token Boolean to control whether the service account token automatically mounts in the build pod.
bearer_token Default bearer token used to launch build pods.
bearer_token_overwrite_allowed Boolean to allow projects to specify a bearer token used to create the build pod.
build_container_security_context Sets a container security context for the build container. Read more about security context .
cap_add Specify Linux capabilities that should be added to the job pod containers. Read more about capabilities configuration in Kubernetes executor .
cap_drop Specify Linux capabilities that should be dropped from the job pod containers. Read more about capabilities configuration in Kubernetes executor .
cleanup_grace_period_seconds When a job completes, the duration in seconds that the pod has to terminate gracefully. After this period, the processes are forcibly halted with a kill signal. Ignored if terminationGracePeriodSeconds is specified.
dns_policy Specify the DNS policy that should be used when constructing the pod: none , default , cluster-first , cluster-first-with-host-net . The Kubernetes default ( cluster-first ) is used if not set.
dns_config Specify the DNS configuration that should be used when constructing the pod. Read more about using pod’s DNS config .
helper_container_security_context Sets a container security context for the helper container. Read more about security context .
helper_image (Advanced) Override the default helper image used to clone repositories and upload artifacts.
helper_image_flavor Sets the helper image flavor ( alpine , alpine3.18 , alpine3.19 , alpine3.21 , or ubuntu ). Defaults to alpine . Using alpine is the same as alpine3.19 .
host_aliases List of additional host name aliases that are added to all containers. Read more about using extra host aliases .
image_pull_secrets An array of items containing the Kubernetes docker-registry secret names used to authenticate Docker image pulling from private registries.
init_permissions_container_security_context Sets a container security context for the init-permissions container. Read more about security context .
namespace Namespace in which to run Kubernetes Pods.
namespace_per_job Isolate jobs in separate namespaces. If enabled, namespace and namespace_overwrite_allowed are ignored.
namespace_overwrite_allowed Regular expression to validate the contents of the namespace overwrite environment variable (documented below). When empty, it disables the namespace overwrite feature.
node_selector A table of key=value pairs in the format of string=string ( string:string in the case of environment variables). Setting this limits the creation of pods to Kubernetes nodes matching all the key=value pairs. Read more about using node selectors .
node_tolerations A table of "key=value" = "Effect" pairs in the format of string=string:string . Setting this allows pods to schedule to nodes with all or a subset of tolerated taints. Only one toleration can be supplied through environment variable configuration. The key , value , and effect match with the corresponding field names in Kubernetes pod toleration configuration.
pod_annotations A table of key=value pairs in the format of string=string . The table contains a list of annotations to be added to each build pod created by the runner. The value of these can include environment variables for expansion. Pod annotations can be overwritten in each build.
pod_annotations_overwrite_allowed Regular expression to validate the contents of the pod annotations overwrite environment variable. When empty, it disables the pod annotations overwrite feature.
pod_labels A table of key=value pairs in the format of string=string . The table contains a list of labels to be added to each build pod created by the runner. The value of these can include environment variables for expansion. Pod labels can be overwritten in each build by using pod_labels_overwrite_allowed .
pod_labels_overwrite_allowed Regular expression to validate the contents of the pod labels overwrite environment variable. When empty, it disables the pod labels overwrite feature. Note that pod labels in the runner.gitlab.com label namespace cannot be overwritten.
pod_security_context Configured through the configuration file, this sets a pod security context for the build pod. Read more about security context .
pod_termination_grace_period_seconds Pod-level setting which determines the duration in seconds which the pod has to terminate gracefully. After this, the processes are forcibly halted with a kill signal. Ignored if terminationGracePeriodSeconds is specified.
poll_interval How frequently, in seconds, the runner polls the Kubernetes pod it has just created to check its status (default = 3).
poll_timeout The amount of time, in seconds, that needs to pass before the runner times out attempting to connect to the container it has just created. Use this setting for queueing more builds than the cluster can handle at a time (default = 180).
cleanup_resources_timeout The total amount of time for Kubernetes resources to be cleaned up after the job completes. Supported syntax: 1h30m , 300s , 10m . Default is 5 minutes ( 5m ).
priority_class_name Specify the Priority Class to be set to the pod. The default one is used if not set.
privileged Run containers with the privileged flag.
pull_policy Specify the image pull policy: never , if-not-present , always . If not set, the cluster’s image default pull policy is used. For more information and instructions on how to set multiple pull policies, see using pull policies . See also if-not-present , never security considerations . You can also restrict pull policies .
resource_availability_check_max_attempts The maximum number of attempts to check if a resource (service account and/or pull secret) set is available before giving up. There is 5 seconds interval between each attempt. Introduced in GitLab 15.0. Read more about resources check during prepare step .
runtime_class_name A Runtime class to use for all created pods. If the feature is unsupported by the cluster, jobs exit or fail.
service_container_security_context Sets a container security context for the service containers. Read more about security context .
scheduler_name Scheduler to use for scheduling build pods.
service_account Default service account job/executor pods use to talk to Kubernetes API.
service_account_overwrite_allowed Regular expression to validate the contents of the service account overwrite environment variable. When empty, it disables the service account overwrite feature.
services List of services attached to the build container using the sidecar pattern . Read more about using services .
use_service_account_image_pull_secrets When enabled, the pod created by the executor lacks imagePullSecrets . This causes the pod to be created using the imagePullSecrets from the service account , if set.
terminationGracePeriodSeconds Duration after the processes running in the pod are sent a termination signal and the time when the processes are forcibly halted with a kill signal. Deprecated in favour of cleanup_grace_period_seconds and pod_termination_grace_period_seconds .
volumes Configured through the configuration file, the list of volumes that is mounted in the build container. Read more about using volumes .
pod_spec This setting is an experiment. Overwrites the pod specification generated by the runner manager with a list of configurations set on the pod used to run the CI Job. All the properties listed Kubernetes Pod Specification can be set. For more information, see Overwrite generated pod specifications (experiment) .
retry_limit The maximum number of attempts to communicate with Kubernetes API. The retry interval between each attempt is based on a backoff algorithm starting at 500 ms.
retry_backoff_max Custom maximum backoff value in milliseconds for the retry interval to reach for each attempt. The default value is 2000 ms and it can not be lower than 500 ms. The default maximum retry interval to reach for each attempt is 2 seconds and can be customized with retry_backoff_max .
retry_limits How many times each request error is to be retried.
logs_base_dir Base directory to be prepended to the generated path to store build logs. For more information, see Change the base directory for build logs and scripts .
scripts_base_dir Base directory to be prepended to the generated path to store build scripts. For more information, see Change the base directory for build logs and scripts .
print_pod_warning_events When enabled, this feature retrieves all warning events associated with the pod when jobs fail. This functionality is enabled by default and requires a service account with at least events: list permissions .

Configuration example

The following sample shows an example configuration of the config.toml file for the Kubernetes executor.

concurrent = 4
[[runners]]
  name = "myRunner"
  url = "https://gitlab.com/ci"
  token = "......"
  executor = "kubernetes"
  [runners.kubernetes]
    host = "https://45.67.34.123:4892"
    cert_file = "/etc/ssl/kubernetes/api.crt"
    key_file = "/etc/ssl/kubernetes/api.key"
    ca_file = "/etc/ssl/kubernetes/ca.crt"
    namespace = "gitlab"
    namespace_overwrite_allowed = "ci-.*"
    bearer_token_overwrite_allowed = true
    privileged = true
    cpu_limit = "1"
    memory_limit = "1Gi"
    service_cpu_limit = "1"
    service_memory_limit = "1Gi"
    helper_cpu_limit = "500m"
    helper_memory_limit = "100Mi"
    poll_interval = 5
    poll_timeout = 3600
    dns_policy = "cluster-first"
    priority_class_name = "priority-1"
    logs_base_dir = "/tmp"
    scripts_base_dir = "/tmp"
    [runners.kubernetes.node_selector]
      gitlab = "true"
    [runners.kubernetes.node_tolerations]
      "node-role.kubernetes.io/master" = "NoSchedule"
      "custom.toleration=value" = "NoSchedule"
      "empty.value=" = "PreferNoSchedule"
      "onlyKey" = ""

Configure the executor service account

To configure the executor service account, you can set the KUBERNETES_SERVICE_ACCOUNT environment variable or use the --kubernetes-service-account flag.

Pods and containers

You can configure pods and containers to control how jobs are executed.

Default labels for job pods

You cannot override these labels through runner configuration or .gitlab-ci.yml files. Any attempts to set or modify labels in the runner.gitlab.com namespace are ignored and logged as debug messages.

Key Description
project.runner.gitlab.com/id The ID of the project, unique across projects in the GitLab instance.
project.runner.gitlab.com/name The name of the project.
project.runner.gitlab.com/namespace-id The ID of the project’s namespace.
project.runner.gitlab.com/namespace The name of the project’s namespace.
project.runner.gitlab.com/root-namespace The ID of the project’s root namespace. For example, /gitlab-org/group-a/subgroup-a/project , where the root namespace is gitlab-org
manager.runner.gitlab.com/name The name of the runner configuration that launched this job.
manager.runner.gitlab.com/id-short The ID of the runner configuration that launched the job.
job.runner.gitlab.com/pod Internal label used by the Kubernetes executor.

Default annotations for job pods

History