HashiQube - DevOps Lab
Youtube Channel Medium Posts Riaan Nolan Linkedin Riaan Nolan Hashicorp Ambassador

.

GitLab

GitLab Logo

A complete DevOps platform in a single application

🚀 About

GitLab provides a complete CI/CD toolchain in a single application. One interface. One conversation. One permission model. Thousands of features. GitLab simplifies DevOps by providing everything you need to build, test, deploy, and monitor your applications in one place.

⏱️ Setup Information

  • Duration: 15-30 minutes
  • Requirements: Your Docker daemon should have at least 12GB RAM
    • GitLab: 6GB
    • Minikube: 2GB
    • Operating System: 2GB
  • Process: We'll bring up the Docker daemon and Minikube, then deploy GitLab on top of Minikube using Helm

📋 Provision

Open in GitHub Codespaces

bash docker/docker.sh
bash minikube/minikube.sh
bash gitlab/gitlab.sh
vagrant up --provision-with basetools,docker,docsify,minikube,gitlab
docker compose exec hashiqube /bin/bash
bash hashiqube/basetools.sh
bash docker/docker.sh
bash docsify/docsify.sh
bash minikube/minikube.sh
bash gitlab/gitlab.sh

🖥️ Installation Process

During the installation, you can monitor progress via the Kubernetes Dashboard once Minikube is installed. Initially, you'll see some red indicators as GitLab pods and services start up, which will gradually turn green as the deployment completes.

Minikube Dashboard during GitLab installation

Minikube Dashboard showing GitLab deployment progress

The GitLab provisioning process will look like this:

GitLab provision

Terminal output during GitLab provisioning

🔑 Accessing GitLab

Once installation is complete, you can access GitLab at:

  • URL: http://localhost:5580
  • Username: root
  • Password: The password is printed in the terminal output
    • Example: jMh629reoQ7FqtillBmLQZPY69JUStSFATXD11T5wMk39NtNezqIKohcIIwoxwvl
GitLab login page

GitLab login page

After logging in, you'll see the GitLab dashboard:

GitLab first login

GitLab dashboard after first login

🛠️ Hands-On Tutorial

Creating Your First Project

  1. Click on Create a ProjectCreate a Blank project
  2. Enter the project name as test
  3. Select the namespace as root
  4. Make it a Public repository
  5. Click Create Project
GitLab Create Project

Creating a new project in GitLab

Once created, you'll see your new repository:

GitLab Created Test Project

Newly created test project

Adding SSH Keys

To clone the repository using SSH, you need to add your SSH key to GitLab:

  1. Click on your profile icon in the top left corner
  2. Select Preferences
GitLab Navigate to Preferences

Navigating to user preferences

  1. Navigate to SSH Keys in the sidebar
GitLab Navigate to Preferences SSH Keys

SSH Keys section in user preferences

  1. On your local machine, retrieve your public SSH key:

    cat ~/.ssh/id_rsa.pub
  2. Copy the key and paste it into the GitLab SSH key field

  3. Important: Remove the expiry date

  4. Click Add Key

GitLab Enter SSH Keys

Adding an SSH key to your GitLab account

After adding the key:

GitLab Added SSH Keys

SSH key successfully added

Cloning Your Repository

  1. Navigate back to your test project
  2. Click the Clone button
  3. Copy the Clone with SSH URL

    ⚠️ Note: The HTTP link doesn't work correctly due to a bug with the port configuration. Use SSH instead.

GitLab Copy SSH Clone URL

Copying the SSH clone URL

  1. Clone the repository:

    git clone ssh://git@localhost:32022/root/test.git
GitLab SSH Clone Test Repository

Successfully cloning the repository

Creating a GitLab CI Pipeline

  1. In your local repository, create a .gitlab-ci.yml file:

    cd test
    nano .gitlab-ci.yml
  2. Add the following pipeline configuration:

    variables:
      REPOSITORY_URL: xxxxxxxxxxxxx.dkr.ecr.eu-west-1.amazonaws.com/container
    
    stages:
      - test
      - build
      - dev
      - stg
      - prd
    
    test:
      stage: test
      script:
        - echo 'Here you can run tests'
    
    build:
      stage: build
      script:
        - echo 'After Test stage was successful, here you can run build your container'
    
    dev:
      stage: dev
      script:
        - echo 'After Build stage was successful, here you can run your Development environment deployment'
    
    stg:
      stage: stg
      script:
        - echo 'After Dev stage was successful, here you can run your Staging environment deployment'
    
    prd:
      stage: prd
      script:
        - echo 'After Stg stage was successful, here you can run your Production environment deployment'
  3. Commit and push the changes:

    git add .gitlab-ci.yml
    git commit -am "adding .gitlab-ci.yml pipeline file"
    git push
