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
    
  2. Next, install the operator via helm using:

    helm install gitlab-operator gitlab-operator/gitlab-operator --create-namespace --namespace gitlab-system
    
  3. Ensure that the operator pod is running without any crashes:

    kubectl -n gitlab-system get po
    
  4. 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-here>
    
  5. 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
    
  6. Apply the CR:

    kubectl -n gitlab-system apply -f gitlab.yml 
    
  7. 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