====== Criação de uma Máquina Virtual em Ambiente de Virtualização KVM com Terraform ====== Este tutorial demonstra como criar uma máquina virtual (VM) utilizando KVM e Terraform, assumindo que o Terraform, KVM e o provider **libvirt** já estão instalados. ===== Pré-requisitos ===== Antes de começar, certifique-se de que: * KVM está instalado e configurado no seu sistema. * Terraform está instalado na máquina. * O provider **libvirt** do Terraform está disponível. ===== 1. Definir Variáveis e Configuração do Terraform ===== Crie um arquivo ''main.tf'' com o seguinte conteúdo: # Definindo variáveis para configuração da VM variable "vm_template" { type = map(any) } # # Define os provedores necessários para o Terraform. terraform { required_providers { libvirt = { source = "dmacvicar/libvirt" } } } # Configura o provedor libvirt com a URI do sistema QEMU. provider "libvirt" { uri = "qemu:///system" } Aqui, o provider **libvirt** será usado para gerenciar a VM via KVM. ===== 2. Criar os Volumes da VM ===== # Volume de imagem do sistema operacional resource "libvirt_volume" "os_image" { name = var.vm_template["os_image_name"] pool = var.vm_template["storage_pool"] source = var.vm_template["os_image_url"] format = "qcow2" } # Volume de dados da VM resource "libvirt_volume" "os_datas" { name = var.vm_template["os_volume_name"] base_volume_id = libvirt_volume.os_image.id pool = var.vm_template["storage_pool"] size = var.vm_template["disksize"] * 1024 * 1024 * 1024 # Converte para bytes } Esse trecho define os volumes usados pela VM, especificando a imagem do SO e o volume de dados. ===== 3. Definir o Disco cloud-init ===== # Definir o arquivo cloud-init para automação data "template_file" "user_data" { template = file("${path.module}/${var.vm_template["cloud_init_file"]}") } resource "libvirt_cloudinit_disk" "cloudinit" { name = "cloudinit.iso" user_data = data.template_file.user_data.rendered pool = var.vm_template["storage_pool"] } O **cloud-init** permite automatizar a configuração inicial da VM, como a criação de usuários e a instalação de pacotes. ===== 4. Configurar o Domínio (VM) ===== resource "libvirt_domain" "domain" { name = var.vm_template["name"] memory = var.vm_template["memory"] vcpu = var.vm_template["cpu"] cpu { mode = "host-passthrough" } cloudinit = libvirt_cloudinit_disk.cloudinit.id network_interface { network_name = var.vm_template["network_name"] wait_for_lease = true } console { type = "pty" target_type = "virtio" target_port = "1" } disk { volume_id = libvirt_volume.os_datas.id } graphics { type = "spice" listen_type = "address" autoport = true } } output "ip" { value = libvirt_domain.domain.network_interface[0].addresses[0] } Este trecho define a configuração principal da VM, incluindo CPU, memória, rede e interface gráfica. ===== 5. Variáveis de Configuração ===== Crie um arquivo `variables.tf` ou defina diretamente no `main.tf`: vm_template = { name = "tf-vm-01" cpu = 2 memory = 2048 disksize = 32 storage_pool = "default" os_image_name = "tf_vm_01_image.qcow2" os_volume_name = "tf_vm_01_volume.qcow2" network_name = "default" cloud_init_file = "cloud-init.yml" os_image_url = "/home/user/kvm/templates/debian-12-generic-amd64.qcow2" } Altere os valores conforme necessário para a sua infraestrutura. ===== 6. Arquivo cloud-init ===== Crie um arquivo ''cloud-init.yml'' para automatizar a configuração da VM: **Definição para acesso ssh por senha** #cloud-config hostname: vm-tf ssh_pwauth: yes # Habilita login por senha para usuários users: - name: gean sudo: ALL=(ALL) NOPASSWD:ALL # Permite 'gean' usar sudo sem senha groups: users, sudo shell: /bin/bash lock_passwd: false # Desbloqueia o usuário 'gean' para usar senhas passwd: $6$uGQol.HnKU0nvpEy$YJl94Y7/p1cWZVlu0gsZIeebssh4oHCIQ9VNX721T1/Lx0UbQVbjfbzS2.9.2EGz4Hdxi0ICNKAua8lo/AsuT1 # Senha criptografada de 'gean' chpasswd: list: | root:$6$uGQol.HnKU0nvpEy$YJl94Y7/p1cWZVlu0gsZIeebssh4oHCIQ9VNX721T1/Lx0UbQVbjfbzS2.9.2EGz4Hdxi0ICNKAua8lo/AsuT1 # Senha criptografada de root expire: False # Define que as senhas não expiram packages: - qemu-guest-agent # Instala o agente QEMU para máquinas virtuais - bash-completion # Completa comandos no Bash package_update: true # Atualiza lista de pacotes package_upgrade: true # Atualiza os pacotes instalados # Definir a localidade e fuso horário (opcional) locale: pt_BR.UTF-8 timezone: America/Sao_Paulo Esse arquivo define o hostname, usuários, senha root, e instala pacotes. ==== Configuração para acesso por ssh senha senha ==== # vim main.tf # Definindo variáveis para configuração da VM variable "vm_template" { type = map(any) } terraform { required_providers { libvirt = { source = "dmacvicar/libvirt" } } } provider "libvirt" { uri = "qemu:///system" } # Volume de imagem do sistema operacional resource "libvirt_volume" "os_image" { name = var.vm_template["os_image_name"] pool = var.vm_template["storage_pool"] source = var.vm_template["os_image_url"] format = "qcow2" } # Volume de dados da VM resource "libvirt_volume" "os_datas" { name = var.vm_template["os_volume_name"] base_volume_id = libvirt_volume.os_image.id pool = var.vm_template["storage_pool"] size = var.vm_template["disksize"] * 1024 * 1024 * 1024 # Converte para bytes } # Definir o arquivo cloud-init para automação data "template_file" "user_data" { template = file("${path.module}/${var.vm_template["cloud_init_file"]}") vars = { hostname = var.vm_template["hostname"] ssh_key = var.vm_template["ssh_key"] } } # Criando disco Cloud-Init resource "libvirt_cloudinit_disk" "cloudinit" { name = "cloudinit.iso" user_data = data.template_file.user_data.rendered pool = var.vm_template["storage_pool"] } # Criando a VM com libvirt resource "libvirt_domain" "domain" { name = var.vm_template["name"] memory = var.vm_template["memory"] vcpu = var.vm_template["cpu"] cpu { mode = "host-passthrough" } cloudinit = libvirt_cloudinit_disk.cloudinit.id network_interface { network_name = var.vm_template["network_name"] wait_for_lease = true } console { type = "pty" target_type = "virtio" target_port = "1" } disk { volume_id = libvirt_volume.os_datas.id } graphics { type = "spice" listen_type = "address" autoport = true } } output "ip" { value = libvirt_domain.domain.network_interface[0].addresses[0] } # vim cloud-init.yml #cloud-config # Configuração do Hostname hostname: ${hostname} # Criação de usuário users: - name: gean sudo: ALL=(ALL) NOPASSWD:ALL groups: users, sudo shell: /bin/bash ssh-authorized-keys: - ${ssh_key} # Definir senha root chpasswd: list: | root:$6$R4tXC5apTx$f4WVAylB/SZ/0ppE7Zp4lurvzAhcm.BaU3xJKaoESu7cv13sR7RYVkjVQwxtvA9/vUggWu/a9N0L9EP1lg/Ez1 expire: False # Pacotes a serem instalados packages: - qemu-guest-agent - bash-completion # Atualização do sistema package_update: true package_upgrade: true # Localidade e fuso horário locale: pt_BR.UTF-8 timezone: America/Sao_Paulo # Logs de inicialização para depuração final_message: "A VM foi provisionada corretamente!" $ cat terraform.tfvars vm_template = { name = "tf-vm-01" cpu = 2 memory = 2048 disksize = 32 storage_pool = "default" hostname = "tf-vm-01" os_image_name = "tf_vm_01_image.qcow2" os_volume_name = "tf_vm_01_volume.qcow2" network_name = "default" cloud_init_file = "cloud-init.yml" os_image_url = "/home/gean/kvm/templates/ubuntu-22.04-server-cloudimg-amd64.img" ssh_key = "ssh-ed25519 AAAA..." } ===== 7. Gerar Senha e Chave SSH ===== * Para gerar a senha root: mkpasswd --method=SHA-512 * Para gerar a chave SSH: ssh-keygen -t ed25519 -C "your_email@example.com" -f ~/.ssh/tfvms ===== 8. Construção da Infraestrutura ===== Execute os comandos Terraform: terraform init # Inicializar o Terraform terraform fmt # Formatar arquivos terraform validate # Validar a configuração terraform plan # Planejar a infraestrutura terraform apply # Aplicar a infraestrutura ===== 9. Outras Opções ===== * Aplicar com parâmetros personalizados: terraform apply -var="vm_name=custom_name" -var="vm_memory=4096" * Aplicar com um arquivo de variáveis: terraform apply -var-file="custom_variables.tfvars" ===== Conclusão ===== Este tutorial fornece um processo completo para criar uma VM no KVM usando Terraform, com foco em automação e personalização.