Integració amb CI/CD
8. Integració amb CI/CD
L'automatització d'infraestructures amb Ansible o Puppet cobra tot el seu sentit quan s'integra amb pipelines de CI/CD. Vegem com fer-ho efectivament.
Per què Integrar Configuration Management amb CI/CD?
La integració entre configuration management i CI/CD crea un workflow complet des del codi fins a producció. Quan un desenvolupador fa push de codi, el pipeline de CI/CD pot automàticament:
- Executar tests del codi de l'aplicació
- Construir artefactes (imatges Docker, paquets, etc.)
- Actualitzar la configuració d'infraestructura si és necessari
- Desplegar l'aplicació utilitzant Ansible o Puppet
- Verificar que el desplegament ha tingut èxit
- Fer rollback automàticament si hi ha problemes
Integració d'Ansible amb Pipelines CI/CD
Ansible s'integra molt naturalment amb pipelines CI/CD perquè és una eina de línia de comandes que pot ser cridada des de qualsevol script.
Exemple amb GitLab CI:
stages:
- build
- test
- deploy-staging
- deploy-production
variables:
ANSIBLE_VERSION: "9.0.0"
.ansible_setup: &ansible_setup
before_script:
- apt-get update -qq
- apt-get install -y python3-pip sshpass openssh-client
- pip3 install ansible==${ANSIBLE_VERSION}
- ansible-galaxy collection install community.general
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- echo "$ANSIBLE_VAULT_PASSWORD" > .vault_pass
build:
stage: build
image: node:18
script:
- npm ci
- npm run build
- npm run test
artifacts:
paths:
- dist/
- node_modules/
expire_in: 1 hour
deploy-staging:
stage: deploy-staging
image: ubuntu:22.04
<<: *ansible_setup
script:
- ansible-playbook -i inventories/staging/hosts.ini
playbooks/deploy-app.yml
--vault-password-file .vault_pass
-e "deploy_version=${CI_COMMIT_SHORT_SHA}"
only:
- develop
environment:
name: staging
url: https://staging.cloudshop.com
deploy-production:
stage: deploy-production
image: ubuntu:22.04
<<: *ansible_setup
script:
- ansible-playbook -i inventories/production/hosts.ini
playbooks/deploy-app.yml
--vault-password-file .vault_pass
-e "deploy_version=${CI_COMMIT_TAG}"
--extra-vars "confirm_production=yes"
only:
- tags
when: manual
environment:
name: production
url: https://www.cloudshop.com
Integració de Puppet amb Pipelines CI/CD
Amb Puppet, la integració és una mica diferent perquè Puppet utilitza un model pull. Hi ha diverses estratègies:
Estratègia 1: Deployament de Control Repository
El codi de Puppet (manifests, modules) es guarda en un repositori Git. El pipeline de CI/CD pot: 1. Executar tests del codi de Puppet (amb rspec-puppet, puppet-lint) 2. Desplegar el codi al Puppet Server 3. Esperar que els agents puguin la nova configuració
# .gitlab-ci.yml per Puppet Control Repo
stages:
- validate
- test
- deploy
puppet-validate:
stage: validate
image: puppet/puppet-agent:7
script:
- puppet parser validate manifests/**/*.pp
- puppet-lint --fail-on-warnings manifests/
puppet-test:
stage: test
image: ruby:3.1
script:
- bundle install
- bundle exec rake spec
deploy-to-puppetserver:
stage: deploy
script:
- rsync -avz --delete ./ puppetserver:/etc/puppetlabs/code/environments/production/
- ssh puppetserver 'puppet code deploy production --wait'
only:
- main
Estratègia 2: Triggering Manual de Puppet Runs
El pipeline pot també disparar execucions de Puppet en nodes específics utilitzant l'API de Puppet Server o eines com Bolt:
deploy-application:
stage: deploy
script:
# Actualitzar el control repo
- ssh puppetserver 'cd /etc/puppetlabs/code/environments/production && git pull'
- ssh puppetserver 'puppet code deploy production --wait'
# Disparar Puppet en els webservers
- bolt task run puppet agent=on_demand
--targets webservers
--user deploy
--private-key ~/.ssh/id_rsa
# Verificar que els serveis estan healthy
- ansible -i inventories/production/hosts.ini webservers
-m uri -a "url=http://localhost:3000/health status_code=200"
only:
- tags
Testing d'Infraestructura com a Codi
Una part important de la integració CI/CD és testejar el codi d'infraestructura abans de desplegar-lo.
Per Ansible:
Pots utilitzar Molecule per testejar roles d'Ansible:
# molecule/default/molecule.yml
---
dependency:
name: galaxy
driver:
name: docker
platforms:
- name: instance
image: ubuntu:22.04
pre_build_image: true
provisioner:
name: ansible
verifier:
name: ansible
I després executar tests en el pipeline:
test-ansible-roles:
stage: test
image: python:3.11
services:
- docker:dind
script:
- pip install molecule[docker] ansible
- cd roles/nginx
- molecule test
Per Puppet:
Pots utilitzar rspec-puppet per tests unitaris:
# spec/classes/nginx_spec.rb
require 'spec_helper'
describe 'nginx' do
context 'with default parameters' do
it { should compile.with_all_deps }
it { should contain_package('nginx') }
it { should contain_service('nginx').with_ensure('running') }
end
end
I beaker per tests d'integració que despleguen en màquines virtuals reals.
Rollback Strategies en CI/CD
Un aspecte crucial de la integració CI/CD és tenir estratègies de rollback clares.
Rollback amb Ansible:
Pots crear un job manual de rollback en el pipeline:
rollback-production:
stage: deploy-production
image: ubuntu:22.04
<<: *ansible_setup
script:
- ansible-playbook -i inventories/production/hosts.ini
playbooks/rollback.yml
--vault-password-file .vault_pass
-e "rollback_to_version=${ROLLBACK_VERSION}"
when: manual
only:
- main
El playbook de rollback podria reutilitzar el mateix playbook de deploy però amb una versió específica: