Este tutorial explica como configurar uma infraestrutura utilizando KVM com Terraform para provisionar um cluster Docker Swarm. A infraestrutura inclui um manager e dois workers, além de um container para registro de imagens Docker.
Este arquivo define os recursos que serão provisionados no KVM usando o provider Libvirt.
variable "vms" {
type = list(map(any))
}
terraform {
required_providers {
libvirt = {
source = "dmacvicar/libvirt"
}
}
}
provider "libvirt" {
uri = "qemu:///system"
}
resource "libvirt_network" "swarm" {
name = "swarm"
mode = "nat"
addresses = ["10.2.3.0/24"]
autostart = true
dhcp {
enabled = false
}
dns {
enabled = true
}
}
resource "libvirt_volume" "os_image" {
for_each = { for vm in var.vms : vm.name => vm }
name = each.value["os_image_name"]
pool = each.value["storage_pool"]
source = each.value["os_image_url"]
format = "qcow2"
}
resource "libvirt_volume" "os_datas" {
for_each = { for vm in var.vms : vm.name => vm }
name = each.value["os_datas_name"]
base_volume_id = libvirt_volume.os_image[each.key].id
pool = each.value["storage_pool"]
size = each.value["disksize"] * 1024 * 1024 * 1024
}
data "template_file" "user_data" {
for_each = { for vm in var.vms : vm.name => vm }
template = file("${path.module}/${each.value["user_data"]}")
vars = {
hostname = each.value["hostname"]
}
}
data "template_file" "network_config" {
for_each = { for vm in var.vms : vm.name => vm }
template = file("${path.module}/${each.value["network_config"]}")
vars = {
network_ip = each.value["network_ip"]
}
}
resource "libvirt_cloudinit_disk" "cloudinit" {
for_each = { for vm in var.vms : vm.name => vm }
name = "${each.key}-cloudinit.iso"
user_data = data.template_file.user_data[each.key].rendered
network_config = data.template_file.network_config[each.key].rendered
pool = each.value["storage_pool"]
}
resource "libvirt_domain" "domain" {
for_each = { for vm in var.vms : vm.name => vm }
name = each.value["name"]
memory = each.value["memory"]
vcpu = each.value["cpu"]
cpu {
mode = "host-passthrough"
}
cloudinit = libvirt_cloudinit_disk.cloudinit[each.key].id
network_interface {
network_name = each.value["network_name"]
}
console {
type = "pty"
target_port = "0"
target_type = "serial"
}
console {
type = "pty"
target_type = "virtio"
target_port = "1"
}
disk {
volume_id = libvirt_volume.os_datas[each.key].id
}
graphics {
type = "spice"
listen_type = "address"
autoport = true
}
}
Este arquivo define as variáveis usadas para configurar as VMs. Ajuste os valores conforme sua necessidade.
vms = [
{
name = "docker-manager"
cpu = 2
memory = 4096
disksize = 32
storage_pool = "default"
hostname = "docker-manager"
os_image_name = "docker_manager_image.qcow2"
os_datas_name = "docker_manager_datas.qcow2"
network_name = "swarm"
user_data = "cloud-init.yml"
network_config = "network-config.yml"
network_ip = "10.2.3.10"
os_image_url = "/home/gean/kvm/templates/ubuntu-22.04-server-cloudimg-amd64.img"
},
{
name = "docker-worker1"
cpu = 2
memory = 2048
disksize = 32
storage_pool = "default"
hostname = "docker-worker1"
os_image_name = "docker_worker1_image.qcow2"
os_datas_name = "docker_worker1_datas.qcow2"
network_name = "swarm"
user_data = "cloud-init.yml"
network_config = "network-config.yml"
network_ip = "10.2.3.11"
os_image_url = "/home/gean/kvm/templates/ubuntu-22.04-server-cloudimg-amd64.img"
},
{
name = "docker-worker2"
cpu = 2
memory = 2048
disksize = 32
storage_pool = "default"
hostname = "docker-worker2"
os_image_name = "docker_worker2_image.qcow2"
os_datas_name = "docker_worker2_datas.qcow2"
network_name = "swarm"
user_data = "cloud-init.yml"
network_config = "network-config.yml"
network_ip = "10.2.3.12"
os_image_url = "/home/gean/kvm/templates/ubuntu-22.04-server-cloudimg-amd64.img"
},
{
name = "docker-registry"
cpu = 2
memory = 2048
disksize = 32
storage_pool = "default"
hostname = "docker-registry"
os_image_name = "docker_registry_image.qcow2"
os_datas_name = "docker_registry_datas.qcow2"
network_name = "swarm"
user_data = "cloud-init.yml"
network_config = "network-config.yml"
network_ip = "10.2.3.13"
os_image_url = "/home/gean/kvm/templates/ubuntu-22.04-server-cloudimg-amd64.img"
},
]
Este arquivo define a configuração de inicialização da VM, como hostname, criação de usuários, e instalação de pacotes.
#cloud-config # Definindo o hostname dinamicamente hostname: ${hostname} # Criação de usuário e configuração de SSH users: - name: gean sudo: ALL=(ALL) NOPASSWD:ALL groups: users, sudo shell: /bin/bash ssh_authorized_keys: - ${file("~/.ssh/tfvms.pub")} # Definir senha root chpasswd: list: | root:$6$R4tXC5apTx$f4WVAylB/SZ/0ppE7Zp4lurvzAhcm.BaU3xJKaoESu7cv13sR7RYVkjVQwxtvA9/vUggWu/a9N0L9EP1lg/Ez1 expire: False # Atualização de pacotes e instalação de utilitários package_update: true package_upgrade: true # Lista de pacotes para instalar packages: - qemu-guest-agent - bash-completion
Arquivo que define as configurações de rede da VM, como IP e rota de gateway.
#cloud-config network: version: 2 ethernets: ens3: addresses: - ${network_ip}/24 nameservers: addresses: - 10.2.3.1 routes: - to: default via: 10.2.3.1
1. Instale o Terraform e KVM em sua máquina. 2. Crie um diretório de trabalho e coloque os arquivos `main.tf`, `terraform.tfvars`, `cloud-init.yml` e `network-config.yml` nesse diretório. 3. Execute os comandos a seguir no terminal para iniciar a infraestrutura:
terraform init
terraform fmt
terraform validate
terraform apply
4. O Terraform criará o cluster Docker Swarm com as VMs definidas.
terraform.tfvars conforme sua infraestrutura.