title: How can I use the rancher2 Terraform provider to create an HA RKE cluster in Azure?
body: <p>I have an issue with creating an RKE cluster with the <code>rancher/rancher2</code> Terraform provider and help would be highly appreciated because I already tested too many things to install an HA K8s cluster (using rancher to launch K8s on new nodes in an infrastructure provider).</p>
  <p>The infrastructure Provider is Azure.</p>
  <p>In order to be able to use the node scaling Rancher feature, I need to use node templates/pools and specify an infrastructure provider (Azure).</p>
  <p>The issues I am facing are:</p>
  <ul>
  <li><p>If I create a single node cluster (all roles, worker, control, etcd) rancher will create the VM, availability set, public IP and k8s install will be successful. No Load Balancer.</p>
  </li>
  <li><p>If I create a 3+ nodes cluster, it will create a public IP for all nodes or private IP for all nodes depending on if the <code>no_public_ip</code> argument is set to <code>true</code> or <code>false</code> in the terraform <code>rancher2_node_template</code> resource. Rancher will not create an LB even if I specify a custom availability set and network security group for worker nodes.</p>
  </li>
  </ul>
  <p>As Rancher (Rancher server installed on AKS as control management cluster) provisions the VMs, if I want to add a public LB with worker nodes in the backend pool, I need the network interfaces of the VMs, but Rancher is creating them in Azure, not me, so it is not ideal to create an LB and add the NICs (that I have to retrieve) because on scaling up/down the new nodes, they will not be added to the LB and I'll have to add them myself.</p>
  <p>The goal for me is to have an HA RKE cluster with at 3 nodes for the control plane (etcd+control plane) and 2 worker nodes. I need to use node pools/node templates for manual node scaling in the Rancher UI. And for an HA RKE cluster, I need an Azure Load Balancer in front of the cluster.</p>
  <p><strong>Documentation:</strong></p>
  <ul>
  <li><a href="https://rancher.com/docs/rancher/v2.6/en/cluster-provisioning/" rel="nofollow noreferrer">Launching Kubernetes on New Nodes in an Infrastructure Provider (See the last section &quot;Programatically Creating Clusters&quot;</a></li>
  <li><a href="https://rancher.com/docs/rancher/v2.6/en/cluster-provisioning/" rel="nofollow noreferrer">Here they talk about Load Balancer for RKE Azure cluster (Azure Security Group Section), Rancher states that &quot;A custom Azure Network Securoty Group (securityGroupName) is needed to allow Azure Load Balancer to work&quot;.</a></li>
  <li><a href="https://rancher.com/docs/rancher/v2.6/en/cluster-provisioning/rke-clusters/node-pools/azure/" rel="nofollow noreferrer">Creating an RKE Cluster In Azure</a></li>
  </ul>
  <p>I also tried to use AKS (which creates an Azure Load Balancer) instead of RKE for the downstream cluster but it does not allow for scaling nodes in the Rancher UI, the scaling of nodes is done by the AKS autoscaler when using max node and min node in the configuration of the cluster.
  I've been trying to create the RKE HA cluster with a public load balancer but without success and I start thinking that I am missing something or this it is not possible then, why mention Azure Load Balancer L7 and L4 in the documentation?</p>
  <p>Here is the code that creates successfully the downstream cluster with private IP only and virtual network peering between the Rancher control cluster network and the downstream RKE network:</p>
  <pre><code>
  ## Create Resource Group for the downstream cluster
  
  resource &quot;azurerm_resource_group&quot; &quot;rg&quot; {
    name     = &quot;${var.rke_name_prefix}-rg&quot;
    location = var.azure_region
  }
  
  ## Create the Virtual Network and Subnet for downstream cluster
  
  resource &quot;azurerm_virtual_network&quot; &quot;vnet&quot; {
    name                = &quot;${var.rke_name_prefix}-vnet&quot;
    address_space       = var.rke_address_space
    location            = var.azure_region
    resource_group_name = azurerm_resource_group.rg.name
  }
  
  resource &quot;azurerm_subnet&quot; &quot;subnet&quot; {
    name                 = &quot;${var.rke_name_prefix}-subnet&quot;
    resource_group_name  = azurerm_resource_group.rg.name
    virtual_network_name = azurerm_virtual_network.vnet.name
    address_prefixes     = var.rke_address_prefixes
  }
  
  ## Create Virtual Network Peering between the Rancher control cluster and the downstream RKE cluster network
  
  resource &quot;azurerm_virtual_network_peering&quot; &quot;rancher_control_cluster&quot; {
    name                      = &quot;control-vnet-peering&quot;
    resource_group_name       = azurerm_resource_group.rg.name
    virtual_network_name      = azurerm_virtual_network.vnet.name
    remote_virtual_network_id = var.rancher_control_vnet_id
  }
  
  resource &quot;azurerm_virtual_network_peering&quot; &quot;rancher_downstream_cluster&quot; {
    name                      = &quot;downstream-vnet-peering&quot;
    resource_group_name       = var.rancher_control_rg
    virtual_network_name      = var.rancher_control_vnet_name
    remote_virtual_network_id = azurerm_virtual_network.vnet.id
  }
  
  ## Create Security Group and Availabity Set for Worker
  
  resource &quot;azurerm_network_security_group&quot; &quot;worker_nsg&quot; {
    name                = &quot;worker-nsg&quot;
    location            = azurerm_resource_group.rg.location
    resource_group_name = azurerm_resource_group.rg.name
  
    security_rule {
      name                       = &quot;in_22&quot;
      priority                   = 100
      direction                  = &quot;Inbound&quot;
      access                     = &quot;Allow&quot;
      protocol                   = &quot;Tcp&quot;
      source_port_range          = &quot;*&quot;
      destination_port_range     = &quot;22&quot;
      source_address_prefix      = &quot;*&quot;
      destination_address_prefix = &quot;*&quot;
    }
  
    security_rule {
      name                       = &quot;in_443&quot;
      priority                   = 200
      direction                  = &quot;Inbound&quot;
      access                     = &quot;Allow&quot;
      protocol                   = &quot;Tcp&quot;
      source_port_range          = &quot;*&quot;
      destination_port_range     = &quot;443&quot;
      source_address_prefix      = &quot;*&quot;
      destination_address_prefix = &quot;*&quot;
    }
  
    security_rule {
      name                       = &quot;in_2376&quot;
      priority                   = 110
      direction                  = &quot;Inbound&quot;
      access                     = &quot;Allow&quot;
      protocol                   = &quot;Tcp&quot;
      source_port_range          = &quot;*&quot;
      destination_port_range     = &quot;2376&quot;
      source_address_prefix      = &quot;*&quot;
      destination_address_prefix = &quot;*&quot;
    }
  
    security_rule {
      name                       = &quot;in_8472&quot;
      priority                   = 120
      direction                  = &quot;Inbound&quot;
      access                     = &quot;Allow&quot;
      protocol                   = &quot;Tcp&quot;
      source_port_range          = &quot;*&quot;
      destination_port_range     = &quot;8472&quot;
      source_address_prefix      = &quot;*&quot;
      destination_address_prefix = &quot;*&quot;
    }
  
    security_rule {
      name                       = &quot;in_10250&quot;
      priority                   = 130
      direction                  = &quot;Inbound&quot;
      access                     = &quot;Allow&quot;
      protocol                   = &quot;Tcp&quot;
      source_port_range          = &quot;*&quot;
      destination_port_range     = &quot;10250&quot;
      source_address_prefix      = &quot;*&quot;
      destination_address_prefix = &quot;*&quot;
    }
  
    security_rule {
      name                       = &quot;in_9099&quot;
      priority                   = 140
      direction                  = &quot;Inbound&quot;
      access                     = &quot;Allow&quot;
      protocol                   = &quot;Tcp&quot;
      source_port_range          = &quot;*&quot;
      destination_port_range     = &quot;9099&quot;
      source_address_prefix      = &quot;*&quot;
      destination_address_prefix = &quot;*&quot;
    }
  
    security_rule {
      name                       = &quot;in_10254&quot;
      priority                   = 150
      direction                  = &quot;Inbound&quot;
      access                     = &quot;Allow&quot;
      protocol                   = &quot;Tcp&quot;
      source_port_range          = &quot;*&quot;
      destination_port_range     = &quot;10254&quot;
      source_address_prefix      = &quot;*&quot;
      destination_address_prefix = &quot;*&quot;
    }
  
    security_rule {
      name                       = &quot;in_30000-32767&quot;
      priority                   = 160
      direction                  = &quot;Inbound&quot;
      access                     = &quot;Allow&quot;
      protocol                   = &quot;Tcp&quot;
      source_port_range          = &quot;*&quot;
      destination_port_range     = &quot;30000-32767&quot;
      source_address_prefix      = &quot;*&quot;
      destination_address_prefix = &quot;*&quot;
    }
  
    security_rule {
      name                       = &quot;in_80&quot;
      priority                   = 170
      direction                  = &quot;Inbound&quot;
      access                     = &quot;Allow&quot;
      protocol                   = &quot;Tcp&quot;
      source_port_range          = &quot;*&quot;
      destination_port_range     = &quot;80&quot;
      source_address_prefix      = &quot;*&quot;
      destination_address_prefix = &quot;*&quot;
    }
  }
  
  resource &quot;azurerm_availability_set&quot; &quot;worker_availset&quot; {
    name                = &quot;availset-worker&quot;
    location            = azurerm_resource_group.rg.location
    resource_group_name = azurerm_resource_group.rg.name
  }
  
  ## Create a new rancher2 RKE Cluster
  
  resource &quot;rancher2_cluster&quot; &quot;rke&quot; {
    name =  &quot;${var.rke_name_prefix}-cluster&quot;
    description = &quot;Downstream RKE Cluster&quot;
    rke_config {
      network {
        plugin = &quot;canal&quot;
      }
      ingress {
        provider = &quot;nginx&quot;
      }
  
      cloud_provider {
        name = &quot;azure&quot;
        azure_cloud_provider {
          aad_client_id                  = azuread_application.app.application_id
          aad_client_secret              = azuread_service_principal_password.auth.value
          subscription_id                = data.azurerm_subscription.subscription.subscription_id
          tenant_id                      = data.azurerm_subscription.subscription.tenant_id
          load_balancer_sku              = &quot;standard&quot;
          subnet_name                    = azurerm_subnet.subnet.name
          vnet_name                      = azurerm_virtual_network.vnet.name
          resource_group                 = azurerm_resource_group.rg.name
        }
      }
    }
  
    provider = rancher2.admin
  }
  
  ## Create Node Templates
  
  resource &quot;rancher2_node_template&quot; &quot;control_plane&quot; {
    name                 = &quot;control_plane-template&quot;
    description          = &quot;Node Template for RKE Cluster on Azure&quot;
    cloud_credential_id  = rancher2_cloud_credential.cloud_credential.id
    engine_install_url   = &quot;https://releases.rancher.com/install-docker/20.10.sh&quot;
    azure_config {
      managed_disks         = true
      location              = var.azure_region
      size                  = &quot;Standard_A2&quot;
      storage_type          = &quot;Standard_LRS&quot;
      resource_group        = azurerm_resource_group.rg.name
      environment           = &quot;AzurePublicCloud&quot;
      no_public_ip          = true
      subnet                = azurerm_subnet.subnet.name
      vnet                  = azurerm_virtual_network.vnet.name
      open_port             = [&quot;2379-2380&quot;,8472,443,6443,10250]
    }
  
    provider = rancher2.admin
  }
  
  resource &quot;rancher2_node_template&quot; &quot;worker&quot; {
    name                 = &quot;worker-template&quot;
    description          = &quot;Node Template for RKE Cluster on Azure&quot;
    cloud_credential_id  = rancher2_cloud_credential.cloud_credential.id
    engine_install_url   = &quot;https://releases.rancher.com/install-docker/20.10.sh&quot;
    azure_config {
      managed_disks                  = true
      location                       = var.azure_region
      size                           = &quot;Standard_A2&quot;
      storage_type                   = &quot;Standard_LRS&quot;
      resource_group                 = azurerm_resource_group.rg.name
      environment                    = &quot;AzurePublicCloud&quot;
      no_public_ip                   = true
      subnet                         = azurerm_subnet.subnet.name
      vnet                           = azurerm_virtual_network.vnet.name
      nsg                            = azurerm_network_security_group.worker_nsg.name
      availability_set               = azurerm_availability_set.worker_availset.name
    }
  
    provider = rancher2.admin
  }
  
  ## Create Node Pools
  
  resource &quot;rancher2_node_pool&quot; &quot;control_plane&quot; {
    cluster_id        =  rancher2_cluster.rke.id
    name              = &quot;control-plane-node-pool&quot;
    hostname_prefix   = &quot;${var.rke_name_prefix}&quot;
    node_template_id  = rancher2_node_template.control_plane.id
    quantity          = 3
    control_plane     = true
    etcd              = true
    worker            = false
  
    provider = rancher2.admin
  }
  
  resource &quot;rancher2_node_pool&quot; &quot;worker&quot; {
    cluster_id        =  rancher2_cluster.rke.id
    name              = &quot;worker-node-pool&quot;
    hostname_prefix   = &quot;${var.rke_name_prefix}&quot;
    node_template_id  = rancher2_node_template.worker.id
    quantity          = 2
    control_plane     = false
    etcd              = false
    worker            = true
  
    provider = rancher2.admin
  }
  </code></pre>