Guía completa de configuración y uso de Jenkins para CI/CD

Instalación y configuración inicial

Requisitos previos del sistema

Entorno Java

apt update
apt search openjdk
apt install -y openjdk-11-jdk
java -version

Despliegue de Jenkins

# Obtención del paquete WAR desde el repositorio oficial
wget https://get.jenkins.io/war-stable/2.426.2/jenkins.war

# Ajuste de fuentes de plugins para mejorar velocidad de descarga
sed -i 's|https://updates.jenkins.io/download|https://mirrors.tuna.tsinghua.edu.cn/jenkins|g' /var/lib/jenkins/updates/default.json
sed -i 's|https://www.google.com|https://www.baidu.com|g' /var/lib/jenkins/updates/default.json

Extensiones recomendadas

# Lista de plugins esenciales para un entorno productivo
# Gestión de carpetas y formateo
Folders
OWASP Markup Formatter
Build Timeout

# Credenciales y autenticación
Credentials Binding
PAM Authentication

# Utilidades de construcción
Timestamper
Workspace Cleanup
Environment Injector
Build Name and Description Setter
Display Console Output

# Soporte para pipelines
Pipeline
Pipeline Graph Analysis
Pipeline: API
Pipeline: Basic Steps
Pipeline: Declarative

# Control de versiones
Git
Git Parameter

# Conectividad con agentes
SSH Build Agents
Matrix Authorization Strategy

# Notificaciones y correo
Email Extension
Mailer

# Integraciones externas
GitLab
build user vars
DingTalk

# Herramientas de construcción
Ant
NodeJs

# Interfaz y visualización
Blue Ocean
Active Choices
Job Configuration History

# Contenedores y orquestación
Docker
Docker Pipeline
Kubernetes

Configuración de agentes remotos

Agentes basados en nodos físicos o virtuales

# 1. Preparar el entorno Java en el nodo esclavo
apt update && apt install -y openjdk-11-jdk

# 2. Configurar el agente en Jenkins:
#    - Establecer el directorio de trabajo
#    - Asignar etiquetas (labels) separadas por espacios
#    - Registrar una clave SSH pública

Agentes en clúster Kubernetes

# Extraer la dirección del servidor K8s
grep server ~/.kube/config

# Generar archivos de certificado a partir del kubeconfig
grep certificate-authority-data ~/.kube/config | base64 -d > ca.pem
grep client-certificate-data ~/.kube/config | base64 -d > client.pem
grep client-key-data ~/.kube/config | base64 -d > client-key.pem

# Crear archivo PKCS12 para importar como credencial
openssl pkcs12 -export \
  -out kube-cred.pfx \
  -inkey client-key.pem \
  -in client.pem \
  -certfile ca.pem

# Subir el archivo .pfx como nueva credencial en Jenkins y verificar conexión

Sistema de Pipelines

Gestión de credenciales

# Opciones disponibles para almacenar credenciales:
# - Usuario con contraseña
# - Clave privada SSH
# - Token de acceso (GitLab, GitHub, etc.)
# - Texto secreto
# - Archivo secreto

# Cada credencial posee:
# - ID: identificador único visible en Jenkins
# - Descripción: nota explicativa sobre su propósito

Conceptos fundamentales del Pipeline

Pipeline

Secuencia automatizada de pasos que implementa el flujo de entrega continua, compuesta por múltiples etapas encadenadas.

Nodo (Agent)

Representa un ejecutor del pipeline, ya sea el nodo maestro o un agente esclavo. Cada agente actúa como una máquina independiente que recibe y ejecuta tareas asignadas.

Etapa (Stage)

Agrupación lógica de acciones relacionadas que pertenecen a una fase específica del proceso, como compilación, pruebas o despliegue.

Paso (Step)

Operación individual dentro de una etapa, representando la unidad mínima de ejecución en el pipeline.

Sintaxis disponibles

Sintaxis declarativa

pipeline {
    agent any
    stages {
        stage('Compilacion') {
            steps {
                sh 'make build'
            }
        }
        stage('Verificacion') {
            steps {
                sh 'make test'
                junit 'results/**/*.xml'
            }
        }
        stage('Publicacion') {
            steps {
                sh 'make release'
            }
        }
    }
}

