From 8063e5fdcbf375cd6f7026a9ad0bffd2be52d7b7 Mon Sep 17 00:00:00 2001 From: admin Date: Sat, 7 Mar 2026 19:55:56 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A1=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=20=D0=BC?= =?UTF-8?q?=D0=BE=D0=B4=D1=83=D0=BB=D1=8C=20lxc=5Fdynamic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .terraform/modules/modules.json | 2 +- README.md | 181 +++++++++++++++++++++++++++- main.tf | 23 ++++ modules/lxc_dynamic/main.tf | 39 +++++++ modules/lxc_dynamic/outputs.tf | 6 + modules/lxc_dynamic/variables.tf | 23 ++++ modules/lxc_dynamic/versions.tf | 8 ++ terraform.tfstate | 195 ++++++++++++++++++++++++++++++- terraform.tfstate.backup | 4 +- terraform.tfvars | 2 +- 10 files changed, 476 insertions(+), 7 deletions(-) create mode 100644 modules/lxc_dynamic/main.tf create mode 100644 modules/lxc_dynamic/outputs.tf create mode 100644 modules/lxc_dynamic/variables.tf create mode 100644 modules/lxc_dynamic/versions.tf diff --git a/.terraform/modules/modules.json b/.terraform/modules/modules.json index cdb8310..cb452a9 100644 --- a/.terraform/modules/modules.json +++ b/.terraform/modules/modules.json @@ -1 +1 @@ -{"Modules":[{"Key":"","Source":"","Dir":"."},{"Key":"app","Source":"./modules/lxc_container","Dir":"modules/lxc_container"}]} \ No newline at end of file +{"Modules":[{"Key":"","Source":"","Dir":"."},{"Key":"app","Source":"./modules/lxc_container","Dir":"modules/lxc_container"},{"Key":"apps","Source":"./modules/lxc_dynamic","Dir":"modules/lxc_dynamic"}]} \ No newline at end of file diff --git a/README.md b/README.md index 8c06e5c..0ac68ef 100644 --- a/README.md +++ b/README.md @@ -15,4 +15,183 @@ В modules/lxc_container/outputs.tf выходные данные, которые нужно передать из модуля в основной файл main. -В modules/lxc_container/variables.tf происходит инициализация переменных, которые передаются из основного main в модуль. \ No newline at end of file +В modules/lxc_container/variables.tf происходит инициализация переменных, которые передаются из основного main в модуль. + + +Создан модуль modules/lxc_dynamic для создания нескольких ВМ используя for_each. + +``` +andy@mercower:~/terraform-proxmox$ terraform plan +module.app.proxmox_lxc.app_container: Refreshing state... [id=px/lxc/100] + +Note: Objects have changed outside of Terraform + +Terraform detected the following changes made outside of Terraform since the last "terraform apply" which may have affected this plan: + + # module.app.proxmox_lxc.app_container has been deleted + - resource "proxmox_lxc" "app_container" { + - hostname = "app-01" -> null + id = "px/lxc/100" + tags = null + # (35 unchanged attributes hidden) + + # (2 unchanged blocks hidden) + } + + +Unless you have made equivalent changes to your configuration, or ignored the relevant attributes using ignore_changes, the following plan may include actions to undo or respond to these changes. + +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + +Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + + create + +Terraform will perform the following actions: + + # module.app.proxmox_lxc.app_container will be created + + resource "proxmox_lxc" "app_container" { + + arch = "amd64" + + cmode = "tty" + + console = true + + cores = 2 + + cpulimit = 0 + + cpuunits = 1024 + + current_node = (known after apply) + + hostname = "app-01" + + id = (known after apply) + + memory = 2048 + + onboot = false + + ostemplate = "local:vztmpl/ubuntu-22.04-custome.tar.zst" + + ostype = (known after apply) + + password = (sensitive value) + + protection = false + + ssh_public_keys = <<-EOT + ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPiX5bOEXfX3AvwstdAyYYHgSyGDF12NzOBCwfNPQVgo terraform@lxc + EOT + + start = true + + swap = 512 + + target_node = "px" + + tty = 2 + + unprivileged = false + + unused = (known after apply) + + vmid = (known after apply) + + + network { + + bridge = "vmbr1" + + firewall = true + + gw = "10.10.10.1" + + hwaddr = (known after apply) + + id = (known after apply) + + ip = "10.10.10.3/24" + + name = "eth0" + + tag = (known after apply) + + trunks = (known after apply) + + type = (known after apply) + } + + + rootfs { + + size = "8G" + + storage = "local" + + volume = (known after apply) + } + } + + # module.apps.proxmox_lxc.app_container["nginx01"] will be created + + resource "proxmox_lxc" "app_container" { + + arch = "amd64" + + cmode = "tty" + + console = true + + cores = 2 + + cpulimit = 0 + + cpuunits = 1024 + + current_node = (known after apply) + + hostname = "nginx01" + + id = (known after apply) + + memory = 2048 + + onboot = false + + ostemplate = "local:vztmpl/ubuntu-22.04-custome.tar.zst" + + ostype = (known after apply) + + password = (sensitive value) + + protection = false + + ssh_public_keys = <<-EOT + ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPiX5bOEXfX3AvwstdAyYYHgSyGDF12NzOBCwfNPQVgo terraform@lxc + EOT + + start = true + + swap = 512 + + target_node = "px" + + tty = 2 + + unprivileged = false + + unused = (known after apply) + + vmid = (known after apply) + + + network { + + bridge = "vmbr1" + + firewall = true + + gw = "10.10.10.1" + + hwaddr = (known after apply) + + id = (known after apply) + + ip = "10.10.10.5/24" + + name = "eth0" + + tag = (known after apply) + + trunks = (known after apply) + + type = (known after apply) + } + + + rootfs { + + size = "8G" + + storage = "local" + + volume = (known after apply) + } + } + + # module.apps.proxmox_lxc.app_container["nginx02"] will be created + + resource "proxmox_lxc" "app_container" { + + arch = "amd64" + + cmode = "tty" + + console = true + + cores = 2 + + cpulimit = 0 + + cpuunits = 1024 + + current_node = (known after apply) + + hostname = "nginx02" + + id = (known after apply) + + memory = 2048 + + onboot = false + + ostemplate = "local:vztmpl/ubuntu-22.04-custome.tar.zst" + + ostype = (known after apply) + + password = (sensitive value) + + protection = false + + ssh_public_keys = <<-EOT + ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPiX5bOEXfX3AvwstdAyYYHgSyGDF12NzOBCwfNPQVgo terraform@lxc + EOT + + start = true + + swap = 512 + + target_node = "px" + + tty = 2 + + unprivileged = false + + unused = (known after apply) + + vmid = (known after apply) + + + network { + + bridge = "vmbr1" + + firewall = true + + gw = "10.10.10.1" + + hwaddr = (known after apply) + + id = (known after apply) + + ip = "10.10.10.6/24" + + name = "eth0" + + tag = (known after apply) + + trunks = (known after apply) + + type = (known after apply) + } + + + rootfs { + + size = "8G" + + storage = "local" + + volume = (known after apply) + } + } + +Plan: 3 to add, 0 to change, 0 to destroy. + +``` diff --git a/main.tf b/main.tf index 17d9352..4aa08ae 100644 --- a/main.tf +++ b/main.tf @@ -19,3 +19,26 @@ module "app" { } } +module "apps" { + source = "./modules/lxc_dynamic" + + target_node = "px" + ostemplate = "local:vztmpl/ubuntu-22.04-custome.tar.zst" + ssh_public_key = file("./ssh/id_terraform.pub") + private_key = file("./ssh/id_terraform") + gateway = "10.10.10.1" + bridge = "vmbr1" + storage = "local" + size = "8G" + + lxc_resources = { + cores = 2 + memory = 2048 + swap = 512 + } + + containers = { + nginx01 = { ip = "10.10.10.5/24" } + nginx02 = { ip = "10.10.10.6/24" } + } +} diff --git a/modules/lxc_dynamic/main.tf b/modules/lxc_dynamic/main.tf new file mode 100644 index 0000000..0fa4262 --- /dev/null +++ b/modules/lxc_dynamic/main.tf @@ -0,0 +1,39 @@ +resource "proxmox_lxc" "app_container" { + for_each = var.containers + + target_node = var.target_node + hostname = each.key + ostemplate = var.ostemplate + password = "password" + + ssh_public_keys = var.ssh_public_key + + cores = var.lxc_resources.cores + memory = var.lxc_resources.memory + swap = var.lxc_resources.swap + + rootfs { + storage = var.storage + size = var.size + } + + network { + name = "eth0" + bridge = var.bridge + ip = each.value.ip + gw = var.gateway + firewall = true + } + + start = true + + connection { + type = "ssh" + host = trimsuffix(each.value.ip, "/24") + user = "root" + private_key = var.private_key + timeout = "2m" + } + + +} diff --git a/modules/lxc_dynamic/outputs.tf b/modules/lxc_dynamic/outputs.tf new file mode 100644 index 0000000..3a9a785 --- /dev/null +++ b/modules/lxc_dynamic/outputs.tf @@ -0,0 +1,6 @@ +output "vm_hostnames" { + description = "Hostnames of created containers" + value = { + for name, container in proxmox_lxc.app_container : name => container.hostname + } +} diff --git a/modules/lxc_dynamic/variables.tf b/modules/lxc_dynamic/variables.tf new file mode 100644 index 0000000..e45370a --- /dev/null +++ b/modules/lxc_dynamic/variables.tf @@ -0,0 +1,23 @@ +variable "target_node" {} +variable "ostemplate" {} +variable "ssh_public_key" {} +variable "private_key" {} +variable "gateway" {} +variable "bridge" {} +variable "storage" {} +variable "size" {} + +variable "lxc_resources" { + type = object({ + cores = number + memory = number + swap = number + }) +} + +variable "containers" { + description = "Map of containers to create" + type = map(object({ + ip = string + })) +} diff --git a/modules/lxc_dynamic/versions.tf b/modules/lxc_dynamic/versions.tf new file mode 100644 index 0000000..c540864 --- /dev/null +++ b/modules/lxc_dynamic/versions.tf @@ -0,0 +1,8 @@ +terraform { + required_providers { + proxmox = { + source = "telmate/proxmox" + version = "3.0.2-rc07" + } + } +} diff --git a/terraform.tfstate b/terraform.tfstate index 51150b1..d934ed0 100644 --- a/terraform.tfstate +++ b/terraform.tfstate @@ -1,7 +1,7 @@ { "version": 4, "terraform_version": "1.14.6", - "serial": 3, + "serial": 7, "lineage": "f4c291e8-3767-da71-b85c-0fdc56b7a316", "outputs": {}, "resources": [ @@ -45,7 +45,7 @@ "firewall": true, "gw": "10.10.10.1", "gw6": "", - "hwaddr": "BC:24:11:7F:7E:1B", + "hwaddr": "BC:24:11:ED:E9:01", "id": 0, "ip": "10.10.10.3/24", "ip6": "", @@ -103,6 +103,197 @@ "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWZhdWx0IjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH19" } ] + }, + { + "module": "module.apps", + "mode": "managed", + "type": "proxmox_lxc", + "name": "app_container", + "provider": "provider[\"registry.terraform.io/telmate/proxmox\"]", + "instances": [ + { + "index_key": "nginx01", + "schema_version": 0, + "attributes": { + "arch": "amd64", + "bwlimit": 0, + "clone": null, + "clone_storage": null, + "cmode": "tty", + "console": true, + "cores": 2, + "cpulimit": 0, + "cpuunits": 1024, + "current_node": "px", + "description": "", + "features": [], + "force": false, + "full": null, + "hagroup": "", + "hastate": "", + "hookscript": "", + "hostname": "nginx01", + "id": "px/lxc/102", + "ignore_unpack_errors": false, + "lock": "", + "memory": 2048, + "mountpoint": [], + "nameserver": "", + "network": [ + { + "bridge": "vmbr1", + "firewall": true, + "gw": "10.10.10.1", + "gw6": "", + "hwaddr": "BC:24:11:C4:95:36", + "id": 0, + "ip": "10.10.10.5/24", + "ip6": "", + "mtu": 0, + "name": "eth0", + "rate": 0, + "tag": 0, + "trunks": "", + "type": "veth" + } + ], + "onboot": false, + "ostemplate": "local:vztmpl/ubuntu-22.04-custome.tar.zst", + "ostype": "ubuntu", + "password": "password", + "pool": null, + "protection": false, + "restore": false, + "rootfs": [ + { + "acl": false, + "quota": false, + "replicate": false, + "ro": false, + "shared": false, + "size": "8G", + "storage": "local", + "volume": "local:102/vm-102-disk-0.raw" + } + ], + "searchdomain": "", + "ssh_public_keys": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPiX5bOEXfX3AvwstdAyYYHgSyGDF12NzOBCwfNPQVgo terraform@lxc\n", + "start": true, + "startup": "", + "swap": 512, + "tags": "", + "target_node": "px", + "template": false, + "timeouts": null, + "tty": 2, + "unique": false, + "unprivileged": false, + "unused": [], + "vmid": 102 + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "password" + } + ] + ], + "identity_schema_version": 0, + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWZhdWx0IjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH19" + }, + { + "index_key": "nginx02", + "schema_version": 0, + "attributes": { + "arch": "amd64", + "bwlimit": 0, + "clone": null, + "clone_storage": null, + "cmode": "tty", + "console": true, + "cores": 2, + "cpulimit": 0, + "cpuunits": 1024, + "current_node": "px", + "description": "", + "features": [], + "force": false, + "full": null, + "hagroup": "", + "hastate": "", + "hookscript": "", + "hostname": "nginx02", + "id": "px/lxc/101", + "ignore_unpack_errors": false, + "lock": "", + "memory": 2048, + "mountpoint": [], + "nameserver": "", + "network": [ + { + "bridge": "vmbr1", + "firewall": true, + "gw": "10.10.10.1", + "gw6": "", + "hwaddr": "BC:24:11:49:21:DB", + "id": 0, + "ip": "10.10.10.6/24", + "ip6": "", + "mtu": 0, + "name": "eth0", + "rate": 0, + "tag": 0, + "trunks": "", + "type": "veth" + } + ], + "onboot": false, + "ostemplate": "local:vztmpl/ubuntu-22.04-custome.tar.zst", + "ostype": "ubuntu", + "password": "password", + "pool": null, + "protection": false, + "restore": false, + "rootfs": [ + { + "acl": false, + "quota": false, + "replicate": false, + "ro": false, + "shared": false, + "size": "8G", + "storage": "local", + "volume": "local:101/vm-101-disk-0.raw" + } + ], + "searchdomain": "", + "ssh_public_keys": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPiX5bOEXfX3AvwstdAyYYHgSyGDF12NzOBCwfNPQVgo terraform@lxc\n", + "start": true, + "startup": "", + "swap": 512, + "tags": "", + "target_node": "px", + "template": false, + "timeouts": null, + "tty": 2, + "unique": false, + "unprivileged": false, + "unused": [], + "vmid": 101 + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "password" + } + ] + ], + "identity_schema_version": 0, + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWZhdWx0IjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH19" + } + ] } ], "check_results": null diff --git a/terraform.tfstate.backup b/terraform.tfstate.backup index 999035e..51150b1 100644 --- a/terraform.tfstate.backup +++ b/terraform.tfstate.backup @@ -1,7 +1,7 @@ { "version": 4, "terraform_version": "1.14.6", - "serial": 1, + "serial": 3, "lineage": "f4c291e8-3767-da71-b85c-0fdc56b7a316", "outputs": {}, "resources": [ @@ -45,7 +45,7 @@ "firewall": true, "gw": "10.10.10.1", "gw6": "", - "hwaddr": "BC:24:11:9A:C9:FA", + "hwaddr": "BC:24:11:7F:7E:1B", "id": 0, "ip": "10.10.10.3/24", "ip6": "", diff --git a/terraform.tfvars b/terraform.tfvars index 5a72f77..c6f416c 100644 --- a/terraform.tfvars +++ b/terraform.tfvars @@ -1 +1 @@ -pm_token_secret = "API_TOKEN" +pm_token_secret = "e71efc34-8635-41fd-b8e9-019858b451a7"