# $ vim main.tf
# Configuração do provider Terraform para o uso de libvirt para provisionamento de VMs
terraform {
required_providers {
libvirt = {
source = "dmacvicar/libvirt"
}
}
}
# Definição do provider libvirt com a URI do sistema qemu, que é um hypervisor local
provider "libvirt" {
uri = "qemu:///system"
}
# Declaração de variável para armazenar a configuração das VMs
variable "vms" {
description = "A list of virtual machines"
type = list(object({
name = string
cpu = number
memory = number
disksize = number
docker_vol = number
storage_pool = string
os_image_name = string
os_datas_name = string
docker_vol_name = string
network_name = string
user_data = string
network_config = string
os_image_url = string
}))
default = []
}
# Configuração de rede virtual no libvirt com NAT, sem DHCP, indicando mais controle sobre a conectividade
resource "libvirt_network" "tfnet" {
name = "tfnet"
mode = "nat"
addresses = ["10.1.2.0/24"]
autostart = true
dhcp {
enabled = false
}
dns {
enabled = true
local_only = true
}
}
# Criação de volumes para as imagens do sistema operacional de cada VM, usando contagem baseada no número de VMs
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"
}
# Criação de volumes para os discos de dados de cada VM
resource "libvirt_volume" "os_volume" {
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 // GB to bytes
}
# Criação de volumes para os discos de dados de cada VM
resource "libvirt_volume" "docker_vol" {
for_each = { for vm in var.vms : vm.name => vm }
name = each.value.docker_vol_name
pool = each.value.storage_pool
size = each.value.docker_vol * 1024 * 1024 * 1024 // GB to bytes
}
# Geração de configurações de usuário e rede a partir de templates de arquivos de cloud-init
data "template_file" "user_data" {
for_each = { for vm in var.vms : vm.name => vm }
template = file("${path.module}/${each.value.user_data}")
}
data "template_file" "network_config" {
for_each = { for vm in var.vms : vm.name => vm }
template = file("${path.module}/${each.value.network_config}")
}
# Criação de discos de cloud-init para as VMs, contendo as configurações de usuário e rede
resource "libvirt_cloudinit_disk" "cloudinit" {
for_each = { for vm in var.vms : vm.name => vm }
name = "${each.key}_cloudinit.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
}
# Definição das domínios das VMs, configurando recursos como memória, CPU e interfaces de rede
resource "libvirt_domain" "domain" {
for_each = { for vm in var.vms : vm.name => vm }
name = each.key
memory = each.value.memory
vcpu = each.value.cpu
cloudinit = libvirt_cloudinit_disk.cloudinit[each.key].id
cpu {
mode = "host-passthrough"
}
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_volume[each.key].id
}
disk {
volume_id = libvirt_volume.docker_vol[each.key].id
}
graphics {
type = "spice"
listen_type = "address"
autoport = true
}
}
# $ vim debian-cloud-init.yml #cloud-config # Usuários e grupos users: - name: gean sudo: ALL=(ALL) NOPASSWD:ALL groups: sudo,users shell: /bin/bash ssh-authorized-keys: - ${file("~/.ssh/tfvms.pub")} # Desativa a senha para todos os usuários, exceto root disable_root: false ssh_pwauth: false # Configuração da senha do root permitida apenas no console chpasswd: list: | root:root expire: False # Garantir que o acesso por senha esteja desativado para todos, exceto para o console system_info: default_user: lock_passwd: true # Configurações de segurança para SSH sshd_config: PermitRootLogin: prohibit-password PasswordAuthentication: no ChallengeResponseAuthentication: no UsePAM: yes PermitEmptyPasswords: no # Pacotes a serem instalados packages: - qemu-guest-agent - bash-completion # Configurações de atualização de pacotes package_update: true package_upgrade: true ## Set Hostname runcmd: - hostnamectl set-hostname docker-ded
$ cat debian-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
# $ vim ol9-cloud-init.yml #cloud-config # Usuários e grupos users: - name: gean sudo: ALL=(ALL) NOPASSWD:ALL groups: whell,adm,users shell: /bin/bash ssh-authorized-keys: - ${file("~/.ssh/tfvms.pub")} # Desativa a senha para todos os usuários, exceto root disable_root: false ssh_pwauth: false # Configuração da senha do root permitida apenas no console chpasswd: list: | root:root expire: False # Garantir que o acesso por senha esteja desativado para todos, exceto para o console system_info: default_user: lock_passwd: true # Configurações de segurança para SSH sshd_config: PermitRootLogin: prohibit-password PasswordAuthentication: no ChallengeResponseAuthentication: no UsePAM: yes PermitEmptyPasswords: no # Pacotes a serem instalados packages: - qemu-guest-agent - bash-completion # Configurações de atualização de pacotes package_update: true package_upgrade: true ## Set Hostname runcmd: - hostnamectl set-hostname docker-ol
# $ vim ol9-network-config.yml #cloud-config network: version: 1 config: - type: physical name: eth0 subnets: - type: static address: 10.1.2.101/24 gateway: 10.1.2.1
# $ vim ubuntu-cloud-init.yml #cloud-config # Usuários e grupos users: - name: gean sudo: ALL=(ALL) NOPASSWD:ALL groups: sudo,adm,users shell: /bin/bash ssh-authorized-keys: - ${file("~/.ssh/tfvms.pub")} # Desativa a senha para todos os usuários, exceto root disable_root: false ssh_pwauth: false # Configuração da senha do root permitida apenas no console chpasswd: list: | root:root expire: False # Garantir que o acesso por senha esteja desativado para todos, exceto para o console system_info: default_user: lock_passwd: true # Configurações de segurança para SSH sshd_config: PermitRootLogin: prohibit-password PasswordAuthentication: no ChallengeResponseAuthentication: no UsePAM: yes PermitEmptyPasswords: no # Pacotes a serem instalados packages: - qemu-guest-agent - bash-completion # Configurações de atualização de pacotes package_update: true package_upgrade: true ## Set Hostname runcmd: - hostnamectl set-hostname docker-ub
# $ vim ubuntu-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
# $ vim terraform.tfvars
vms = [
{
name = "debian"
cpu = 2
memory = 2048
disksize = 32
docker_vol = 32
storage_pool = "default"
os_image_name = "debian_image.qcow2"
os_datas_name = "debian_datas.qcow2"
docker_vol_name = "debian_docker.qcow2"
network_name = "tfnet"
user_data = "debian-cloud-init.yml"
network_config = "debian-network-config.yml"
os_image_url = "/home/gean/kvm/templates/debian-12-generic-amd64.qcow2"
},
{
name = "oracle"
cpu = 2
memory = 2048
disksize = 64
docker_vol = 32
storage_pool = "default"
os_image_name = "oracle_image.qcow2"
os_datas_name = "oracle_datas.qcow2"
docker_vol_name = "oracle_docker.qcow2"
network_name = "tfnet"
user_data = "ol9-cloud-init.yml"
network_config = "ol9-network-config.yml"
os_image_url = "/home/gean/kvm/templates/OL9U3_x86_64-kvm-b220.qcow2"
},
{
name = "ubuntu"
cpu = 2
memory = 2048
disksize = 32
docker_vol = 32
storage_pool = "default"
os_image_name = "ubuntu_image.qcow2"
os_datas_name = "ubuntu_datas.qcow2"
docker_vol_name = "ubuntu_docker.qcow2"
network_name = "tfnet"
user_data = "ubuntu-cloud-init.yml"
network_config = "ubuntu-network-config.yml"
os_image_url = "/home/gean/kvm/templates/ubuntu-22.04-server-cloudimg-amd64.img"
},
]
# $ vim debian-cloud-init.yml #cloud-config # Usuários e grupos users: - name: gean sudo: ALL=(ALL) NOPASSWD:ALL groups: sudo,users shell: /bin/bash ssh-authorized-keys: - ${file("~/.ssh/tfvms.pub")} # Desativa a senha para todos os usuários, exceto root disable_root: false ssh_pwauth: false # Configuração da senha do root permitida apenas no console chpasswd: list: | root:root expire: False # Garantir que o acesso por senha esteja desativado para todos, exceto para o console system_info: default_user: lock_passwd: true # Configurações de segurança para SSH sshd_config: PermitRootLogin: prohibit-password PasswordAuthentication: no ChallengeResponseAuthentication: no UsePAM: yes PermitEmptyPasswords: no # Pacotes a serem instalados packages: - qemu-guest-agent - bash-completion # Configurações de atualização de pacotes package_update: true package_upgrade: true runcmd: - hostnamectl set-hostname docker-ded - mkdir /var/lib/docker - mkfs.ext4 /dev/vdb - mount /dev/vdb /var/lib/docker - echo "/dev/vdb /var/lib/docker ext4 defaults 0 0" >> /etc/fstab