diff --git a/cluster/locals.tf b/cluster/locals.tf index 7e6ee11..1606811 100644 --- a/cluster/locals.tf +++ b/cluster/locals.tf @@ -1,52 +1,159 @@ # nodes — описание виртуальных машин # +# Общая идея: +# - каждая VM может иметь несколько сетевых интерфейсов (network_devices) +# - каждый интерфейс полностью описывает свою сеть (bridge, VLAN, IP, gateway) +# - порядок элементов в network_devices важен: +# [0] → eth0 (основной интерфейс, обычно с default gateway) +# [1] → eth1 +# [2] → eth2 +# +# network_devices: +# - список сетевых интерфейсов VM +# +# поля: +# +# bridge: +# - имя Proxmox bridge (например vmbr0, vmbr1) +# - ОБЯЗАТЕЛЬНО +# # vlan_id: -# - опциональный параметр -# - если НЕ указан → VM будет в обычной сети (untagged, vmbr0) -# - если указан → VM попадет в соответствующий VLAN (например 20 → 192.168.20.0/24) +# - опционально +# - если НЕ указан → интерфейс untagged +# - если указан → интерфейс будет в VLAN (например 20 → зависит от настройки Proxmox bridge) +# +# ip: +# - IPv4 адрес без CIDR (например "192.168.20.11") +# - если не указан → будет использован DHCP (если доступен в сети) +# +# cidr: +# - маска сети (например 24) +# - используется вместе с ip → итог: ip/cidr +# +# gateway: +# - опционально +# - указывать ТОЛЬКО для одного интерфейса (обычно первого) +# - задаёт default route внутри VM +# +# ВАЖНО: +# - gateway должен быть только у одного интерфейса +# - порядок network_devices критичен (eth0, eth1 и т.д.) +# - неправильный порядок → потеря доступа к VM +# +# # cloudinit: # - опциональный параметр -# - указывает имя cloud-init файла для конкретной VM -# - файл должен находиться в root: cloud-config/<имя>.yml -# - если НЕ указан → используется "default.yml" -# - если файл НЕ найден в root → используется fallback из модуля (modules/node/cloud-config/default.yml) +# - имя cloud-init файла +# - ищется в: +# cloud-config/<имя>.yml (root) +# - если не найден → fallback: +# modules/node/cloud-config/default.yml # # пример: -# - cloudinit = "worker.yml" → будет использован cloud-config/worker.yml -# - cloudinit не задан → будет использован default.yml +# - cloudinit = "worker.yml" → cloud-config/worker.yml +# - не указан → default.yml +# +# +# пример одной сети (single NIC): +# +# network_devices = [ +# { +# bridge = "vmbr0" +# vlan_id = 20 +# ip = "192.168.20.11" +# cidr = 24 +# gateway = "192.168.20.1" +# } +# ] +# +# +# пример двух сетей: +# +# network_devices = [ +# { +# bridge = "vmbr0" +# vlan_id = 20 +# ip = "192.168.20.23" +# cidr = 24 +# gateway = "192.168.20.1" +# }, +# { +# bridge = "vmbr1" +# ip = "192.168.22.26" +# cidr = 24 +# } +# ] +# +# +# РЕКОМЕНДАЦИИ: +# - первый интерфейс (eth0) → management сеть +# - второй интерфейс → storage / overlay / secondary +# - не задавать gateway на вторичных интерфейсах +# +# +# ПОВЕДЕНИЕ: +# - ip_config генерируется автоматически из network_devices +# - соответствие: порядок массива = порядок интерфейсов +# locals { nodes = { - k8s-master-1 = { + k8s-master-1 = { cloudinit = "master.yml" index = 1 cpu = var.worker_cpu - memory = 4092 + memory = 4092 disk = var.worker_disk datastore = var.worker_datastore - ip_offset = 10 - vlan_id = 20 - } - - k8s-worker-1 = { + + network_devices = [ + { + bridge = var.node_bridge + vlan_id = 20 + ip = "192.168.20.11" + cidr = 24 + gateway = "192.168.20.1" + } + ] + }, + k8s-worker-1 = { cloudinit = "worker.yml" index = 2 - cpu = 4 - memory = 8192 + cpu = var.worker_cpu + memory = 8192 disk = var.worker_disk datastore = var.worker_datastore - ip_offset = 20 - vlan_id = 20 - } - k8s-worker-2 = { - cloudinit = "worker.yml" + + network_devices = [ + { + bridge = var.node_bridge + vlan_id = 20 + ip = "192.168.20.22" + cidr = 24 + gateway = "192.168.20.1" + } + ] + }, + k8s-worker-2 = { + cloudinit = "worker.yml" index = 3 - cpu = 4 - memory = 8192 + cpu = var.worker_cpu + memory = 8192 disk = var.worker_disk datastore = var.worker_datastore - ip_offset = 20 - vlan_id = 20 - } + + network_devices = [ + { + bridge = var.node_bridge + vlan_id = 20 + ip = "192.168.20.23" + cidr = 24 + gateway = "192.168.20.1" + }, + { + bridge = "vmbr0" + } + ] + } } } \ No newline at end of file diff --git a/cluster/main.tf b/cluster/main.tf index beb3713..f57953d 100644 --- a/cluster/main.tf +++ b/cluster/main.tf @@ -8,7 +8,6 @@ module "cluster" { nodes = local.nodes ssh_key = trimspace(data.local_file.ssh_key.content) - cluster_ip_start = var.cluster_ip_start worker_vmid_start = var.worker_vmid_start cloudinit_datastore = var.cloudinit_datastore @@ -19,9 +18,5 @@ module "cluster" { image_file = var.image_file disk_interface = var.disk_interface - network_base = var.network_base - network_cidr = var.network_cidr - cluster_gateway = var.cluster_gateway - data_datastore = var.data_datastore } diff --git a/cluster/variables.tf b/cluster/variables.tf index 7929429..2ded399 100644 --- a/cluster/variables.tf +++ b/cluster/variables.tf @@ -41,23 +41,6 @@ variable "worker_disk" { default = 20 } -variable "network_base" { - default = "192.168.22" -} - -variable "network_cidr" { - default = "24" -} - -variable "cluster_gateway" { - default = "192.168.22.1" -} - -variable "cluster_ip_start" { - default = 10 -} - - variable "worker_ip_offset" { default = 5 } @@ -66,6 +49,7 @@ variable "node_bridge" { default = "vmbr0" } + variable "worker_datastore" { type = string default = "local-lvm" diff --git a/modules/node/locals.tf b/modules/node/locals.tf index d4d36f4..ea90f92 100644 --- a/modules/node/locals.tf +++ b/modules/node/locals.tf @@ -6,13 +6,7 @@ locals { name => node } -ip_map = { - for name, node in local.nodes : - name => coalesce( - lookup(node, "ip", null), - "${var.network_base}.${var.cluster_ip_start + node.ip_offset + node.index}" - ) -} + vmid_map = { for name, node in local.nodes : diff --git a/modules/node/main.tf b/modules/node/main.tf index a2f1d49..319b0bb 100644 --- a/modules/node/main.tf +++ b/modules/node/main.tf @@ -54,11 +54,13 @@ resource "proxmox_virtual_environment_vm" "nodes" { dedicated = each.value.memory } - network_device { - bridge = var.node_bridge - # vlan_id = try(each.value.vlan_id, null) - vlan_id = each.value.vlan_id + dynamic "network_device" { + for_each = each.value.network_devices + content { + bridge = network_device.value.bridge + vlan_id = try(network_device.value.vlan_id, null) + } } disk { @@ -77,16 +79,19 @@ resource "proxmox_virtual_environment_vm" "nodes" { size = disk.value } } +initialization { + datastore_id = each.value.datastore + user_data_file_id = proxmox_virtual_environment_file.cloudinit[each.key].id - initialization { - datastore_id = each.value.datastore - user_data_file_id = proxmox_virtual_environment_file.cloudinit[each.key].id + dynamic "ip_config" { + for_each = each.value.network_devices -ip_config { - ipv4 { - address = "${local.ip_map[each.key]}/${var.network_cidr}" - gateway = var.cluster_gateway + content { + ipv4 { + address = try(ip_config.value.ip, "dhcp") == null ? "dhcp" : "${ip_config.value.ip}/${ip_config.value.cidr}" + gateway = try(ip_config.value.gateway, null) + } + } } } - } } \ No newline at end of file diff --git a/modules/node/variables.tf b/modules/node/variables.tf index f769d7e..c2fc9af 100644 --- a/modules/node/variables.tf +++ b/modules/node/variables.tf @@ -4,24 +4,26 @@ variable "ssh_key" { variable "nodes" { type = map(object({ - # role = string index = number cpu = number memory = number disk = number datastore = string - ip_offset = optional(number) - ip = optional(string) vmid = optional(number) - vlan_id = optional(number) data_disk = optional(number) cloudinit = optional(string) + + network_devices = list(object({ + bridge = string + vlan_id = optional(number) + + ip = optional(string) + cidr = optional(number) + gateway = optional(string) + })) })) } -variable "cluster_ip_start" { - type = number -} variable "worker_vmid_start" { type = number @@ -51,20 +53,6 @@ variable "disk_interface" { type = string } -variable "network_base" { - type = string -} - -variable "network_cidr" { - type = number -} - -variable "cluster_gateway" { - type = string -} - - - variable "data_datastore" { type = string description = "Datastore for data disk"