Sintaxis scriptada

node {
    stage('Compilacion') {
        sh 'make build'
    }
    stage('Verificacion') {
        sh 'make test'
    }
    stage('Publicacion') {
        sh 'make release'
    }
}

Métodos de construcción

Interfaz clásica

Permite escribir directamente el código del pipeline en el editor integrado de Jenkins.

Blue Ocean

Ofrece una interfaz visual intuitiva para diseñar y ejecutar pipelines de forma gráfica.

Integración con repositorio SCM

# Crear un proyecto en GitLab, clonar localmente
git clone git@gitlab.example.com:equipo/proyecto-ci.git

# Generar el archivo Jenkinsfile y subirlo al repositorio
git add Jenkinsfile
git commit -m "Agregar pipeline de integracion continua"
git push origin main

# En Jenkins, seleccionar "Pipeline from SCM"
# Configurar la URL del repositorio y las credenciales de acceso

Generación de fragmentos de código

La herramienta de sintaxis del pipeline permite generar fragmentos de código reutilizables como plantillas.

Referencia de sintaxis del Pipeline

Documentación oficial: https://www.jenkins.io/zh/doc/book/pipeline/syntax/

Estructura general

# El bloque pipeline encapsula stages, steps e instrucciones
pipeline {
    # Las sentencias no requieren separadores
    # Cada directiva ocupa su propia línea
}

Directiva agent

Obligatoria. Puede declararse a nivel global o dentro de cada etapa. Parámetros soportados:

  • any: ejecutar en cualquier agente disponible
  • none: sin agente global, cada etapa debe definir el suyo
  • label: filtrar agentes por etiqueta
  • node: similar a label con opciones adicionales
  • docker: ejecutar dentro de un contenedor específico
  • dockerfile: construir imagen desde un Dockerfile y ejecutar en ella

Ejecución en agente por etiqueta

pipeline {
    agent {
        label 'worker-alpha'
    }
    stages {
        stage('Verificacion') {
            steps {
                sh 'hostname'
            }
        }
    }
}

Ejecución en contenedor Docker

pipeline {
    agent {
        docker {
            image 'registry.example.com/tools/alpine:v2'
            label 'worker-alpha'
        }
    }
    stages {
        stage('Verificacion') {
            steps {
                sh 'hostname -i'
            }
        }
    }
}

Construcción desde Dockerfile

pipeline {
    agent {
        dockerfile {
            filename 'Dockerfile'
            dir './containers/alpine'
            label 'worker-alpha'
            additionalBuildArgs '--build-arg entorno=produccion'
        }
    }
    stages {
        stage('Verificacion') {
            steps {
                sh 'hostname -i'
            }
        }
    }
}

Bloque post

Define acciones que se ejecutan según el resultado del pipeline o de una etapa. Los condicionales disponibles son:

  • always: se ejecuta sin importar el resultado
  • changed: se ejecuta solo si el estado cambió respecto a la ejecución anterior
  • failure: se ejecuta cuando el estado es fallido (rojo en la interfaz)
  • success: se ejecuta cuando el estado es exitoso (verde o azul)
  • unstable: se ejecuta cuando hay fallos en pruebas o violaciones de código (amarillo)
  • aborted: se ejecuta cuando el pipeline fue cancelado manualmente (gris)
pipeline {
    agent any
    stages {
        stage('Ejemplo') {
            steps {
                echo 'Hola Mundo'
            }
        }
    }
    post {
        always {
            echo 'Este mensaje aparece siempre'
        }
    }
}

Ejemplo con post en múltiples niveles

