Table of Contents
Terraform libvirt - Criando VM para estudos
Introdução
Os seguintes scripts Terraform foram desenvolvidos para automatizar a criação e configuração de máquinas virtuais usando o provedor libvirt. O libvirt é uma API de virtualização de código aberto que oferece suporte a uma variedade de hipervisores, como QEMU/KVM, Xen e VirtualBox.
Objetivo
O objetivo desses scripts é provisionar uma máquina virtual Ubuntu com base em uma imagem pré-existente, configurar o CloudInit para personalizar a inicialização da máquina virtual e atribuir uma chave SSH para acesso remoto seguro.
Componentes
Os scripts Terraform consistem em vários arquivos:
- provider.tf: Este arquivo configura o provedor libvirt.
- volume.tf: Aqui são definidos os volumes necessários para a máquina virtual, incluindo o volume para a imagem do sistema operacional e o volume para o disco da máquina virtual.
- cloudinit.tf: Neste arquivo, são configuradas as opções do CloudInit, permitindo a personalização da inicialização da máquina virtual, como a configuração de usuários, grupos e pacotes.
- domain.tf: Aqui é definido o domínio da máquina virtual, especificando detalhes como nome, memória, CPU, interface de rede e configurações de disco.
- variables.tf: Este arquivo define as variáveis necessárias para os scripts, como configurações da máquina virtual e caminhos para arquivos.
- outputs.tf: Aqui são definidas as saídas dos scripts, como o endereço IP da máquina virtual.
Utilização
Para utilizar esses scripts, você pode personalizar as configurações da máquina virtual no arquivo terraform.tfvars e executar o comando terraform apply para provisionar a máquina virtual de acordo com suas especificações.
Sem redimencionar o disco
- main.tf
#main.tf terraform { required_providers { libvirt = { source = "dmacvicar/libvirt" } } }
- provider.tf
#provider.tf provider "libvirt" { uri = "qemu:///system" }
- variables.tf
#variables.tf variable "vm_config" { description = "Configuration for the virtual machine" type = map(any) }
- volume.tf
#volume.tf resource "libvirt_volume" "os_image" { name = var.vm_config["os_image_name"] pool = var.vm_config["storage_pool"] source = var.vm_config["os_image_url"] format = "qcow2" }
- cloudinit.tf
#cloudinit.tf data "template_file" "user_data" { template = file(var.vm_config["cloud_init_file"]) } resource "libvirt_cloudinit_disk" "cloudinit_resized" { name = "cloudinit_resized.iso" user_data = data.template_file.user_data.rendered pool = var.vm_config["storage_pool"] }
- domain.tf
#domain.tf resource "libvirt_domain" "virtual_machine" { name = var.vm_config["name"] memory = var.vm_config["memory"] vcpu = var.vm_config["cpu"] cpu { mode = "host-passthrough" } cloudinit = libvirt_cloudinit_disk.cloudinit_resized.id network_interface { network_name = var.vm_config["network_name"] wait_for_lease = true } console { type = "pty" target_port = "0" target_type = "serial" } console { type = "pty" target_type = "virtio" target_port = "1" } disk { volume_id = libvirt_volume.os_image.id } graphics { type = "spice" listen_type = "address" autoport = true } }
- outputs.tf
#outputs.tf output "ip" { value = libvirt_domain.virtual_machine.network_interface[0].addresses[0] }
- ubuntu-cloud-init.yml
#ubuntu-cloud-init.yml #cloud-config ## 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: gke-suporte gecos: GKE Suporte groups: users, admin shell: /bin/bash sudo: ALL=(ALL) NOPASSWD:ALL lock_passwd: true ssh_authorized_keys: - ${file("~/.ssh/id_ed25519.pub")} - name: eks-suporte gecos: EKS Suporte groups: users, admin shell: /bin/bash sudo: ALL=(ALL) NOPASSWD:ALL lock_passwd: true ssh_authorized_keys: - ${file("~/.ssh/id_ed25519.pub")} - name: eks-projeto gecos: EKS Projeto groups: users, admin 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 - vm - git - python
- main.tf
#terraform.tfvars vm_config = { name = "ubuntu" cpu = 2 memory = 2048 disksize = 32 storage_pool = "default" os_image_name = "ubuntu.qcow2" network_name = "default" cloud_init_file = "ubuntu-cloud-init.yml" os_image_url = "/var/lib/libvirt/templates/jammy-server-cloudimg-amd64.img" }
Redimencionando o diso
- main.tf
#main.tf terraform { required_providers { libvirt = { source = "dmacvicar/libvirt" } } }
- provider.tf
#provider.tf provider "libvirt" { uri = "qemu:///system" }
- variables.tf
#variables.tf variable "vm_config" { description = "Configuration for the virtual machine" type = map(any) }
- volume.tf
#volume.tf resource "libvirt_volume" "os_image" { name = var.vm_config["os_image_name"] pool = var.vm_config["storage_pool"] source = var.vm_config["os_image_url"] format = "qcow2" } resource "libvirt_volume" "disk_resized" { name = "disk.qcow2" base_volume_id = libvirt_volume.os_image.id pool = var.vm_config["storage_pool"] size = var.vm_config["disksize"] * 1024 * 1024 * 1024 }
- cloudinit.tf
#cloudinit.tf data "template_file" "user_data" { template = file(var.vm_config["cloud_init_file"]) } resource "libvirt_cloudinit_disk" "cloudinit_resized" { name = "cloudinit_resized.iso" user_data = data.template_file.user_data.rendered pool = var.vm_config["storage_pool"] }
- domain.tf
#domain.tf resource "libvirt_domain" "virtual_machine" { name = var.vm_config["name"] memory = var.vm_config["memory"] vcpu = var.vm_config["cpu"] cpu { mode = "host-passthrough" } cloudinit = libvirt_cloudinit_disk.cloudinit_resized.id network_interface { network_name = var.vm_config["network_name"] wait_for_lease = true } console { type = "pty" target_port = "0" target_type = "serial" } console { type = "pty" target_type = "virtio" target_port = "1" } disk { volume_id = libvirt_volume.disk_resized.id } graphics { type = "spice" listen_type = "address" autoport = true } }
- outputs.tf
#outputs.tf output "ip" { value = libvirt_domain.virtual_machine.network_interface[0].addresses[0] }
- ubuntu-cloud-init.yml
#ubuntu-cloud-init.yml #cloud-config ## 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: gke-suporte gecos: GKE Suporte groups: users, admin shell: /bin/bash sudo: ALL=(ALL) NOPASSWD:ALL lock_passwd: true ssh_authorized_keys: - ${file("~/.ssh/id_ed25519.pub")} - name: eks-suporte gecos: EKS Suporte groups: users, admin shell: /bin/bash sudo: ALL=(ALL) NOPASSWD:ALL lock_passwd: true ssh_authorized_keys: - ${file("~/.ssh/id_ed25519.pub")} - name: eks-projeto gecos: EKS Projeto groups: users, admin 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 - vm - git - python
- main.tf
#terraform.tfvars vm_config = { name = "ubuntu" cpu = 2 memory = 2048 disksize = 32 storage_pool = "default" os_image_name = "ubuntu.qcow2" network_name = "default" cloud_init_file = "ubuntu-cloud-init.yml" os_image_url = "/var/lib/libvirt/templates/jammy-server-cloudimg-amd64.img" }
$ terraform apply data.template_file.user_data: Reading... data.template_file.user_data: Read complete after 0s [id=bc718697370c1302222f8c6d6ff150f5996a70c7a12d75f916f9f8de2a6ba8d4] Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # libvirt_cloudinit_disk.cloudinit_resized will be created + resource "libvirt_cloudinit_disk" "cloudinit_resized" { + id = (known after apply) + name = "cloudinit_resized.iso" + pool = "default" + user_data = <<-EOT #cloud-config ## 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: gke-suporte gecos: GKE Suporte groups: users, admin shell: /bin/bash sudo: ALL=(ALL) NOPASSWD:ALL lock_passwd: true ssh_authorized_keys: - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAwHB1kIi15h/qdqbk7T3hk+rBKLylzr33cEIdTiO4ZO gean@inspiron - name: eks-suporte gecos: EKS Suporte groups: users, admin shell: /bin/bash sudo: ALL=(ALL) NOPASSWD:ALL lock_passwd: true ssh_authorized_keys: - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAwHB1kIi15h/qdqbk7T3hk+rBKLylzr33cEIdTiO4ZO gean@inspiron - name: eks-projeto gecos: EKS Projeto groups: users, admin shell: /bin/bash sudo: ALL=(ALL) NOPASSWD:ALL lock_passwd: true ssh_authorized_keys: - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAwHB1kIi15h/qdqbk7T3hk+rBKLylzr33cEIdTiO4ZO gean@inspiron - name: root ssh_authorized_keys: - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAwHB1kIi15h/qdqbk7T3hk+rBKLylzr33cEIdTiO4ZO gean@inspiron ## Install packages package_update: true package_upgrade: true packages: - qemu-guest-agent - vm - git - python EOT } # libvirt_domain.virtual_machine will be created + resource "libvirt_domain" "virtual_machine" { + arch = (known after apply) + autostart = (known after apply) + cloudinit = (known after apply) + emulator = (known after apply) + fw_cfg_name = "opt/com.coreos/config" + id = (known after apply) + machine = (known after apply) + memory = 2048 + name = "ubuntu" + qemu_agent = false + running = true + type = "kvm" + vcpu = 2 + console { + source_host = "127.0.0.1" + source_service = "0" + target_port = "0" + target_type = "serial" + type = "pty" } + console { + source_host = "127.0.0.1" + source_service = "0" + target_port = "1" + target_type = "virtio" + type = "pty" } + cpu { + mode = "host-passthrough" } + disk { + scsi = false + volume_id = (known after apply) } + graphics { + autoport = true + listen_address = "127.0.0.1" + listen_type = "address" + type = "spice" } + network_interface { + addresses = (known after apply) + hostname = (known after apply) + mac = (known after apply) + network_id = (known after apply) + network_name = "default" + wait_for_lease = true } } # libvirt_volume.disk_resized will be created + resource "libvirt_volume" "disk_resized" { + base_volume_id = (known after apply) + format = (known after apply) + id = (known after apply) + name = "disk" + pool = "default" + size = 34359738368 } # libvirt_volume.os_image will be created + resource "libvirt_volume" "os_image" { + format = "qcow2" + id = (known after apply) + name = "ubuntu.qcow2" + pool = "default" + size = (known after apply) + source = "/var/lib/libvirt/templates/jammy-server-cloudimg-amd64.img" } Plan: 4 to add, 0 to change, 0 to destroy. Changes to Outputs: + ip = (known after apply) Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes
libvirt_cloudinit_disk.cloudinit_resized: Creating... libvirt_volume.os_image: Creating... libvirt_volume.os_image: Creation complete after 0s [id=/var/lib/libvirt/images/ubuntu.qcow2] libvirt_volume.disk_resized: Creating... libvirt_cloudinit_disk.cloudinit_resized: Creation complete after 0s [id=/var/lib/libvirt/images/cloudinit_resized.iso;961426d4-803b-4390-a9c8-6ca3fed6402f] libvirt_volume.disk_resized: Creation complete after 0s [id=/var/lib/libvirt/images/disk] libvirt_domain.virtual_machine: Creating... libvirt_domain.virtual_machine: Still creating... [10s elapsed] libvirt_domain.virtual_machine: Creation complete after 15s [id=f9fd0383-54cb-4cff-8ddc-05637c58140a] Apply complete! Resources: 4 added, 0 changed, 0 destroyed. Outputs: ip = "192.168.122.10"
