Gebruik van GitLab Runner als Ansible Control Node
Categories:
Probleem
Veel organisaties streven ernaar om Ansible Automatiseringsplatform ( AAP ) te gebruiken voor orkestratietaken, maar het is mogelijk niet altijd beschikbaar. In dergelijke gevallen hebben teams een alternatieve control node nodig om Ansible playbooks uit te voeren voor provisioning, terwijl ze beveiliging, schaalbaarheid en integratie met bestaande tools zoals GitLab behouden. Het kiezen van GitLab Runner voor dit doel introduceert uitdagingen zoals het beheren van meerdere pipelines, het uitvoeren van omgevingscontroles en het beperken van provisioning tot nodes die overeenkomen met de omgeving van de branch. Deze uitdagingen bestaan niet bij AAP, omdat het specifiek is ontworpen om orkestratie veilig te configureren en af te handelen, inclusief omgevingspecifieke controles, role-based access en gecentraliseerd beheer zonder aangepaste pipeline-logica.
Context
Ansible vereist een control node om playbooks uit te voeren tegen target hosts. Terwijl AAP een robuuste, enterprise-grade oplossing biedt, kunnen GitLab Runners dienen als een tijdelijk of lichtgewicht alternatief. Dit is vooral nuttig in omgevingen met GitLab CI/CD, waar runners kunnen worden geconfigureerd met Ansible execution environments. De aanpak veronderstelt dat een GitLab Runner met Ansible al is ingesteld en richt zich op het creëren van pipelines voor provisioning, met gebruik van features zoals CI/CD inputs voor flexibiliteit.
Deze setup vindt plaats in de context van een inventory project met group-based environments. De selectie van GitLab Runner als control node creëert uitdagingen zoals het afhandelen van meerdere pipelines voor verschillende taken, het valideren van omgevingen om ongeautoriseerde provisioning te voorkomen en het ervoor zorgen dat playbooks alleen nodes targeten in de bijbehorende omgevingsgroep op basis van de branch.
Oplossing
Configureer een GitLab CI/CD pipeline om een runner te gebruiken als de Ansible control node.
Dit omvat het instellen van een hoofd .gitlab-ci.yml
-bestand dat conditionele
sub-bestanden bevat voor standaardtaken of Ansible provisioning. Gebruik CI/CD variables en
inputs om de pipeline dynamisch en veilig te maken.
Aanpassen van de Pipeline voor Dubbele Workflows
Verander de gewone GitLab CI/CD pipeline voor het
inventory project om
twee distincte workflows te ondersteunen: één voor standaardtaken (bijv. linting,
packaging) en een extra voor Ansible provisioning. Definieer
CI/CD inputs in het hoofd .gitlab-ci.yml
voor het selecteren van playbooks en CLI
opties. Maak sub-bestanden zoals .gitlab-ci/ansible.yml
voor provisioning en
.gitlab-ci/default.yml
voor niet-provisioning taken. Gebruik conditionals om
het juiste sub-bestand in te sluiten op basis van pipeline triggers of variables.
Implementeren van Branch Validatie voor Provisioning
Voeg controles toe om ervoor te zorgen dat Ansible provisioning alleen kan draaien op specifieke branches,
namelijk die welke overeenkomen met
group-based environments in het
inventory
project. De pipeline moet falen als een gebruiker probeert te provisionen vanaf de
master branch of een feature branch. Stel vereiste project variables in GitLab
settings in, zoals PX_ANSIBLE_ENVIRONMENTS
voor toegestane branches. In het
provisioning sub-bestand, sluit validatielogica in om de huidige branch te controleren
tegen deze lijst voordat je doorgaat.
Beperken van Playbook Uitvoering tot de Omgeving
Wanneer de Ansible pipeline draait vanaf een correcte omgevingsbranch, wijzig dan het
ansible-playbook
-commando om alleen nodes in die omgevingsgroep te targeten. Gebruik
de --limit
optie om uitvoering te beperken tot hosts in de bijbehorende groep,
waardoor provisioning alleen de beoogde omgeving beïnvloedt. Pas deze limit automatisch toe op basis van de branch-naam, om beveiliging te bevorderen en accidentele wijzigingen aan niet-gerelateerde hosts te voorkomen.
Volg deze richtlijnen:
- Definieer CI/CD inputs in het hoofd
.gitlab-ci.yml
voor het selecteren van playbooks en CLI opties. - Maak een sub-bestand (bijv.
.gitlab-ci/ansible.yml
) voor de provisioning stage, inclusief variable checks, branch validatie en playbook uitvoering met omgevingslimits. - Maak een ander sub-bestand (bijv.
.gitlab-ci/default.yml
) voor niet-provisioning taken zoals linting en packaging, die alleen draaien op merge requests of de default branch. - Stel vereiste project variables in GitLab settings in, zoals
PX_ANSIBLE_ENVIRONMENTS
voor toegestane branches. - Zorg ervoor dat de runner een veilige image gebruikt met Ansible geïnstalleerd, en pas access controls toe voor beveiliging.
Voordelen
- Maakt Ansible provisioning mogelijk zonder AAP, met gebruik van bestaande GitLab infrastructuur.
- Bevordert flexibiliteit met dynamische inputs voor playbooks en opties.
- Verbetert beveiliging door branch validatie en automatische beperking tot omgevingen.
- Ondersteunt schaalbaarheid door integratie met GitLab’s CI/CD features voor automatisering.
Alternatieven (Optioneel)
Direct Ansible uitvoeren vanaf een lokale machine of dedicated server is mogelijk, maar het gebruik van GitLab Runners is verkozen voor integratie met version control, geautomatiseerde pipelines en schaalbaarheid in teamomgevingen. Als AAP beschikbaar wordt, migreer dan voor geavanceerde features zoals job scheduling en RBAC.
Voorbeelden en Implementatie
Deze sectie biedt YAML voorbeelden voor de pipeline-bestanden. Veronderstel een GitLab project met Ultimate features voor CI/CD inputs. De setup creëert twee pipelines: een default voor taken zoals linting, en een provisioning voor Ansible playbooks.
Hoofd Pipeline Bestand
Dit hoofd GitLab CI/CD pipeline bestand .gitlab-ci.yml
definieert inputs en
sluit andere YAML-bestanden conditioneel in.
---
spec:
inputs:
play:
type: string
description: Ansible playbook file
options: ["plays/core/linux.yml", "plays/core/windows.yml", "none"]
default: 'none'
cli_options:
type: string
description: Ansible CLI options
default: --check
---
variables:
ANSIBLE_PLAY: "\"$[[ inputs.play ]]\""
ANSIBLE_CLI_OPTIONS: "\"$[[ inputs.cli_options ]]\""
include:
- local: .gitlab-ci/default.yml
rules:
- if: "\"$[[ inputs.play ]]\" == \"none\""
- local: .gitlab-ci/ansible.yml
rules:
- if: "\"$[[ inputs.play ]]\" != \"none\""
Ansible Provisioning Pipeline
Handhabt provisioning met controles en playbook uitvoering.
---
default:
image: registry.gitlab.com/c2platform/rws/ansible-execution-environment:0.1.25
stages:
- validate
- provision
validate:
stage: validate
script:
- bash ./.gitlab-ci/scripts/validate.sh
artifacts:
paths:
- variables.env
expire_in: 1 hour
provision:
stage: provision
needs: [validate]
script: |
# Load exported variables
source variables.env
# Log and run the playbook
echo "Running Ansible playbook: $CLEAN_PLAY, with options: $CLEAN_OPTIONS"
echo "$ANSIBLE_CLI $CLEAN_PLAY $CLEAN_OPTIONS"
# eval "$ANSIBLE_CLI \"$CLEAN_PLAY\" $CLEAN_OPTIONS"
De validate.sh
script valideert dat de branch correct is, met andere woorden een toegestane
omgevingsbranch is (geconfigureerd met PX_ANSIBLE_ENVIRONMENTS
). En het zorgt ervoor dat --limit
wordt gebruikt om
de
group te targeten die
.gitlab-ci/scripts/validate.sh
#!/bin/bash
# Check required variables
if [ -z "$PX_ANSIBLE_ENVIRONMENTS" ]; then
echo "Error: Required variable PX_ANSIBLE_ENVIRONMENTS is not defined. Set it in CI/CD settings (e.g., 'development,test,acceptance,production'). Failing pipeline."
exit 1
fi
if [ -z "$ANSIBLE_PLAY" ]; then
echo "Error: Required variable ANSIBLE_PLAY is not defined. Set it to your playbook file/path (e.g., 'plays/core/linux.yml'). Failing pipeline."
exit 1
fi
if [ -z "$ANSIBLE_CLI" ]; then
ANSIBLE_CLI="ansible-playbook" # Default if not set
echo "ANSIBLE_CLI not defined. Defaulting to '$ANSIBLE_CLI'."
fi
# Strip surrounding double quotes from variables
clean_play="${ANSIBLE_PLAY#\"}"
clean_play="${clean_play%\"}"
clean_options="${ANSIBLE_CLI_OPTIONS#\"}"
clean_options="${clean_options%\"}"
clean_options=$(echo "$clean_options" | sed 's/""//g' | xargs) # Trim extra spaces
# Validate branch
environments=$(echo "$PX_ANSIBLE_ENVIRONMENTS" | tr ',' ' ')
found=""
for env in $environments; do
if [ "$CI_COMMIT_REF_NAME" = "$env" ]; then
found="1"
break
fi
done
if [ -z "$found" ]; then
echo "Error: Branch '$CI_COMMIT_REF_NAME' is not in allowed environments ($PX_ANSIBLE_ENVIRONMENTS). Failing pipeline."
exit 1
fi
# Modify clean_options based on --limit
env="$CI_COMMIT_REF_NAME"
if echo "$clean_options" | grep -q -- --limit; then
clean_options=$(echo "$clean_options" | sed -E "s/--limit ([^ ]+)/--limit \1:\&$env/")
else
clean_options="$clean_options --limit $env"
fi
# Export to env file for next job
echo "CLEAN_PLAY=$clean_play" > variables.env
echo "CLEAN_OPTIONS=$clean_options" >> variables.env
echo "ANSIBLE_CLI=$ANSIBLE_CLI" >> variables.env
Default Pipeline
Voor linting, packaging en releasing. Dit is in .gitlab-ci/default.yml
.
---
default:
image: registry.gitlab.com/c2platform/rws/ansible-execution-environment:0.1.25
variables:
DOWNLOAD_SCRIPT: download.py
COLLECTIONS_DIR: ansible-collections-tarball
C2_PACKAGE_NAME: phx-ansible-collections
before_script:
- python3 --version
- pip3 --version
- ansible --version
- ansible-lint --version
- yamllint --version
workflow: # run the pipeline only on MRs and default branch
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
stages:
- prepare
- linters
- package
- release
yamllint:
stage: linters
script:
- yamllint -c .yamllint .
ansible-lint:
stage: linters
script:
- ansible-lint -c .ansible-lint
prepare:
stage: prepare
script:
- C2_VERSION=$(grep -oP '\d+\.\d+\.\d+' CHANGELOG.md | head -1)
- echo "C2_VERSION=$C2_VERSION" >> variables.env
artifacts:
reports:
dotenv: variables.env
package:
stage: package
when: manual
only:
- master
script:
- |
ansible-galaxy collection download -r collections/requirements.yml -p ./$COLLECTIONS_DIR
cd $COLLECTIONS_DIR
tar -czvf ../${C2_PACKAGE_NAME}.${C2_VERSION}.tar.gz .
artifacts:
paths:
- ${C2_PACKAGE_NAME}.${C2_VERSION}.tar.gz
publish:
stage: package
only:
- master
needs:
- job: package
- job: prepare
script:
- |
env | grep C2
curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file ${C2_PACKAGE_NAME}.${C2_VERSION}.tar.gz \
${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${C2_PACKAGE_NAME}/${C2_VERSION}/${C2_PACKAGE_NAME}.${C2_VERSION}.tar.gz
release:
stage: release
only:
- master
image: registry.gitlab.com/gitlab-org/release-cli:latest
needs:
- job: publish
- job: package
before_script: []
script:
- echo "Create release for $C2_VERSION"
release:
name: phx-inventory-$C2_VERSION
description: PHX Ansible Inventory Project
tag_name: $C2_VERSION
ref: $CI_COMMIT_SHA
assets:
links:
- name: "${C2_PACKAGE_NAME}.${C2_VERSION}.tar.gz"
url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${C2_PACKAGE_NAME}/${C2_VERSION}/${C2_PACKAGE_NAME}.${C2_VERSION}.tar.gz"
Gebruiksnotities
- Stel CI/CD variables in zoals
PX_ANSIBLE_ENVIRONMENTS
in project settings. - De pipeline valideert branches en beperkt playbooks tot de huidige omgeving.
- Gebruik een veilige runner image en access controls voor best practices.
- Deze setup schaalt goed met GitLab zonder AAP nodig te hebben.
Aanvullende Informatie
Voor aanvullende inzichten en begeleiding:
- Omgevingen op basis van Groepen: Organiseer je Ansible-inventaris en variabelen voor verschillende omgevingen.
- Ansible Inventarisproject: Een Ansible Inventarisproject bevat inventarisbestanden, plays, hostconfiguraties, groepsvariabelen en kluisbestanden. Het wordt ook wel aangeduid als een playbook-project of configuratieproject.
Feedback
Was deze pagina nuttig?
Fijn om te horen! Vertel ons alstublieft hoe we kunnen verbeteren.
Jammer om dat te horen. Vertel ons alstublieft hoe we kunnen verbeteren.