GitLab Add Pipeline File

Adding a CI pipeline file to the repository

After pushing, you'll see the file in your repository:

GitLab Added Pipeline File

Pipeline file added to the repository

Setting Up a GitLab Runner

  1. In your project, navigate to SettingsCI/CD
GitLab Navigate to Settings CICD

Navigating to CI/CD settings

  1. Expand the Runners section
GitLab Expand Runners

Expanding the Runners section

  1. Click New Project Runner
  2. In the configuration form, check Run Untagged Jobs
  3. Click Create Runner
GitLab New Project Runner

Creating a new project runner

⚠️ Note: Due to a known bug, you might be redirected to a blank page. If this happens, manually add :5580 to the URL:

Instead of: http://localhost/root/test/-/runners/1/register?platform=linux
Use: http://localhost:5580/root/test/-/runners/1/register?platform=linux

GitLab Create Project Runner Correct Page

Runner registration page

Registering the Runner

  1. Copy the registration command, but remember to add the port :5580:

    Incorrect:

    gitlab-runner register --url http://localhost --token glrt-NRYUnqLZ2yzyutC1MYVV

    Correct:

    gitlab-runner register --url http://localhost:5580 --token glrt-NRYUnqLZ2yzyutC1MYVV
  2. SSH into your HashiQube instance:

    vagrant ssh
Vagrant SSH

SSHing into HashiQube to register the runner

  1. Register the runner with the corrected command

  2. Start the runner:

    gitlab-runner run
Vagrant SSH GitLab Runner Run

Starting the GitLab runner

  1. Return to GitLab to see the confirmation:
GitLab Runner Run Success

Runner successfully registered

  1. Click Go to the Runners page to see your registered runner:
GitLab Runners Page

Runners page showing the registered runner

Running Your Pipeline

  1. Navigate to BuildPipelines in the left sidebar
GitLab Test Project Run Pipeline

Pipelines section

  1. You'll see your pipeline is running:
GitLab Pipeline In Progress

Pipeline running in progress

  1. To see job details, navigate to Jobs in the left sidebar and click on a job:
GitLab Pipeline Job Details

Job details showing execution results

📚 Additional Resources

🔧 GitLab Provisioner Script

The GitLab environment is set up using this script:

#!/bin/bash

# https://docs.gitlab.com/charts/installation/version_mappings.html#previous-chart-versions
GITLAB_HELM_CHART_VERSION=7.2.4 # Which is Gitlab v16.2.4

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Cleanup"
echo -e '\e[38;5;198m'"++++ "
sudo docker stop gitlab
sudo docker rm gitlab
sudo docker stop gitlab-runner
sudo docker rm gitlab-runner
yes | sudo docker system prune -a
yes | sudo docker system prune --volumes
sudo --preserve-env=PATH -u vagrant helm list
sudo --preserve-env=PATH -u vagrant helm uninstall gitlab
sudo --preserve-env=PATH -u vagrant helm list

arch=$(lscpu | grep "Architecture" | awk '{print $NF}')
if [[ $arch == x86_64* ]]; then
  ARCH="amd64"
elif  [[ $arch == aarch64 ]]; then
  ARCH="arm64"
fi
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"CPU is $ARCH"
echo -e '\e[38;5;198m'"++++ "

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"Ensure Minikube is running"
echo -e '\e[38;5;198m'"++++ "
if pgrep -x "minikube" >/dev/null
then
  echo "Minikube is running"
else
  echo -e '\e[38;5;198m'"Minikube is not running, launching"
  sudo bash /vagrant/minikube/minikube.sh
fi

# https://docs.gitlab.com/charts/development/minikube/ Gitlab via minikube
# https://gitlab.com/gitlab-org/charts/gitlab
# https://docs.gitlab.com/ee/administration/troubleshooting/kubernetes_cheat_sheet.html
# https://docs.gitlab.com/runner/install/kubernetes.html

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ helm repo add gitlab https://charts.gitlab.io/"
echo -e '\e[38;5;198m'"++++ "
sudo --preserve-env=PATH -u vagrant helm repo add gitlab https://charts.gitlab.io/

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ helm repo update"
echo -e '\e[38;5;198m'"++++ "
sudo --preserve-env=PATH -u vagrant helm repo update

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ helm search repo gitlab"
echo -e '\e[38;5;198m'"++++ "
sudo --preserve-env=PATH -u vagrant helm search repo gitlab

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Launch Gitlab on minikube using Helm Charts"
echo -e '\e[38;5;198m'"++++ "

