This Terraform module creates and configures an AVI (NSX Advanced Load Balancer) Controller on Azure
The module is meant to be modular and can create all or none of the prerequisite resources needed for the AVI Azure Deployment including:
- VNET and Subnet for the Controller and SEs (configured with create_networking variable)
- VNET Peering (configured with the configure_vnet_peering variable)
- Azure Active Directory Application, Service Principal, Custom Role, and Role Assignment for the Controller (configured with create_iam variable)
- Network Security Groups for AVI Controller and SE communication (future work)
- Azure Virtual Machine Instance using an official AVI Azure Marketplace image
- High Availability AVI Controller Deployment (configured with controller_ha variable)
During the creation of the Controller instance the following initialization steps are performed:
- Copy Ansible playbook to controller using the assigned public IP
- Run Ansible playbook to configure initial settings and Azure Full Access Cloud
The Ansible playbook can optionally add these configurations:
- Create DNS Profile (configured with the configure_dns_profile variable)
- Create Avi DNS Virtual Service (configured with the configure_dns_vs variable)
- Configure GSLB (configured with the configure_gslb variable)
The following are Azure prerequisites for running this module:
- Subscription created
- Account with either Contributor role (if create_iam is false) or Owner (if create_iam is true)
For authenticating to the Azure Provider the instructions found here should be followed - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs
The azurerm provider block may need to be configured for setting addtional settings depending on the environment. The settings as shown in the example below have been tested sucessfully:
provider "azurerm" {
features {
resource_group {
prevent_deletion_if_contains_resources = false
}
}
skip_provider_registration = "true"
}
This module will use the Azure Marketplace for deploying the Avi image. The terms of the image and more information can be found in this link - https://azuremarketplace.microsoft.com/en-us/marketplace/apps/avi-networks.avi-vantage-adc. By default the marketplace agreement is accepted with the create_marketplace_agreement variable.
The following packages must be installed on the host operating system:
- curl
This is an example of an HA controller deployment that creates the controller and all other requisite Azure resources.
terraform {
backend "local" {
}
}
provider "azurerm" {
features {
resource_group {
prevent_deletion_if_contains_resources = false
}
}
skip_provider_registration = "true"
}
module "avi_controller_azure" {
source = "vmware/avi-alb-deployment-azure/azurerm"
version = "1.0.x"
region = "westus2"
name_prefix = "companyname"
controller_default_password = "Value Redacted and available within the VMware Customer Portal"
controller_password = "<newpassword>"
create_networking = true
create_iam = true
controller_ha = true
controller_public_address = true
custom_tags = { "Role" : "Avi-Controller", "Owner" : "user@email.com", "Department" : "IT" }
se_ha_mode = "active/active"
vnet_address_space = "10.255.0.0/16"
avi_subnet = "10.255.0.0/24"
}
output "controller_info" {
value = module.avi_controller_azure.controllers
}
For GSLB to be configured successfully the configure_gslb and configure_dns_vs variables must be configured. By default a new Service Engine Group (g-dns) and user (gslb-admin) will be created for the configuration.
The following is a description of the configure_gslb variable parameters and their usage:
Parameter | Description | Type |
---|---|---|
enabled | Must be set to "true" for Active GSLB sites | bool |
leader | Must be set to "true" for only one GSLB site that will be the leader | bool |
site_name | Name of the GSLB site | string |
domains | List of GSLB domains that will be configured | list(string) |
create_se_group | Determines whether a g-dns SE group will be created | bool |
se_size | The Azure VM Size used for the Avi Service Engines | string |
additional_sites | Additional sites that will be configured. This parameter should only be set for the primary GSLB site | string |
The example below shows a GSLB deployment with 2 regions utilized. VNET Peering is configured (with configure_vnet_peering variable) between the two newly created Avi VNETs so that the controllers can communicate.
terraform {
backend "local" {
}
}
provider "azurerm" {
features {
resource_group {
prevent_deletion_if_contains_resources = false
}
}
skip_provider_registration = "true"
}
module "avi_controller_azure_westus2" {
source = "vmware/avi-alb-deployment-azure/azurerm"
version = "1.0.x"
region = "westus2"
name_prefix = "companyname"
controller_default_password = "Value Redacted and available within the VMware Customer Portal"
controller_password = "<newpassword>"
create_networking = true
configure_vnet_peering = { enabled = true, global_peering = true, resource_group = "rg-<name_prefix>-avi-<region>", vnet_name = "<name_prefix>-avi-vnet-<region>" }
create_iam = true
controller_ha = true
controller_public_address = true
custom_tags = { "Role" : "Avi-Controller", "Owner" : "user@email.com", "Department" : "IT" }
se_ha_mode = "active/active"
vnet_address_space = "10.251.0.0/16"
avi_subnet = "10.251.0.0/24"
configure_dns_profile = { "enabled" = "true", usable_domains = ["west2.avidemo.net"] }
configure_dns_vs = { "enabled" = "true", allocate_public_ip = "false" }
configure_gslb = {"enabled = "true", site_name = "West2" }
}
module "avi_controller_azure_eastus2" {
source = "vmware/avi-alb-deployment-azure/azurerm"
version = "1.0.x"
region = "eastus2"
name_prefix = "companyname"
controller_default_password = "Value Redacted and available within the VMware Customer Portal"
controller_password = "<newpassword>"
create_networking = true
configure_vnet_peering = { enabled = true, global_peering = true, resource_group = "rg-<name_prefix>-avi-<region>", vnet_name = "<name_prefix>-avi-vnet-<region>" }
create_iam = true
controller_ha = true
controller_public_address = true
custom_tags = { "Role" : "Avi-Controller", "Owner" : "user@email.com", "Department" : "IT" }
se_ha_mode = "active/active"
vnet_address_space = "10.252.0.0/16"
avi_subnet = "10.252.0.0/24"
configure_dns_profile = { "enabled" = "true", usable_domains = ["east2.avidemo.net"] }
configure_dns_vs = { "enabled" = "true", allocate_public_ip = "false" }
configure_gslb = {"enabled = "true", leader = "true", site_name = "East2", domains = ["gslb.avidemo.net"], additional_sites = [{name = "West2", ip_address_list = module.avi_controller_azure_westus2.controllers[*].private_ip_address }] }
}
output "eastus2_controller_info" {
value = module.avi_controller_azure_eastus2.controllers
}
output "westus2_controller_info" {
value = module.avi_controller_azure_westus2.controllers
}
For a controller deployment that is only accesible via private IPs the controller_public_address should be set to false to enable this connectivity. In addition it is recommended to either configure VNET peering with the configure_vnet_peering or manually create resource group and VNET/Subnets and specify them with the create-networking = false, custom_controller_resource_group, custom_vnet_name, and custom_subnet_name variables. This is needed so that the controller IPs can be reached by the Ansible provisioner.
The module copies and runs an Ansible play for configuring the initial day 1 Avi config. The plays listed below can be reviewed by connecting to the Avi Controller by SSH. In an HA setup the first controller will have these files.
This play will configure the Avi Cloud, Network, IPAM/DNS profiles, DNS Virtual Service, GSLB depending on the variables used. The initial run of this play will output into the ansible-playbook.log file which can be reviewed to determine what tasks were ran.
Example run (appropriate variable values should be used):
~$ ansible-playbook avi-controller-azure-all-in-one-play.yml -e password=${var.controller_password} -e azure_app_id=${var.controller_az_app_id} -e azure_auth_token=${var.controller_az_client_secret} -e azure_tenant_id=${data.azurerm_subscription.current.tenant_id} > ansible-playbook-run.log
This play will upgrade or patch the Avi Controller and SEs depending on the variables used. When ran this play will output into the ansible-playbook.log file which can be reviewed to determine what tasks were ran. This play can be ran during the initial Terraform deployment with the avi_upgrade variable as shown in the example below:
avi_upgrade = { enabled = "true", upgrade_type = "patch", upgrade_file_uri = "URL Copied From portal.avipulse.vmware.com"}
An full version upgrade can be done by changing changing the upgrade_type to "system". It is recommended to run this play in a lower environment before running in a production environment and is not recommended for a GSLB setup at this time.
Example run (appropriate variable values should be used):
~$ ansible-playbook avi-upgrade.yml -e password=${var.controller_password} -e upgrade_type=${var.avi_upgrade.upgrade_type} -e upgrade_file_uri=${var.avi_upgrade.upgrade_file_uri} > ansible-playbook-run.log
This play will register the Controller with Avi Cloud Services. This can be done to enable centralized licensing, live security threat updates, and proactive support. When ran this play will output into the ansible-playbook.log file which can be reviewed to determine what tasks were ran. This play can be ran during the initial Terraform deployment with the register_controller variable as shown in the example below:
register_controller = { enabled = "true", jwt_token = "TOKEN", email = "EMAIL", organization_id = "LONG_ORG_ID" }
The organization_id can be found as the Long Organization ID field from https://console.cloud.vmware.com/csp/gateway/portal/#/organization/info.
The jwt_token can be retrieved at https://portal.avipulse.vmware.com/portal/controller/auth/cspctrllogin.
Example run (appropriate variable values should be used):
~$ ansible-playbook avi-cloud-services-registration.yml -e password=${var.controller_password} -e register_controller.jwt_token=${var.register_controller.jwt_token} > ansible-playbook-run.log
This play will disable all Virtual Services, delete all existing Avi service engines, and de-register the controller from Cloud Services. This playbook should be ran before deleting the controller with terraform destroy to clean up the resources created by the Avi Controller. Note that additional items created by the controller may be created and need to be manually removed.
Example run (appropriate variable values should be used and -e register_controller.jwt_token is only needed when register_controller.enabled is set to true):
~$ ansible-playbook avi-cleanup.yml -e password=${var.controller_password} -e register_controller.jwt_token=${var.register_controller.jwt_token}
The terraform-azurerm-avi-alb-deployment-azure project team welcomes contributions from the community. Before you start working with this project please read and sign our Contributor License Agreement (https://cla.vmware.com/cla/1/preview). If you wish to contribute code and you have not signed our Contributor Licence Agreement (CLA), our bot will prompt you to do so when you open a Pull Request. For any questions about the CLA process, please refer to our FAQ. For more detailed information, refer to CONTRIBUTING.md.
Name | Version |
---|---|
terraform | >= 1.3.0 |
azuread | ~> 2.30.0 |
azurerm | ~> 3.29.1 |
null | ~> 3.2.0 |
random | ~> 3.4.3 |
Name | Version |
---|---|
azuread | 2.26.1 |
azurerm | 3.14.0 |
null | 3.1.1 |
random | 3.3.2 |
No modules.
Name | Type |
---|---|
azuread_application.avi | resource |
azuread_application_password.avi | resource |
azuread_service_principal.avi | resource |
azurerm_linux_virtual_machine.avi_controller | resource |
azurerm_marketplace_agreement.avi | resource |
azurerm_network_interface.avi | resource |
azurerm_network_interface_security_group_association.controller | resource |
azurerm_network_security_group.avi_controller_mgmt | resource |
azurerm_public_ip.avi | resource |
azurerm_resource_group.avi | resource |
azurerm_role_assignment.contributor | resource |
azurerm_role_assignment.custom_controller | resource |
azurerm_role_definition.custom_controller | resource |
azurerm_subnet.avi | resource |
azurerm_virtual_network.avi | resource |
azurerm_virtual_network_peering.avi | resource |
null_resource.ansible_provisioner | resource |
random_uuid.role_definition | resource |
azuread_client_config.current | data source |
azurerm_resource_group.custom | data source |
azurerm_subnet.custom | data source |
azurerm_subscription.current | data source |
azurerm_virtual_network.custom | data source |
Name | Description | Type | Default | Required |
---|---|---|---|---|
avi_subnet | The CIDR that will be used for creating a subnet in the Avi VNET | string |
"10.255.0.0/24" |
no |
avi_upgrade | This variable determines if a patch upgrade is performed after install. The enabled key should be set to true and the url from the Avi Cloud Services portal for the should be set for the upgrade_file_uri key. Valid upgrade_type values are patch or system | object({ |
{ |
no |
avi_version | The major and minor version of the AVI Controller version that will be deployed. 20.1, 21.1, or 22.1 are valid values. | string |
"21.1" |
no |
ca_certificates | Import one or more Root or Intermediate Certificate Authority SSL certificates for the controller. The certificate must be in the PEM format and base64 encoded without line breaks. An example command for generating the proper format is 'base64 -w 0 ca.pem > ca.base64' | list(object({ |
[ |
no |
cluster_ip | Sets the IP address of the Avi Controller cluster. This address must be in the same subnet as the Avi Controller VMs. | string |
null |
no |
configure_controller | Configure the Avi Cloud via Ansible after controller deployment. If not set to true this must be done manually with the desired config | bool |
"true" |
no |
configure_dns_profile | Configure a DNS Profile for DNS Record Creation for Virtual Services. The usable_domains is a list of domains that Avi will be the Authoritative Nameserver for and NS records may need to be created pointing to the Avi Service Engine addresses. Supported profiles for the type parameter are AWS or AVI | object({ |
{ |
no |
configure_dns_vs | Create Avi DNS Virtual Service. The subnet_name parameter must be an existing AWS Subnet. If the allocate_public_ip parameter is set to true a EIP will be allocated for the VS. The VS IP address will automatically be allocated via the AWS IPAM | object({ |
{ |
no |
configure_gslb | Configures GSLB. In addition the configure_dns_vs variable must also be set for GSLB to be configured. See the GSLB Deployment README section for more information. | object({ |
{ |
no |
configure_vnet_peering | This variable is used to peer the created VNET with another VNET | object({ |
{ |
no |
controller_az_app_id | If the create_iam variable is set to false, this is the Azure Application ID that the Avi Controller will use to create Azure resources | string |
null |
no |
controller_az_client_secret | If the create_iam variable is set to false, this is the Azure Client Secret that the Avi Controller will use to create Azure resources | string |
null |
no |
controller_default_password | This is the default password for the AVI controller image and can be found in the image download page. | string |
n/a | yes |
controller_disk_size | The root disk size for the AVI controller | number |
128 |
no |
controller_disk_type | The Type of Storage Account which should back this the Internal OS Disk. Possible values are Premium_LRS, Standard_LRS, StandardSSD_LRS | string |
"Premium_LRS" |
no |
controller_ha | If true a HA controller cluster is deployed and configured | bool |
"false" |
no |
controller_password | The password that will be used authenticating with the AVI Controller. This password be a minimum of 8 characters and contain at least one each of uppercase, lowercase, numbers, and special characters | string |
n/a | yes |
controller_public_address | This variable controls if the Controller has a Public IP Address. When set to false the Ansible provisioner will connect to the private IP of the Controller. | bool |
"false" |
no |
controller_vm_size | The VM size for the AVI Controller | string |
"Standard_D8s_v3" |
no |
create_firewall_rules | This variable controls the Network Security Group (NSG) rule creation for the Avi Controllers. When set to false the necessary firewall rules must be in place before the deployment | bool |
"true" |
no |
create_iam | Create Azure AD Application and Service Principal, Controller Custom Role, and Application Role Binding for Avi Azure Full Access Cloud | bool |
"false" |
no |
create_marketplace_agreement | If set to true the user agrees to the terms and conditions for the Avi Marketplace image as found here https://azuremarketplace.microsoft.com/en-us/marketplace/apps/avi-networks.avi-vantage-adc. When multiple instances of this module are used only 1 should have this value set to true to prevent duplicate deployments | bool |
"true" |
no |
create_networking | This variable controls the VNET and subnet creation for the AVI Controller. When set to false the custom_controller_resource_group, custom_vnet_name and custom_subnet_name variables must be configured. | bool |
"true" |
no |
create_resource_group | If true a Resource Group is created and used for the AVI Controllers and Service Engines | bool |
"true" |
no |
custom_controller_resource_group | This field can be used to specify an existing Resource Group for AVI Controllers. The create_resource_group variable must also be set to false for this resource group to be used. | string |
"" |
no |
custom_se_resource_group | This field can be used to specify an existing Resource Group for Service Engines. | string |
null |
no |
custom_subnet_name | This field can be used to specify a list of existing VNET Subnet for the controller and SEs. The create_networking variable must also be set to false for this network to be used. | string |
"" |
no |
custom_tags | Custom tags added to Resources created by the module | map(string) |
{} |
no |
custom_vnet_name | This field can be used to specify an existing VNET for the controller and SEs. The create_networking variable must also be set to false for this network to be used. | string |
"" |
no |
dns_search_domain | The optional DNS search domain that will be used by the controller | string |
null |
no |
dns_servers | The optional DNS servers that will be used for local DNS resolution by the controller. The dns_search_domain variable must also be specified if this variable is set. Example ["8.8.4.4", "8.8.8.8"] | list(string) |
null |
no |
email_config | The Email settings that will be used for sending password reset information or for trigged alerts. The default setting will send emails directly from the Avi Controller | object({ |
{ |
no |
license_key | The license key that will be applied when the tier is set to ENTERPRISE with the license_tier variable | string |
"" |
no |
license_tier | The license tier to use for Avi. Possible values are ENTERPRISE_WITH_CLOUD_SERVICES or ENTERPRISE | string |
"ENTERPRISE_WITH_CLOUD_SERVICES" |
no |
name_prefix | This prefix is appended to the names of the Controller and SEs | string |
n/a | yes |
ntp_servers | The NTP Servers that the Avi Controllers will use. The server should be a valid IP address (v4 or v6) or a DNS name. Valid options for type are V4, DNS, or V6 | list(object({ |
[ |
no |
portal_certificate | Import a SSL certificate for the controller's web portal. The key and certificate must be in the PEM format and base64 encoded without line breaks. An example command for generating the proper format is 'base64 -w 0 certificate.pem > cert.base64' | object({ |
{ |
no |
region | The Region that the AVI controller and SEs will be deployed to | string |
n/a | yes |
register_controller | If enabled is set to true the controller will be registered and licensed with Avi Cloud Services. The Long Organization ID (organization_id) can be found from https://console.cloud.vmware.com/csp/gateway/portal/#/organization/info. The jwt_token can be retrieved at https://portal.avipulse.vmware.com/portal/controller/auth/cspctrllogin. Optionally the controller name and description used during the registration can be set; otherwise, the name_prefix and configure_gslb.site_name variables will be used. | object({ |
{ |
no |
se_ha_mode | The HA mode of the Service Engine Group. Possible values active/active, n+m, or active/standby | string |
"active/active" |
no |
se_vm_size | The VM size for the AVI Service Engines. This value can be changed in the Service Engine Group configuration after deployment. | string |
"Standard_F2s" |
no |
securechannel_certificate | Import a SSL certificate for the controller's secure channel communication. Only if there is strict policy that requires all SSL certificates to be signed a specific CA should this variable be used otherwise the default generated certificate is recommended. The full cert chain is necessary and can be provided within the certificate PEM file or separately with the ca_certificates variable. The key and certificate must be in the PEM format and base64 encoded without line breaks. An example command for generating the proper format is 'base64 -w 0 certificate.pem > cert.base64' | object({ |
{ |
no |
use_azure_dns | If true the AVI Cloud is configured to use Azure DNS | bool |
"false" |
no |
use_standard_alb | If true the AVI Cloud is configured to use standard SKU for the Azure LBs that route to Avi SEs | bool |
"false" |
no |
vnet_address_space | The CIDR that will be used for creating a VNET for Avi resources | string |
"10.255.0.0/16" |
no |
Name | Description |
---|---|
controller_private_addresses | The Private IP Addresses allocated for the Avi Controller(s) |
controller_resource_group | The Resource Group used for the Avi Controller |
controller_vnet | The VNET that the Avi Controller is deployed to |
controllers | The AVI Controller(s) Information |