Feat/deploy k8s vms #8

Merged
Vezpi merged 15 commits from feat/deploy-k8s-vms into main 2026-09-18 15:37:00 +02:00
3 changed files with 156 additions and 0 deletions
Showing only changes of commit d19a2c3798 - Show all commits
+72
View File
@@ -0,0 +1,72 @@
module "pve_vm" {
source = "../../modules/pve_vm"
for_each = local.vm_list
node_name = each.value.node_name
vm_name = each.key
vm_cpu = each.value.vm_cpu
vm_ram = each.value.vm_ram
vm_vlan = each.value.vm_vlan
vm_tags = var.vm_tags
}
locals {
node_stats = [
for i, name in data.proxmox_virtual_environment_nodes.pve_nodes.names : {
name = name
free_mib = floor(data.proxmox_virtual_environment_nodes.pve_nodes.memory_available[i] / 1024 / 1024)
}
if data.proxmox_virtual_environment_nodes.pve_nodes.online[i]
]
max_free_mib = length(local.node_stats) > 0 ? max([for node in local.node_stats : node.free_mib]...) : 0
# Online nodes ordered by available memory, most available first (name as tie-break)
node_order = var.target_node != "" ? [var.target_node] : [
for key in sort([
for node in local.node_stats : "${format("%012d", local.max_free_mib - node.free_mib)}|${node.name}"
]) : split("|", key)[1]
]
vm_layout = flatten([
for role in ["master", "worker"] : [
for i in range(role == "master" ? var.master_count : var.worker_count) : {
vm_name = "kub-${var.vm_env}-${substr(role, 0, 1)}${format("%02d", i + 1)}"
seq_index = (role == "master" ? 0 : var.master_count) + i
vm_role = role
}
]
])
vm_list = {
for vm in local.vm_layout :
vm.vm_name => {
node_name = length(local.node_order) > 0 ? local.node_order[vm.seq_index % length(local.node_order)] : ""
vm_cpu = var.vm_attr[vm.vm_role].cpu
vm_ram = var.vm_attr[vm.vm_role].ram
vm_vlan = var.vm_attr[vm.vm_role].vlan
vm_role = vm.vm_role
}
}
roles = toset([for vm in local.vm_list : vm.vm_role])
}
data "proxmox_virtual_environment_nodes" "pve_nodes" {}
output "vm_ip" {
value = { for k, v in module.pve_vm : k => v.vm_ip }
}
resource "ansible_group" "vm_groups" {
for_each = local.roles
name = each.key
}
resource "ansible_host" "vm_hosts" {
for_each = module.pve_vm
name = each.key
variables = {
ansible_host = each.value.vm_ip
}
groups = [local.vm_list[each.key].vm_role]
}
@@ -0,0 +1,21 @@
terraform {
required_providers {
proxmox = {
source = "bpg/proxmox"
}
ansible = {
source = "ansible/ansible"
}
}
}
provider "proxmox" {
endpoint = var.proxmox_endpoint
api_token = var.proxmox_api_token
insecure = false
ssh {
agent = false
private_key = file("~/.ssh/id_ed25519")
username = "root"
}
}
@@ -0,0 +1,63 @@
variable "proxmox_endpoint" {
description = "Proxmox URL endpoint"
type = string
}
variable "proxmox_api_token" {
description = "Proxmox API token"
type = string
sensitive = true
}
variable "target_node" {
description = "Node which hosts the VMs when set; otherwise a node is selected based on available resources"
type = string
default = ""
}
variable "master_count" {
description = "Number of Kubernetes control-plane (master) VMs to deploy"
type = number
default = 3
validation {
condition = var.master_count >= 1
error_message = "master_count must be at least 1."
}
}
variable "worker_count" {
description = "Number of Kubernetes worker VMs to deploy"
type = number
default = 3
validation {
condition = var.worker_count >= 1
error_message = "worker_count must be at least 1."
}
}
variable "vm_attr" {
description = "VM attributes"
type = map(object({
ram = number
cpu = number
vlan = number
}))
default = {
"master" = { ram = 2048, cpu = 2, vlan = 66 }
"worker" = { ram = 4096, cpu = 2, vlan = 66 }
}
}
variable "vm_env" {
description = "VM environment"
type = string
default = "prod"
}
variable "vm_tags" {
description = "Tags for the VM"
type = list(any)
default = ["prod"]
}