This commit is contained in:
Peter 2025-10-26 11:42:08 +01:00
parent 5def74736b
commit 26be097fda
Signed by: Peter
SSH key fingerprint: SHA256:B5tYaxBExaDm74r1px9iVeZ6F/ZDiyiy9SbBqfZYrvg
13 changed files with 356 additions and 184 deletions

View file

@ -0,0 +1,43 @@
name: Tofu Plan
on:
pull_request:
branches: [ main ]
push:
branches-ignore:
- main
permissions:
contents: read
jobs:
tofu:
runs-on: ubuntu-latest
defaults:
run:
shell: bash
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.9.8
- name: Terraform Format Check
run: terraform fmt -check -recursive
- name: Terraform Init
run: terraform init -backend=false
- name: Terraform Validate
run: terraform validate
- name: Terraform Plan
env:
TF_VAR_proxmox_endpoint: ${{ secrets.PROXMOX_ENDPOINT }}
TF_VAR_proxmox_api_token: ${{ secrets.PROXMOX_API_TOKEN }}
run: terraform plan -out=tfplan

View file

@ -1,47 +1,82 @@
# This file is maintained automatically by "tofu init". # This file is maintained automatically by "tofu init".
# Manual edits may be lost in future updates. # Manual edits may be lost in future updates.
provider "registry.opentofu.org/siderolabs/talos" { provider "registry.opentofu.org/bpg/proxmox" {
version = "0.9.0" version = "0.85.1"
constraints = "0.9.0" constraints = "0.85.1"
hashes = [ hashes = [
"h1:50TaymX/KnjXcURmpKsVd7JUyLRrMDNXMHFgqzSe88U=", "h1:VWZI8z0O7flk66jBrWK8rltUKEU8zCjljZvoQ54wwf0=",
"zh:0fa82a384b25a58b65523e0ea4768fa1212b1f5cfc0c9379d31162454fedcc9d", "zh:0866c44f3bc222d01fb6cc998eadef102cda2434464b929466998719c98ef77f",
"zh:249ab08b810bb96ef7c35354a12622907df7cbda59c83ff314ee85e8b851128d", "zh:1db527d7a8b12c9fc99151798469352e756d9af0ba2fbfb155dea935df3b423a",
"zh:4f284c21f0cb4b7012fdb231ebba4803e5c389f7ea380fb5958ebfa6b822d055", "zh:2e9dbbc846028cd7fdf21fda884c766bf3d81b7d8a2e5f9924cc48759805fe74",
"zh:6049f8d06bc92ab1a46d56c2b37799e6a1b7ce3c61905acf8f0c2009942be8ac", "zh:32817963c835c7e4528c6e13147f183647b201fd17d189f102a41c478d3994e7",
"zh:7de5f0a6429c6856ade3c7e59d5041a7fe8e0010aea14a2074e91f8a526283ce", "zh:3ef2915dee3a0c4fea4f205afde7d3318401e91989df99ee560a42302ff0d4d7",
"zh:9760420cf5feec0550556664962bc6f1af45115b9ea5bcbf47aa9bffd3dd4ac2", "zh:5829f4d0b9731057febf6209d854a5a424d5787297ae9fb6b7f5106fc4271c04",
"zh:9860272a9fbcea65393c478dc579ad2677a44338de24677702ce699a027801aa", "zh:69f932cb1c5b4594914fc4bba0c110311cc5de79c56c75cf9ff6e85faf8ddd38",
"zh:a60311a8bf267b18dcf1c8250f45e371b51c6aef086e037a3f9496602f190187", "zh:87840842b229796c34ef07bd7c01016f19b11a83646cc6ff19c1ce3aeec010f7",
"zh:b74c119b2a964cae8d17b5b5f14c8eecf44708e3817c1f65ac89b813856aed98", "zh:9299c9aeeca2afc836066e971f587facff2287125c52658b9031c97e1b62eb24",
"zh:bc33e14650052c246ac2e6492a0a24755d4e8d27cb7259e3996f07b0537f2c77", "zh:ce3bbb9375518a3ad8a7a4b8434ff72bfe2d6543309f419e4128961b73d6d84e",
"zh:c4bc2c65b3dcef2508c14dbbfc18937c5ede11670c02a644cbc28c83a57de92b", "zh:d0b5fa229ae989350f47e42244dfcf91f149c27c1f229fe5b8ad9828f21a896e",
"zh:c98bf4809220568d76ea2db232a88a60c29fd90d4c9e2f8c8a68cf91ceed066a", "zh:d80cc976b0cc4726d18d6cac094b520c0a670898494c7f8cdb5a72903ba7b57e",
"zh:de0179ee9c55bf36d3474049ceac3a105ed7bc1fb9c4787d4076c4b15d268b66", "zh:f1d3919f53f195e9163ca6d85f5906fc3f40d9aac4c320cbc04aee0103780242",
"zh:e99e019d950131c2c4259c1cbca1d072cb813bdfdbbbf9359f5901d6b7542a0d", "zh:f26e0763dbe6a6b2195c94b44696f2110f7f55433dc142839be16b9697fa5597",
"zh:feb941cc673692c6858f96590f3ca082683a62aa2d2842b9bfffcd327eb840d3", "zh:ff1ae863a11fcbfb5850dc8f0b652c17c0e6ec0a1a4f4877e95143023426a2f7",
] ]
} }
provider "registry.opentofu.org/telmate/proxmox" { provider "registry.opentofu.org/hashicorp/http" {
version = "3.0.2-rc05" version = "3.5.0"
constraints = ">= 3.0.2-rc05, 3.0.2-rc05"
hashes = [ hashes = [
"h1:PG5/Mu1UUP6/WIdtytJKZ8NxQJg8OIGygFwJOoPdmZw=", "h1:eClUBisXme48lqiUl3U2+H2a2mzDawS9biqfkd9synw=",
"zh:042d748367f33aaf440698644be4f2a2875f9db31915c1ef84616f176fc6174f", "zh:0a2b33494eec6a91a183629cf217e073be063624c5d3f70870456ddb478308e9",
"zh:1488781da1920d60d933c8ce926c34b5e989ffae58e3fbe437973d2b1d2faafc", "zh:180f40124fa01b98b3d2f79128646b151818e09d6a1a9ca08e0b032a0b1e9cb1",
"zh:283dd6f74627f1d1d75d616b31f8ced3f97fd5277a07c9535e85cfa765d7a321", "zh:3e29e1de149dc10bf78620526c7cb8c62cd76087f5630dfaba0e93cda1f3aa7b",
"zh:378f1c2da21aeea083ac2e632db274a02c7a01e2486a40d3c813d05a21142db3", "zh:4420950200cf86042ec940d0e2c9b7c89966bf556bf8038ba36217eae663bca5",
"zh:38d63d0961f8c32273392caaace30f50cff8ab06e5dda17f67a8827ebffeba98", "zh:5d1f7d02109b2e2dca7ec626e5563ee765583792d0fd64081286f16f9433bd0d",
"zh:52159782df101ec98f20faff81e8f2d9d92cb4ec903314fcddcc57ec16cdaacb", "zh:8500b138d338b1994c4206aa577b5c44e1d7260825babcf43245a7075bfa52a5",
"zh:6ca47b90c66b1d2706cb3cbb05da8b3f90a202c4865010202b2962e2b64d217e", "zh:b42165a6c4cfb22825938272d12b676e4a6946ac4e750f85df870c947685df2d",
"zh:6e7b85cb2380e4dc0be694dd0e4a24927f7f66df41960eca3cfe907443d4f0b9", "zh:b919bf3ee8e3b01051a0da3433b443a925e272893d3724ee8fc0f666ec7012c9",
"zh:758775f733673ab5c196db6a33648458037746f94d4bef7ce148cb01474efe2d", "zh:d13b81ea6755cae785b3e11634936cdff2dc1ec009dc9610d8e3c7eb32f42e69",
"zh:7c31a3ca6d52db39da2bdd60be37af71d59d808fc206de50fe661535ea436da3", "zh:f1c9d2eb1a6b618ae77ad86649679241bd8d6aacec06d0a68d86f748687f4eb3",
"zh:af16984350a2f4d77c21f66a479007801e2527543310567c99cd82eb421e249e", ]
"zh:c1f965d3f96cf3f87af2c12ab9d4bde42f8ef660f8dc34ba3cfc9b20435a7269", }
"zh:c2b9022a31103919a5ffbac6ee8d7feb6c4f5f580c1766f769569c2e8e4ce7f1",
"zh:e90162c42f1237323291e3d0de0c62701b3f89350fae18246da06702f41a6123", provider "registry.opentofu.org/hashicorp/null" {
version = "3.2.4"
hashes = [
"h1:i+WKhUHL2REY5EGmiHjfUljJB8UKZ9QdhdM5uTeUhC4=",
"zh:1769783386610bed8bb1e861a119fe25058be41895e3996d9216dd6bb8a7aee3",
"zh:32c62a9387ad0b861b5262b41c5e9ed6e940eda729c2a0e58100e6629af27ddb",
"zh:339bf8c2f9733fce068eb6d5612701144c752425cebeafab36563a16be460fb2",
"zh:36731f23343aee12a7e078067a98644c0126714c4fe9ac930eecb0f2361788c4",
"zh:3d106c7e32a929e2843f732625a582e562ff09120021e510a51a6f5d01175b8d",
"zh:74bcb3567708171ad83b234b92c9d63ab441ef882b770b0210c2b14fdbe3b1b6",
"zh:90b55bdbffa35df9204282251059e62c178b0ac7035958b93a647839643c0072",
"zh:ae24c0e5adc692b8f94cb23a000f91a316070fdc19418578dcf2134ff57cf447",
"zh:b5c10d4ad860c4c21273203d1de6d2f0286845edf1c64319fa2362df526b5f58",
"zh:e05bbd88e82e1d6234988c85db62fd66f11502645838fff594a2ec25352ecd80",
]
}
provider "registry.opentofu.org/siderolabs/talos" {
version = "0.5.0"
constraints = "0.5.0"
hashes = [
"h1:YemD0Cy0cRa9LHtHzIKMQcbTV2aIo9Wh2TEeRTVdVB8=",
"zh:0f71f2624576224c9bc924b136b601b734243efa7a7ad8280dfd8bd583e4afa5",
"zh:0fa82a384b25a58b65523e0ea4768fa1212b1f5cfc0c9379d31162454fedcc9d",
"zh:33c50dacc5029fa20caed702001fb1439899c94f203b1f37dccb970f504bca45",
"zh:3c97a6e2692b88d3f4631a3f8769146f602c210e881b46fa1b3b82c545e51cd1",
"zh:44077a137613bcfe29eef00315b5aa50d83390c3c727580a4ff0f4b87f22d228",
"zh:5bd02f278aec5567f94dd057d1c758363998ce581ff17b0869515bb682c02186",
"zh:80f40939bc3b55f0005c03b77122ceea86ec4deb82f5557950a97ad96fbb1557",
"zh:94c1b17f25bc30eacde926e46f196f1f135032674730d9f50c986ef6b7a854f0",
"zh:95ad665b2fdeed38180f5c471164833a34d07c1ef0470c1652565fe8cf4e9c4a",
"zh:a50ef6088afcb129c176dd4ba86c345e9be7b14358bb3b21c34f06930d8f39ef",
"zh:aa71da1da00ed66f1dddf1b69c10b829f24ac89e207de07d32c455dd04482096",
"zh:abb7eeb2b089081b4814ed80a295673e1a92f82ce092dde37b5bc92e75efec2c",
"zh:db9b9b54a0db5ae151376d5a73e0d28497c3e06181840e71ef8349213ac03e50",
"zh:e50ed8aa90b736508fce63680e8339240cecb74709ab9563d34d2c2ce7bc8445",
"zh:f3a279723ff31a095d7bfff21857abfcc9a2cfdeeea8521d179630ae6565d581",
] ]
} }

