Terraform libvirt - Script para criar uma infra Kubernetes

main.tf
main.tf 
# Provedor necessário para interagir com o Libvirt
terraform {
  required_providers {
    libvirt = {
      source = "dmacvicar/libvirt"
    }
  }
}
 
# URI para conectar ao Libvirt
provider "libvirt" {
  #uri = "qemu:///system"  
  uri = "qemu+ssh://gean@192.168.0.250/system"
}
 
resource "libvirt_network" "kube_net" {
  name      = "kube_net"
  mode      = "nat"
  addresses = ["10.1.2.0/24"]
  autostart = true
 
  dhcp {
    enabled = false
  }
 
}
 
variable "vms" {
  type = list(object({
    name           = string # Nome da VM
    cpu            = number # Número de CPUs
    memory         = number # Quantidade de memória (MB)
    disksize       = number # Tamanho do disco (GB)
    storage_pool   = string # Pool de armazenamento
    os_image_name  = string # Nome da imagem do sistema operacional
    os_datas_name  = string # Nome dos dados do sistema operacional
    network_name   = string # Nome da rede
    user_data      = string # Caminho para o arquivo de configuração de inicialização em nuvem
    network_config = string # Caminho para o arquivo de configuração de rede
    os_image_url   = string # URL da imagem do sistema operacional
  }))
}
 
# Recurso para criar volumes de imagens do sistema operacional
resource "libvirt_volume" "os_image" {
  for_each = { for vm in var.vms : vm.name => vm }
 
  name   = each.value.os_image_name
  pool   = each.value.storage_pool
  source = each.value.os_image_url
  format = "qcow2"
}
 
# Recurso para criar volumes de dados do sistema operacional baseados nas imagens
resource "libvirt_volume" "os_datas" {
  for_each = { for vm in var.vms : vm.name => vm }
 
  name           = each.value.os_datas_name
  base_volume_id = libvirt_volume.os_image[each.key].id
  pool           = each.value.storage_pool
  size           = each.value.disksize * 1024 * 1024 * 1024
}
 
# Recurso para carregar arquivos de configuração de inicialização em nuvem
data "template_file" "user_data" {
  for_each = { for vm in var.vms : vm.name => vm }
 
  template = file(each.value.user_data)
}
 
# Recurso para carregar arquivos de configuração de rede
data "template_file" "network_config" {
  for_each = { for vm in var.vms : vm.name => vm }
 
  template = file(each.value.network_config)
}
 
# Recurso para criar discos de inicialização em nuvem
resource "libvirt_cloudinit_disk" "cloudinit" {
  for_each = { for vm in var.vms : vm.name => vm }
 
  name           = "cloudinit_${each.key}.iso"
  user_data      = data.template_file.user_data[each.key].rendered
  network_config = data.template_file.network_config[each.key].rendered
  pool           = each.value.storage_pool
}
 
# Recurso para criar as instâncias de máquinas virtuais
resource "libvirt_domain" "domain" {
  for_each = { for vm in var.vms : vm.name => vm }
 
  name   = each.value.name
  memory = each.value.memory
  vcpu   = each.value.cpu
 
  cpu {
    mode = "host-passthrough"
  }
 
  cloudinit = libvirt_cloudinit_disk.cloudinit[each.key].id
 
  network_interface {
    network_name   = each.value.network_name
  }
 
  console {
    type        = "pty"
    target_port = "0"
    target_type = "serial"
  }
 
  console {
    type        = "pty"
    target_type = "virtio"
    target_port = "1"
  }
 
  disk {
    volume_id = libvirt_volume.os_datas[each.key].id
  }
 
  graphics {
    type        = "spice"
    listen_type = "address"
    autoport    = true
  }
}
kube-master-cloud-init.yml
#cloud-config
 
fqdn: kube-master-01.exemple.com
manage_etc_hosts: true
 
## Modifying root password
chpasswd:
  list: |
    root:root
  expire: False
 
## Enable direct root access
disable_root: false
 
## Allow ssh password authentication
ssh_pwauth: true
 
## Setup users and ssh keys
users:
  - name: gean
    gecos: Gean Martins
    groups: users, sudo
    shell: /bin/bash
    sudo: ALL=(ALL) NOPASSWD:ALL
    lock_passwd: true
    ssh_authorized_keys:
      - ${file("~/.ssh/id_ed25519.pub")}
  - name: root
    ssh_authorized_keys:
      - ${file("~/.ssh/id_ed25519.pub")}
 
## Install packages
package_update: true
package_upgrade: true
packages:
  - qemu-guest-agent
  - vim
  - git
  - python
 
## Set Hostname
runcmd:
  - hostnamectl set-hostname kube-master-01.exemple.com
kube-master-network-config.yml
#cloud-config
network:
  version: 2
  ethernets:
    ens3:
      addresses:
        - 10.1.2.100/24
      nameservers:
        addresses: 
          - 10.1.2.1
      routes:
        - to: default
          via: 10.1.2.1
