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