From b0aab6ad123f52ee4af42f2affbd92c6c918f79f Mon Sep 17 00:00:00 2001 From: mcpovel Date: Wed, 30 Oct 2024 09:25:16 +0100 Subject: [PATCH] Dbp 995 add ha ionos vms (#37) * Copy of IONOS-HA VM --------- Co-authored-by: github-actions[bot] --- modules/ionos-basic-vm/main.tf | 2 +- modules/ionos-ha-vms/README.md | 71 +++++++++++++++ modules/ionos-ha-vms/data.tf | 3 + modules/ionos-ha-vms/locals.tf | 3 + modules/ionos-ha-vms/main.tf | 141 ++++++++++++++++++++++++++++++ modules/ionos-ha-vms/outputs.tf | 19 ++++ modules/ionos-ha-vms/variables.tf | 119 +++++++++++++++++++++++++ modules/ionos-ha-vms/versions.tf | 12 +++ 8 files changed, 369 insertions(+), 1 deletion(-) create mode 100644 modules/ionos-ha-vms/README.md create mode 100644 modules/ionos-ha-vms/data.tf create mode 100644 modules/ionos-ha-vms/locals.tf create mode 100644 modules/ionos-ha-vms/main.tf create mode 100644 modules/ionos-ha-vms/outputs.tf create mode 100644 modules/ionos-ha-vms/variables.tf create mode 100644 modules/ionos-ha-vms/versions.tf diff --git a/modules/ionos-basic-vm/main.tf b/modules/ionos-basic-vm/main.tf index efce938..5dae667 100644 --- a/modules/ionos-basic-vm/main.tf +++ b/modules/ionos-basic-vm/main.tf @@ -15,7 +15,7 @@ resource "ionoscloud_lan" "basic_vm_server_lan" { resource "opentelekomcloud_dns_recordset_v2" "a_records" { zone_id = data.opentelekomcloud_dns_zone_v2.dns_zone.id name = "${var.fulldomainname}" - ttl = 3600 + ttl = 300 type = "A" records = [local.public_ip] diff --git a/modules/ionos-ha-vms/README.md b/modules/ionos-ha-vms/README.md new file mode 100644 index 0000000..064381c --- /dev/null +++ b/modules/ionos-ha-vms/README.md @@ -0,0 +1,71 @@ + + +## Providers + +| Name | Version | +|------|---------| +| [ionoscloud](#provider\_ionoscloud) | 6.4.18 | +| [opentelekomcloud](#provider\_opentelekomcloud) | n/a | +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [conventions\_coordinates](#module\_conventions\_coordinates) | ../conventions-coordinates | n/a | +| [ha\_backup\_vms](#module\_ha\_backup\_vms) | ../ionos-basic-vm/ | n/a | +| [ha\_main\_vm](#module\_ha\_main\_vm) | ../ionos-basic-vm/ | n/a | +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [coordinates](#input\_coordinates) | n/a | `map(any)` | n/a | yes | +| [cpu\_family](#input\_cpu\_family) | n/a | `string` | n/a | yes | +| [datacenter](#input\_datacenter) | n/a | `string` | n/a | yes | +| [datacenter\_location](#input\_datacenter\_location) | n/a | `string` | n/a | yes | +| [domain\_base](#input\_domain\_base) | Domains will be [-]. | `string` | n/a | yes | +| [domain\_without\_top\_level](#input\_domain\_without\_top\_level) | domain without top level | `string` | n/a | yes | +| [image](#input\_image) | image of the vm | `string` | n/a | yes | +| [name](#input\_name) | name of the ha cluster, used for names the components and the domain | `string` | n/a | yes | +| [server\_cpu](#input\_server\_cpu) | cpus of the vm servers | `number` | n/a | yes | +| [server\_memory](#input\_server\_memory) | memory of the vm servers | `number` | n/a | yes | +| [top\_level\_domain](#input\_top\_level\_domain) | Top-level domain mapping for environments | `map(any)` | n/a | yes | +| [volume\_size](#input\_volume\_size) | volume size for vm | `number` | n/a | yes | +| [create\_second\_volume](#input\_create\_second\_volume) | n/a | `bool` | `true` | no | +| [ha\_node\_count](#input\_ha\_node\_count) | Number of VMs/Nodes in the HA Cluster | `number` | `2` | no | +| [initial\_public\_key](#input\_initial\_public\_key) | The public key of the initial user created via the cloud init script. | `string` | `""` | no | +| [initial\_uid](#input\_initial\_uid) | The uid of the initial user created via the cloud init script. | `string` | `""` | no | +| [initial\_user](#input\_initial\_user) | The initial user to be created via the cloud init script. | `string` | `""` | no | +| [permanent\_vm](#input\_permanent\_vm) | Create a permanent VM that mustn't be deleted, if false then a VM that can be deleted and that ignores changes to ram and cpu is created | `bool` | `true` | no | +| [port\_ranges](#input\_port\_ranges) | port rangs to open in the IONOS firewall provided as objects in a list [{protocol = ???, name = ???, port\_start = ???, port\_end, source\_ip = ???}], source\_ip is optional. | `list` | `[]` | no | +| [ports](#input\_ports) | ports to open in the IONOS firewall provided as objects in a list [{protocol = ???, name = ???, port = ???, source\_ip = ???}], source\_ip is optional. | `list` | `[]` | no | +| [second\_volume\_disk\_type](#input\_second\_volume\_disk\_type) | n/a | `string` | `"HDD"` | no | +| [second\_volume\_size](#input\_second\_volume\_size) | size of the second volume | `string` | `100` | no | +| [user\_data\_script](#input\_user\_data\_script) | Decide which user-data.sh script to use | `string` | `"user-data-cloud-init.tpl"` | no | +## Outputs + +| Name | Description | +|------|-------------| +| [ha\_common\_address](#output\_ha\_common\_address) | n/a | +| [ha\_dns\_name](#output\_ha\_dns\_name) | n/a | +| [ha\_internal\_lan\_id](#output\_ha\_internal\_lan\_id) | n/a | +| [ha\_public\_lan\_id](#output\_ha\_public\_lan\_id) | n/a | +| [ha\_vms\_server\_id](#output\_ha\_vms\_server\_id) | n/a | +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 0.13 | +| [ionoscloud](#requirement\_ionoscloud) | 6.4.18 | +## Resources + +| Name | Type | +|------|------| +| [ionoscloud_ipblock.floating_ip](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.4.18/docs/resources/ipblock) | resource | +| [ionoscloud_ipblock.node_ips](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.4.18/docs/resources/ipblock) | resource | +| [ionoscloud_ipfailover.failover](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.4.18/docs/resources/ipfailover) | resource | +| [ionoscloud_lan.lan_internal](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.4.18/docs/resources/lan) | resource | +| [ionoscloud_lan.lan_public](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.4.18/docs/resources/lan) | resource | +| [ionoscloud_nic.private_nic_backup_vms](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.4.18/docs/resources/nic) | resource | +| [ionoscloud_nic.private_nic_main_vm](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.4.18/docs/resources/nic) | resource | +| [opentelekomcloud_dns_recordset_v2.a_records](https://registry.terraform.io/providers/opentelekomcloud/opentelekomcloud/latest/docs/resources/dns_recordset_v2) | resource | +| [opentelekomcloud_dns_zone_v2.dns_zone](https://registry.terraform.io/providers/opentelekomcloud/opentelekomcloud/latest/docs/data-sources/dns_zone_v2) | data source | + \ No newline at end of file diff --git a/modules/ionos-ha-vms/data.tf b/modules/ionos-ha-vms/data.tf new file mode 100644 index 0000000..ea8abba --- /dev/null +++ b/modules/ionos-ha-vms/data.tf @@ -0,0 +1,3 @@ +data "opentelekomcloud_dns_zone_v2" "dns_zone" { + name = module.conventions_coordinates.dns_zone_name +} \ No newline at end of file diff --git a/modules/ionos-ha-vms/locals.tf b/modules/ionos-ha-vms/locals.tf new file mode 100644 index 0000000..5f88ba6 --- /dev/null +++ b/modules/ionos-ha-vms/locals.tf @@ -0,0 +1,3 @@ +locals { + availability_zones = ["ZONE_1", "ZONE_2"] +} \ No newline at end of file diff --git a/modules/ionos-ha-vms/main.tf b/modules/ionos-ha-vms/main.tf new file mode 100644 index 0000000..24fc343 --- /dev/null +++ b/modules/ionos-ha-vms/main.tf @@ -0,0 +1,141 @@ +module "conventions_coordinates" { + source = "../conventions-coordinates" + coordinates = var.coordinates + domain_without_top_level = var.domain_without_top_level + top_level_domain = var.top_level_domain +} + +# This VM has to be created seperatly because: +# It has to exist when the failover is created (defined as master) +# The other VM(s) can only be created after the Failover IP is configured, +# otherwise you get an error because the IP is already in use by the first VM +module "ha_main_vm" { + source = "../ionos-basic-vm/" + coordinates = var.coordinates + fulldomainname = "${var.name}-0.${var.domain_base}" + datacenter = var.datacenter + datacenter_location = var.datacenter_location + create_lan = false + lan_id = ionoscloud_lan.lan_public.id + cpu_family = var.cpu_family + availability_zone = local.availability_zones[0] + image = var.image + server_name = "${var.name}-0" + ports = var.ports + port_ranges = var.port_ranges + create_ip_pool = false + public_ip = ionoscloud_ipblock.node_ips.ips[0] + additional_ips = [ionoscloud_ipblock.floating_ip.ips[0]] + basic_vm_server_memory = var.server_memory + basic_vm_server_cpu = var.server_cpu + basic_vm_volume_size = var.volume_size + domain_without_top_level = var.domain_without_top_level + top_level_domain = var.top_level_domain + basic_vm_create_second_volume = var.create_second_volume + basic_vm_second_volume_disk_type = var.second_volume_disk_type + basic_vm_second_volume_size = var.second_volume_size + permanent_vm = var.permanent_vm + user_data_script = var.user_data_script + + depends_on = [ ionoscloud_lan.lan_public ] + + initial_user = var.initial_user + initial_uid = var.initial_uid + initial_public_key = var.initial_public_key +} + +resource "ionoscloud_nic" "private_nic_main_vm" { + count = var.ha_node_count - 1 + datacenter_id = var.datacenter + server_id = module.ha_main_vm.basic_vm_server_id + lan = ionoscloud_lan.lan_internal.id + dhcp = true + firewall_active = false +} + +module "ha_backup_vms" { + count = var.ha_node_count - 1 + source = "../ionos-basic-vm/" + coordinates = var.coordinates + fulldomainname = "${var.name}-${count.index+1}.${var.domain_base}" + datacenter = var.datacenter + datacenter_location = var.datacenter_location + create_lan = false + lan_id = ionoscloud_lan.lan_public.id + cpu_family = var.cpu_family + availability_zone = local.availability_zones[(count.index+1)%2] + image = var.image + server_name = "${var.name}-${count.index+1}" + ports = var.ports + port_ranges = var.port_ranges + create_ip_pool = false + public_ip = ionoscloud_ipblock.node_ips.ips[count.index+1] + additional_ips = [ionoscloud_ipblock.floating_ip.ips[0]] + basic_vm_server_memory = var.server_memory + basic_vm_server_cpu = var.server_cpu + basic_vm_volume_size = var.volume_size + domain_without_top_level = var.domain_without_top_level + top_level_domain = var.top_level_domain + basic_vm_create_second_volume = var.create_second_volume + basic_vm_second_volume_disk_type = var.second_volume_disk_type + basic_vm_second_volume_size = var.second_volume_size + permanent_vm = var.permanent_vm + user_data_script = var.user_data_script + + depends_on = [ ionoscloud_lan.lan_public, ionoscloud_ipfailover.failover ] + + initial_user = var.initial_user + initial_uid = var.initial_uid + initial_public_key = var.initial_public_key +} + +resource "ionoscloud_nic" "private_nic_backup_vms" { + count = var.ha_node_count - 1 + datacenter_id = var.datacenter + server_id = module.ha_backup_vms[count.index].basic_vm_server_id + lan = ionoscloud_lan.lan_internal.id + dhcp = true + firewall_active = false +} + +resource "ionoscloud_ipblock" "floating_ip" { + name = "${module.conventions_coordinates.global_identifier}-${var.name}" + location = var.datacenter_location + size = 1 +} + +resource "ionoscloud_ipblock" "node_ips" { + name = "${module.conventions_coordinates.global_identifier}-${var.name}-nodes" + location = var.datacenter_location + size = var.ha_node_count +} + +resource "ionoscloud_lan" "lan_public" { + datacenter_id = var.datacenter + public = true + name = "${var.name}-public" +} + +resource "ionoscloud_lan" "lan_internal" { + datacenter_id = var.datacenter + public = false + name = "${var.name}-private" +} + +resource "ionoscloud_ipfailover" "failover" { + datacenter_id = var.datacenter + lan_id = ionoscloud_lan.lan_public.id + ip = ionoscloud_ipblock.floating_ip.ips[0] + nicuuid = module.ha_main_vm.basic_vm_server_nicuuid[0] +} + +resource "opentelekomcloud_dns_recordset_v2" "a_records" { + zone_id = data.opentelekomcloud_dns_zone_v2.dns_zone.id + name = "${var.name}.${var.domain_base}" + ttl = 3600 + type = "A" + records = [ionoscloud_ipblock.floating_ip.ips[0]] + lifecycle { + ignore_changes = [zone_id] + } +} diff --git a/modules/ionos-ha-vms/outputs.tf b/modules/ionos-ha-vms/outputs.tf new file mode 100644 index 0000000..a1e0f01 --- /dev/null +++ b/modules/ionos-ha-vms/outputs.tf @@ -0,0 +1,19 @@ +output "ha_internal_lan_id" { + value = ionoscloud_lan.lan_internal.id +} + +output "ha_public_lan_id" { + value = ionoscloud_lan.lan_public.id +} + +output "ha_dns_name" { + value = opentelekomcloud_dns_recordset_v2.a_records.name +} + +output "ha_common_address" { + value = ionoscloud_ipblock.floating_ip.ips[0] +} + +output "ha_vms_server_id" { + value = concat([module.ha_main_vm.basic_vm_server_id],module.ha_backup_vms[*].basic_vm_server_id) +} diff --git a/modules/ionos-ha-vms/variables.tf b/modules/ionos-ha-vms/variables.tf new file mode 100644 index 0000000..2b691ce --- /dev/null +++ b/modules/ionos-ha-vms/variables.tf @@ -0,0 +1,119 @@ +variable "datacenter" { + type = string +} + +variable "datacenter_location" { + type = string +} + +variable "server_memory" { + type = number + description = "memory of the vm servers" +} + +variable "server_cpu" { + type = number + description = "cpus of the vm servers" +} + +variable "volume_size" { + type = number + description = "volume size for vm" +} + +variable "create_second_volume" { + type = bool + default = true +} + +variable "second_volume_disk_type" { + type = string + default = "HDD" +} + +variable "cpu_family" { + type = string +} + +variable "coordinates" { + type = map(any) +} + +variable "top_level_domain" { + type = map(any) + description = "Top-level domain mapping for environments" +} + +variable "domain_without_top_level" { + type = string + description = "domain without top level" +} + +variable "image" { + type = string + description = "image of the vm" +} + +variable "name" { + type = string + description = "name of the ha cluster, used for names the components and the domain" +} + +variable "second_volume_size" { + type = string + description = "size of the second volume" + default = 100 +} + +variable "ports" { + type = list + description = "ports to open in the IONOS firewall provided as objects in a list [{protocol = ???, name = ???, port = ???, source_ip = ???}], source_ip is optional." + default = [] +} + +variable "port_ranges" { + type = list + description = "port rangs to open in the IONOS firewall provided as objects in a list [{protocol = ???, name = ???, port_start = ???, port_end, source_ip = ???}], source_ip is optional." + default = [] +} + +variable "permanent_vm" { + type = bool + description = "Create a permanent VM that mustn't be deleted, if false then a VM that can be deleted and that ignores changes to ram and cpu is created" + default = true +} + +variable "user_data_script" { + type = string + description = "Decide which user-data.sh script to use" + default = "user-data-cloud-init.tpl" +} + +variable "ha_node_count" { + type = number + description = "Number of VMs/Nodes in the HA Cluster" + default = 2 +} + +variable "domain_base" { + type = string + description = "Domains will be [-]." +} + +variable "initial_user" { + type = string + description = "The initial user to be created via the cloud init script." + default = "" +} + +variable "initial_uid" { + type = string + description = "The uid of the initial user created via the cloud init script." + default = "" +} + +variable "initial_public_key" { + type = string + description = "The public key of the initial user created via the cloud init script." + default = "" +} diff --git a/modules/ionos-ha-vms/versions.tf b/modules/ionos-ha-vms/versions.tf new file mode 100644 index 0000000..38a887c --- /dev/null +++ b/modules/ionos-ha-vms/versions.tf @@ -0,0 +1,12 @@ +terraform { + required_providers { + ionoscloud = { + source = "ionos-cloud/ionoscloud" + version = "6.4.18" + } + opentelekomcloud = { + source = "opentelekomcloud/opentelekomcloud" + } + } + required_version = ">= 0.13" +}