Gitlab is one of the limited choices for an air-gapped environment where cloud-based Git repository is simply not an option. This paper documents the implementation of Gitlab (11.4) on top of IBM Cloud Private 3.1. While some of the steps are specific to ICP 3.1, most are generic to a private kubernetes on-premises.

1. Add helm chart repo

We will use the Gitlab Helm Chart version hosted on charts.gitlab.io, instead of the deprecated version on Kubernetes charts. Let's add the helm repo first.



helm repo update helm repo add gitlab https://charts.gitlab.io helm repo update

2. Enable images from different registries on ICP

ICP 3.1 enhanced the image security allowing the docker image to be used only when you have an explicitly defined policy.

Let’s create the following image policy.

apiVersion: securityenforcement.admission.cloud.ibm.com/v1beta1

kind: ClusterImagePolicy

metadata:

name: gitlab-cluster-image-policy

spec:

repositories:

- name: registry.gitlab.com/gitlab-org/*

- name: docker.io/*

- name: quay.io/kubernetes-ingress-controller/*

- name: k8s.gcr.io/*

Save it as a yaml file, run the kubectl to apply it like

kubectl apply -f img.policy.yaml

3. Deploy it with helm

Its assumed that in your private Kubernetes setup the followings are already there, in which ICP3.1 already has.

A default dynamic storage class is ready to provision the PVC request.

An ingress controller to handle ingress object and request.

The command to deploy the helm chart is listed as below.

helm install gitlab/gitlab --tls \

--set global.edition=ee \

\

--set global.ingress.enabled=true \

--set nginx-ingress.enabled=false \

\

--set certmanager.install=false \

--set global.ingress.configureCertmanager=false \

--set gitlab-runner.install=false \

\

--set global.hosts.https=true \

--set global.hosts.externalIP=192.168.64.246 \

--set global.hosts.domain=192.168.64.246.nip.io\

--set global.ingress.class= \

\

--set prometheus.install=false \

--set gitlab.sidekiq.minReplicas=1 \

--set gitlab.sidekiq.maxReplicas=1 \

--set registry.minReplicas=1 \

--set registry.maxReplicas=1 \

--set gitlab.unicorn.minReplicas=1 \

--set gitlab.unicorn.maxReplicas=1 \

--set gitlab.gitlab-shell.minReplicas=1 \

--set gitlab.gitlab-shell.maxReplicas=1

For “global.edition”, you can select to use EE or CE edition of Gitlab.

We enable the ingress instead of using the NodePort, for a more user friendly way to expose the git services.

Since ICP already have nginx-ingress installed and running as one of the base functional component (ICP has a dedicated Proxy node for it), we set nginx-ingress.enabled as false.

Gitlab uses the cert manager to issue HTTPS certificate based on ACME (Automated Certificate Management Environment). But this is not available in an airgap environment. We disable the cert manager installation and the ingress configuration for it. We will use a self-signed cert, and because of that the gitlab-runner service is not available. So we have the option as below,

--set certmanager.install=false \

--set global.ingress.configureCertmanager=false \

--set gitlab-runner.install=false \

We still use https service with ingress.

The DNS domain can be your own domain in the organization. For testing purpose, I am using the wildcard DNS service provided by nip.io. Notice the DNS needs to resolve to the IP where the ingress controller running and the port 80 and 443 are exposed. In the ICP case, it is the ICP Proxy Node. This leads to

--set global.hosts.https=true \

--set global.hosts.externalIP=192.168.64.246 \

--set global.hosts.domain=192.168.64.246.nip.io\

--set global.ingress.class= \

Its noted that we set global.ingress.class as empty, so that kubernetes.io/ingress.class will be empty on purpose. With that empty setting, the existing nginx ingress controller in the cluster will monitor and manage the ingress setting from Gitlab. (Refer to the multi ingress controller for more details).

By all these ingress settings, if you access

https://gitlab.192.168.64.246.nip.io

The ingress controller will redirect the traffic to the Gitlab unicorn services. You can refer to the resulted ingress as below.

$ k describe ingress rafting-gecko-unicorn

Name: rafting-gecko-unicorn

Namespace: default

Address: 192.168.64.246

Default backend: default-http-backend:80 (<none>)

TLS:

rafting-gecko-wildcard-tls terminates gitlab.192.168.64.246.nip.io

Rules:

Host Path Backends

---- ---- --------

gitlab.192.168.64.246.nip.io

/ rafting-gecko-unicorn:8181 (<none>)

Annotations:

nginx.ingress.kubernetes.io/proxy-body-size: 512m

nginx.ingress.kubernetes.io/proxy-connect-timeout: 15

nginx.ingress.kubernetes.io/proxy-read-timeout: 600

kubernetes.io/ingress.class:

kubernetes.io/ingress.provider: nginx

Lastly, we set the minimum and maximum replica to one for the testing purpose.

4. Access Gitlab

Once the helm chart deployed and all the pods are ready, you can access Gitlab service, in my case https://gitlab.192.168.64.246.nip.io