Photo by Josue Isai Ramos Figueroa on Unsplash

Kubernetes executor on GitLab (not a GitLab managed cluster)

Some of us that work with Gitlab, regardless on where we work or the role you thrive in (development, sysadmins, etc.), benefit hugely from GitLab’s ability to streamline and automate a deployment process.

Whether it’s a process that deploys an application or some tedious time-consuming process that sysadmins have to perform, can be automated.

Unfortunately not everyone or every company can afford to use the enterprise version of Gitlab. This is especially the case for Gitlab instances that run on homelabs.

Usually this doesn’t affect the functionality of the platform, however Gitlab has a really awesome toolset that allows it to manage a kubernetes’ deployment that’s included with the enterprise version.

We can work around this with the use of a Gitlab Kubernetes executor.

Enter the Kubernetes Executor

The Kubernetes executor is basically what it’s name states, it’s pod that’s deployed on a kubernetes namespace that can run processes.

What kind of processes? Anything that can be done with any other executor can be done by this executor.

Once deployed it’s a pretty hands-off experience. If you need to update it, you can update it with no downtime and the main benefit it has is that, since it’s not run on a specific VM or HW you don’t have another machine to add to your infrastructure and maintain. This last one can become overwhelming after a while (100 machines is easy to maintain, try 4000).


This kind of executor needs some stuff to work:

  • A GitLab Instance
  • A Kubernetes instance, doesn’t matter which type, it can be a full fledged k8s cluster, OpenShift cluster or even k3s.
  • A namespace on the kubernetes cluster.
  • Access to create secrets on the namespace.
  • kubectl and helm3

That’s basically all you need to do this.


Kubernetes’ side


You’re going to need a namespace to install the executor, in this case we’re going with gitlab-executor (make sure you can access the kubernetes instance from your machine):

kubectl create namespace gitlab-executor
GitLab registration Token

The registration token can be acquired from your GitLab instance, either from a full instance perspective, a GitLab-wide admin.

Or you can just define it for a project group or a single project.

The steps are pretty much the same.

For a project:

Go on the project settings -> CI/CD -> Runners -> Expand

And you’ll see the registration token.

Helm Chart

Once the namespace is created you need to set up Helm, start by adding the GitLab repo:

helm repo add gitlab

Then update the repo:

helm repo update

Afterwards, you need a values.yaml file, which can be found here. From that file you’re going to need to focus on the following entries (to begin with):

runnerRegistrationToken: "XXXXXXXXXXXXXXXXX"
  image: ubuntu:16.04
  privileged: true

There’s a lot more entries on that file, you can decide which ones do you need, right now we’re focusing on the gitlabUrl, the registration token and whether the container is going to run on privileged mode (yes, this can run DockerInDocker).

Save the values.yaml on your local machine and then run the following command:

helm install gitlab-runner -f values.yaml -n gitlab-executor gitlab/gitlab-runner

Make sure you have the proper permissions to deploy an application on that namespace (although, if you’ve already created the namespace you should already have those.)

GitLab’s side

There’s not much to do on GitLab’s side, just wait until the runner is registered and you can use it.

Testing our shiny new runner

We’re going to perform an easy test,just a hello world to check that the runner runs a task.

For this you need a repo with the following files:


Yes, just one.

Within that gitlab-ci.yml file you need the following contents (we’re borrowing from the official GitLab wiki, the main article is here:

  stage: build
    - echo "Hello, $GITLAB_USER_LOGIN!"

  stage: test
    - echo "This job tests something"

  stage: test
    - echo "This job tests something, but takes more time than test-job1."
    - echo "After the echo commands complete, it runs the sleep command for 20 seconds"
    - echo "which simulates a test that runs 20 seconds longer than test-job1"
    - sleep 20

  stage: deploy
    - echo "This job deploys something from the $CI_COMMIT_BRANCH branch."

After you commit and push the file to your project repo, the pipeline should run automatically and show the echo results.