View file

@ -1,68 +1,110 @@
terraform {
required_providers {
proxmox = {
source = "Telmate/proxmox"
version = "3.0.2-rc05"
}
talos = {
source = "siderolabs/talos"
version = "0.9.0"
}
}
}
provider "proxmox" { provider "proxmox" {
pm_api_url = "https://10.167.84.10:8006/api2/json" endpoint = var.proxmox_endpoint
pm_api_token_id = "" api_token = var.proxmox_api_token
pm_api_token_secret = "" insecure = true
pm_tls_insecure = true
} }
locals { locals {
talos_version = "1.11.3" cluster_name = "k8s-wheatley"
} kubernetes_version = "1.34.1"
talos_version = "1.11.3"
ipv4_gateway = "10.13.38.1"
cluster_endpoint_ip = "10.13.38.20"
module "controlplanes" {
source = "./modules/controlplane"
controlplanes = { controlplanes = {
cpu = 4 cpu = 4
memory = 4 memory = 4
disk = "40G" disk = 40
storagepool = "nvme-fastpool" storagepool = "nvme-fastpool"
talos_version = local.talos_version talos_version = local.talos_version
cluster_name = local.cluster_name
kubernetes_version = local.kubernetes_version
ipv4_gateway = local.ipv4_gateway
nodes = [ nodes = [
{ {
name = "cp01" name = "cp01"
ip_address = "10.13.38.20" ip_address = "10.13.38.21"
mac_address = "BC:24:11:11:9D:71"
}, },
{ # {
name = "cp02" # name = "cp02"
ip_address = "10.13.38.21" # ip_address = "10.13.38.22"
}, # mac_address = "BC:24:11:11:9D:72"
{ # },
name = "cp03" # {
ip_address = "10.13.38.22" # name = "cp03"
}] # ip_address = "10.13.38.23"
# mac_address = "BC:24:11:11:9D:73"
]
} }
# workers = {
# cpu = 4
# memory = 4
# disk = "40G"
# storagepool = "nvme-fastpool"
# talos_version = local.talos_version
# cluster_name = local.cluster_name
# kubernetes_version = local.kubernetes_version
# nodes = [
# {
# name = "worker01"
# ip_address = "10.13.38.20"
# },
# {
# name = "worker02"
# ip_address = "10.13.38.21"
# },
# {
# name = "worker03"
# ip_address = "10.13.38.22"
# }]
# }
} }
module "workers" { module "talos-image" {
source = "./modules/worker" source = "./modules/talos-image"
workers = { talos_version = local.talos_version
cpu = 4
memory = 4
disk = "40G"
storagepool = "nvme-fastpool"
talos_version = local.talos_version
nodes = [
{
name = "worker01"
ip_address = "10.13.38.30"
},
{
name = "worker02"
ip_address = "10.13.38.31"
}]
}
} }
# module "controlplanes" {
# depends_on = [module.talos-image]
#
# source = "./modules/controlplane"
# for_each = { for node in local.controlplanes.nodes : node.name => node }
#
# controlplane = {
# cpu = local.controlplanes.cpu
# memory = local.controlplanes.memory
# disk = local.controlplanes.disk
# storagepool = local.controlplanes.storagepool
# talos_version = local.talos_version
# cluster_name = local.cluster_name
# kubernetes_version = local.kubernetes_version
# node_name = format("k8s-wheatley-%s", each.value.name)
# node_ipv4_address = each.value.ip_address
# cluster_endpoint = format("https://%s:6443", local.cluster_endpoint_ip)
# ipv4_gateway = local.ipv4_gateway
# mac_address = each.value.mac_address
# }
# }
# module "workers" {
# source = "./modules/worker"
# for_each = { for node in local.workers.nodes : node.name => node }
#
# workers = {
# cpu = local.workers.cpu
# memory = local.workers.memory
# disk = local.workers.disk
# storagepool = local.workers.storagepool
# talos_version = local.talos_version
# cluster_name = local.cluster_name
# kubernetes_version = local.kubernetes_version
# node_name = format("k8s-wheatley-%s", each.value.name)
# node_ipv4_address = each.value.ip_address
# }
# }

