====== 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
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"
}
==== Redimencionando o diso ====
#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"