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.
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.
Os scripts Terraform consistem em vários arquivos:
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.
#main.tf
terraform {
required_providers {
libvirt = {
source = "dmacvicar/libvirt"
}
}
}
#provider.tf
provider "libvirt" {
uri = "qemu:///system"
}
#variables.tf
variable "vm_config" {
description = "Configuration for the virtual machine"
type = map(any)
}
#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
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
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
output "ip" {
value = libvirt_domain.virtual_machine.network_interface[0].addresses[0]
}
#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
#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"
}
#main.tf
terraform {
required_providers {
libvirt = {
source = "dmacvicar/libvirt"
}
}
}
#provider.tf
provider "libvirt" {
uri = "qemu:///system"
}
#variables.tf
variable "vm_config" {
description = "Configuration for the virtual machine"
type = map(any)
}
#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
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
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
output "ip" {
value = libvirt_domain.virtual_machine.network_interface[0].addresses[0]
}
#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
#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"