Pesquisa de site

Como provisionar VMs em oVirt/RHEV com Terraform


Este guia discutirá como você pode automatizar a criação de VM oVirt/RHEV com Terraform. Não é apenas para a criação de VMs que você pode usar o terraform, mas para o provisionamento de outros recursos, como disco, rede, instantâneos, etc. Em nosso artigo anterior, discutimos como você pode usar o Terraform para automatizar sua infraestrutura KVM.

Para instalação do terraform, consulte:

  • Instale o Terraform no Ubuntu/Debian/CentOS/Fedora/Arch Linux

Pré-requisito de configuração

Você deve ter instalado o provedor Terraform para oVirt/RHEV usando o guia abaixo.

  • Como instalar o plug-in Terraform oVirt/RHEV

Este guia discutirá como você pode automatizar sua automação de VM oVirt/RHEV com Terraform. Não é apenas para a criação de VMs que você pode usar o terraform, mas para o provisionamento de outros recursos, como disco, rede, instantâneos, etc. Em nosso artigo anterior, discutimos como você pode usar o Terraform para automatizar sua infraestrutura KVM.

Preparação do modelo VM

Certifique-se de que seu modelo de VM tenha o cloud-init instalado.

### CentOS / Rocky Linux ###
sudo yum -y update
sudo yum -y install epel-release
sudo yum install cloud-init cloud-utils-growpart
sudo systemctl enable --now cloud-init


### Debian / Ubuntu ###
sudo apt-get -y update
sudo apt-get -y install cloud-init

Pré-requisito de configuração

Você deve ter instalado o provedor Terraform para oVirt/RHEV usando o guia abaixo.

  • Como instalar o plug-in Terraform oVirt/RHEV

Entre os recursos suportados pelo provedor terraform oVirt estão:

  • ovirt_cluster
  • ovirt_datacenter
  • ovirt_disk
  • ovirt_disk_attachment
  • ovirt_host
  • ovirt_mac_pool
  • ovirt_network
  • ovirt_snapshot
  • ovirt_storage_domain
  • ovirt_tag
  • ovirt_user
  • ovirt_vm
  • ovirt_vnic
  • ovirt_vnic_profile

As fontes de dados são:

  • ovirt_authzs
  • ovirt_clusters
  • ovirt_datacenters
  • ovirt_disks
  • ovirt_hosts
  • ovirt_mac_pools
  • ovirt_networks
  • ovirt_nics
  • ovirt_storagedomains
  • ovirt_users
  • ovirt_vms
  • ovirt_vnic_profiles

A documentação oficial do provedor Terraform oVirt fornece mais detalhes sobre o uso desses recursos e fontes de dados. Cobriremos apenas os casos de uso mais básicos e comuns.

Criando módulos Terraform

Um módulo é um contêiner para vários recursos usados juntos. Os módulos podem ser usados para criar abstrações leves, para que você possa descrever sua infraestrutura em termos de arquitetura, em vez de diretamente em termos de objetos físicos.

Em termos de estrutura, mais comumente, os módulos usam:

  • Variáveis de entrada para aceitar valores do módulo de chamada.
  • Valores de saída para retornar resultados ao módulo de chamada, que ele pode usar para preencher argumentos em outro lugar.
  • Recursos para definir um ou mais objetos de infraestrutura que o módulo irá gerenciar.

Criaremos dois módulos para ovirt_vm e ovirt_network. Vamos começar criando a pasta do projeto.

mkdir -p ~/terraform/modules/{vms,disk}

Criar módulo para criação de VM

Crie um módulo para o recurso ovirt_vm que é usado para gerenciar recursos de VM dentro do oVirt.

Criar recurso:

$ vim ~/terraform/modules/vms/main.tf

resource "ovirt_vm" "vm" {
  name                 = "${var.vm_name}"
  clone                = "false"
  high_availability    = "true"
  cluster_id           = "${var.cluster_id}"
  memory               = "${var.vm_memory}"
  template_id          = "${var.vm_template_id}"
  cores                = "${var.vm_cpu_cores}"
  sockets              = "${var.vm_cpu_sockets}"
  threads              = "${var.vm_cpu_threads}"

  initialization {
    authorized_ssh_key = "${var.vm_authorized_ssh_key}"
    host_name          = "${var.vm_hostname}"
    timezone           = "${var.vm_timezone}"
    user_name          = "${var.vm_user_name}"
    custom_script      = "${var.vm_custom_script}"
    dns_search         = "${var.vm_dns_search}"
    dns_servers        = "${var.vm_dns_servers}"

    nic_configuration {
      label              = "${var.vm_nic_device}"
      boot_proto         = "${var.vm_nic_boot_proto}"
      address            = "${var.vm_nic_ip_address}"
      gateway            = "${var.vm_nic_gateway}"
      netmask            = "${var.vm_nic_netmask}"
      on_boot            = "${var.vm_nic_on_boot}"
    }
  }
}

