Terraform+Proxmox, la experiencia en mi homelab, parte 3

En esta entrada veremos como interactuar con Terraform y los contenedores o CTs, como comúnmente los llamamos.

Nota: para este procedimiento se requiere la plantilla de CT de Debian11 para Proxmox, la cual se puede descargar por la interfaz de proxmox:

O por consola y copiarla en /var/lib/vz/template/cache:

wget -c http://download.proxmox.com/images/system/debian-11-standard_11.0-1_amd64.tar.gz -P /var/lib/vz/template/cache

Lo primero es crear una carpeta dónde vamos a trabajar, el nombre no importa cual sea, sólo que sea un identificativo para el trabajo que haremos. Crearemos un contenedor o CT, llamado test, que se encenderá automaticamente cuando encienda el sistema, y lo prepararemos para que haga ciertas funciones, que definiremos en un script que ejecutará después de que el CT esté completamente funcional.

mkdir test; cd test
nano providers.tf

Contenido:

terraform {
  required_providers {
    proxmox = {
      source  = "telmate/proxmox"
      version = "2.9.10"
    }
  }
}
# usando el provider
provider "proxmox" {
  pm_api_url = var.pve_host
  pm_user = var.pve_user
  pm_password = var.pve_pass
  pm_tls_insecure = true
}

Ahora bien, acá en providers.tf hemos definido el provider, que es el plugin telmate/proxmox, que ya descargamos y está en nuestro home, descrito en la parte 1 de esta serie.

Acá vemos también declaración de variables, que ahora mismo veremos donde están y cómo se usan. Para ello necesitaremos el archivo vars.tf:

nano vars.tf

Contenido:

# servidor proxmox, ajustar según las necesidades
variable "pve_host" {
  description = "Proxmox server"
  default = "https://192.168.0.250:8006/api2/json"
}
# usuario del proxmox
variable "pve_user" {
  description = "Proxmox username"
  type  = string
  sensitive = true
  default = "root@pam"
}
# password el proxmox se necesita para que terraform le pase parámetros por la API
variable "pve_pass" {
  description = "Proxmox password"
  type = string
  sensitive = true
  default = "ZmVjMjNQNmNlZpU2ZmQ2ZjkyNTMzZDdm"
}
# password del ct
variable "ct_pass" {
  description = "Container password"
  type = string
  sensitive = true
  default = "Admin*123"
}
# hostname del ct
variable "hostname" {
    default = "test"
}
# dns server
variable "dns_server" {
    default = "192.168.0.2"
}
# dominio
variable "dns_domain" {
    default = "inutil.cu"
}
# cat .ssh/id_rsa.pub
variable "ssh_key" {
  default = "ssh-rsa AAAAB3NzaC1yc2EAaAADAqABAAABgQCyQiMi2HhPtLRS+HFCVwPY41EI5cwAbshyUt3J48MKvWSOW0exgJp6jbSm3xgfZMJ4BfLr8KXo5mx7CS3PcrSlBaWg7ebUsWXKdbgVmehE77+0ZIjvo9McT/xZIJnlb6FYRUcPvww5ay03AWg8D0QBskCeYnfEd4fPadxzvtKWJ5CoG+wabvcv50+QbkOWcBUWUQ3XEp97thb9bQxPeMRRmnJu2g5LwZ9ZKgg5Vu4r4TKaHEnofFxJDLzLBdTu4ms3WjBMiMAdwfykgMQxTBPA2BCSqraMH5q/osGPRKqDnZsqwYgCkF/KBHnZpTmJzIA9Lt2ujQmix4CdOyd0O1ECwqfcx8FLGdZr4lGP0jepHgZ9tsD08HQq629R/ljf8DR7iiVF0LEJLPH2EGf/2ulDFlxyCcC6zMQztQNaCPrLcqAGZPTqNz9erfZ9GllyGJh91T8ucy+yCYYHEkLURuhL4w3GdkPlpuDstY33T7wszOr/lawCNTsTcYZ1764+aC0= koratsuki@happyharry"
}
# Aca va la plantilla que usaremos, puede ser Debian/Ubuntu u otra.
variable "template_name" {
    default = "external:vztmpl/debian-11-standard_11.0-1_amd64.tar.gz"
}