pipeline {
    agent {
        dockerfile {
            filename 'Dockerfile'
            dir './containers/alpine'
            label 'worker-alpha'
            additionalBuildArgs '--build-arg version=stable'
        }
    }
    stages {
        stage('Compilacion') {
            steps {
                sh 'hostname -i'
            }
            post {
                always {
                    echo "Ejecucion completada"
                }
                success {
                    echo "Compilacion exitosa"
                }
                failure {
                    echo "Compilacion fallida"
                }
            }
        }
    }
    post {
        always {
            echo 'Siempre se ejecuta'
        }
        success {
            echo 'Resultado: exito'
        }
        failure {
            echo 'Resultado: fallo'
        }
        unstable {
            echo 'Resultado: inestable'
        }
        changed {
            echo 'Estado cambiado'
        }
    }
}

Bloque stages

Contenedor obligatorio que agrupa una o más etapas del pipeline.

pipeline {
    agent any
    stages {
        stage('Ejemplo') {
            steps {
                echo 'Hola Mundo'
            }
        }
    }
}

Bloque steps

Define las operaciones concretas a realizar dentro de una etapa. Es obligatorio dentro de cada stage.

pipeline {
    agent any
    stages {
        stage('Ejemplo') {
            steps {
                echo 'Hola Mundo'
            }
        }
    }
}

Variables de entorno

Se declaran con la directiva environment. Su alcance depende de dónde se definan. La función credentials() permite acceder a credenciales almacenadas.

pipeline {
    agent any
    environment {
        COMPILADOR = 'clang'
    }
    stages {
        stage('Ejemplo') {
            environment {
                CLAVE_SECRETA = credentials('mi-texto-secreto')
            }
            steps {
                sh 'printenv'
            }
        }
    }
}

Variables estáticas

# Las variables se resuelven siguiendo un alcance jerárquico interno a externo
pipeline {
    agent {
        dockerfile {
            filename 'Dockerfile'
            dir './containers/alpine'
            label 'worker-alpha'
        }
    }
    environment {
        PROYECTO = 'MiAplicacion'
        AMBIENTE = 'produccion'
    }
    stages {
        stage('Compilacion') {
            environment {
                AMBIENTE = 'pruebas'
            }
            steps {
                sh 'echo "Proyecto: $PROYECTO"'
                sh 'echo "Ambiente: $AMBIENTE"'
            }
        }
    }
}

Variables dinámicas

# Requiere que se haya definido un agente
pipeline {
    agent {
        label 'worker-alpha'
    }
    environment {
        SALUDO = """${sh(
            returnStdout: true,
            script: 'echo "Hola desde el agente"'
        )}"""
        CODIGO_SALIDA = """${sh(
            returnStatus: true,
            script: 'exit 0'
        )}"""
    }
    stages {
        stage('Mostrar') {
            steps {
                sh 'echo "Saludo: $SALUDO"'
                sh 'echo "Codigo: $CODIGO_SALIDA"'
            }
        }
    }
}

Directiva options

Configura comportamientos específicos del pipeline:

  • buildDiscarder: limitar el número de ejecuciones históricas conservadas
  • disableConcurrentBuilds: impedir ejecuciones simultáneas
  • skipDefaultCheckout: omitir la clonación automática del código fuente
  • skipStagesAfterUnstable: detener etapas adicionales si el estado es inestable
  • checkoutToSubdirectory: clonar código en un subdirectorio específico
  • timeout: establecer un límite de tiempo para la ejecución
  • retry: reintentar el pipeline un número determinado de veces en caso de fallo
  • timestamps: añadir marca temporal a cada línea de la consola
pipeline {
    agent any
    options {
        timeout(time: 30, unit: 'MINUTES')
        disableConcurrentBuilds()
        timestamps()
    }
    stages {
        stage('Ejemplo') {
            steps {
                echo 'Proceso con limite de tiempo'
            }
        }
    }
}

Directiva parameters

Define entradas que el usuario proporciona al iniciar la construcción. Se acceden mediante params.NOMBRE.

pipeline {
    agent any
    parameters {
        string(name: 'DESTINATARIO', defaultValue: 'Equipo', description: '¿A quién dirigir el saludo?')
    }
    stages {
        stage('Saludo') {
            steps {
                echo "Hola ${params.DESTINATARIO}"
            }
        }
    }
}

Directiva triggers

