Post

Terraform

Files

  • main.tf
    The main content goes here. It’s also possible that the content is broken into separate files so that the main.tf isn’t modified.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
    terraform {
      required_providers {
        proxmox = {
          source = "telmate/proxmox"
          version = "2.9.8"
        }
      }
    }

    provider "proxmox" {
      # URL is the hostname (FQDN if you have one) for the proxmox host you'd like to connect to to issue the commands. 
      pm_api_url = "proxmox_url"

      # API token id is in the form of: <username>@pam!<tokenId>
      pm_api_token_id = "proxmox_token_user"

      # This is the full secret wrapped in quotes. 
      pm_api_token_secret = "proxmox_api_key"

      # Leave tls_insecure set to true unless you have your proxmox SSL certificate situation fully sorted out (if you do, you will know)
      pm_tls_insecure = true

      # Error Logging.  Not needed but handy to have.
      pm_log_enable = true
      pm_log_file = "terraform-plugin-proxmox.log"
      pm_debug = true
      pm_log_levels = {
        _default = "debug"
        _capturelog = ""
      }
    }
  • vairs.tf Stores variables.
1
2
3
   variable "template_name" {
    default = "ubuntu-2004-cloudinit-template"
}

To use, call it var.template_name

Commands

terraform init
Initiazlizes the main.tf file. Downloads the provider packages.

terraform plan
Shows what’s going to happen when the VM is created.

terraform apply --autoapprove
Creates the VM. The autoapprove allows for the prompt not to appear so that the VM can be created right off the bat.

Error Tracing

In the command prompt:

  • Enable: export TF_LOG=TRACE
  • Disable: export TF_LOG=ERROR

Loops

To create multiple VMs of the same type, looping can be done.

terraform.tfvars Used to store the information that will be used in the loops.

1
2
3
4
5
k8s_masters = {
  m1 = { target_node = "proxmox_node_name", vcpu = "2", memory = "2098", disk_size = "10G", name = "hostname1", ip = "192.168.1.231", gw = "192.168.1.1" },
  m2 = { target_node = "proxmox_node_name", vcpu = "2", memory = "2098", disk_size = "10G", name = "hostname2", ip = "192.168.1.232", gw = "192.168.1.1" },
  m3 = { target_node = "proxmox_node_name", vcpu = "2", memory = "2098", disk_size = "10G", name = "hostname3", ip = "192.168.1.233", gw = "192.168.1.1" }
}

In the variables.tf k8s_masters must be declared.

1
2
3
4
variable "k8s_masters" {
  description = "vm variables in a dictionary "
  type        = map(any)
}

In a new document terraform_vms.tf or whatever you want to call it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
resource "proxmox_vm_qemu" "kube-server"  {
  for_each    = var.k8s_masters
  name        = each.value.name
  target_node = each.value.target_node
  os_type     = "centos"
  full_clone  = true
  memory      = each.value.memory
  sockets     = "1"
  cores       = each.value.vcpu
  cpu         = "host"
  scsihw      = "virtio-scsi-pci"
  clone       = var.template_name
  agent       = 1
  bootdisk    = "scsi0"
  
  disk {
    size = each.value.disk_size
    type = "scsi"
    storage = "vgrp"
    slot = 0
    iothread = 1
  }

  network {
    model  = "virtio"
    bridge = "vmbr0"
  }

  lifecycle {
    ignore_changes = [
      network,
    ]
  }

  # Cloud-init section
  #ipconfig0 = "ip=192.168.1.23${count.index + 1}/24,gw=192.168.1.1"
  ipconfig0 = "ip=${each.value.ip}/24,gw=192.168.1.1"

  # sshkeys set using variables. the variable contains the text of the key.
  sshkeys = <<EOF
  ${var.ssh_key}
  EOF
  }
This post is licensed under CC BY 4.0 by the author.