Skip to content

Gitlab CICD Runner

This page will demonstrate how to setup initial CICD on Gitlab with a runner orchestrated by Docker Compose.

Note

The Gitlab CICD Runner will change in the future, as this is a chicken and a egg problem.

Chicken and Egg Problem

I would like to avoid running things manually as far as possible, but at this point I am planning to run my Gitlab Runners on Kubernetes, but at the time of writing the Kubernetes cluster has not been provisioned yet.

So for the Gitlab Runner Jobs, I will be installing a Gitlab Runner on a amd64 host, with docker compose, so that we can start using Ansible in a Pipeline to execute our playbooks. We can then use this runner for Terraform jobs as well, etc.

Registration Token

I have created a git repository named ansible-provisioning and we need to create a project runner, and we can do that by heading to Settings, CI/CD:

Then expand Runners, and select New project runner:

Then select your platform, in my case it's Linux, I would like to define a tag in my jobs to control to which runner they should go (keeping in mind, I am going to change the runners in the future), in my case I am calling the tag ansible-runner, and the description of the runner:

Once you registered the runner, you should see a output like the following:

Here we want to copy the token value, in my case starting with glrt-*.

Docker Compose Configuration

From our previous step we have copied the registration token, which we will assign it to the variable REGISTRATION_TOKEN and I am using the managed gitlab service, so the value of CI_SERVER_URL in my case will be https://gitlab.com.

The content of our docker-compose.yaml is:

version: '3.7'

services:
  dind:
    image: docker:20-dind
    container_name: "dind"
    hostname: dind
    privileged: true
    volumes:
      - docker-dind:/var/lib/docker
      - certs:/certs/client
    restart: unless-stopped
    command:
      - --tlsverify=false
    networks:
      - public
    environment:
      - DOCKER_TLS_CERTDIR=/certs
    logging:
      driver: "json-file"
      options:
        max-size: "1m"

  runner-ansible:
    image: gitlab/gitlab-runner:alpine3.17-v16.3.0
    container_name: "runner-ansible"
    volumes:
      - ./config/ansible:/etc/gitlab-runner:z
      - ./data/runner/cache:/cache
      - certs:/certs/client
    environment:
      DOCKER_HOST: "tcp://dind:2376"
      DOCKER_TLS_CERTDIR: "/certs/client"
      DOCKER_TLS_VERIFY: "1"
      DOCKER_MACHINE_NAME: "dind"
      DOCKER_CERT_PATH: "/certs/client"
    restart: unless-stopped
    networks:
      - public
    logging:
      driver: "json-file"
      options:
        max-size: "1m"

  runner-ansible-registration:
    image: gitlab/gitlab-runner:alpine3.17-v16.3.0
    container_name: "runner-ansible-registration"
    depends_on:
      - dind
    restart: 'no'
    environment:
      - CI_SERVER_URL=https://gitlab.com
      - REGISTRATION_TOKEN=glrt-xxxxxxx-xxxx
    command:
      - register
      - --non-interactive
      - --locked=true
      - --name=runner-ansible
      - --executor=docker
      - --docker-image=docker:20-dind
      - --docker-volumes=/var/run/docker.sock:/var/run/docker.sock
      - --tag-list="ansible"
      - --registration-token=$REGISTRATION_TOKEN
      - --url=$CI_SERVER_URL
    volumes:
      - ./config/ansible:/etc/gitlab-runner:z
      - ./data/dind/docker:/var/lib/docker
    networks:
      - public
    logging:
      driver: "json-file"
      options:
        max-size: "1m"

volumes:
  docker-dind: {}
  certs: {}

networks:
  public:
    name: public

Once I've written the file to the project directory of choice on a linux host with docker and docker compose installed, then we can start the containers that will run our gitlab runner:

docker-compose up -d

Verify Runner Status

Once the runner container is up it will start the registration process and you can head back to the runners page, and the runner's status should change to green:

Gitlab CI Configuration

In the root directory of the project, create a file named .gitlab-ci.yml with the following content:

default:
  tags:
    - ansible

stages:
  - deploy

build:
  stage: deploy
  image: ruanbekker/ansible:2.15.3
  variables:
    ANSIBLE_CONFIG: $CI_PROJECT_DIR/ansible.cfg
    ROLES_REQUIREMENTS_FILE: $CI_PROJECT_DIR/roles/roles_requirements.yml
    EXTERNAL_ROLE_DIR: $CI_PROJECT_DIR/roles/external
  script:
    - ansible-galaxy install -r "$ROLES_REQUIREMENTS_FILE" --force --no-deps -p "$EXTERNAL_ROLE_DIR"
    - ansible-playbook -i inventory.ini -e "ansible_ssh_user=root ansible_ssh_pass=$ANSIBLE_PASSWORD" playbooks/setup.yml
  only:
    - main