Crie um arquivo de variáveis:

$ vim ~/terraform/modules/vms/vars.tf

# Basic
variable "vm_name" {
  description = " A unique name for the VM"
  default     = ""
}
variable "cluster_id" {
  description = "The ID of cluster the VM belongs to"
  default     = ""
}
variable "vm_template_id" {
  description = "The ID of template the VM based on"
  default     = ""
}
variable "vm_memory" {
  description = "The amount of memory of the VM (in metabytes)"
  default     = "4096"
}
variable "vm_cpu_cores" {
  description = "The amount of cores"
  default     = "2"
}
variable "vm_cpu_sockets" {
  description = "The amount of sockets"
  default     = "1"
}
variable "vm_cpu_threads" {
  description = " The amount of threads"
  default     = "1"
}

# VM initialization

variable "vm_authorized_ssh_key" {
  description = "The ssh key for the VM"
  default     = ""
}
variable "vm_hostname" {
  description = "The hostname for the VM"
  default     = ""
}
variable "vm_timezone" {
  description = "The timezone for the VM"
  default     = ""
}
variable "vm_user_name" {
  description = "The user name for the VM"
  default     = ""
}
variable "vm_custom_script" {
  description = "Set the custom script for the VM"
  default     = ""
}
variable "vm_dns_search" {
  description = "The dns server for the VM"
  default     = ""
}
variable "vm_dns_servers" {
  description = "The dns server for the VM"
  default     = ""
}

# Initialization - Nic Configurations
variable "vm_nic_device" {
  description = "The vNIC to apply this configuration."
  default     = ""
}
variable "vm_nic_boot_proto" {
  description = "The boot protocol for the vNIC configuration."
  default     = "static"
}
variable "vm_nic_ip_address" {
  description = "The IP address for the vNIC"
  default     = ""
}
variable "vm_nic_gateway" {
  description = "The gateway for the vNIC"
  default     = ""
}
variable "vm_nic_netmask" {
  description = "The netmask for the vNIC"
  default     = ""
}
variable "vm_nic_on_boot" {
  description = "The flag to indicate whether the vNIC will be activated at VM booting"
  default     = "true"
}

Arquivo de saída:

$ vim ~/terraform/modules/vms/outputs.tf

output "id" {
  description = "VM ID"
  value       = "${ovirt_vm.vm.id}"
}

Criar módulo para gerenciamento de disco

Aqui colocaremos os seguintes recursos em um módulo:

  • ovirt_disk – Usado para gerenciar um recurso de disco dentro do oVirt.
  • ovirt_disk_attachment – Para gerenciar recursos de anexo de disco no oVirt.

Crie um arquivo de recursos:

$ vim ~/terraform/modules/disk/main.tf

resource "ovirt_disk" "disk" {
  name              = "${var.name}"
  alias             = "${var.name}"
  size              = "${var.size}"
  format            = "${var.format}"
  storage_domain_id = "${var.storage_domain_id}"
  sparse            = "${var.sparse}"
  shareable         = "${var.shareable}"
}

resource "ovirt_disk_attachment" "diskattachment" {
  vm_id                = "${var.vm_id}"
  disk_id              = "${ovirt_disk.disk.id}"
  active               = "${var.active}"
  bootable             = "${var.bootable}"
  interface            = "${var.interface}"
  read_only            = "${var.read_only}"
  use_scsi_reservation = "${var.use_scsi_reservation}"
}

Para variáveis:

$ vim ~/terraform/modules/disk/var.tf

# Disk resource variables
variable "name" {
  default = ""
}
variable "size" {
  default = ""
}
variable "format" {
 default = "cow"
}
variable "storage_domain_id" {
  default = ""
}
variable "sparse" {
 default = "true"
}
variable "shareable" {
  default = "false"
}

# Disk attachment
variable "vm_id" {
 default = ""
}
variable "disk_id" {
  default = ""
}
variable "active" {
  default = "true"
}
variable "bootable" {
  default = "false"
}
variable "interface" {
  default = "virtio_scsi"
}
variable "pass_discard" {
  default = ""
}
variable "read_only" {
  default =  "false"
}
variable "use_scsi_reservation" {
  default = "false"
}

Usando módulos Terraform

Crie a configuração principal do terraform definindo o provedor oVirt.

$ mkdir  ~/terraform/ovirt
$ cd ~/terraform/ovirt
$ vim main.tf

provider "ovirt" {
  url = "${var.ovirt_url}"
  username  = "${var.ovirt_username}"
  password  = "${var.ovirt_password}"
}

terraform {
  backend "local" {
    path = "ovirt_terraform.tfstate"
  }
}

Criar arquivo de variáveis

$ cd ~/terraform/ovirt
$ vim vars.tf

