Skip to content

Integration of automated installation into GitLab CI CD process

mirjan-hoffmann edited this page Apr 1, 2022 · 5 revisions

Use the ansible scripts from one of the "Boxes" to perform an installation on an existing system like your Test/Prod system. Since this is done here via Docker containers in the GitLab CI, the environment from which the installation is performed is always the same and there are no conflicts due to different Ansible versions on the installation host. This makes the installation more stable. You will be able to start the installation fully automatically with a simple click in the browser or even use a scheduled or triggered installation.

In general you need a private GitLab instance that can reach the system to be installed on. Your instance configuration will be stored inside of a private repo in the private GitLab instance - the config-repo. This repository will contain your private configuration like URLs, mail-adresses, passwords, ...

Configuration

Create the config-repository

  • Create the private config-repository in your GitLab - it will contain your private configuration (like URLs, mail-adresses, passwords, ...) and be responsible for the automatic installation

Prepare your target system

  • Create a "work-user" without root-privileges on your system
    • GitLab will process the installation via this user
    • Your services can run under this user
    • A user with root-privileges and ssh-access would be a security risk -> please assure the user has no root-privileges
    • An additional "installation-user" is also conceivable, but in most cases superfluous, since the installation can usually also be executed by the user who runs the services
    • example useradd -m -d /home/YOUR-WORKUSERNAME -s /bin/bash YOUR-WORKUSERNAME
  • If your ansible-scripts contain tasks which require root-privileges, assure you can switch to a user with root-privileges from your work-user (su is used in this examples)

Setup SSH configuration

  • Create SSH-key that can be used by the GitLab-CI
    ssh-keygen -t rsa -b 2048 -N '' -f gitlab-ci
  • Add the public-key to the end of the ~/.ssh/authorized_keys file of your work-user on your target host
    echo "# GitLab-CI" > tmp-auth-key-entry && cat gitlab-ci.pub >> tmp-auth-key-entry
    # => add the content of tmp-auth-key-entry to authorized_keys
    • Create authorized_keys as "work-user", if it does not exist

      mkdir ~/.ssh
      chmod 700 ~/.ssh
      touch ~/.ssh/authorized_keys
      chmod 600 ~/.ssh/authorized_keys
  • Set variables in the GitLab-config-repo: Settings -> CI / CD -> Variables
    • SSH_PRIVATE_KEY - the base64 encoded private key; mask variable: yes; protect variable: no
      echo "Set GitLab-CI Variable 'SSH_PRIVATE_KEY' to:" && base64 gitlab-ci -w 0
    • SSH_KNOWN_HOSTS - append the known host information of all target hosts here; mask variable: no; protect variable: no
      echo "Set GitLab-CI Variable 'SSH_KNOWN_HOSTS' to:" && ssh-keyscan -H -t ecdsa-sha2-nistp256 YOUR-HOSTNAME

Create inventories

  • Create the inventory-file for your target host in the GitLab-config-repo, for example inventory_TEST.yml (see also example in your box -> doc/gitlab-config-example)
    • Have a look at the available ansible groups and variables under "ansible/group_vars" of your box thoroughly.
    • Set the ansible connection variables and group-variables thoroughly for each group
    • If you adjust the filenames of your inventory-files, please assure to also adjust the filenames in .gitlab-ci.yml
all:
  hosts:
    your.host.org:
      # connection variables
      ansible_ssh_user: user              # your "work-user"
      ansible_become_method: su           # become_method for root privileges, if necessary in the box
      ansible_become_password: changeme
      ansible_become_flags: '-'

      # group variables
      # Set all group-specific ansible variables here that are required to install the Box.
      ...

Prepare installation in GitLab Docker-Containers

  • Create the local prerequisites.yml playbook in your GitLab-config-repo (see also example in your box -> doc/gitlab-config-example)
    • There you can execute all tasks needed for the actual installation - for example cloning the box and loading ansible roles from the Ansible-Galaxy.
---
- hosts: all
  tasks:
    - name: checkout box locally
      git:
        repo: 'https://github.com/path-to-your-box-repo'
        dest: '{{ inventory_dir }}/box'
        force: yes
        version: '{{ box_version | default("master") }}'
      delegate_to: localhost
    
    - name: install required ansible-galaxy roles
      shell: ansible-galaxy install -r box/ansible/requirements.yml
      delegate_to: localhost

Configure GitLab-CI

  • Create the .gitlab-ci.yml file in your GitLab-config-repo (see also example in your box -> doc/gitlab-config-example)
stages:
  - deploy

.deploy_job:
  image: willhallonline/ansible:2.11-alpine-3.15
  stage: deploy
  before_script:
    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | base64 -d | tr -d '\r' | ssh-add -
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
    - chmod 644 ~/.ssh/known_hosts
  script:
    - ansible-playbook -v -i ${INVENTORY_FILE} prerequisites.yml
    - ansible-playbook -v -i ${INVENTORY_FILE} ${PLAYBOOK} --extra-vars "gitlab_private_token=$CI_JOB_TOKEN"

Test Update:
  variables:
    INVENTORY_FILE: inventory_TEST.yml
    PLAYBOOK: box/ansible/playbook.yml
  extends: .deploy_job
  only:
    - master
  when: manual

Finally

  • Now you should be able to update your systems via your GitLab-config-repo
    • Call: CI / CD -> Pipelines -> Latest
    • Click the "Play"-Button for the system you want to update
  • Optionally you can activate scheduled installations
    • Create a GitLab-Schedule in your project CI / CD -> Schedules
    • uncomment "scheduled deployment" section in .gitlab-ci.yml and adjust to your inventory-filename

Clone this wiki locally