diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl index 1ca35fb..a0f1583 100644 --- a/.terraform.lock.hcl +++ b/.terraform.lock.hcl @@ -1,6 +1,26 @@ # This file is maintained automatically by "terraform init". # Manual edits may be lost in future updates. +provider "registry.terraform.io/hashicorp/random" { + version = "3.6.3" + constraints = "3.6.3" + hashes = [ + "h1:zG9uFP8l9u+yGZZvi5Te7PV62j50azpgwPunq2vTm1E=", + "zh:04ceb65210251339f07cd4611885d242cd4d0c7306e86dda9785396807c00451", + "zh:448f56199f3e99ff75d5c0afacae867ee795e4dfda6cb5f8e3b2a72ec3583dd8", + "zh:4b4c11ccfba7319e901df2dac836b1ae8f12185e37249e8d870ee10bb87a13fe", + "zh:4fa45c44c0de582c2edb8a2e054f55124520c16a39b2dfc0355929063b6395b1", + "zh:588508280501a06259e023b0695f6a18149a3816d259655c424d068982cbdd36", + "zh:737c4d99a87d2a4d1ac0a54a73d2cb62974ccb2edbd234f333abd079a32ebc9e", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:a357ab512e5ebc6d1fda1382503109766e21bbfdfaa9ccda43d313c122069b30", + "zh:c51bfb15e7d52cc1a2eaec2a903ac2aff15d162c172b1b4c17675190e8147615", + "zh:e0951ee6fa9df90433728b96381fb867e3db98f66f735e0c3e24f8f16903f0ad", + "zh:e3cdcb4e73740621dabd82ee6a37d6cfce7fee2a03d8074df65086760f5cf556", + "zh:eff58323099f1bd9a0bec7cb04f717e7f1b2774c7d612bf7581797e1622613a0", + ] +} + provider "registry.terraform.io/stackitcloud/stackit" { version = "0.55.0" constraints = "0.55.0" diff --git a/00-provider.tf b/00-provider.tf index a046d1d..36cc17f 100644 --- a/00-provider.tf +++ b/00-provider.tf @@ -15,6 +15,10 @@ terraform { source = "stackitcloud/stackit" version = "0.55.0" } + random = { + source = "hashicorp/random" + version = "3.6.3" + } } } diff --git a/01-config.tf b/01-config.tf index 95fb762..394583f 100644 --- a/01-config.tf +++ b/01-config.tf @@ -1,5 +1,5 @@ variable "stackit_project_id" { - type = string + type = string /*default = "XXXXX-XXXX-XXXX-XXXX-XXXXXXX"*/ default = "d75e6aab-b616-4b42-ae3b-aaf161ad626d" } @@ -14,7 +14,7 @@ variable "stackit_service_account_key_path" { default = "./keys/stackit-sa.json" } -variable "debian_image" { +variable "debian_image_id" { type = string default = "b7aedfad-3be7-46e0-9ece-19fd50e2d83e" } @@ -23,3 +23,18 @@ resource "stackit_key_pair" "admin_keypair" { name = "admin-keypair" public_key = chomp(file("~/.ssh/id_rsa.pub")) } + + +locals { + user_data_master = templatefile("cloud-init.yaml", { + type = "MASTER" + priority = "255" + vip = stackit_network_interface.vip01.ipv4 + }) + + user_data_backup = templatefile("cloud-init.yaml", { + type = "BACKUP" + priority = "254" + vip = stackit_network_interface.vip01.ipv4 + }) +} \ No newline at end of file diff --git a/03-network.tf b/02-network.tf similarity index 97% rename from 03-network.tf rename to 02-network.tf index 3e4a667..bd804e5 100644 --- a/03-network.tf +++ b/02-network.tf @@ -1,4 +1,3 @@ -# Create vNET Network resource "stackit_network" "default" { project_id = var.stackit_project_id ipv4_prefix = "10.1.2.0/24" @@ -6,7 +5,6 @@ resource "stackit_network" "default" { ipv4_nameservers = ["9.9.9.9", "1.1.1.1"] } -# Security Group resource "stackit_security_group" "active-passive" { project_id = var.stackit_project_id name = "ha-active-passive" diff --git a/04-master.tf b/03-master.tf similarity index 50% rename from 04-master.tf rename to 03-master.tf index f6ec77c..166f49d 100644 --- a/04-master.tf +++ b/03-master.tf @@ -5,31 +5,26 @@ resource "stackit_server" "example01" { boot_volume = { size = 64 source_type = "image" - source_id = var.debian_image + source_id = var.debian_image_id performance_class = "storage_premium_perf6" delete_on_termination = true } - machine_type = "c1.4" - availability_zone = "eu01-1" - keypair_name = stackit_key_pair.admin_keypair.name - depends_on = [stackit_network_interface.example01] + machine_type = "c1.4" + availability_zone = "eu01-1" + user_data = local.user_data_master + keypair_name = stackit_key_pair.admin_keypair.name + network_interfaces = [stackit_network_interface.example01.network_interface_id] } resource "stackit_network_interface" "example01" { - project_id = var.stackit_project_id - network_id = stackit_network.default.network_id + project_id = var.stackit_project_id + network_id = stackit_network.default.network_id + # security = false allowed_addresses = [format("%s/%s", stackit_network_interface.vip01.ipv4, "32")] security_group_ids = [stackit_security_group.active-passive.security_group_id] } -resource "stackit_server_network_interface_attach" "example01-nic-attachment" { - project_id = var.stackit_project_id - server_id = stackit_server.example01.server_id - network_interface_id = stackit_network_interface.example01.network_interface_id -} - resource "stackit_public_ip" "example01-wan" { project_id = var.stackit_project_id network_interface_id = stackit_network_interface.example01.network_interface_id - depends_on = [stackit_server_network_interface_attach.example01-nic-attachment] } diff --git a/05-backup.tf b/04-backup.tf similarity index 70% rename from 05-backup.tf rename to 04-backup.tf index 18e1c2b..83d8b7b 100644 --- a/05-backup.tf +++ b/04-backup.tf @@ -5,14 +5,18 @@ resource "stackit_server" "example02" { boot_volume = { size = 64 source_type = "image" - source_id = var.debian_image + source_id = var.debian_image_id performance_class = "storage_premium_perf6" delete_on_termination = true } machine_type = "c1.4" availability_zone = "eu01-2" + user_data = local.user_data_backup keypair_name = stackit_key_pair.admin_keypair.name depends_on = [stackit_network_interface.example02] + network_interfaces = [ + stackit_network_interface.example02.network_interface_id + ] } resource "stackit_network_interface" "example02" { @@ -22,14 +26,7 @@ resource "stackit_network_interface" "example02" { security_group_ids = [stackit_security_group.active-passive.security_group_id] } -resource "stackit_server_network_interface_attach" "example02-nic-attachment" { - project_id = var.stackit_project_id - server_id = stackit_server.example02.server_id - network_interface_id = stackit_network_interface.example02.network_interface_id -} - resource "stackit_public_ip" "example02-wan" { project_id = var.stackit_project_id network_interface_id = stackit_network_interface.example02.network_interface_id - depends_on = [stackit_server_network_interface_attach.example02-nic-attachment] } diff --git a/06-ha.tf b/05-ha.tf similarity index 60% rename from 06-ha.tf rename to 05-ha.tf index 055a022..48409f6 100644 --- a/06-ha.tf +++ b/05-ha.tf @@ -4,19 +4,11 @@ resource "stackit_network_interface" "vip01" { security = false } +locals { + x = stackit_network_interface.vip01.ipv4 +} + resource "stackit_public_ip" "vip01-wan" { project_id = var.stackit_project_id network_interface_id = stackit_network_interface.vip01.network_interface_id -} - -output "example01-wan-ip" { - value = stackit_public_ip.example01-wan.ip -} - -output "example02-wan-ip" { - value = stackit_public_ip.example02-wan.ip -} - -output "vip01-wan-ip" { - value = stackit_public_ip.vip01-wan.ip } \ No newline at end of file diff --git a/06-outputs.tf b/06-outputs.tf new file mode 100644 index 0000000..823f9da --- /dev/null +++ b/06-outputs.tf @@ -0,0 +1,32 @@ +output "example01-wan-ip" { + value = stackit_public_ip.example01-wan.ip +} + +output "example01-master-server-id" { + value = stackit_server.example01.server_id +} + +output "example02-wan-ip" { + value = stackit_public_ip.example02-wan.ip +} + +output "example02-backup-server-id" { + value = stackit_server.example02.server_id +} + +output "vip01-wan-ip" { + value = stackit_public_ip.vip01-wan.ip +} + +output "vip01-lan-ip" { + value = stackit_network_interface.vip01.ipv4 +} + +output "vip01-network-interface" { + value = stackit_network_interface.vip01.network_interface_id +} + +output "default-network-id" { + value = stackit_network.default.network_id +} + diff --git a/README.md b/README.md index 44a98da..c862740 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,54 @@ # Basic High Availability (HA) Setup Using VRRP -This guide provides step-by-step instructions for setting up a basic active/passive Virtual Router Redundancy Protocol (VRRP) high availability (HA) cluster using the STACKIT CLI. This configuration ensures one virtual machine (VM) acts as the active primary node while the other remains on standby as a failover. +This guide provides a comprehensive, step-by-step process for setting up a Basic High Availability (HA) cluster using the Virtual Router Redundancy Protocol (VRRP) with the STACKIT CLI. In this HA configuration, one virtual machine (VM) functions as the active primary node while the secondary remains on standby, ready to take over in the event of a failure. -> See [STACKIT Cli-Guide](STACKIT-CLI-GUIDE.md) to perform setup via CLI instead of terraform! +> For setup instructions using the STACKIT CLI instead of Terraform, please refer to the [STACKIT CLI Guide](STACKIT-CLI-GUIDE.md). ## Overview of Core Components -- Two virtual machines in an active/passive configuration. -- VRRP synchronization between the nodes. -- Security group rules for VRRP and ICMP traffic. -- A dedicated internal virtual IP (vIP) bound to a shared NIC port. -- Public IP binding for external access to HA endpoint. +- **Active/Passive VM Configuration**: Ensures redundancy, with one active node and a standby failover node. +- **VRRP Synchronization**: Maintains state information between nodes, enabling seamless failover. +- **Security Group Rules**: Configured to allow VRRP and ICMP traffic. +- **Virtual IP (vIP)**: A dedicated internal IP address bound to a shared network interface card (NIC) port for seamless failover. +- **Public IP Binding**: Enables external access to the HA endpoint. -Diagrams: +### Diagrams -- HA Traffic Flow: +- **HA Traffic Flow**: -  +  -- vIP Binding Concept: +- **vIP Binding Concept**: -  +  +## Testing the Setup + +After completing the setup, use the [test-setup.sh](test-setup.sh) script to verify that the Apache server is operational on each machine. Executing this script should yield the following results: + +```bash +Performing curl on IP: 193.148.177.243 +