Updated project to improve guidance
Some checks failed
terraform / validate (push) Failing after 37s

This commit is contained in:
CodeGit 2026-09-03 19:06:27 +01:00
parent 63008b3ab9
commit 4ea6d8b9e5
26 changed files with 1091 additions and 695 deletions

View file

@ -4,12 +4,24 @@ locals {
prefix_length = split("/", var.network_cidr)[1]
}
# A dedicated pool, separate from libvirt's own `default` same
# "isolated from anything else on the host" motivation as the network
# below, and it's the fix for the storage-permissions problem
# docs/02-k3s.md walks through by hand ("Storage: why a raw path in ~
# doesn't work"): a `dir` pool is a libvirtd-managed location, so volumes
# created in it come out owned correctly for the `libvirt-qemu` process
# that actually runs each VM, regardless of what user (`k8s`) asked for it.
resource "libvirt_pool" "k3s" {
name = var.storage_pool
type = "dir"
path = var.storage_pool_path
}
# Downloaded once and shared as a read-only backing image for every node's
# own disk below (libvirt_volume.node's base_volume_id) the same
# copy-on-write relationship docs/02-k3s.md explains in detail
# ("Building the base image..."). Terraform only re-downloads this if
# base_image_url changes; it doesn't redo it on every apply.
resource "libvirt_volume" "base" {
name = "k3s-base.qcow2"
pool = libvirt_pool.k3s.name
@ -35,6 +47,10 @@ resource "libvirt_network" "k3s" {
}
}
# One overlay disk per node, all backed by the single shared base image
# above `size` here is the overlay's logical capacity (what the guest
# OS sees), not how much host disk it actually consumes; qcow2 overlays
# start small and grow only as the node writes data.
resource "libvirt_volume" "node" {
for_each = var.nodes
name = "${each.key}.qcow2"
@ -44,11 +60,18 @@ resource "libvirt_volume" "node" {
format = "qcow2"
}
# The NoCloud seed ISO for each node this resource is the Terraform
# equivalent of `virt-install --cloud-init` in docs/02-k3s.md, just
# built from two separate templates instead of one hand-assembled file:
resource "libvirt_cloudinit_disk" "node" {
for_each = var.nodes
name = "${each.key}-cloudinit.iso"
pool = libvirt_pool.k3s.name
# "what should exist on this machine" which cloud-init template
# (server vs agent) depends on each.value.role, so a server node and an
# agent node run entirely different runcmd payloads despite sharing this
# one resource block. See cloud-init/server.yaml.tpl and agent.yaml.tpl.
user_data = templatefile("${path.module}/cloud-init/${each.value.role}.yaml.tpl", {
hostname = each.key
ssh_public_key = var.ssh_public_key
@ -57,6 +80,11 @@ resource "libvirt_cloudinit_disk" "node" {
k8s_api_hostname = var.k8s_api_hostname
})
# "how should this machine's network be set up" static, unlike stage
# 2's DHCP-based VM (docs/02-k3s.md), because this network
# (libvirt_network.k3s below) deliberately runs no DHCP server at all;
# every node needs to know its own address up front instead of waiting
# on a lease.
network_config = templatefile("${path.module}/cloud-init/network-config.yaml.tpl", {
ip = each.value.ip
prefix_length = local.prefix_length
@ -64,6 +92,8 @@ resource "libvirt_cloudinit_disk" "node" {
})
}
# The VM itself everything above this point (pool, base image, per-node
# overlay, cloudinit ISO, network) exists only to be wired together here.
resource "libvirt_domain" "node" {
for_each = var.nodes
name = each.key
@ -73,7 +103,10 @@ resource "libvirt_domain" "node" {
cloudinit = libvirt_cloudinit_disk.node[each.key].id
network_interface {
network_id = libvirt_network.k3s.id
network_id = libvirt_network.k3s.id
# false because this network runs no DHCP (see libvirt_network.k3s)
# the node gets its address from cloud-init's network_config instead,
# so waiting on a DHCP lease here would just block forever.
wait_for_lease = false
}