# BUG: https://gitlab.com/gitlab-org/charts/gitlab/-/issues/4205
# https://docs.gitlab.com/charts/charts/globals.html
# https://docs.gitlab.com/charts/charts/globals.html#configure-host-settings
# https://helm.sh/docs/helm/helm_upgrade/
# https://docs.gitlab.com/charts/installation/deployment.html
# https://docs.gitlab.com/charts/installation/command-line-options.html
# https://gitlab.com/gitlab-org/charts/gitlab/-/blob/master/doc/installation/command-line-options.md
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Helm install gitlab"
echo -e '\e[38;5;198m'"++++ "
sudo --preserve-env=PATH -u vagrant helm install --version $GITLAB_HELM_CHART_VERSION \
  --namespace default gitlab \
  --timeout 600s \
  --set global.edition=ce \
  --set global.hosts.https=false \
  --set global.hosts.domain=localhost \
  --set global.hosts.hostSuffix="" \
  --set global.hosts.externalIP=$(sudo --preserve-env=PATH -u vagrant minikube ip) \
  --set global.hosts.gitlab.name=localhost \
  --set gitlab-runner.install=false \
  --set gitlab-runner.gitlabUrl="localhost:5580" \
  --set registry.enabled=false \
  --set gitlab.webservice.registry.enabled=false \
  --set gitlab.sidekiq.registry.enabled=false \
  --set gitlab-runner.runners.privileged=true \
  --set redis.resources.requests.memory=128Mi \
  -f https://gitlab.com/gitlab-org/charts/gitlab/raw/master/examples/values-minikube-minimum.yaml gitlab/gitlab

# INFO: Other flags I have tried during this process 
# --set global.hosts.domain=localhost \
# --set global.hosts.gitlab.name=localhost \
# --set global.hosts.gitlab.hostnameOverride=localhost \
# --set global.hosts.ssh=localhost \
# --set global.hosts.kas.name=localhost \
# --set global.hosts.minio.name=localhost \
# --set global.workhorse.host=localhost \
# --set global.webservice.serviceName=webservice-default \
# --set global.webservice.port=5580 \
# --set gitlab.webservice.service.workhorseExternalPort=5580 \
# --set global.hosts.shell.port=32022 \
# --set global.hosts.externalIP=$(sudo --preserve-env=PATH -u vagrant minikube ip) \
# --set global.hosts.gitlab.hostnameOverride=localhost \
# --set gitlab-runner.gitlabUrl=localhost:5580 \
# --set global.webservice.serviceName=localhost \
# --set global.workhorse.host=localhost \
# --set global.workhorse.serviceName=gitlab-webservice-default \
# --set global.hosts.gitlab.servicePort=5580 \
# --set global.workhorse.port=5580 \
# --set global.hosts.gitlab.name=localhost \
# --set global.hosts.gitlab.hostnameOverride=localhost \
# --set global.hosts.hostSuffix="" \

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Stretch your legs, get a coffee or a drink, ETA 10m.."
echo -e '\e[38;5;198m'"++++ Waiting for Gitlab to become available.."
echo -e '\e[38;5;198m'"++++ See Minikube Dashboard for details: http://localhost:10888"
echo -e '\e[38;5;198m'"++++ "

attempts=0
max_attempts=15
while ! ( sudo --preserve-env=PATH -u vagrant kubectl get po | grep gitlab-webservice | tr -s " " | cut -d " " -f3 | grep Running ) && (( $attempts < $max_attempts )); do
  attempts=$((attempts+1))
  sleep 60;
  echo -e '\e[38;5;198m'"++++ Waiting for Gitlab to become available, (${attempts}/${max_attempts}) sleep 60s"
  sudo --preserve-env=PATH -u vagrant kubectl get po | grep gitlab
  sudo --preserve-env=PATH -u vagrant kubectl get events | grep -e Memory -e OOM
done

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Waiting for Gitlab to stabalize, sleep 60s"
echo -e '\e[38;5;198m'"++++ "
sleep 30;
sudo --preserve-env=PATH -u vagrant kubectl get po | grep gitlab
sudo --preserve-env=PATH -u vagrant kubectl get events | grep -e Memory -e OOM

