add networks many

This commit is contained in:
Iurii Anfinogenov
2026-04-19 17:39:08 +00:00
parent a6ebbb3a4d
commit bb4dc311c1
6 changed files with 163 additions and 90 deletions

View File

@@ -1,19 +1,100 @@
# nodes — описание виртуальных машин # 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: # vlan_id:
# - опциональный параметр # - опционально
# - если НЕ указан → VM будет в обычной сети (untagged, vmbr0) # - если НЕ указан → интерфейс untagged
# - если указан → VM попадет в соответствующий VLAN (например 20 → 192.168.20.0/24) # - если указан → интерфейс будет в 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: # cloudinit:
# - опциональный параметр # - опциональный параметр
# - указывает имя cloud-init файла для конкретной VM # - имя cloud-init файла
# - файл должен находиться в root: cloud-config/<имя>.yml # - ищется в:
# - если НЕ указан → используется "default.yml" # cloud-config/<имя>.yml (root)
# - если файл НЕ найден в root → используется fallback из модуля (modules/node/cloud-config/default.yml) # - если не найден → fallback:
# modules/node/cloud-config/default.yml
# #
# пример: # пример:
# - cloudinit = "worker.yml" → будет использован cloud-config/worker.yml # - cloudinit = "worker.yml" → cloud-config/worker.yml
# - cloudinit не задан → будет использован default.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 { locals {
nodes = { nodes = {
@@ -24,29 +105,55 @@ locals {
memory = 4092 memory = 4092
disk = var.worker_disk disk = var.worker_disk
datastore = var.worker_datastore datastore = var.worker_datastore
ip_offset = 10
vlan_id = 20
}
network_devices = [
{
bridge = var.node_bridge
vlan_id = 20
ip = "192.168.20.11"
cidr = 24
gateway = "192.168.20.1"
}
]
},
k8s-worker-1 = { k8s-worker-1 = {
cloudinit = "worker.yml" cloudinit = "worker.yml"
index = 2 index = 2
cpu = 4 cpu = var.worker_cpu
memory = 8192 memory = 8192
disk = var.worker_disk disk = var.worker_disk
datastore = var.worker_datastore datastore = var.worker_datastore
ip_offset = 20
network_devices = [
{
bridge = var.node_bridge
vlan_id = 20 vlan_id = 20
ip = "192.168.20.22"
cidr = 24
gateway = "192.168.20.1"
} }
]
},
k8s-worker-2 = { k8s-worker-2 = {
cloudinit = "worker.yml" cloudinit = "worker.yml"
index = 3 index = 3
cpu = 4 cpu = var.worker_cpu
memory = 8192 memory = 8192
disk = var.worker_disk disk = var.worker_disk
datastore = var.worker_datastore datastore = var.worker_datastore
ip_offset = 20
network_devices = [
{
bridge = var.node_bridge
vlan_id = 20 vlan_id = 20
ip = "192.168.20.23"
cidr = 24
gateway = "192.168.20.1"
},
{
bridge = "vmbr0"
}
]
} }
} }
} }

View File

@@ -8,7 +8,6 @@ module "cluster" {
nodes = local.nodes nodes = local.nodes
ssh_key = trimspace(data.local_file.ssh_key.content) ssh_key = trimspace(data.local_file.ssh_key.content)
cluster_ip_start = var.cluster_ip_start
worker_vmid_start = var.worker_vmid_start worker_vmid_start = var.worker_vmid_start
cloudinit_datastore = var.cloudinit_datastore cloudinit_datastore = var.cloudinit_datastore
@@ -19,9 +18,5 @@ module "cluster" {
image_file = var.image_file image_file = var.image_file
disk_interface = var.disk_interface 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 data_datastore = var.data_datastore
} }

View File

@@ -41,23 +41,6 @@ variable "worker_disk" {
default = 20 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" { variable "worker_ip_offset" {
default = 5 default = 5
} }
@@ -66,6 +49,7 @@ variable "node_bridge" {
default = "vmbr0" default = "vmbr0"
} }
variable "worker_datastore" { variable "worker_datastore" {
type = string type = string
default = "local-lvm" default = "local-lvm"

View File

@@ -6,13 +6,7 @@ locals {
name => node 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 = { vmid_map = {
for name, node in local.nodes : for name, node in local.nodes :

View File

@@ -54,11 +54,13 @@ resource "proxmox_virtual_environment_vm" "nodes" {
dedicated = each.value.memory dedicated = each.value.memory
} }
network_device { dynamic "network_device" {
bridge = var.node_bridge for_each = each.value.network_devices
# vlan_id = try(each.value.vlan_id, null)
vlan_id = each.value.vlan_id
content {
bridge = network_device.value.bridge
vlan_id = try(network_device.value.vlan_id, null)
}
} }
disk { disk {
@@ -77,15 +79,18 @@ resource "proxmox_virtual_environment_vm" "nodes" {
size = disk.value size = disk.value
} }
} }
initialization { initialization {
datastore_id = each.value.datastore datastore_id = each.value.datastore
user_data_file_id = proxmox_virtual_environment_file.cloudinit[each.key].id user_data_file_id = proxmox_virtual_environment_file.cloudinit[each.key].id
ip_config { dynamic "ip_config" {
for_each = each.value.network_devices
content {
ipv4 { ipv4 {
address = "${local.ip_map[each.key]}/${var.network_cidr}" address = try(ip_config.value.ip, "dhcp") == null ? "dhcp" : "${ip_config.value.ip}/${ip_config.value.cidr}"
gateway = var.cluster_gateway gateway = try(ip_config.value.gateway, null)
}
} }
} }
} }

View File

@@ -4,24 +4,26 @@ variable "ssh_key" {
variable "nodes" { variable "nodes" {
type = map(object({ type = map(object({
# role = string
index = number index = number
cpu = number cpu = number
memory = number memory = number
disk = number disk = number
datastore = string datastore = string
ip_offset = optional(number)
ip = optional(string)
vmid = optional(number) vmid = optional(number)
vlan_id = optional(number)
data_disk = optional(number) data_disk = optional(number)
cloudinit = optional(string) 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" { variable "worker_vmid_start" {
type = number type = number
@@ -51,20 +53,6 @@ variable "disk_interface" {
type = string type = string
} }
variable "network_base" {
type = string
}
variable "network_cidr" {
type = number
}
variable "cluster_gateway" {
type = string
}
variable "data_datastore" { variable "data_datastore" {
type = string type = string
description = "Datastore for data disk" description = "Datastore for data disk"