
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