variable "ovirt_url" {
    description = "oVirt API URL"
    default = "https://ovirthostname/ovirt-engine/api"
}
variable "ovirt_username" {
    description = "oVirt Admin user"
    default     = "admin@internal"
}
variable "ovirt_password" {
    description = "oVirt Admin password"
    default     = "ovirtuserpassword"
}

Defina valores corretos para credenciais de acesso. Uma vez feito. agora você pode criar recursos terraform usando os módulos que criamos.

$ cd ~/terraform/ovirt
$ vim main.tf

# Create VM call temp01
module "temp01" {
  source            = "../modules/vms"
  cluster_id        = "c5529b5d-1b4e-46e6-9cb1-5d44c28cd65b"
  vm_name           = "temp01"
  vm_hostname       = "temp01.example.com"
  vm_dns_servers    = "8.8.8.8"
  vm_dns_search     = "example.com"
  vm_memory         = "2048"
  vm_cpu_cores      = "2"
  vm_timezone       = "Africa/Nairobi"
  vm_template_id    = "fd4b04a9-74b5-4287-adbc-3d5c6711d53f"
  vm_nic_device     = "eth0"
  vm_nic_ip_address = "192.168.10.11"
  vm_nic_gateway    = "192.168.10.254"
  vm_nic_netmask    = "255.255.255.0"
}

Outros parâmetros usados nas variáveis do módulo VM podem ser definidos. Certifique-se de definir as variáveis corretas.

Quando terminar, inicialize o projeto

$ cd ~/terraform/ovirt
$ terraform init
Initializing modules...
- temp01 in ../modules/vms

Initializing the backend...

Successfully configured the backend "local"! Terraform will automatically
use this backend unless the backend configuration changes.

Initializing provider plugins...

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

Valide as configurações do terraform.

$ terraform validate
Success! The configuration is valid.

Planeje sua implantação