View file

@ -0,0 +1,30 @@
debug: false
machine:
install:
disk: ${install_disk}
network:
hostname: ${hostname}
nameservers:
- 10.13.37.2
interfaces:
- interface: eth0
dhcp: false
kubelet:
extraArgs:
pod-max-pids: 1000
extraConfig:
imageGCHighThresholdPercent: 75
imageGCLowThresholdPercent: 70
cluster:
apiServer:
auditPolicy:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
# Log only metadata in audit logs
- level: Metadata
network:
cni:
name: none
proxy:
disabled: true

View file

@ -1,44 +1,63 @@
terraform { terraform {
required_providers { required_providers {
proxmox = { proxmox = {
source = "telmate/proxmox" source = "bpg/proxmox"
version = ">= 3.0.2-rc05" version = "0.85.1"
} }
} }
} }
resource "proxmox_vm_qemu" "controlplane" {
for_each = { for node in var.controlplanes.nodes : node.name => node }
name = format("k8s-wheatley-%s", each.value.name) resource "proxmox_virtual_environment_vm" "controlplane" {
target_node = "pve01"
tags = "k8s-wheatley,controlplane"
onboot = true
bios = "ovmf"
boot = "order=virtio0;net0"
clone = format("talos-%s", var.controlplanes.talos_version)
scsihw = "virtio-scsi-pci"
disk { name = format("k8s-wheatley-%s", var.controlplane.node_name)
size = var.controlplanes.disk node_name = "pve01"
storage = var.controlplanes.storagepool tags = ["k8s-wheatley,controlplane"]
type = "disk" bios = "ovmf"
slot = "virtio0" on_boot = true
format = "raw" machine = "q35"
stop_on_destroy = true
operating_system {
type = "l26"
}
agent {
enabled = true
} }
cpu { cpu {
cores = var.controlplanes.cpu cores = var.controlplane.cpu
sockets = 1 sockets = 1
type = "host"
} }
memory = var.controlplanes.memory * 1024 memory {
dedicated = var.controlplane.memory * 1024
}
network { disk {
id = 0 datastore_id = var.controlplane.storagepool
model = "virtio" interface = "virtio0"
size = var.controlplane.disk * 1024
file_format = "raw"
}
initialization {
datastore_id = var.controlplane.storagepool
ip_config {
ipv4 {
address = var.controlplane.node_ipv4_address
gateway = var.controlplane.ipv4_gateway
}
}
dns {
servers = ["10.13.37.2"]
}
}
network_device {
bridge = "vmbr1" bridge = "vmbr1"
mac_address = var.controlplane.mac_address
} }
ipconfig0 = format("ip=%s/24,gw=10.13.38.1", each.value.ip_address)
skip_ipv6 = true
} }

