Usando Jenkins junto a Terraform para desplegar infraestructura

En la anterior entrada vimos como crear un contenedor LXC en proxmox mediante terraform. He seguido tirando del hilo y haciendo pruebas y he creado una pequeña máquina con Jenkins para realizar pruebas

De una forma resumida, Jenkins, es una plataforma de CI/CD OpenSource basada en Java. En este caso, nos permitirá, mediante el uso de plugins, el crear contenedores LXC de forma sencilla, cómoda y rápida.

La instalación del jenkins no está contemplada en esta guía pero se añade el enlace a la documentación oficial.

De forma básica y sencilla, lo que montaremos para hacer funcionar este laboratorio es lo siguiente:

Desde GitHub crearemos todos los ficheros de configuración necesarios para luego, desde Jenkins, mediante el plugin de Terraform y Git, hacer un checkout del repositorio, modificar esos ficheros de configuración mediante variables que indicaremos en el job de Jenkins y, con Terraform, crear el LXC en el servidor de Proxmox.

Crear repostiorio de Git Hub

Aunque este paso no es obligatorio, si creo que otorga un toque de realidad a lo que puede ser una infraestructura más parecida a un entorno real. Para este laboratorio, he creado un repositorio donde almaceno 3 ficheros diferentes:

  • provider.tf: Fichero de configuración de terraform donde indico el proveedor que usaré
  • main.tf: Configuraciones que quiero indicar para crear el LXC
  • variables.tf: Variables que son llamadas en el main.tf y que son definidas en el job de jenkins.

Sobre todo estes ficheros , hablo en otra entrada de esta misma web. Pongo un ejemplo de estos ficheros por aqui:

provider.tf:

terraform {
  required_providers {
    proxmox = {
      source  = "telmate/proxmox"
      version = ">=1.0.0"
    }
  }
}
provider "proxmox" {
  pm_api_url = "https://192.168.1.106:8006/api2/json"
  pm_api_token_id = "terraform@pam!terraform"
  pm_api_token_secret = "2e9de334-bf80-4ddb-bcd5-dd3e3409f17c"
}

main.tf:

resource "proxmox_lxc" "test" {
  hostname      = var.vm_name   #Nombre del contenedor
  vmid          = 117
  target_node   = "pve"         # Nodo de Proxmox donde se desplegar el CT
  ostemplate    = "local:vztmpl/debian-11-standard_11.7-1_amd64.tar.zst"  # Ruta al template de Debian 11
  rootfs {
    storage     = "local-lvm"   # Almacenamiento para el sistema de archivos raiz
    size        = var.disk_size_gb          # Tam disco raiz
  }
  cores         = var.vm_cores             # Numero de CPUs
  memory        = var.vm_memory_gb           # Memoria en MB
  network {
    name        = "eth0"        # Nombre de la interfaz de red
    bridge      = "vmbr0"       # Bridge de red en Proxmox
    ip          = "dhcp"        # Configuracion de red
  }
#  nameserver    = "192.168.1.1"
  ssh_public_keys = <<-EOT
    <clave publica ssh>
  EOT
}

variables.tf:

variable "vm_name" {
  description = "Nombre de la maquina virtual"
  type        = string
}

variable "hostname" {
  description = "Hostname de la maquina virtual"
  type        = string
}

variable "disk_size_gb" {
  description = "Tamanho del disco en GB"
  type        = string
}

variable "vm_cores" {
  description = "Numero de cores de CPU"
  type        = number
}

variable "vm_memory_gb" {
  description = "Memoria en GB"
  type        = string
}

Con estos 3 ficheros creados podemos proceder al siguiente paso.

Configuración Jenkins

En Jenkins, será necesario instalar 2 plugins, el de Git y el de Terraform. Una vez instalados, procedemos a crear un nuevo Job Pipeline.
Sobre este job tenemos que aplicar las siguientes configuraciones:

Parámetros para definir las variables.

Deberemos añadir los parametros necesarios para cubrir las variables anteriormente mencionadas. Un ejemplo sería:

En el punto 1, marcamos que la ejecucuión debe usar parámetros. A posteriori añadimos los tipos de párametros que se consideren apropiados. En mi caso, he usado uno de cadena para las variables de nombre, disco (debido a que es necesario especificar la unidad, p.j: 8GB) y para el resto, CPU, RAM parámetros de elección

Configurar el proyecto de Git Hub

Para ello añadimos el proyecto en el propio config del job:

En mi caso, el repositorio es privado, por lo que he tenido que loguearme en la máquina de jenkins con el usuario de Jenkins, generar una clave SSH y autorizarla en el repositorio. De esta forma, le damos permisos para poder hacer el checkout del repositorio o otras tareas, que es posible que sean necesarias hacer en un futuro.

Configurar terraform

Con el plugin instalado, desde la configuración de Jenkins, debemos especificar la ruta a los binarios de terraform:

Configuración del Pipeline

Por último, debemos configurar el Pipeline para que ejecute los pasos necesarios:

  1. Hacer checkout del repositorio
  2. Cambiaremos el nombre de la máquina en el fichero tf
  3. Lanzar el terraform init
  4. Lanzar el terraform apply
  5. Borrar el terraform.tfstate para poder lanzar nuevas ejecuciones sin errores

Aqui dejo el script de pipeline resultante:

pipeline {
    agent any
    
    environment {
        TF_VAR_vm_name = "${Nombre}"
        TF_VAR_hostname = "${Nombre}"
        TF_VAR_vm_cores = "${CPU}"
        TF_VAR_disk_size_gb ="${Disco}"
        TF_VAR_vm_memory_gb = "${RAM}"
    }
    
    stages {
        stage('Checkout') {
            steps {
                git branch: 'main', credentialsId: 'jenkins-github', url: 'git@github.com:dporta97/terraform_templates.git'
            }
        }
        
        stage('Cambiar nombre máquina') {
            steps {
                script {
                    sh "sed -i 's/lxc_name/${Nombre}/g' /repos/terraform_templates/main.tf"
                }
            }
        }
        
        
        stage('Terraform initt') {
            steps {
               sh 'terraform init' 
            }
        }
        
        stage('Terraform Apply') {
            steps {
               sh 'terraform apply  -auto-approve' 
            }
        }
        
        stage('Eliminando tfstate') {
            steps {
                script {
                    sh "rm -rf /var/lib/jenkins/workspace/Create LXC with Terrafor/terraform.tfstate"
                }
            }
        }
    }
}

Es necesario modificar el nombre de la máquina de forma manual, debido a que, por lo que he visto, no permiten el uso de variables para definir el nombre o al menos, no he encontrado la forma, todavía.

Conclusión

Con esta sencilla configuración, que todavía se está puliendo para mejorarla, como por ejemplo, mediante el uso de comandos, detectar cual es el último ID disponible a la hora de crear el LXC y que no sea necesario especificarlo a mano, se consigue crear LXC en proxmox de forma sencilla y automatica.