Y ahora el archivo main.tf, el cual nos definirá como se crea el CT:

nano main.tf

Contenido:

resource "proxmox_lxc" "test" {
  count = 1
  onboot = true
  start = true
  vmid = "201"
  hostname = var.hostname
  ostype = "debian"
  cores = 2
  cpulimit = 0
  memory = 1024
  swap = 512
  ostemplate = var.template_name
  password = var.ct_pass
  pool = ""
  ssh_public_keys = var.ssh_key

  rootfs {
    storage= "external"
    size="8G"
  }

  nameserver = var.dns_server
  searchdomain = var.dns_domain

  network {
    name = "eth0"
    bridge = "vmbr0"
    ip = "192.168.0.201/24"
    gw = "192.168.0.254"
    firewall = false
  }

  features {
    nesting = true
  }

  unprivileged = false
  target_node = "pve1"

  connection {
    type     = "ssh"
    user     = "root"
    private_key = file(pathexpand("~/.ssh/id_rsa"))
    host     = "192.168.0.201"
  }

  provisioner "file" {
    source = "config/script.sh"
    destination = "/tmp/script.sh"
  }

  provisioner "remote-exec" {
    inline = [
    "chmod +x /tmp/script.sh",
    "/tmp/script.sh args",
    ]
    on_failure = continue
  }
}

Acá hemos definido lo mismo que hacemos vía web, a la hora de crear un contenedor, pero mediante código, y al final, dentro de la carpeta config hemos creado un script que se copiará al contenedor recién creado y se ejecutará.

nano config/script.sh

Contenido:

#!/bin/bash

# deshabilitamos resolved
systemctl stop systemd-resolved
systemctl disable systemd-resolved
systemctl mask systemd-resolved

# definimos la zona horaria
timedatectl set-timezone America/Havana

# Repos locales en caso de tenerlos
echo "deb http://repo.inutil.cu/debian/bullseye bullseye main contrib non-free" > /etc/apt/sources.list
echo "deb http://repo.inutil.cu/debian/bullseye-security bullseye-security main contrib non-free" >> /etc/apt/sources.list

# Removing unused things
apt purge -y postfix* rpcbind

# Upgrade system
apt update ;; apt dist-upgrade -y

# Installing stuff
apt install -y mc net-tools dnsutils wget git rsync \
 p7zip-full htop iftop nethogs telnet screen multitail \
 ccze lzma xz-utils rar unrar ;; apt clean

Entonces, listo todo, sólo queda ejecutar todo:

$ terraform init

Entonces, empezamos bien, se inicializó terraform y el plugin para proxmox, Ahora:

$ terraform plan

Acá Terraform te muestra todo el plan que vas a ejecutar, en detalle. Ahora sólo queda ejecutar el provisionado:

$ terraform apply

Terraform nos recordará todo lo anterior y nos avisará que estamos listos, que acepte para empezar:


Y listo, empezará el provisionamiento:

Y con esto, ya tenemos nuestro CT creado y provisionado, actualizado mediante script externo. Nos vemos en la parte 4 de este tutorial, donde haremos lo mismo, pero para VMs. Un saludo y happy hacking!

 

Referencias:
https://www.terraform.io/language/values/variables

¿De cuánta utilidad te ha parecido este contenido?

Leslie León Sinclair

Compartir
Publicado por
Leslie León Sinclair

Entradas recientes

Alta disponibilidad de sus base de datos con Percona XtraDB Cluster en Kubernetes

Uno de los grandes retos al que nos podemos enfrentar cuando una aplicación crece, es…

8 meses hace

Home automation (Parte 3) – ESPHome

Qué es lo que deseo hacer en este capítulo? Básicamente un sonoff, quiero encender/apagar las…

1 año hace

Home automation (Parte 2) – Home Assistant

Hace algunos meses estoy escuchando hablar del proyecto Home Assistant (HA). En palabras literales del…

1 año hace

Home automation (Parte 1)

Desde hace varios meses vengo con la idea de automatizar la casa donde vivo. Poco…

1 año hace

Cocinando una imagen personalizada de OpenWRT

El artículo describe el uso para un caso particular de OpenWRT y la creación de…

1 año hace