UNC Campus Git: Gitlab Runner in Openshift Platform

This article describes how to install and configure Gitlab Runner in OpenShift Platform.

 

 

In This Article: 

This process to install and configure Gitlab Runner in OpenShift Platform involves the following steps, which must be performed in order. Use the links below to jump to a specific step.

 

Instructions

 

Step 1: Get access to OpenShift Cloudapps Platform

 

Step 2: Create service account, roles, and role-bindings

oc login -u <onyen> https://api.cloudapps.unc.edu:6443

oc project <gitlab-runner-project-name>

oc create serviceaccount <gitlab-runner-sa> -n <gitlab-runner-project-name>

vi gitlab-runner-rbac.yml  # Use the below yaml with updated names and namespace

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: gitlab-runner-role
  namespace:  <gitlab-runner-project-name>
rules:
- apiGroups: [""]
  resources: ["pods", "pods/exec", "pods/log", "pods/attach", "secrets", "events"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: gitlab-runner-binding
  namespace:  <gitlab-runner-project-name>
subjects:
- kind: ServiceAccount
  name: gitlab-runner-sa
  namespace: <gitlab-runner-project-name>
roleRef:
  kind: Role
  name: gitlab-runner-role
  apiGroup: rbac.authorization.k8s.io

oc apply -f gitlab-runner-rbac.yml

 

Step 3: Create ImageStream

To download the Docker Image in Openshift, create an ImageStream. For the list of available version tags, see GitLab Runner tags. You don't need a BuildConfig for this. You can directly create an ImageStream that imports the image from Docker Hub.

 

Using the command line (oc)

oc import-image gitlab-runner-docker:latest --from=docker.io/gitlab/gitlab-runner:bleeding--confirm -n <gitlab-runner-project-name>

 

Using a YAML definition (imagestream-import.yaml)

Either update in UI(Administrator>Builds>Imagestream>Create ImageStream)

OR

oc apply -f imagestream-import.yaml

apiVersion: image.openshift.io/v1
kind: ImageStream
metadata:
  name: gitlab-runner-docker-hub
  namespace: <gitlab-runner-project-name>
spec:
  tags:
    - name: latest
      from:
        kind: DockerImage
        name: 'docker.io/gitlab/gitlab-runner:bleeding'
      importPolicy:
        scheduled: true
      referencePolicy:
        type: Local

 

Step 4: Get the runner and token info

Get your token info from GitLab

  • Go to your GitLab instance at https://sc.unc.edu
  • Navigate to SettingsCI/CDRunners
  • Find or create a runner and copy the token

 

Step 5: Create ConfigMap

The Advanced Configuration stores the config.toml configuration file for registering runner.

In your OpenShift project:

  • Go to WorkloadsConfigMaps
  • Create ConfigMap
  • Replace the token line with: token = "your-actual-token-here" (sample config.toml below)
  • Click Save

 

Sample config.toml

concurrent = 4
check_interval = 0
log_level = "info"
listen_address = ":9252"  # Optional: for metrics
[session_server]
   session_timeout = 1800
[[runners]]
  name = "ocp-test-runner"  # Use the runner name created in Gitlab
  url = "https://sc.unc.edu" 
  token = "<redacted>"  # Use the token generated in Gitlab
  executor = "kubernetes"
  request_concurrency = 4
  environment = ["FF_USE_ADAPTIVE_REQUEST_CONCURRENCY=true"]  # Auto-adjust concurrency
  [runners.kubernetes]
        namespace = "<openshift_name_space>"
        image = "docker.io/gitlab/gitlab-runner-helper:x86_64-bleeding"
        # CORRECTED helper image tag (no extra hyphen)
        helper_image = "gitlab/gitlab-runner-helper:x86_64-bleeding"
        service_account = <gitlab-runner-sa>
        privileged = false
        pull_policy = "if-not-present"
           [runners.kubernetes.volumes]
             [[runners.kubernetes.volumes.empty_dir]]
               name = "runner-home"
               mount_path = "/home/gitlab-runner"
               medium = "Memory"
            # THIS FIXES THE GIT PERMISSION ISSUE
             [[runners.kubernetes.env]]
               name = "HOME"
               value = "/tmp"
             # Also set a writable GIT_CONFIG path
             [[runners.kubernetes.env]]
               name = "GIT_CONFIG"
               value = "/tmp/.gitconfig"
              # Method 1: Using env_variables (preferred)
             [[runners.kubernetes.env_variables]]
               name = "HOME"
               value = "/tmp"
             [[runners.kubernetes.env_variables]]
               name = "GIT_CONFIG"
               value = "/tmp/.gitconfig"

 

Step 6: Create deployment 

Your deployment will need writable home directory, so add volumes and add ConfigMap so the gitlab-runner will register. That should get the pod up and running. deployment.yml should look something like this:

kind: Deployment
apiVersion: apps/v1
metadata:
  name: gitlab-runner-docker-hub
  namespace: <openshiftnamespace>
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gitlab-runner-docker-hub
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: gitlab-runner-docker-hub
    spec:
      restartPolicy: Always
      serviceAccountName: <gitlab-runner-sa>
      schedulerName: default-scheduler
      terminationGracePeriodSeconds: 30
      securityContext: {}
      containers:
        - resources:
            limits:
              cpu: 200m
              memory: 256Mi
            requests:
              cpu: 100m
              memory: 128Mi
          terminationMessagePath: /dev/termination-log
          name: container
          command:
            - /bin/sh
          env:
            - name: CI_SERVER_URL
              value: 'https://sc.unc.edu'
            - name: CI_SERVER_TOKEN
              valueFrom:
                secretKeyRef:
                  name: pc-docker-test-runner-secret
                  key: CI_SERVER_TOKEN
            - name: HOME
              value: /tmp/runner-home
          securityContext:
            capabilities:
              drop:
                - ALL
            allowPrivilegeEscalation: false
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: runner-home
              mountPath: /tmp/runner-home
            - name: config
              mountPath: /tmp/runner-home/.gitlab-runner
          terminationMessagePolicy: File
          image: 'image-registry.openshift-image-registry.svc:5000/<namespace>/gitlab-runner-docker-hub@sha256:c4209fddcacdd77d8d228aea57f91486d059f6952befaf266e30d22a487407e5'
          args:
            - '-c'
            - |
              echo "Using config from ConfigMap at /tmp/runner-home/.gitlab-runner/config.toml"
              echo "Starting runner..."
              exec gitlab-runner run --user=gitlab-runner --working-directory=/tmp/runner-home
      serviceAccount: pc-gitlab-runner-sa
      volumes:
        - name: runner-home
          emptyDir: {}
        - name: config
          configMap:
            name: pc-test-gitlab-runner-config #configmap name
            defaultMode: 420
      dnsPolicy: ClusterFirst
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 25%
      maxSurge: 25%
  revisionHistoryLimit: 10
  progressDeadlineSeconds: 600

Restart the deployment

  • Go to WorkloadsDeployments
  • Click gitlab-runner-docker-hub
  • Click ActionsRestart Rollout

 

Verify the logs for the running pods

 

OR via CLI

oc logs -f deployment/gitlab-runner-docker-hub -n <projectname>

At this point, the status of the runner in Gitlab UI should be online

 

Step 7: Create pipeline

Create .gitlab-ci.yml file in your Gitlab project’s repository and can be updated by going to Build > PipelineEditor.

Here is an working example of CI file

variables:
  HOME: "/tmp"
  
before_script:
- echo "===== PREPARING ENVIRONMENT ====="
- echo "===== INSTALLING GIT ====="
- git version
- echo "===== CONFIGURING GIT ====="
- git config --global --add safe.directory "$CI_PROJECT_DIR"
- git config --global user.email "runner@example.com"
- git config --global user.name "GitLab Runner"
- echo "===== DEBUG INFO ====="
- whoami
- id
- pwd
- ls -la
- echo "HOME=$HOME"
- echo "CI_PROJECT_DIR=$CI_PROJECT_DIR"
- echo "===== READY ====="
test-job:
  script:
  - echo "Running test job..."
  - echo "System info:- $(uname -a)"
  - echo "Current directory:- $(pwd)"
  - echo "Git status:"
  - git status
  - echo "Creating a test file"
  - echo "Test content $(date)" > test-file.txt
  - echo "Adding file to git"
  - git add test-file.txt
  - echo "Committing file"
  - git commit -m "Add test file from CI job [skip ci]"
  - echo "Git log:"
  - git log --oneline -1
  - echo "All tests passed successfully!"
  
after_script:
  - echo "Job completed with exit code:- $?"

 

Step 8: Run pipeline

  • Trigger the pipeline or run it manually or rerun existing job.
  • You can view the status of the pipeline from Build > Jobs

  • Click on the job to see the pipeline output
Running with gitlab-runner 18.10.0~pre.781.gae674a65 (ae674a65)
  on ocp-test-runner QtDNHcjuV, system ID: r_xxxxxx
Preparing the "kubernetes" executor 00:00
Using default image
Using Kubernetes namespace: <openshit-namespace>
Using Kubernetes executor with image docker.io/gitlab/gitlab-runner-helper:x86_64-bleeding ...
Using attach strategy to execute scripts...
Using effective pull policy of [IfNotPresent] for container build
Using effective pull policy of [IfNotPresent] for container helper
Using effective pull policy of [IfNotPresent] for container init-permissions
Preparing environment 00:14
Using FF_USE_POD_ACTIVE_DEADLINE_SECONDS, the Pod activeDeadlineSeconds will be set to the job timeout: 1h0m0s...
Waiting for pod <namespace>/runner-qtdnhcjuv-project-5051-concurrent-0-ur08v3s9 to be running, status is Pending
Running on runner-qtdnhcjuv-project-5051-concurrent-0-ur08v3s9 via gitlab-runner-docker-hub-7f7d5d4f78-zgsbc...
Getting source from Git repository 00:01
Gitaly correlation ID: 01KKX5V5HMW266V2P3BT5S45T4
Fetching changes with git depth set to 20...
Initialized empty Git repository in /builds/<namespace>/ocp-testapp/.git/
Created fresh repository.
Checking out f57fb498 as detached HEAD (ref is main)...
Skipping Git submodules setup
Executing "step_script" stage of the job script 00:01
$ echo "===== PREPARING ENVIRONMENT ====="
===== PREPARING ENVIRONMENT =====
$ echo "===== INSTALLING GIT ====="
===== INSTALLING GIT =====
$ git version
git version 2.47.3
$ echo "===== CONFIGURING GIT ====="
===== CONFIGURING GIT =====
$ git config --global --add safe.directory "$CI_PROJECT_DIR"
$ git config --global user.email "runner@example.com"
$ git config --global user.name "GitLab Runner"
$ echo "===== DEBUG INFO ====="
===== DEBUG INFO =====
$ whoami
1014910000
$ id
uid=1014910000(1014910000) gid=0(root) groups=0(root),1014910000
$ pwd
/builds/<namespace>ocp-testapp
$ ls -la
total 16
drwxrwsrwx 3 1014910000 1014910000   74 Mar 17 05:56 .
drwxrwsrwx 4 1014910000 1014910000   48 Mar 17 05:56 ..
drwxrwsrwx 6 1014910000 1014910000  113 Mar 17 05:56 .git
-rw-rw-rw- 1 1014910000 1014910000 2329 Mar 17 05:56 .gitlab-ci.yml
-rw-rw-rw- 1 1014910000 1014910000 6175 Mar 17 05:56 README.md
-rw-rw-rw- 1 1014910000 1014910000  137 Mar 17 05:56 index.php
$ echo "HOME=$HOME"
HOME=/tmp
$ echo "CI_PROJECT_DIR=$CI_PROJECT_DIR"
CI_PROJECT_DIR=/builds/<namespace>/ocp-testapp
$ echo "===== READY ====="
===== READY =====
$ echo "Running test job..."
Running test job...
$ echo "System info:- $(uname -a)"
System info:- Linux runner-qtdnhcjuv-project-5051-concurrent-0-ur08v3s9 5.14.0-427.109.1.el9_4.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Jan 28 17:07:26 EST 2026 x86_64 GNU/Linux
$ echo "Current directory:- $(pwd)"
Current directory:- /builds/<namespace>/ocp-testapp
$ echo "Git status:"
Git status:
$ git status
HEAD detached at f57fb49
nothing to commit, working tree clean
$ echo "Creating a test file"
Creating a test file
$ echo "Test content $(date)" > test-file.txt
$ echo "Adding file to git"
Adding file to git
$ git add test-file.txt
$ echo "Committing file"
Committing file
$ git commit -m "Add test file from CI job [skip ci]"
[detached HEAD d535b50] Add test file from CI job [skip ci]
 1 file changed, 1 insertion(+)
 create mode 100644 test-file.txt
$ echo "Git log:"
Git log:
$ git log --oneline -1
d535b50 Add test file from CI job [skip ci]
$ echo "All tests passed successfully!"
All tests passed successfully!
Running after_script 00:01
Running after script...
$ echo "Job completed with exit code:- $?"
Job completed with exit code:- 0
Cleaning up project directory and file based variables 00:00
Job succeeded