View file

@ -1,15 +1,18 @@
variable "controlplanes" { variable "controlplane" {
description = "Control plane node configuration" description = "Control plane node configuration"
type = object({ type = object({
cpu = number cpu = number
memory = number memory = number
disk = string disk = string
storagepool = string storagepool = string
talos_version = string talos_version = string
nodes = list(object({ cluster_name = string
name = string kubernetes_version = string
ip_address = string node_name = string
})) node_ipv4_address = string
cluster_endpoint = string
ipv4_gateway = string
mac_address = string
}) })
} }

View file

@ -0,0 +1,25 @@
data "http" "schematic" {
url = "https://factory.talos.dev/schematics"
method = "POST"
request_body = file("${path.module}/schematic.yaml")
request_headers = {
"Content-Type" = "application/x-yaml"
}
}
locals {
schematic_id = jsondecode(data.http.schematic.response_body)["id"]
iso_url = "${"https://factory.talos.dev/image"}/${local.schematic_id}/${var.talos_version}/nocloud-amd64.iso"
iso_file = "${var.iso_path}/talos-${local.schematic_id}-${var.talos_version}-nocloud-amd64.iso"
}
resource "null_resource" "download_iso" {
provisioner "local-exec" {
command = <<-EOT
mkdir -p ${var.iso_path}
if [ ! -f "${local.iso_file}" ]; then
curl -L -o "${local.iso_file}" "${local.iso_url}"
fi
EOT
}
}