$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.temp01.ovirt_vm.vm will be created
  + resource "ovirt_vm" "vm" {
      + clone             = true
      + cluster_id        = "c5529b5d-1b4e-46e6-9cb1-5d44c28cd65b"
      + cores             = 2
      + high_availability = true
      + id                = (known after apply)
      + memory            = 2048
      + name              = "temp01"
      + sockets           = 1
      + status            = (known after apply)
      + template_id       = "fd4b04a9-74b5-4287-adbc-3d5c6711d53f"
      + threads           = 1

      + initialization {
          + dns_search  = "example.com"
          + dns_servers = "8.8.8.8"
          + host_name   = "temp01.example.com"
          + timezone    = "Africa/Nairobi"

          + nic_configuration {
              + address    = "192.168.10.11"
              + boot_proto = "static"
              + gateway    = "192.168.10.254"
              + label      = "eth0"
              + netmask    = "255.255.255.0"
              + on_boot    = true
            }
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Executar criação

$ terraform apply
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.temp01.ovirt_vm.vm will be created
  + resource "ovirt_vm" "vm" {
      + clone             = true
      + cluster_id        = "c5529b5d-1b4e-46e6-9cb1-5d44c28cd65b"
      + cores             = 2
      + high_availability = true
      + id                = (known after apply)
      + memory            = 2048
      + name              = "temp01"
      + sockets           = 1
      + status            = (known after apply)
      + template_id       = "fd4b04a9-74b5-4287-adbc-3d5c6711d53f"
      + threads           = 1

      + initialization {
          + dns_search  = "example.com"
          + dns_servers = "8.8.8.8"
          + host_name   = "temp01.example.com"
          + timezone    = "Africa/Nairobi"

          + nic_configuration {
              + address    = "192.168.10.11"
              + boot_proto = "static"
              + gateway    = "192.168.10.254"
              + label      = "eth0"
              + netmask    = "255.255.255.0"
              + on_boot    = true
            }
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

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

O comando apply terá uma saída semelhante à abaixo.

module.temp01.ovirt_vm.vm: Creating...
module.temp01.ovirt_vm.vm: Still creating... [10s elapsed]
module.temp01.ovirt_vm.vm: Still creating... [20s elapsed]
module.temp01.ovirt_vm.vm: Still creating... [30s elapsed]
module.temp01.ovirt_vm.vm: Still creating... [40s elapsed]
module.temp01.ovirt_vm.vm: Still creating... [50s elapsed]
module.temp01.ovirt_vm.vm: Still creating... [1m0s elapsed]
module.temp01.ovirt_vm.vm: Still creating... [1m10s elapsed]
module.temp01.ovirt_vm.vm: Still creating... [1m20s elapsed]
module.temp01.ovirt_vm.vm: Still creating... [1m30s elapsed]
module.temp01.ovirt_vm.vm: Still creating... [1m40s elapsed]
module.temp01.ovirt_vm.vm: Still creating... [1m50s elapsed]
module.temp01.ovirt_vm.vm: Still creating... [2m0s elapsed]
module.temp01.ovirt_vm.vm: Still creating... [2m10s elapsed]
module.temp01.ovirt_vm.vm: Creation complete after 2m11s [id=2ad55c71-2e1a-4ce0-89a0-cda845f83fa2]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.

State path: ovirt_terraform.tfstate

Faça login em seu ambiente RHEV/oVirt e confirme a criação da VM.

Modifique main.tf para adicionar mais recursos

Vamos atualizar o arquivo para criar outra VM e disco.

# Create VM call temp01
module "temp01" {
  source            = "../modules/vms"
  cluster_id        = "c5529b5d-1b4e-46e6-9cb1-5d44c28cd65b"
  vm_name           = "temp01"
  vm_hostname       = "temp01.example.com"
  vm_dns_servers    = "8.8.8.8"
  vm_dns_search     = "example.com"
  vm_memory         = "2048"
  vm_cpu_cores      = "2"
  vm_timezone       = "Africa/Nairobi"
  vm_template_id    = "fd4b04a9-74b5-4287-adbc-3d5c6711d53f"
  vm_nic_device     = "eth0"
  vm_nic_ip_address = "192.168.10.11"
  vm_nic_gateway    = "192.168.10.254"
  vm_nic_netmask    = "255.255.255.0"
}

module "temp02" {
  source            = "../modules/vms"
  cluster_id        = "c5529b5d-1b4e-46e6-9cb1-5d44c28cd65b"
  vm_name           = "temp02"
  vm_hostname       = "temp02.example.com"
  vm_dns_servers    = "8.8.8.8"
  vm_dns_search     = "example.com"
  vm_memory         = "2048"
  vm_cpu_cores      = "2"
  vm_timezone       = "Africa/Nairobi"
  vm_template_id    = "fd4b04a9-74b5-4287-adbc-3d5c6711d53f"
  vm_nic_device     = "eth0"
  vm_nic_ip_address = "192.168.10.12"
  vm_nic_gateway    = "192.168.10.254"
  vm_nic_netmask    = "255.255.255.0"
}

## Create and attach Disk to VM temp02
module "temp02_disk02" {
  source            = "../modules/vms"
  name              = "temp02_disk02"
  size              = "50"
  storage_domain_id = "a5542689-bd73-4f16-846e-697822e4ad2c"
  vm_id             = "${module.temp02.id}"
}

Execute a inicialização.

$ terraform init

Aplicar configurações:

$ terraform plan
$ terraform apply

Destruir sua infraestrutura requer apenas um comando

$ terraform destroy
module.temp01.ovirt_vm.vm: Refreshing state... [id=2ad55c71-2e1a-4ce0-89a0-cda845f83fa2]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  # module.temp01.ovirt_vm.vm will be destroyed
  - resource "ovirt_vm" "vm" {
      - clone             = true -> null
      - cluster_id        = "c5529b5d-1b4e-46e6-9cb1-5d44c28cd65b" -> null
      - cores             = 2 -> null
      - high_availability = true -> null
      - id                = "2ad55c71-2e1a-4ce0-89a0-cda845f83fa2" -> null
      - memory            = 2048 -> null
      - name              = "temp01" -> null
      - sockets           = 1 -> null
      - status            = "up" -> null
      - template_id       = "fd4b04a9-74b5-4287-adbc-3d5c6711d53f" -> null
      - threads           = 1 -> null

      - initialization {
          - dns_search  = "example.com" -> null
          - dns_servers = "8.8.8.8" -> null
          - host_name   = "temp01.example.com" -> null
          - timezone    = "Africa/Nairobi" -> null

          - nic_configuration {
              - address    = "192.168.10.11" -> null
              - boot_proto = "static" -> null
              - gateway    = "192.168.10.254" -> null
              - label      = "eth0" -> null
              - netmask    = "255.255.255.0" -> null
              - on_boot    = true -> null
            }
        }
    }

Plan: 0 to add, 0 to change, 1 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes
module.temp01.ovirt_vm.vm: Destroying... [id=2ad55c71-2e1a-4ce0-89a0-cda845f83fa2]
module.temp01.ovirt_vm.vm: Still destroying... [id=2ad55c71-2e1a-4ce0-89a0-cda845f83fa2, 10s elapsed]
module.temp01.ovirt_vm.vm: Destruction complete after 20s

Destroy complete! Resources: 1 destroyed.

Consulte as páginas de documentação para obter mais exemplos sobre como usar recursos e fontes de dados do provedor oVirt.

Mais sobre terraforma:

  • Implante instâncias de VM na Hetzner Cloud com Terraform
  • Como provisionar VMs em KVM com Terraform
  • Instale o Terraform no Windows 10/Windows Server

Artigos relacionados: