Terraform writeup
This commit is contained in:
parent
92507301ac
commit
2b17edc92b
2 changed files with 138 additions and 0 deletions
BIN
src/content/homelab/images/i-have-homelab.webp
Normal file
BIN
src/content/homelab/images/i-have-homelab.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
138
src/content/homelab/terraform.md
Normal file
138
src/content/homelab/terraform.md
Normal file
|
@ -0,0 +1,138 @@
|
|||
---
|
||||
title: Terraform + Proxmox = <3
|
||||
description: Using Terraform to deploy Virtual Machines
|
||||
pubDate: 08.03.2024
|
||||
---
|
||||
|
||||
## I am tired of UIs
|
||||
|
||||
Up until now, every time i wanted to deploy a VM in my homelab i did it with the Proxmox GUI. Don't get me wrong, the GUI is nice, but i would like to not have to repeat the same mundane task every time i want a new VM.
|
||||
There is an argument to be made that i probably shouldn't run that many VMs, and that for the number of VMs i need, this isn't worth it. However, being able to deploy a VM by just changing a few variables in a file and running `terraform apply` just tickles something in my nerd brain.
|
||||
|
||||
I also really like the repeatability of this, as i use these VM definitions to deploy K3S hosts, docker hosts and others where i want a "default" setup.
|
||||
|
||||
## Initial requirements
|
||||
|
||||
To use Terraform with Proxmox we use a privoder created by [Telmate](https://github.com/Telmate/terraform-provider-proxmox). We create the initial `provider.tf` file as so:
|
||||
```json
|
||||
terraform {
|
||||
required_providers {
|
||||
proxmox = {
|
||||
source = "telmate/proxmox"
|
||||
version = "3.0.1-rc3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
variable "proxmox_api_url" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "proxmox_user" {
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "proxmox_password" {
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "ssh_public_key" {
|
||||
type = string
|
||||
}
|
||||
|
||||
provider "proxmox"{
|
||||
pm_api_url = var.proxmox_api_url
|
||||
pm_user = var.proxmox_user
|
||||
pm_password = var.proxmox_password
|
||||
pm_tls_insecure = true
|
||||
pm_otp = ""
|
||||
}
|
||||
```
|
||||
|
||||
I have stored all secrets to access the proxmox API in custom variables located in a `.auto.tfvars` file that i do not track in git. Those variables are defined in the provider such that if they are not present Terraform will complain.
|
||||
|
||||
In this step i had some trouble, as you can see i use a release candidate version. There seems to be a bug in version `2.9.3`, and instead of trying to track it down i just switched to release candidate.
|
||||
|
||||
## Defining the virtual machine
|
||||
|
||||
Now as i mentioned previously, i already have templates created in my proxmox cluster (i made these with Ansible). Therefore i can use these as a base for the provisioning of a new VM.
|
||||
|
||||
Here is an example definition of a VM
|
||||
|
||||
```terraform
|
||||
resource "proxmox_vm_qemu" "havneboks" {
|
||||
name = "havneboks"
|
||||
desc = "Docker master"
|
||||
target_node = "poseidon"
|
||||
|
||||
agent = 1
|
||||
onboot = true
|
||||
|
||||
clone = "VM 9001"
|
||||
cores = 4
|
||||
sockets = 1
|
||||
cpu = "host"
|
||||
memory = 3096
|
||||
|
||||
# Setup the disk
|
||||
disks {
|
||||
ide {
|
||||
ide2 {
|
||||
cloudinit {
|
||||
storage = "basseng"
|
||||
}
|
||||
}
|
||||
}
|
||||
scsi {
|
||||
scsi0 {
|
||||
disk {
|
||||
size = "10G"
|
||||
storage = "basseng"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
network {
|
||||
bridge = "vmbr0"
|
||||
model = "virtio"
|
||||
}
|
||||
scsihw = "virtio-scsi-pci"
|
||||
os_type = "cloud-init"
|
||||
ipconfig0 = "ip=192.168.1.51/24,gw=192.168.1.1"
|
||||
nameserver = "192.168.1.69"
|
||||
ciuser = "ansible"
|
||||
sshkeys = var.ssh_public_key
|
||||
}
|
||||
```
|
||||
|
||||
A VM is defined using the resource type of `proxmox_vm_qemu` with a name. I really like to use the names of the service just translated to norwegian, so in this case, this VM is called `havneboks` (meaning docker box).
|
||||
|
||||
- name: The name of the VM (hostname)
|
||||
- desc: A description of the VM
|
||||
- target_node: Which node in the cluster should the VM be provisioned to, in this case i provision it to the node `poseidon`(hostname)
|
||||
- agent: Just select 1
|
||||
- onboot: Set the VM to start when the host boots
|
||||
- clone: Which template to clone the VM from
|
||||
- cores: How much horsepowa u want?
|
||||
- sockets: I only got 1 cpu in each of my boxes
|
||||
- memory: How much RAM u want?
|
||||
|
||||
Now, a really important part of this is the disk setup, as you have to mimic the setup of the template (sizes can be chosen freely). So in my case, i have the cloud-init disk on `ide2` and the OS disk on `scsi0` in the template. Therefore we create the same exact setup for this resource.
|
||||
|
||||
- network: Just mimic the cloud-init
|
||||
- scsihw: Which hardware do you want the host system to use to provide scsi?
|
||||
- os_type: I use cloud-init, so we select cloud-init
|
||||
- ipconfig: Now this is quite interesting, you should set a static IP and gateway such that the VM starts with a proper IP adress (you can also use DHCP here)
|
||||
- namesever: I use a custom dns on adress `.69`(nice) so i set that, but if this is not set it will use "same as host"
|
||||
- ciuser: A user to be created by cloud-init for this VM
|
||||
- sshkeys: Initial SSH public keys to allow access. This is stored in a variable in my case.
|
||||
|
||||
## Just run?
|
||||
|
||||
Bing bang bom. You can now deploy your VM fully automatically and about 43 seconds later access it via SSH. Now all i did was configure it with ansible, and i have a fully reproducible homelab setup.
|
||||
|
||||

|
Loading…
Reference in a new issue