View file

@ -0,0 +1,4 @@
customization:
systemExtensions:
officialExtensions:
- siderolabs/qemu-guest-agent

View file

@ -0,0 +1,10 @@
variable "talos_version" {
description = "Talos version to download"
type = string
}
variable "iso_path" {
description = "Path to store downloaded Talos ISO images"
type = string
default = "/var/lib/vz/template/iso"
}

View file

@ -1,44 +0,0 @@
terraform {
required_providers {
proxmox = {
source = "telmate/proxmox"
version = ">= 3.0.2-rc05"
}
}
}
resource "proxmox_vm_qemu" "worker" {
for_each = { for node in var.workers.nodes : node.name => node }
name = format("k8s-wheatley-%s", each.value.name)
target_node = "pve01"
tags = "k8s-wheatley,worker"
onboot = true
bios = "ovmf"
boot = "order=virtio0;net0"
clone = format("talos-%s", var.workers.talos_version)
scsihw = "virtio-scsi-pci"
disk {
size = var.workers.disk
storage = var.workers.storagepool
type = "disk"
slot = "virtio0"
format = "raw"
}
cpu {
cores = var.workers.cpu
sockets = 1
}
memory = var.workers.memory * 1024
network {
id = 0
model = "virtio"
bridge = "vmbr1"
}
ipconfig0 = format("ip=%s/24,gw=10.13.38.1", each.value.ip_address)
skip_ipv6 = true
}

View file

@ -1,15 +0,0 @@
variable "workers" {
description = "Worker node configuration"
type = object({
cpu = number
memory = number
disk = string
storagepool = string
talos_version = string
nodes = list(object({
name = string
ip_address = string
}))
})
}

View file

@ -0,0 +1,12 @@
terraform {
required_providers {
talos = {
source = "siderolabs/talos"
version = "0.5.0"
}
proxmox = {
source = "bpg/proxmox"
version = "0.85.1"
}
}
}

View file

@ -0,0 +1,8 @@
variable "proxmox_endpoint" {
description = "Proxmox API endpoint"
type = string
}
variable "proxmox_api_token" {
description = "Proxmox API token"
type = string
}