platform: OpenTofu/Ansible für Proxmox, CI, Makefile, Doku-Abgleich

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 00:54:23 +02:00
co-authored by Claude Opus 5.5
parent cb5a413169
commit f22eaa8449
27 changed files with 623 additions and 6 deletions
+153
View File
@@ -0,0 +1,153 @@
# GPU-Mappings, GPU-VMs und Infra-LXC aus sites/<site>/proxmox.yaml.
# Nicht gegen einen echten Cluster getestet – beim gemeinsamen Deployment zuerst `tofu plan`.
resource "proxmox_virtual_environment_hardware_mapping_pci" "gpu" {
for_each = local.site.pci_mappings
name = each.key
map = [{
node = each.value.node
path = each.value.path
id = each.value.id
subsystem_id = each.value.subsystem_id
iommu_group = each.value.iommu_group
}]
}
resource "proxmox_virtual_environment_vm" "gpu" {
for_each = local.site.vms
name = each.key
node_name = each.value.node
vm_id = each.value.vmid
tags = ["knaster", each.value.role, each.value.driver_generation]
machine = "q35"
bios = "ovmf"
on_boot = true
clone {
vm_id = local.site.cluster.template_vmid
full = true
}
cpu {
cores = each.value.cores
type = "host"
}
# PCI-Passthrough pinnt den gesamten RAM → kein Ballooning
memory {
dedicated = each.value.memory_mb
floating = 0
}
efi_disk {
datastore_id = local.site.cluster.storage_vm
type = "4m"
}
disk {
datastore_id = local.site.cluster.storage_vm
interface = "scsi0"
size = each.value.disk_gb
discard = "on"
ssd = true
}
# Modelle: eigenes Disk-Image, nicht repliziert, nicht gesichert (ADR-0002)
disk {
datastore_id = local.site.cluster.storage_vm
interface = "scsi1"
size = each.value.models_disk_gb
discard = "on"
ssd = true
backup = false
replicate = false
}
hostpci {
device = "hostpci0"
mapping = proxmox_virtual_environment_hardware_mapping_pci.gpu[each.value.gpu].name
pcie = true
rombar = true
}
network_device {
bridge = local.site.cluster.bridge
vlan_id = local.site.cluster.vlan_svc
}
initialization {
datastore_id = local.site.cluster.storage_vm
ip_config {
ipv4 {
address = each.value.ip
gateway = local.site.cluster.gateway
}
}
dns {
servers = [local.site.cluster.dns]
}
user_account {
username = "knaster"
keys = [local.ssh_key]
}
}
}
resource "proxmox_virtual_environment_container" "infra" {
for_each = local.site.containers
node_name = each.value.node
vm_id = each.value.vmid
tags = ["knaster", "infra"]
unprivileged = true
start_on_boot = true
features {
nesting = true # Docker im LXC
}
cpu {
cores = each.value.cores
}
memory {
dedicated = each.value.memory_mb
}
disk {
datastore_id = local.site.cluster.storage_vm
size = each.value.disk_gb
}
operating_system {
template_file_id = "${local.site.cluster.storage_iso}:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst"
type = "debian"
}
network_interface {
name = "eth0"
bridge = local.site.cluster.bridge
vlan_id = local.site.cluster.vlan_svc
}
initialization {
hostname = each.key
ip_config {
ipv4 {
address = each.value.ip
gateway = local.site.cluster.gateway
}
}
user_account {
keys = [local.ssh_key]
}
}
}
resource "proxmox_virtual_environment_haresource" "infra" {
for_each = { for k, v in local.site.containers : k => v if try(v.ha, false) }
resource_id = "ct:${each.value.vmid}"
state = "started"
comment = "knaster ${each.key}"
depends_on = [proxmox_virtual_environment_container.infra]
}
+7
View File
@@ -0,0 +1,7 @@
output "gpu_vms" {
value = { for k, v in proxmox_virtual_environment_vm.gpu : k => { node = v.node_name, vmid = v.vm_id } }
}
output "infra_containers" {
value = { for k, v in proxmox_virtual_environment_container.infra : k => { node = v.node_name, vmid = v.vm_id } }
}
+22
View File
@@ -0,0 +1,22 @@
variable "site" {
description = "Name des Standorts unter sites/"
type = string
default = "knaster"
}
variable "proxmox_api_token" {
description = "API-Token im Format user@realm!tokenid=secret"
type = string
sensitive = true
}
variable "proxmox_insecure" {
description = "Selbstsigniertes Zertifikat akzeptieren"
type = bool
default = true
}
locals {
site = yamldecode(file("${path.module}/../../../sites/${var.site}/proxmox.yaml"))
ssh_key = trimspace(file(pathexpand(local.site.cluster.ssh_public_key_file)))
}
+18
View File
@@ -0,0 +1,18 @@
terraform {
required_version = ">= 1.6"
required_providers {
proxmox = {
source = "bpg/proxmox"
version = "~> 0.66"
}
}
}
provider "proxmox" {
endpoint = local.site.cluster.endpoint
api_token = var.proxmox_api_token
insecure = var.proxmox_insecure
ssh {
agent = true
}
}