Phase 1 (author-only): node provisioning IaC — tofu + cloud-init + Ansible (T-1.1/1.2/1.3)
OpenTofu libvirt module (k3s-dev NAT 10.73.0.0/24, 3x 6GiB/4vCPU VMs, 20G OS +
40G thin data, host-passthrough), cloud-init baseline (k3s/Cilium/Longhorn
prereqs, static net), Ansible k3s-HA + Cilium (kube-proxy replacement, Gateway
API, Hubble; flannel/kube-proxy/Traefik disabled). PM fix: escape ${...} in a
cloud-init template comment (tofu templatefile parse). tofu fmt/init/validate =
Success; ansible --syntax-check + yamllint pass. NOTHING executed (no apply).
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
1 parent
224cd8ac35
commit
f2a7e42068
29 files changed
+1168
-6
No files matched your search
@@ -0,0 +1,151 @@
|
||||
# variables.tf — every sizing / IP / image knob is a variable (Phase 1 T-1.1).
|
||||
# Defaults encode the LOCKED decisions in infra/PHASE1-SCOPE.md. Override via
|
||||
# terraform.tfvars (see terraform.tfvars.example).
|
||||
|
||||
variable "libvirt_uri" {
|
||||
description = "libvirt connection URI."
|
||||
type = string
|
||||
default = "qemu:///system"
|
||||
}
|
||||
|
||||
variable "pool_name" {
|
||||
description = "libvirt storage pool for all volumes (base image, OS + data disks, seed ISOs)."
|
||||
type = string
|
||||
default = "default"
|
||||
}
|
||||
|
||||
# --- cluster identity / naming ---------------------------------------------
|
||||
|
||||
variable "cluster_name" {
|
||||
description = "Logical cluster name; used as a resource-name prefix."
|
||||
type = string
|
||||
default = "k3s-dev"
|
||||
}
|
||||
|
||||
variable "node_name_prefix" {
|
||||
description = "VM hostname prefix. Nodes are <prefix>1, <prefix>2, ... (LOCKED: k3s-dev-1/2/3)."
|
||||
type = string
|
||||
default = "k3s-dev-"
|
||||
}
|
||||
|
||||
variable "node_count" {
|
||||
description = "Number of k3s nodes (LOCKED: 3-server HA embedded etcd)."
|
||||
type = number
|
||||
default = 3
|
||||
|
||||
validation {
|
||||
condition = var.node_count == length(var.node_ips)
|
||||
error_message = "node_count must equal the number of entries in node_ips."
|
||||
}
|
||||
}
|
||||
|
||||
# --- per-node sizing (LOCKED: 4 vCPU / 6 GiB / 20 GiB OS + 40 GiB data) -----
|
||||
|
||||
variable "vcpu" {
|
||||
description = "vCPUs per node."
|
||||
type = number
|
||||
default = 4
|
||||
}
|
||||
|
||||
variable "memory_mib" {
|
||||
description = "RAM per node in MiB (6 GiB)."
|
||||
type = number
|
||||
default = 6144
|
||||
}
|
||||
|
||||
variable "os_disk_gib" {
|
||||
description = "OS (root) disk size per node, GiB. Thin qcow2 backed by the cloud image."
|
||||
type = number
|
||||
default = 20
|
||||
}
|
||||
|
||||
variable "data_disk_gib" {
|
||||
description = "Dedicated Longhorn data disk per node, GiB. Thin qcow2, blank."
|
||||
type = number
|
||||
default = 40
|
||||
}
|
||||
|
||||
variable "cpu_mode" {
|
||||
description = "libvirt CPU mode. host-passthrough exposes nested-virt for KubeVirt (Phase 5)."
|
||||
type = string
|
||||
default = "host-passthrough"
|
||||
}
|
||||
|
||||
# --- network (LOCKED: dedicated NAT k3s-dev 10.73.0.0/24, gw .1) ------------
|
||||
|
||||
variable "network_name" {
|
||||
description = "libvirt NAT network name."
|
||||
type = string
|
||||
default = "k3s-dev"
|
||||
}
|
||||
|
||||
variable "network_cidr" {
|
||||
description = "Cluster NAT subnet in CIDR. Gateway (network_gateway) is the libvirt bridge host IP."
|
||||
type = string
|
||||
default = "10.73.0.0/24"
|
||||
}
|
||||
|
||||
variable "network_prefix" {
|
||||
description = "Netmask prefix length for node static addressing."
|
||||
type = number
|
||||
default = 24
|
||||
}
|
||||
|
||||
variable "network_gateway" {
|
||||
description = "Default gateway / DNS for nodes = libvirt bridge host IP (LOCKED: 10.73.0.1)."
|
||||
type = string
|
||||
default = "10.73.0.1"
|
||||
}
|
||||
|
||||
variable "node_ips" {
|
||||
description = "Static IPs per node, in order (LOCKED: .11/.12/.13)."
|
||||
type = list(string)
|
||||
default = ["10.73.0.11", "10.73.0.12", "10.73.0.13"]
|
||||
}
|
||||
|
||||
# Reserved for Cilium L2-announcement ingress VIPs (LOCKED: .240-.250).
|
||||
# Not materialised as libvirt objects; surfaced in outputs and kept OUT of any
|
||||
# DHCP range so nothing else claims them. Cilium's IP pool (WS-NET, Phase 2)
|
||||
# consumes this range.
|
||||
variable "cilium_l2_vip_range_start" {
|
||||
description = "First reserved Cilium L2 VIP."
|
||||
type = string
|
||||
default = "10.73.0.240"
|
||||
}
|
||||
|
||||
variable "cilium_l2_vip_range_end" {
|
||||
description = "Last reserved Cilium L2 VIP."
|
||||
type = string
|
||||
default = "10.73.0.250"
|
||||
}
|
||||
|
||||
# --- base OS image ----------------------------------------------------------
|
||||
|
||||
variable "image_source" {
|
||||
description = <<-EOT
|
||||
Source for the base OS volume: a URL or local path to a minimal cloud image
|
||||
(qcow2). Default is Debian 12 (bookworm) genericcloud amd64. Point at a local
|
||||
path to avoid re-downloading on every apply.
|
||||
EOT
|
||||
type = string
|
||||
default = "https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2"
|
||||
}
|
||||
|
||||
# --- cloud-init identity ----------------------------------------------------
|
||||
|
||||
variable "ssh_authorized_key" {
|
||||
description = "SSH PUBLIC key injected into the login user (public only — never a private key)."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "login_user" {
|
||||
description = "Non-root login user created by cloud-init; also the Ansible ansible_user."
|
||||
type = string
|
||||
default = "k3s"
|
||||
}
|
||||
|
||||
variable "node_domain" {
|
||||
description = "DNS domain suffix for node FQDNs (informational; dev uses split-horizon / hosts)."
|
||||
type = string
|
||||
default = "k3s.dev.local"
|
||||
}
|
||||
Reference in new issue
Block a user