====== 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.