Introduction#

Note: This is a mere Proof of Concept. I will be writing a full-fledged guide soon. Until then, this can be used to deploy a test Gitlab installation for fun.

Gitlab is probably the best alternative to Github as of today. It can be a bit complex to deploy (especially on Kubernetes) but most configurations are well-documented.

Although the operator is listed as “not yet suitable for production” on the Gitlab website, it’s still fun to play around with it on a test setup.

This is what the official Gitlab documentation says about the Gitlab operator:

“The GitLab Operator is under active development and is not yet suitable for production use. See our Minimal to Viable Epic for more information.”

Setup#

The steps listed here were carried out on a Dell PowerEdge R620 (Diablo), my cute little 1U rack server.

  1. The kubernetes distro of my choice is RKE2 (thanks, Mr.coat), with 3 control plane nodes and 5 worker nodes. Note: Kubernetes 1.25 is not supported at the moment by the Gitlab operator. Ensure that you’re not on 1.25 or above before proceeding with the installation!

  2. Each one of the worker nodes has 16 GBs of memory and 8 vCPUs.

  3. Storage is provided by the Rook Ceph operator.

  4. MetalLB is set up in BGP mode (BGP router running outside the Kubernetes cluster using FRRouting) to provide external access to the services running in the Kubernetes cluster.

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: address-pool-64
  namespace: metallb-system
spec:
  addresses:
  - 192.168.64.1-192.168.64.254
---
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
  name: bgp-peer
  namespace: metallb-system
spec:
  myASN: 64513
  peerASN: 64512
  peerAddress: 10.0.0.2
---
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
  name: bgp-advertisement
  namespace: metallb-system

Installation#

  1. First, add the helm repository for the operator itself. This can be done by using:
helm repo add gitlab-operator https://gitlab.com/api/v4/projects/18899486/packages/helm/stable
  1. Next, install the operator via helm using:
helm install gitlab-operator gitlab-operator/gitlab-operator --create-namespace --namespace gitlab-system
  1. Ensure that the operator pod is running without any crashes:
kubectl -n gitlab-system get po
  1. Since I need LDAP authentication for my Gitlab instance (with FreeIPA!) I’ll have to create two secrets - one for the ipa server certificate and the other containing the ldap password.

    Note: ipa.pem is the file in the current working directory which contains the CA cert for the IPA instance. Ensure that the secret key has an extension of .crt

kubectl -n gitlab-system create secret generic ipa-server-ca-cert --from-file=ipa-server.crt=ipa.pem
kubectl -n gitlab-system create secret generic ldap-auth --from-literal=ldap-password=secret-pass
  1. Next, we create a Gitlab CR called gitlab.yml that the Gitlab operator will use to create a Gitlab instance:
apiVersion: apps.gitlab.com/v1beta1
kind: GitLab
metadata:
  name: gitlab
spec:
  chart:
    version: "6.11.1"
    values:
      global:
        hosts:
          domain: internal.nanibot.net
        ingress:
          configureCertmanager: false
        certificates:
          customCAs:
            - secret: ipa-server-ca-cert
        appConfig:
          ldap:
            preventSignin: false
            servers:
              main:
                label: 'LDAP'
                host: 'ipa.internal.nanibot.net'
                port: 636
                uid: 'uid'
                bind_dn: 'uid=service,cn=users,cn=accounts,dc=internal,dc=nanibot,dc=net'
                base: 'cn=users,cn=accounts,dc=internal,dc=nanibot,dc=net'
                encryption: 'simple_tls'
                password:
                  secret: ldap-auth
                  key: ldap-password
                ca_file: '/etc/ssl/certs/ipa-server.pem'
      certmanager:
        install: false
      nginx-ingress:
        controller:
          service:
            type: LoadBalancer
  1. Apply the CR:
kubectl -n gitlab-system apply -f gitlab.yml
  1. Monitor the Gitlab deployment until the status is Running:
kubectl -n gitlab-system get gitlab -w

Most values set above are self-explanatory except for a few:

  1. values.global.hosts.domain is set to internal.nanibot.net because this is the domain that will be used for creating ingresses to the relevant services. For example, gitlab.internal.nanibot.net, minio.internal.nanibot.net etc.

  2. values.global.ingress.configureCertmanager is set to false since I do not wish for a certificate to be generated by cert manager. Note that self-signed certificates will be generated by a job in this case.

  3. values.certmanager.install is set to false for similar reasons as above.

  4. values.nginx-ingress.controller.service.type is set to LoadBalancer so that an external IP is assigned to the nginx ingress controller service.

kubectl -n gitlab-system get ingress

The above command will display all services deployed by Gitlab

Finally, the Gitlab UI will be available on gitlab.internal.nanibot.net