Define los mecanismos que inician la ejecución del pipeline:

  • cron: programación temporal con sintaxis cron
  • pollSCM: sondeo del repositorio de código con detección de cambios
  • upstream: activación cuando otros trabajos completan con un estado mínimo
triggers {
    cron('H 2 * * 1-5')        // Ejecutar de lunes a viernes a las 2 AM
    pollSCM('H/15 * * * *')    // Verificar cambios cada 15 minutos
    upstream('compilar,empaquetar', threshold: hudson.model.Result.SUCCESS)
}

Directiva input

Crea puntos de interacción donde el pipeline espera confirmación o datos del usuario.

pipeline {
    agent any
    stages {
        stage('Aprobacion') {
            input {
                message "¿Deseas continuar con el despliegue?"
                ok "Sí, desplegar"
                submitter "admin,lider-tecnico"
                parameters {
                    string(name: 'VERSION', defaultValue: '1.0.0', description: 'Version a desplegar')
                }
            }
            steps {
                echo "Desplegando version ${VERSION}"
            }
        }
    }
}

Directiva when

Controla la ejecución condicional de etapas. Se evalúa antes de asignar el agente a la etapa. Condiciones disponibles:

  • branch: coincide con el nombre de la rama (solo pipelines multibranch)
  • environment: verifica el valor de una variable de entorno
  • expression: evalúa una expresión Groovy
  • not: invierte la condición anidada
  • allOf: todas las condiciones deben cumplirse (AND lógico)
  • anyOf: al menos una condición debe cumplirse (OR lógico)

Directiva parallel

Ejecuta múltiples etapas simultáneamente, distribuyéndolas entre diferentes agentes para optimizar el tiempo.

pipeline {
    agent any
    stages {
        stage('Preparacion') {
            steps {
                sh 'hostname; date'
                echo 'Etapa inicial de preparacion'
            }
        }
        stage('Ejecucion paralela') {
            parallel {
                stage('Analisis') {
                    agent { label 'worker-alpha' }
                    steps {
                        sh 'hostname; date'
                        echo 'Ejecutando analisis de codigo'
                        sleep 8
                    }
                }
                stage('Pruebas') {
                    agent any
                    steps {
                        sh 'hostname; date'
                        echo 'Ejecutando suite de pruebas'
                        sleep 5
                    }
                }
            }
        }
        stage('Finalizacion') {
            agent { label 'worker-alpha' }
            steps {
                sh 'hostname; date'
                echo 'Etapa final completada'
            }
        }
    }
}

Manejo de secretos en pipelines

Texto secreto

pipeline {
    agent {
        label 'worker-alpha'
    }
    environment {
        TOKEN_ACCESO = credentials('secreto-k8s')
    }
    stages {
        stage('Uso') {
            steps {
                sh 'echo $TOKEN_ACCESO'  // Se muestra enmascarado en la consola
            }
        }
    }
}

Credenciales de usuario y contraseña

pipeline {
    agent {
        label 'worker-alpha'
    }
    environment {
        GITLAB_CREDS = credentials('cred-gitlab')
        GITLAB_USUARIO = credentials('cred-gitlab')
        GITLAB_CONTRASENA = credentials('cred-gitlab')
    }
    stages {
        stage('Autenticacion') {
            steps {
                sh 'echo "Usuario: $GITLAB_USUARIO"'          // Visible en texto plano
                sh 'echo "Password: $GITLAB_CONTRASENA"'      // Enmascarado en consola
                sh 'echo "Credencial: $GITLAB_CREDS"'         // usuario:contraseña enmascarado
            }
        }
    }
}

Herramientas (Tools)

Las herramientas representan utilidades instaladas en los agentes, como Maven, Docker o Git. Cada versión se registra con un nombre único, facilitando su invocación dentro del pipeline.

Casos de uso prácticos

Integración continua (CI)

Objetivo: al enviar código al repositorio, ejecutar automáticamente la obtención del código, análisis estático, compilación y publicación de artefactos en un registro privado.

Plugins necesarios: GitLab, SonarQube Scanner, Harbor.

Obtención del código fuente

Configurar clave SSH en el agente