kube-node-01-cloud-init.yml
#cloud-config
 
fqdn: kube-node-01.exemple.com
manage_etc_hosts: true
 
## Modifying root password
chpasswd:
  list: |
    root:root
  expire: False
 
## Enable direct root access
disable_root: false
 
## Allow ssh password authentication
ssh_pwauth: true
 
## Setup users and ssh keys
users:
  - name: gean
    gecos: Gean Martins
    groups: users, sudo
    shell: /bin/bash
    sudo: ALL=(ALL) NOPASSWD:ALL
    lock_passwd: true
    ssh_authorized_keys:
      - ${file("~/.ssh/id_ed25519.pub")}
  - name: root
    ssh_authorized_keys:
      - ${file("~/.ssh/id_ed25519.pub")}
 
## Install packages
package_update: true
package_upgrade: true
packages:
  - qemu-guest-agent
  - vim
  - git
  - python
 
## Set Hostname
runcmd:
  - hostnamectl set-hostname kube-node-01.exemple.com
kube-node-01-network-config.yml
#cloud-config
network:
  version: 2
  ethernets:
    ens3:
      addresses: 
        - 10.1.2.101/24
      nameservers:
        addresses: 
          - 10.1.2.1
      routes:
        - to: default
          via: 10.1.2.1
kube-node-02-cloud-init.yml
#cloud-config
 
fqdn: kube-node-02.exemple.com
manage_etc_hosts: true
 
## Modifying root password
chpasswd:
  list: |
    root:root
  expire: False
 
## Enable direct root access
disable_root: false
 
## Allow ssh password authentication
ssh_pwauth: true
 
## Setup users and ssh keys
users:
  - name: gean
    gecos: Gean Martins
    groups: users, sudo
    shell: /bin/bash
    sudo: ALL=(ALL) NOPASSWD:ALL
    lock_passwd: true
    ssh_authorized_keys:
      - ${file("~/.ssh/id_ed25519.pub")}
  - name: root
    ssh_authorized_keys:
      - ${file("~/.ssh/id_ed25519.pub")}
 
## Install packages
package_update: true
package_upgrade: true
packages:
  - qemu-guest-agent
  - vim
  - git
  - python
 
## Set Hostname
runcmd:
  - hostnamectl set-hostname kube-node-02.exemple.com
kube-node-02-network-config.yml
#cloud-config
network:
  version: 2
  ethernets:
    ens3:
      addresses: 
        - 10.1.2.102/24
      nameservers:
        addresses: 
          - 10.1.2.1
      routes:
        - to: default
          via: 10.1.2.1

Opções para definição de rede

network:
  ethernets:
    ens160:
      addresses:
      - 10.10.20.6/24
      nameservers:
        addresses:
        - 10.10.20.71
      routes:
          - to: default
            via: 10.10.20.1
  version: 2
network:
  ethernets:
    ens160:
      addresses:
      - 10.10.20.6/24
      - 2001:678:e20:20::6/64
      nameservers:
        addresses:
        - 10.10.20.71
      routes:
          - to: default
            via: 10.10.20.1
          - to: default
            via: 2001:678:e20:20::1
  version: 2
terraform.tfstate
# Configurações das máquinas virtuais
vms = [
  {
    name           = "kube-master-01"
    cpu            = 2
    memory         = 2048
    disksize       = 32
    storage_pool   = "default"
    os_image_name  = "kube_master_01_image.qcow2"
    os_datas_name  = "kube_master_01_datas.qcow2"
    network_name   = "kube_net"
    ip_address     = "10.1.2.100"
    user_data      = "kube-master-cloud-init.yml"
    network_config = "kube-master-network-config.yml"
    os_image_url   = "/var/lib/libvirt/templates/debian-12-generic-amd64.qcow2"
  },
  {
    name           = "kube-node-01"
    cpu            = 2
    memory         = 2048
    disksize       = 32
    storage_pool   = "default"
    os_image_name  = "kube_01_image.qcow2"
    os_datas_name  = "kube_01_datas.qcow2"
    network_name   = "kube_net"
    ip_address     = "10.1.2.101"
    user_data      = "kube-node-01-cloud-init.yml"
    network_config = "kube-node-01-network-config.yml"
    os_image_url   = "/var/lib/libvirt/templates/debian-12-generic-amd64.qcow2"
  },
 
  {
    name           = "kube-node-02"
    cpu            = 2
    memory         = 2048
    disksize       = 32
    storage_pool   = "default"
    os_image_name  = "kube_02_image.qcow2"
    os_datas_name  = "kube_02_datas.qcow2"
    network_name   = "kube_net"
    ip_address     = "10.1.2.102"
    user_data      = "kube-node-02-cloud-init.yml"
    network_config = "kube-node-02-network-config.yml"
    os_image_url   = "/var/lib/libvirt/templates/debian-12-generic-amd64.qcow2"
  }
]

Referências