# On-Premises HCI Infrastructure Module # Supports Azure Stack HCI and vSphere-based HCI clusters locals { env = var.environment_config # Extract on-prem config onprem_config = try(local.env.onprem, {}) hci_config = try(local.env.azure_stack_hci, {}) # Extract infrastructure config infra = try(local.env.infrastructure, {}) k8s_config = try(local.infra.kubernetes, {}) hci_k8s = try(local.k8s_config.hci, {}) # Naming name_prefix = "${local.env.name}-${var.environment}" # HCI platform hci_platform = try(local.onprem_config.hci_platform, "azure-stack-hci") # Node pools node_pools = try(local.hci_k8s.node_pools, {}) } # ============================================ # AZURE STACK HCI # ============================================ # Azure Stack HCI uses Azure Arc to manage Kubernetes clusters # The cluster is pre-provisioned on-prem, we just onboard it to Azure Arc resource "azapi_resource" "azure_stack_hci_cluster" { count = local.hci_platform == "azure-stack-hci" && try(local.hci_config.enabled, false) ? 1 : 0 type = "Microsoft.Kubernetes/connectedClusters@2023-11-01-preview" name = try(local.hci_config.cluster_name, "${local.name_prefix}-hci") location = try(local.hci_config.location, "westus") # Azure region for Arc resource parent_id = "/subscriptions/${var.azure_subscription_id}/resourceGroups/${try(local.hci_config.resource_group, "rg-hci-${var.environment}")}" body = jsonencode({ properties = { agentPublicKeyCertificate = "" # Will be populated by Arc agent installed on-prem distribution = "AKS" infrastructure = "azure_stack_hci" } }) tags = var.tags } # ============================================ # VSPHERE-BASED HCI # ============================================ # For vSphere, we provision VMs and install Kubernetes # Data sources for vSphere data "vsphere_datacenter" "dc" { count = local.hci_platform == "vsphere" ? 1 : 0 name = try(local.onprem_config.datacenter, "datacenter1") } data "vsphere_datastore" "datastore" { count = local.hci_platform == "vsphere" ? 1 : 0 name = try(local.onprem_config.datastore, "datastore1") datacenter_id = data.vsphere_datacenter.dc[0].id } data "vsphere_compute_cluster" "cluster" { count = local.hci_platform == "vsphere" ? 1 : 0 name = try(local.onprem_config.cluster, "cluster1") datacenter_id = data.vsphere_datacenter.dc[0].id } data "vsphere_network" "network" { count = local.hci_platform == "vsphere" ? 1 : 0 name = try(local.onprem_config.network, "VM Network") datacenter_id = data.vsphere_datacenter.dc[0].id } data "vsphere_virtual_machine" "template" { count = local.hci_platform == "vsphere" ? 1 : 0 name = try(local.onprem_config.vm_template, "ubuntu-22.04-template") datacenter_id = data.vsphere_datacenter.dc[0].id } # System nodes resource "vsphere_virtual_machine" "system" { count = local.hci_platform == "vsphere" && try(local.node_pools.system.count, 0) > 0 ? local.node_pools.system.count : 0 name = "${local.name_prefix}-system-${count.index + 1}" resource_pool_id = data.vsphere_compute_cluster.cluster[0].resource_pool_id datastore_id = data.vsphere_datastore.datastore[0].id num_cpus = 2 memory = 4096 guest_id = data.vsphere_virtual_machine.template[0].guest_id scsi_type = data.vsphere_virtual_machine.template[0].scsi_type firmware = data.vsphere_virtual_machine.template[0].firmware network_interface { network_id = data.vsphere_network.network[0].id } disk { label = "disk0" size = 100 eagerly_scrub = false thin_provisioned = true } clone { template_uuid = data.vsphere_virtual_machine.template[0].id customize { linux_options { host_name = "${local.name_prefix}-system-${count.index + 1}" domain = try(local.env.identity.domain, "local") } network_interface { ipv4_address = cidrhost(try(local.env.infrastructure.networking.subnet_cidr, "192.168.1.0/24"), count.index + 10) ipv4_netmask = 24 } ipv4_gateway = try(local.env.infrastructure.networking.gateway, "192.168.1.1") dns_server_list = ["8.8.8.8", "8.8.4.4"] } } tags = [for k, v in var.tags : "${k}=${v}"] } # Validator nodes resource "vsphere_virtual_machine" "validators" { count = local.hci_platform == "vsphere" && try(local.node_pools.validators.count, 0) > 0 ? local.node_pools.validators.count : 0 name = "${local.name_prefix}-validator-${count.index + 1}" resource_pool_id = data.vsphere_compute_cluster.cluster[0].resource_pool_id datastore_id = data.vsphere_datastore.datastore[0].id num_cpus = 4 memory = 8192 guest_id = data.vsphere_virtual_machine.template[0].guest_id scsi_type = data.vsphere_virtual_machine.template[0].scsi_type firmware = data.vsphere_virtual_machine.template[0].firmware network_interface { network_id = data.vsphere_network.network[0].id } disk { label = "disk0" size = 512 eagerly_scrub = false thin_provisioned = true } clone { template_uuid = data.vsphere_virtual_machine.template[0].id customize { linux_options { host_name = "${local.name_prefix}-validator-${count.index + 1}" domain = try(local.env.identity.domain, "local") } network_interface { ipv4_address = cidrhost(try(local.env.infrastructure.networking.subnet_cidr, "192.168.1.0/24"), count.index + 20) ipv4_netmask = 24 } ipv4_gateway = try(local.env.infrastructure.networking.gateway, "192.168.1.1") dns_server_list = ["8.8.8.8", "8.8.4.4"] } } tags = [for k, v in var.tags : "${k}=${v}"] } # RPC nodes resource "vsphere_virtual_machine" "rpc" { count = local.hci_platform == "vsphere" && try(local.node_pools.rpc.count, 0) > 0 ? local.node_pools.rpc.count : 0 name = "${local.name_prefix}-rpc-${count.index + 1}" resource_pool_id = data.vsphere_compute_cluster.cluster[0].resource_pool_id datastore_id = data.vsphere_datastore.datastore[0].id num_cpus = 4 memory = 8192 guest_id = data.vsphere_virtual_machine.template[0].guest_id scsi_type = data.vsphere_virtual_machine.template[0].scsi_type firmware = data.vsphere_virtual_machine.template[0].firmware network_interface { network_id = data.vsphere_network.network[0].id } disk { label = "disk0" size = 256 eagerly_scrub = false thin_provisioned = true } clone { template_uuid = data.vsphere_virtual_machine.template[0].id customize { linux_options { host_name = "${local.name_prefix}-rpc-${count.index + 1}" domain = try(local.env.identity.domain, "local") } network_interface { ipv4_address = cidrhost(try(local.env.infrastructure.networking.subnet_cidr, "192.168.1.0/24"), count.index + 30) ipv4_netmask = 24 } ipv4_gateway = try(local.env.infrastructure.networking.gateway, "192.168.1.1") dns_server_list = ["8.8.8.8", "8.8.4.4"] } } tags = [for k, v in var.tags : "${k}=${v}"] } # Note: Kubernetes cluster installation on these VMs would be done via: # - Cloud-init scripts # - Ansible playbooks # - kubeadm # - Rancher/K3s # This is outside Terraform's scope but can be orchestrated via provisioners or external tools