doc: добавление документации по созданию вм через tf
This commit is contained in:
@@ -1,3 +1,11 @@
|
||||
# tfTemplate
|
||||
# vm.dev.nubes.ru
|
||||
|
||||
Шаблон для разворачивания ВМ через tf
|
||||
Развёртывание ВМ в VMware Cloud Director (OpenTofu).
|
||||
|
||||
---
|
||||
|
||||
**Нужно поднять простую ВМ?** — см. [simpleVm/README.md](simpleVm/README.md).
|
||||
|
||||
---
|
||||
|
||||
*Здесь со временем можно добавить ссылки на другие сценарии (например, несколько vDC, сложные конфигурации).*
|
||||
|
||||
@@ -14,7 +14,7 @@ crash.*.log
|
||||
# password, private keys, and other secrets. These should not be part of version
|
||||
# control as they are data points which are potentially sensitive and subject
|
||||
# to change depending on the environment.
|
||||
*.tfvars
|
||||
# *.tfvars
|
||||
*.tfvars.json
|
||||
|
||||
# Ignore override files as they are usually used to override resources locally and so
|
||||
@@ -33,4 +33,5 @@ override.tf.json
|
||||
# Ignore CLI configuration files
|
||||
.terraformrc
|
||||
terraform.rc
|
||||
|
||||
.terraform.lock.hcl
|
||||
terraform.tfstate
|
||||
@@ -0,0 +1,120 @@
|
||||
# Развёртывание ВМ в VMware Cloud Director через tf
|
||||
|
||||
Используется **OpenTofu** (`tofu`). Конфигурация создаёт виртуальные машины в vCD: можно задать несколько ВМ, размеры CPU/RAM/дисков и сеть.
|
||||
|
||||
---
|
||||
|
||||
## Быстрый старт
|
||||
|
||||
1. **Установите OpenTofu** ([opentofu.org](https://opentofu.org)).
|
||||
|
||||
2. **Задайте переменные окружения** (доступ к vCD):
|
||||
```bash
|
||||
export TF_VAR_vmware_username="ваш_пользователь_vCD"
|
||||
export TF_VAR_vmware_password="ваш_пароль_vCD"
|
||||
```
|
||||
Пароль администратора ВМ можно не задавать — тогда он сгенерируется автоматически (см. `tools.tf`). Чтобы задать свой: `export TF_VAR_admin_password="ваш_пароль"`.
|
||||
|
||||
3. **Отредактируйте `terraform.tfvars`** — укажите нужный vDC, имя vApp, параметры ВМ (см. раздел «Конфигурация» ниже).
|
||||
|
||||
4. **Разверните инфраструктуру:**
|
||||
```bash
|
||||
tofu init
|
||||
tofu plan
|
||||
tofu apply
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Конфигурация
|
||||
|
||||
### Переменные окружения
|
||||
|
||||
Обязательные для доступа к vCD:
|
||||
|
||||
- `TF_VAR_vmware_username` — пользователь VMware Cloud Director
|
||||
- `TF_VAR_vmware_password` — пароль VMware Cloud Director
|
||||
|
||||
Опционально: `TF_VAR_admin_password` — пароль администратора на ВМ (если не задан, генерируется автоматически).
|
||||
|
||||
```
|
||||
vcds = {
|
||||
"vdcconfiguration1" = {
|
||||
url = "https://ngcloud.ru/api"
|
||||
org = "dev"
|
||||
vdc = "dev"
|
||||
network_routed = "dev-mgmt-network"
|
||||
servers = {
|
||||
"vappname01" = {
|
||||
"vmname01" = {
|
||||
cpu = "4"
|
||||
memory = "4096"
|
||||
osDisk = "16384"
|
||||
dataDisk = {
|
||||
"1" = "30720"
|
||||
"2" = "15360"
|
||||
}
|
||||
network = {
|
||||
mode = "auto"
|
||||
ip = ""
|
||||
}
|
||||
catalog_name = "dev"
|
||||
template_name = "RockyLinux_9-16G-customize"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Переменная задаётся в `terraform.tfvars`; схема — в [var.tf](var.tf), использование — [provider.tf](provider.tf), [vapp.tf](vapp.tf), [vm.tf](vm.tf), [local.tf](local.tf).
|
||||
|
||||
*** Ключ vcds — произвольное имя контура (можно несколько vDC в одной конфигурации) ***
|
||||
```
|
||||
vcds = {
|
||||
"test" = {
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*** Настройка vDC ***
|
||||
```
|
||||
url = URL API Cloud Director (https://<хост>/api)
|
||||
org = имя организации
|
||||
vdc = имя vDC
|
||||
network_routed = имя routed-сети, куда подключаются ВМ
|
||||
```
|
||||
|
||||
*** Настройка vApp (ключи внутри servers — имена vApp) ***
|
||||
```
|
||||
servers = {
|
||||
"testservers" = { ... } # первый vApp
|
||||
"testvapp2" = { ... } # второй vApp
|
||||
}
|
||||
```
|
||||
|
||||
*** Настройка сервера (параметры ВМ) ***
|
||||
```
|
||||
"testservers" = {
|
||||
"test01" = {
|
||||
cpu = кол-во ядер CPU
|
||||
memory = объём RAM (МБ)
|
||||
osDisk = размер системного диска (МБ)
|
||||
dataDisk = { # ключ — unit, значение — размер в МБ
|
||||
"1" = "30720"
|
||||
"2" = "15360"
|
||||
}
|
||||
network = { # mode "auto" (IP из пула) или "manual" (указать ip)
|
||||
mode = "auto"
|
||||
ip = ""
|
||||
}
|
||||
network = mode "auto" (IP из пула) или "manual" (указать ip)
|
||||
mode = "auto"
|
||||
ip = ""
|
||||
catalog_name = каталог с шаблоном
|
||||
template_name = имя шаблона образа
|
||||
# опционально (cloud-init):
|
||||
init_username = "deploy"
|
||||
ssh_authorized_keys = ["ssh-ed25519 AAAA..."]
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,39 @@
|
||||
locals {
|
||||
#######################
|
||||
admin_password = var.admin_password != "" ? var.admin_password : random_password.admin_pass.result
|
||||
#######################
|
||||
# Получаем объект с ключами в виде имен серверов и содержимым всего,
|
||||
# что мы хотим видеть при передаче из vars
|
||||
servers = merge([
|
||||
for vcd_key, vcd_config in var.vcds :
|
||||
merge([
|
||||
for server_group, servers in vcd_config.servers :
|
||||
{
|
||||
for server_name, server_config in servers :
|
||||
"${server_name}.${server_group}" => {
|
||||
vcd_key = vcd_key
|
||||
server_group = server_group
|
||||
server_name = server_name
|
||||
config = server_config
|
||||
network_routed = vcd_config.network_routed
|
||||
role = server_group
|
||||
}
|
||||
}
|
||||
]...)
|
||||
]...)
|
||||
|
||||
# Получаем объект с ключами в виде сервера-uidдиска,
|
||||
# и содержимым в виде его сайзинга
|
||||
disks = merge([
|
||||
for serverName, serverConfig in local.servers:
|
||||
{
|
||||
for diskUid, diskSize in serverConfig.config.dataDisk:
|
||||
"${serverName}-${diskUid}" => {
|
||||
vcd_key = serverConfig.vcd_key
|
||||
vm_name = serverName
|
||||
unit_num = diskUid
|
||||
disk_size = diskSize
|
||||
}
|
||||
}
|
||||
]...)
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
vcd = {
|
||||
source = "vmware/vcd"
|
||||
version = "3.14.1"
|
||||
}
|
||||
random = {
|
||||
source = "hashicorp/random"
|
||||
version = "3.5.1"
|
||||
}
|
||||
local = {
|
||||
source = "hashicorp/local"
|
||||
version = "2.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Почему такая конфигурация не будет работать
|
||||
# https://github.com/hashicorp/terraform/issues/24476
|
||||
#
|
||||
# Но решили тут
|
||||
# https://github.com/opentofu/opentofu/issues/2123
|
||||
|
||||
provider "vcd" {
|
||||
alias = "al"
|
||||
for_each = var.vcds
|
||||
|
||||
user = var.vmware_username
|
||||
password = var.vmware_password
|
||||
|
||||
org = each.value.org
|
||||
vdc = each.value.vdc
|
||||
url = each.value.url
|
||||
|
||||
max_retry_timeout = "10"
|
||||
allow_unverified_ssl = "true"
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#cloud-config
|
||||
hostname: ${hostname}
|
||||
package_update: true
|
||||
package_upgrade: false
|
||||
packages:
|
||||
- curl
|
||||
- git
|
||||
- jq
|
||||
|
||||
users:
|
||||
- name: ${username}
|
||||
sudo: "ALL=(ALL) NOPASSWD:ALL"
|
||||
groups: "sudo"
|
||||
shell: /bin/bash
|
||||
ssh_authorized_keys:
|
||||
%{ if length(ssh_authorized_keys) > 0 ~}
|
||||
%{ for key in ssh_authorized_keys ~}
|
||||
- ${key}
|
||||
%{ endfor ~}
|
||||
%{ else ~}
|
||||
[]
|
||||
%{ endif ~}
|
||||
@@ -0,0 +1,39 @@
|
||||
#######################################################
|
||||
# Импортируемые переменные из TF_VAR
|
||||
# vmware_username = ""
|
||||
# vmware_password = ""
|
||||
|
||||
|
||||
#######################################################
|
||||
|
||||
vcds = {
|
||||
"test" = {
|
||||
url = "https://ngcloud.ru/api"
|
||||
org = "dev"
|
||||
vdc = "dev"
|
||||
network_routed = "dev-mgmt-network"
|
||||
servers = {
|
||||
"testservers" = {
|
||||
"test01" = {
|
||||
cpu = "1"
|
||||
memory = "1024"
|
||||
osDisk = "35000"
|
||||
dataDisk = {
|
||||
"1" = "10000"
|
||||
"2" = "5480"
|
||||
}
|
||||
network = {
|
||||
mode = "auto"
|
||||
ip = ""
|
||||
}
|
||||
catalog_name = "dev"
|
||||
template_name = "Ubuntu_24-20G"
|
||||
init_username = "deploy"
|
||||
ssh_authorized_keys = [
|
||||
"ssh-ed25519 *********"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# Генерируем пароль для админского пользователя
|
||||
resource "random_password" "admin_pass" {
|
||||
length = 20
|
||||
special = false
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
resource "vcd_vapp" "vapp" {
|
||||
for_each = var.vcds
|
||||
|
||||
provider = vcd.al[each.key]
|
||||
|
||||
name = each.key
|
||||
power_on = false
|
||||
}
|
||||
|
||||
|
||||
resource "vcd_vapp_org_network" "routed_network" {
|
||||
for_each = vcd_vapp.vapp
|
||||
|
||||
provider = vcd.al[each.key]
|
||||
|
||||
vapp_name = each.value.name
|
||||
org_network_name = var.vcds[each.key].network_routed
|
||||
reboot_vapp_on_removal = true
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
####################################################
|
||||
variable "vmware_username" {
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
variable "vmware_password" {
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
|
||||
####################################################
|
||||
# Пароль от ВМ (если пустой — подставляется сгенерированный из tools.tf)
|
||||
variable "admin_password" {
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
|
||||
####################################################
|
||||
variable "vcds" {
|
||||
type = map(object({
|
||||
url = string
|
||||
org = string
|
||||
vdc = string
|
||||
network_routed = string
|
||||
servers = map(map(object({
|
||||
cpu = string
|
||||
memory = string
|
||||
osDisk = string
|
||||
catalog_name = string
|
||||
template_name = string
|
||||
dataDisk = map(string)
|
||||
network = object({
|
||||
mode = string
|
||||
ip = string
|
||||
})
|
||||
# cloud-init: пользователь и SSH-ключи (опционально)
|
||||
init_username = optional(string, "deploy")
|
||||
ssh_authorized_keys = optional(list(string), [])
|
||||
})))
|
||||
}))
|
||||
}
|
||||
####################################################
|
||||
@@ -0,0 +1,84 @@
|
||||
resource "vcd_vapp_vm" "vm" {
|
||||
for_each = local.servers
|
||||
|
||||
provider = vcd.al[each.value.vcd_key]
|
||||
|
||||
vapp_name = vcd_vapp.vapp[each.value.vcd_key].name
|
||||
name = each.key
|
||||
computer_name = each.key
|
||||
catalog_name = each.value.config["catalog_name"]
|
||||
template_name = each.value.config["template_name"]
|
||||
memory = each.value.config["memory"]
|
||||
cpus = each.value.config["cpu"]
|
||||
|
||||
network {
|
||||
type = "org"
|
||||
name = each.value.network_routed
|
||||
ip_allocation_mode = lookup(each.value.config["network"], "mode", "auto") == "manual" ? "MANUAL" : "POOL"
|
||||
is_primary = true
|
||||
|
||||
# Устанавливаем IP, только если режим "manual"
|
||||
ip = lookup(each.value.config["network"], "mode", "auto") == "manual" ? lookup(each.value.config["network"], "ip", null) : null
|
||||
}
|
||||
|
||||
override_template_disk {
|
||||
bus_type = "paravirtual"
|
||||
size_in_mb = each.value.config["osDisk"]
|
||||
bus_number = 0
|
||||
unit_number = 0
|
||||
}
|
||||
|
||||
customization {
|
||||
enabled = true
|
||||
#force = var.forceRecustomization || !contains(var.servers, var.servers[count.index])
|
||||
#force = var.forceRecustomization
|
||||
force = false
|
||||
allow_local_admin_password = true
|
||||
auto_generate_password = false
|
||||
admin_password = local.admin_password
|
||||
}
|
||||
|
||||
set_extra_config {
|
||||
key = "disk.EnableUUID"
|
||||
value = "TRUE"
|
||||
}
|
||||
|
||||
guest_properties = {
|
||||
"user-data" = base64encode(templatefile("${path.module}/templates/cloudinit.yaml", {
|
||||
hostname = each.key
|
||||
username = each.value.config["init_username"]
|
||||
ssh_authorized_keys = each.value.config["ssh_authorized_keys"]
|
||||
}))
|
||||
}
|
||||
|
||||
# Игноирование изменений дисков (PVC - Named Disks)
|
||||
lifecycle {
|
||||
ignore_changes = [
|
||||
disk, # Игнорирует изменения всех дисков
|
||||
]
|
||||
}
|
||||
|
||||
depends_on = [
|
||||
vcd_vapp_org_network.routed_network
|
||||
]
|
||||
}
|
||||
|
||||
resource "vcd_vm_internal_disk" "vmdisk" {
|
||||
for_each = local.disks
|
||||
|
||||
provider = vcd.al[each.value.vcd_key]
|
||||
|
||||
vapp_name = vcd_vapp.vapp[each.value.vcd_key].name
|
||||
vm_name = each.value.vm_name
|
||||
|
||||
bus_type = "paravirtual"
|
||||
bus_number = 0
|
||||
unit_number = each.value.unit_num
|
||||
size_in_mb = each.value.disk_size
|
||||
|
||||
allow_vm_reboot = true
|
||||
|
||||
depends_on = [
|
||||
vcd_vapp_vm.vm
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user