[Infrastructure as Code (IaC) Pulumi] Use Pulumi kubernetes (K8S) Helm Chart to deploy GitLabRunner

GitLab Runner

GitLab Runner is an application that works with GitLab CI/CD to run jobs in a pipeline.

This article is about how to use Pulumi, kubernetes (K8S) provider, Helm Chart and TypeScript SDK to deploy GitLab Runner within Kubernetes (K8S).

Prerequisites

Usage

Pulumi New

Create the workspace directory.

1
2
3
$ mkdir -p col-example-pulumi-typescript-gitlab-runner

$ cd col-example-pulumi-typescript-gitlab-runner

Pulumi login into local file system.

1
2
3
$ pulumi login file://.
Logged in to cloudolife as cloudolife (file://.)
or visit https://pulumi.com/docs/reference/install/ for manual instructions and release notes.

Pulumi new a project with kubernetes-typescript SDK.

1
$ pulumi new kubernetes-typescript

The above command will create some files within the current directory.

1
2
3
4
5
6
7
8
tree . -L 1
.
├── node_modules/
├── package.json
├── package.json.lock
├── Pulumi.dev.yaml
├── Pulumi.yaml
└── main.ts

Install js-yaml package to load and parse yaml file.

1
$ npm i js-yaml

Pulumi Configuration

Configure Kubernetes

By default, Pulumi will look for a kubeconfig file in the following locations, just like kubectl:

  • The environment variable: $KUBECONFIG,

  • Or in current user’s default kubeconfig directory: ~/.kube/config

If the kubeconfig file is not in either of these locations, Pulumi will not find it, and it will fail to authenticate against the cluster. Set one of these locations to a valid kubeconfig file, if you have not done so already.

Configure Values.yaml

Edit values.yaml and replace content within {{ }}.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# values.yaml · master · GitLab.org / charts / GitLab Runner · GitLab
# https://gitlab.com/gitlab-org/charts/gitlab-runner/-/blob/main/values.yaml

## The GitLab Server URL (with protocol) that want to register the runner against
## ref: https://docs.gitlab.com/runner/commands/README.html#gitlab-runner-register
##
gitlabUrl: {{ .Values.gitlabUrl }}

## The registration token for adding new Runners to the GitLab server. This must
## be retrieved from your GitLab instance.
## ref: https://docs.gitlab.com/ee/ci/runners/
##
runnerRegistrationToken: {{ .Values.runnerRegistrationToken }}

## For RBAC support:
rbac:
create: true

## Run the gitlab-bastion container with the ability to deploy/manage containers of jobs
## cluster-wide or only within namespace
clusterWideAccess: true

## Use the following Kubernetes Service Account name if RBAC is disabled in this Helm chart (see rbac.create)
##
serviceAccountName: gitlab-runner-gitlab-runner

rules:
- apiGroups: [""] #"" indicates the core API group
resources: ["*"]
verbs: ["*"]
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["*"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["*"]

## Configuration for the Pods that the runner launches for each new job
##
runners:
# runner configuration, where the multi line strings is evaluated as
# template so you can specify helm values inside of it.
#
# tpl: https://helm.sh/docs/howto/charts_tips_and_tricks/#using-the-tpl-function
# runner configuration: https://docs.gitlab.com/runner/configuration/advanced-configuration.html
config: |
[[runners]]
[runners.kubernetes]
namespace = "{{.Release.Namespace}}"

## Specify the name for the runner.
##
name = "{{ .Values.runer.name }}"

# Specify whether the runner should be locked to a specific project: true, false. Defaults to true.
#
locked: false

# Specify the tags associated with the runner. Comma-separated list of tags.
#
# ref: https://docs.gitlab.com/ce/ci/runners/#use-tags-to-limit-the-number-of-jobs-using-the-runner
#
tags: ""

# Specify the name for the runner.
#
name: {{ .Values.runer.name }}

# Specify if jobs without tags should be run.
# If not specified, Runner will default to true if no tags were specified. In other case it will
# default to false.
#
# ref: https://docs.gitlab.com/ce/ci/runners/#runner-is-allowed-to-run-untagged-jobs
#
runUntagged: false

# Specify whether the runner should only run protected branches.
# Defaults to False.
#
# ref: https://docs.gitlab.com/ee/ci/runners/#prevent-runners-from-revealing-sensitive-information
#
protected: false

# Service Account to be used for runners
#
serviceAccountName: gitlab-runner-gitlab-runner

See and modify main.ts file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// main.ts

import * as pulumi from "@pulumi/pulumi";

import * as k8s from "@pulumi/kubernetes";

const yaml = require('js-yaml');
const fs = require('fs');

const nameGitLabRunner = "gitlab-runner"

// kubernetes.core/v1.Namespace | Pulumi
// https://www.pulumi.com/docs/reference/pkg/kubernetes/core/v1/namespace/
const namespaceGitLabRunner = new k8s.core.v1.Namespace(nameGitLabRunner, {
metadata: {
name: nameGitLabRunner,
},
})

const values = yaml.safeLoad(fs.readFileSync("./values.yaml", 'utf8'))

const charNameGitLabRunner = "gitlab-runner"

// kubernetes.helm.sh/v3.Chart | Pulumi
// https://www.pulumi.com/docs/reference/pkg/kubernetes/helm/v3/chart/

// GitLab Runner Helm Chart | GitLab
// https://docs.gitlab.com/runner/install/kubernetes.html
const charGitLabRunner = new k8s.helm.v3.Chart(charNameGitLabRunner, {
chart: charNameGitLabRunner,
version: "0.33.1",
fetchOpts:{
repo: "https://charts.gitlab.io",
},
namespace: namespaceGitLabRunner.metadata.name,
values: values,
});

Pulumi Up

Run pulumi up to create the namespace and pods.

1
$ pulumi up

See pods about gitlab-runner.

1
2
3
$ kubectl get pods -n gitlab-runner
NAME READY STATUS RESTARTS AGE
gitlab-runner-gitlab-runner-864d89d666-9h8fq 1/1 Running 0 43h

Pulumi Destroy

Destroy all resources created by Pulumi.

1
$ pulumi destroy

FAQs

“system:serviceaccount:gitlab-runner:default” cannot get resource “deployments” in API group “apps” in the namespace “gitlab-runner”

1
2
3
4
Error from server (Forbidden): error when retrieving current configuration of:
Resource: "apps/v1, Resource=deployments", GroupVersionKind: "apps/v1, Kind=Deployment"
Name: "nginx-deployment", Namespace: "gitlab-runner"
from server for: "nginx.yaml": deployments.apps "nginx-deployment" is forbidden: User "system:serviceaccount:gitlab-runner:default" cannot get resource "deployments" in API group "apps" in the namespace "gitlab-runner"

Use ServiceAccount gitlab-runner-gitlab-runner to solve that issue.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# values.yaml · master · GitLab.org / charts / GitLab Runner · GitLab
# https://gitlab.com/gitlab-org/charts/gitlab-runner/-/blob/main/values.yaml

# ...

## For RBAC support:
rbac:

## Use the following Kubernetes Service Account name if RBAC is disabled in this Helm chart (see rbac.create)
##
+ serviceAccountName: gitlab-runner-gitlab-runner

+ rules:
+ - apiGroups: [""] #"" indicates the core API group
+ resources: ["*"]
+ verbs: ["*"]
+ - apiGroups: ["networking.k8s.io"]
+ resources: ["ingresses"]
+ verbs: ["*"]
+ - apiGroups: ["apps"]
+ resources: ["deployments"]
+ verbs: ["*"]

## Configuration for the Pods that the runner launches for each new job
##
runners:

# Service Account to be used for runners
#
+ serviceAccountName: gitlab-runner-gitlab-runner

# ...

References

[1] GitLab Runner Helm Chart | GitLab - https://docs.gitlab.com/runner/install/kubernetes.html

[2] Files · main · GitLab.org / charts / GitLab Runner · GitLab - https://gitlab.com/gitlab-org/charts/gitlab-runner/-/tree/main

[3] values.yaml · main · GitLab.org / charts / GitLab Runner · GitLab - https://gitlab.com/gitlab-org/charts/gitlab-runner/blob/main/values.yaml

[4] GitLab Runner | GitLab - https://docs.gitlab.com/runner/

[5] Kubernetes Getting Started | Pulumi - https://www.pulumi.com/docs/get-started/kubernetes/

[6] Pulumi - Modern Infrastructure as Code - https://www.pulumi.com/

[7] Kubernetes - https://kubernetes.io/

[8] TypeScript: Typed JavaScript at Any Scale. - https://www.typescriptlang.org/

[9] Helm - https://helm.sh/