Registrar la clave pública del agente en la configuración de acceso del repositorio GitLab.

Verfiicar la conexión

Crear un pipeline simple que ejecute git clone para confirmar que las credenciales funcionan correctamente.

Análisis estático con SonarQube

Configurar SonarQube Server

Registrar la instancia de SonarQube en la cnofiguración global de Jenkins.

Integrar con GitLab

# Instalar el plugin GitLab Branch Source
# Configurar la conexión con el servidor GitLab

Crear webhook de notificación

# Definir un pipeline y anotar la URL del webhook junto con el token generado
# Registrar dicha URL como webhook en la configuración del proyecto en GitLab

Registrar la herramienta sonar-scanner

En la configuración global de herramientas de Jenkins, agregar una entrada para sonar-scanner apuntando a la instalación local.

Archivo de configuración del proyecto

# Crear el archivo sonar-project.properties en la raíz del repositorio
sonar.projectKey=mia-app
sonar.projectName=Mia App
sonar.sources=src

Pipeline de análisis

node {
    stage('Obtener codigo') {
        checkout scm
    }
    stage('Analisis SonarQube') {
        def scanner = tool 'sonar-scanner'
        withSonarQubeEnv() {
            sh "${scanner}/bin/sonar-scanner"
        }
    }
}

Empaquetado de aplicaciones

Construcción de imagen Docker

stage('Empaquetar') {
    steps {
        script {
            def imagen = docker.build("registry.interno/mia-app:${env.BUILD_ID}", "-f docker/Dockerfile .")
            imagen.push()
            imagen.push('latest')
        }
    }
}

Compilación con Maven

pipeline {
    agent {
        docker {
            image 'registry.interno/maven:3.8'
            args '-v /opt/maven-conf/settings.xml:/usr/share/maven/conf/settings.xml'
        }
    }
    stages {
        stage('Compilar') {
            steps {
                sh 'mvn clean package -DskipTests=true'
            }
        }
    }
}

Entrega continua (CD)

Plugins requeridos

  • Git: obtiene el código fuente desde repositorios remotos
  • Docker: gestiona entornos contenedorizados y credenciales de registros
  • Kubernetes: provisiona agentes dinámicos dentro del clúster para ejecutar trabajos
  • Kubernetes CLI: proporciona el entorno para ejecutar comandos kubectl y helm
  • Config File Provider: almacena archivos de configuración reutilizables (settings.xml, properties, etc.)
  • Pipeline Utility Steps: facilita la lectura y manipulación de archivos como pom.xml, JSON o YAML
  • Git Parameter: lista dinámicamente las ramas del repositorio para que el usuario seleccione cuál desplegar

Credenciales necesarias

  • Credencial de acceso al repositorio Git
  • Token de servicio para el clúster Kubernetes
  • Credencial de acceso al registro de contenedores Docker

Pipeline de despliegue con agentes Kubernetes

pipeline {
    agent {
        kubernetes {
            yaml '''
apiVersion: v1
kind: Pod
metadata:
  labels:
    app: jenkins-worker
spec:
  nodeSelector:
    kubernetes.io/hostname: node-trabajo-01
  volumes:
    - name: bin-kubectl
      hostPath:
        path: /usr/local/bin/kubectl
    - name: kube-config
      hostPath:
        path: /home/deploy/.kube/config
  containers:
    - name: jnlp
      image: registry.interno/jnlp-agent:latest
      workingDir: /home/jenkins/workspace
    - name: herramientas
      image: registry.interno/busybox:stable
      volumeMounts:
        - name: bin-kubectl
          mountPath: /usr/bin/kubectl
        - name: kube-config
          mountPath: /root/.kube/config
      command:
        - cat
      tty: true
'''
            retries 2
        }
    }
    stages {
        stage('Desplegar') {
            steps {
                container('herramientas') {
                    sh 'kubectl get nodes'
                    sh 'kubectl apply -f k8s/deployment.yaml'
                }
            }
        }
    }
}

Etiquetas: Jenkins CI/CD Pipeline Groovy Docker

Publicado el 6-11 16:25