# https://gitlab.com/gitlab-org/charts/gitlab/-/issues/2572 Error 422
# https://stackoverflow.com/questions/67084554/how-to-kubectl-port-forward-gitlab-webservice
attempts=0
max_attempts=20
while ! ( sudo netstat -nlp | grep "0.0.0.0:5580" ) && (( $attempts < $max_attempts )); do
  attempts=$((attempts+1))
  sleep 60;
  echo -e '\e[38;5;198m'"++++ "
  echo -e '\e[38;5;198m'"++++ kubectl port-forward -n default service/gitlab-webservice-default 5580:8181 --address=\"0.0.0.0\", (${attempts}/${max_attempts}) sleep 60s"
  echo -e '\e[38;5;198m'"++++ "
  sudo --preserve-env=PATH -u vagrant kubectl port-forward -n default service/gitlab-webservice-default 5580:8181 --address="0.0.0.0" > /dev/null 2>&1 &
done

attempts=0
max_attempts=20
while ! ( sudo netstat -nlp | grep "0.0.0.0:80" ) && (( $attempts < $max_attempts )); do
  attempts=$((attempts+1))
  sleep 60;
  echo -e '\e[38;5;198m'"++++ "
  echo -e '\e[38;5;198m'"++++ kubectl port-forward -n default service/gitlab-webservice-default 80:8181 --address=\"0.0.0.0\", (${attempts}/${max_attempts}) sleep 60s"
  echo -e '\e[38;5;198m'"++++ "
  sudo --preserve-env=PATH -u vagrant kubectl port-forward -n default service/gitlab-webservice-default 80:8181 --address="0.0.0.0" > /dev/null 2>&1 &
done

attempts=0
max_attempts=20
while ! ( sudo netstat -nlp | grep "0.0.0.0:8181" ) && (( $attempts < $max_attempts )); do
  attempts=$((attempts+1))
  sleep 60;
  echo -e '\e[38;5;198m'"++++ "
  echo -e '\e[38;5;198m'"++++ kubectl port-forward -n default service/gitlab-webservice-default 8181:8181 --address=\"0.0.0.0\", (${attempts}/${max_attempts}) sleep 60s"
  echo -e '\e[38;5;198m'"++++ "
  sudo --preserve-env=PATH -u vagrant kubectl port-forward -n default service/gitlab-webservice-default 8181:8181 --address="0.0.0.0" > /dev/null 2>&1 &
done

# https://gitlab.com/gitlab-org/charts/gitlab/-/issues/2572 Error 422
# https://stackoverflow.com/questions/67084554/how-to-kubectl-port-forward-gitlab-webservice
attempts=0
max_attempts=20
while ! ( sudo netstat -nlp | grep 32022 ) && (( $attempts < $max_attempts )); do
  attempts=$((attempts+1))
  sleep 60;
  echo -e '\e[38;5;198m'"++++ "
  echo -e '\e[38;5;198m'"++++ kubectl port-forward -n default service/gitlab-gitlab-shell 32022:32022 --address=\"0.0.0.0\", (${attempts}/${max_attempts}) sleep 60s"
  echo -e '\e[38;5;198m'"++++ "
  sudo --preserve-env=PATH -u vagrant kubectl port-forward -n default service/gitlab-gitlab-shell 32022:32022 --address="0.0.0.0" > /dev/null 2>&1 &
done

attempts=0
max_attempts=30
while ! ( curl -s -w '%{http_code}' -o /dev/null "http://localhost:5580/users/sign_in" | grep 200) && (( $attempts < $max_attempts )); do
  attempts=$((attempts+1))
  sleep 60;
  echo -e '\e[38;5;198m'"++++ Waiting for Gitlab web interface to become ready, (${attempts}/${max_attempts}) sleep 60s"
  curl -s -w '%{http_code}' -o /dev/null "http://localhost:5580/users/sign_in"
done

# https://docs.gitlab.com/runner/install/linux-manually.html
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Installing Gitlab-Runner"
echo -e '\e[38;5;198m'"++++ "
curl -s https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
sudo DEBIAN_FRONTEND=noninteractive apt-get install -qq --allow-downgrades --assume-yes gitlab-runner=16.3.0 < /dev/null > /dev/null

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Gitlab CE http://localhost:5580 and login with Username: root and below password: "
sudo --preserve-env=PATH -u vagrant kubectl get secret gitlab-gitlab-initial-root-password -ojsonpath='{.data.password}' | base64 --decode ; echo

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Please login to Gitlab and create a project called test"
echo -e '\e[38;5;198m'"++++ Please follow the rest of the instructions here: http://localhost:3333/#/gitlab/README?id=you-are-here"
echo -e '\e[38;5;198m'"++++ "