Notas Mentales de Un SysAdmin

blog sobre tecnologías para sysadmin y devops

jenkins

Chuleta – Pipeline para Jenkins

En mi día a día, trabajo bastante con Jenkins. Nada del otro universo, una maquinita local, corriendo jenkins, vinculada con gcloud y cuenta de servicio. Tengo toda la potencia del bash de unix y la versatilidad de Jenkins como CI.

pipeline {
        agent any
        environment {
            STAGE_NAME_BB = ""
            SRC_PATH="[local_src_path]" #Ruta donde deberá encontrarse el proyecto GIT que debe ser compilado.
            SCRIPTS_PATH="[scripts_path]" #Ruta donde se almacena el script para eliminar las imágenes antiguas
            NAMESPACE="[k8_namespace]"
            K8_OBJ="[workload_type]/[workload_name]"
            CONTAINER="[container_name]"
            IMAGE="[src_image]"
        }

        stages {
            stage("Compile Code"){
                steps {
                    notifyBuild("STARTED")
                    script{
                        STAGE_NAME_BB = "Compile Code"
                    }
                    echo "Building..."
                    sh "Comandos a ejecutar para la compilación del código"
                }
            }
            stage("Unit Testing"){
                steps {
                    script{
                        STAGE_NAME_BB = "Unit testing"
                    }
                    echo "En este apartado puedes configurar los test para tu código"
                }
            }
            stage("Image Push & Tag into Container Registry"){
                steps {
                    script{
                        STAGE_NAME_BB = "Image Push & Tag into Container Registry"
                    }
                    echo "# Subir la imagen al container registry..."
                    sh "cd ${SRC_PATH} && mvn jib:build -Djib.to.image=${IMAGE}:${BUILD_NUMBER}"
                    echo "# Agregar la etiqueta latest a la imagen que acabamos de subir"
                    sh "cd ${SRC_PATH} && gcloud container images add-tag ${IMAGE}:${BUILD_NUMBER} ${IMAGE}:latest --quiet"
                }
            }
            stage("Deploying Image into its Kubernetes Container"){
                steps {
                    script{
                        STAGE_NAME_BB = "Deploying Image into its Kubernetes Container"
                    }
                    echo "# Connecting to dev cluster"
                    sh "gcloud container clusters get-credentials [cluster-name] --zone [cluster-zone] --project [project-name]"
                    echo "# Configurar la nueva imagen como la ultima imagen de la carga de trabajo especificada"
                    sh "cd ${SRC_PATH} && kubectl set image ${K8_OBJ} ${CONTAINER}=${IMAGE}:${BUILD_NUMBER} --record -n ${NAMESPACE}"
                    }
                }
            stage("Delete Container Registry Old Images"){
                steps {
                    script{
                        STAGE_NAME_BB = "Delete Container Registry Old Images"
                    }
                    echo "# Deleting old images"
                    echo "# Para mas detalles de este script, podéis consultar esta entrada"
                    sh "cd ${SCRIPTS_PATH} && ./delete_old_images.sh ${IMAGE}"
                }
            }
        }
        post {
            success {
                notifyBuild("SUCCESSFUL")
            }
            failure {
                notifyBuild("FAILED ${STAGE_NAME_BB}")
            }
        }
    }

    def notifyBuild(String buildStatus = 'STARTED') {
        // build status of null means successful
        buildStatus =  buildStatus ?: 'SUCCESSFUL'

        // Default values
        def colorName = 'RED'
        def colorCode = '#FF0000'
        def subject = "${buildStatus}: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'"
        def summary = "${subject} (${env.BUILD_URL})"

        // Override default values based on build status
        if (buildStatus == 'STARTED'){
            color = 'YELLOW'
            colorCode = '#FFFF00'
            summary = "${subject} (${env.BUILD_URL})"
        }
        else if (buildStatus == 'SUCCESSFUL') {
            color = 'GREEN'
            colorCode = '#00FF00'
        }
    }

Problema resuelto!

Pipeline en Jenkins para Rollback en Función del Entorno

La entrada de hoy es algo de lo que me siento realmente orgullosa. Llevo pocos meses trabajando con Jenkins y familiarizándome con su lenguaje, y hacer un script que te permita el rollback es una herramienta que pienso guardar en mi cajón de sastre.

Las necesidades que tenía eran:

  • Elegir la imagen del container registry para un deployment y un container dado de Kubernetes, en función del entornos, en mi caso prod y dev.
  • Necesitaba que me generara una lista de las etiquetas de la imagen del Container Registry de GCP en función del entorno.
  • Necesitaba que fuera interactivo, y que el usuario que lo lanza pudiera decidir que versión restaurar.

En mi caso, he elegido el objeto de Jenkins pipeline, que me da un poco más de manga ancha para «programar». Y este es el resultado:

pipeline {

    agent any

    environment {
            ENVIRONMENT = ""
            IMAGE = gcr.io/[PROJECT_ID]/[IMAGE_NAME]
            CMD=""
            TAGS=""
            K8_OBJ="deployment/[deployment-name]"
            CONTAINER="[container_name]"
        }

    stages {

        stage("Select Environment") {
            steps {
                script {
                    // Variables for input

                    // Get the environment
                    def envInput = input(
                            id: 'envInput', message: 'Enter path of test reports:?',
                            parameters: [
                                    choice(name: 'ENVIRONMENT',
                                            choices: ['prod','dev'].join('\n'),
                                            description: 'Please select the Environment')
                            ])

                    // Save to variables. Default to empty string if not found.
                    ENVIRONMENT = envInput?:''


                }
            }
        }
        stage("Select IMAGE f(x) env") {
            steps {
                script {
                    if (ENVIRONMENT == 'prod') {
                        //Image si prod
                        IMAGE = "gcr.io/[PROJECT_ID]/[IMAGE_NAME]"
                    } else {
                        //Image si dev
                        IMAGE = "gcr.io/[PROJECT_ID]/[IMAGE_NAME]"
                    }
                }
            }
        }
        stage("Select available tag") {
            steps {
                script {
                    //Generar la lista de etiquetas disponibles para la imagen dada
                    CMD="gcloud container images list-tags $IMAGE | awk 'NR==2,NR==12' | awk '{print \$2}' | awk -F, '{print \$1}'"
                    TAGS=sh (returnStdout: true, script: CMD ).trim()
                    //Recoger la etiqueta seleccionada por el usuario
                    def tagInput = input(
                            id: 'tagInput', message: 'Enter path of test reports:?',
                            parameters: [
                                    choice(name: 'TAGS',
                                            choices: [TAGS].join('\n'),
                                            description: 'Please select the Environment')
                            ])

                    //Guardar la etiqueta seleccionada por el usuario.
                    TAG = tagInput?:''
                }
            }
        }
        stage("Rollback To Selected Version"){
                steps {
                    sh "kubectl set image ${K8_OBJ} ${CONTAINER}=${IMAGE}:${TAG} --record -n ${ENVIRONMENT}"
                }
            }
    }
}

Y ya estaría. Problema resuelto!

Scroll hacia arriba