I have written the below code for creating a virtual network in terraform azure:
I have files in the root folder for main.tf,variables.tf and terraform.tfvars. I have got two modules for resource group and virtual network.
In the root folder I have the below code:
main.tf
#Resource Group Creation
module "resource_group" {
source = "./modules/resource_group"
rgname_var = var.resource_group
loc_var = var.location
}
#Virtual Network Creation
module "vnet" {
source = "./modules/vnet"
loc = module.resource_group.loc_o
rgname = module.resource_group.rgname_o
address_space = var.vnet_address_space
terraform.tfvars:
vnet_name = "VirtualNetwork"
vnet_address_space = "<ip>"
subnet1_address_prefix="<ip1>"
subnet2_address_prefix="<ip2>"
subnet3_address_prefix="<ip3">
In the vnet module, I have the below code:
resource "azurerm_virtual_network" "vnet" {
name = var.vnet_name
location = var.loc
resource_group_name = var.rgname
address_space = var.vnet_address_space
}
#Subnet Creation
resource "azurerm_subnet" "subnet-1" {
name= var.subnet_name1
resource_group_name = var.rgname
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefix = var.subnet1_address_prefix
}
#Subnet Creation
resource "azurerm_subnet" "subnet-2" {
name= var.subnet_name2
resource_group_name = var.rgname
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefix = var.subnet2_address_prefix
}
#Subnet Creation
resource "azurerm_subnet" "subnet-3" {
name= var.subnet_name3
name= var.subnet_name1
resource_group_name = var.rgname
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefix = var.subnet3_address_prefix
}
I am getting the below error :
address_space = var.vnet_address_space |---------------- | var.vnet_address_space is ""
Inappropriate value for attribute "address_space": list of string required.*
I have tried giving one ip for virtual network address space at the first place,because it was working for single subnets. then the system was expecting list instead of string. Any idea how to set the values for virtual network?
Your current var.vnet_address_space is just a string:
vnet_address_space = "<ip>"
However address_space should be a list of strings, not a single string only.
The easiest way to change it to list of strings would be:
vnet_address_space = ["<ip>"]
Alternatively, you can do it as follows:
resource "azurerm_virtual_network" "vnet" {
name = var.vnet_name
location = var.loc
resource_group_name = var.rgname
address_space = [var.vnet_address_space]
}
Related
I have a virtual network with 2 subnets
Virtual network: vNetVPN-Dev
Subnet: snet-vgp-dev
Subnet: snet-internal-vm
resource "azurerm_virtual_network" "virtual_network" {
name = "vNetVPN-Dev"
location = var.resource_group_location_north_europe
resource_group_name = var.resource_group_name
address_space = ["10.1.16.0/23", "10.2.0.0/16", "172.16.100.0/24"]
subnet {
name = "snet-vgp-dev"
address_prefix = "10.2.1.0/24"
}
# =================== Virtual network for vm
subnet {
name = "snet-internal-vm"
address_prefix = "10.2.10.0/24"
}
tags = {
environment = var.tag_dev
}
}
and now I want to reference snet-internal-vm in this block of code (below)
resource "azurerm_network_interface" "nic" {
name = "internal-nic-vm"
location = var.resource_group_location_north_europe
resource_group_name = var.resource_group_name
ip_configuration {
name = "internal-vm"
subnet_id = **here_I_want_to_reference**
private_ip_address_allocation = "Dynamic"
}
}
I tried to reproduce the same in my environment to create NIC creation with Subnet reference:
Terraform Code
provider "azurerm" {
features {}
}
resource "azurerm_virtual_network" "virtual_network" {
name = "vNetVPN-Dev"
location = data.azurerm_resource_group.example.location
resource_group_name = data.azurerm_resource_group.example.name
address_space = ["10.1.16.0/23", "10.2.0.0/16", "172.16.100.0/24"]
subnet {
name = "snet-vgp-dev"
address_prefix = "10.2.1.0/24"
}
subnet {
name = "snet-internal-vm"
address_prefix = "10.2.10.0/24"
}
}
#-----NIC Creation-----------
resource "azurerm_network_interface" "nic" {
name = "internal-nic-vm"
location = data.azurerm_resource_group.example.location
resource_group_name = data.azurerm_resource_group.example.name
ip_configuration {
name = "internal-vm"
subnet_id = azurerm_virtual_network.virtual_network.subnet.*.id[1]
private_ip_address_allocation = "Dynamic"
}
}
Terraform Apply.
As mentioned by #sylvainmtz , I could get subnet referred successfully while creating NIC.
Based on your question, I can only assume you should be using data blocks to do this. https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/subnet
How we can call subnet into Virtual network gateway?
Subnet
resource "azurerm_virtual_network" "virtual_network" {
name = "vNetVPN-Dev"
location = var.resource_group_location_north_europe
resource_group_name = var.resource_group_name
address_space = ["10.1.16.0/23", "10.2.0.0/16", "172.16.100.0/24"]
subnet {
name = "snet-vpg-dev"
address_prefix = "10.2.1.0/24"
}
tags = {
environment = var.tag_dev
}
}
Virtual network gateway
resource "azurerm_virtual_network_gateway" "virtual_network_gateway" {
name = "vgw-vgp-dev"
location = var.resource_group_location_north_europe
resource_group_name = var.resource_group_name
type = "Vpn"
vpn_type = "RouteBased"
active_active = false
enable_bgp = false
sku = "Basic"
ip_configuration {
name = azurerm_public_ip.public_ip_address.name
public_ip_address_id = azurerm_public_ip.public_ip_address.id
private_ip_address_allocation = "Static"
subnet_id = **here I wan to call my subnet which is defined in the code above**
}
}
so as you can see that there are 2 code blocks, 1 is subnet and the other is virtual network gateway.
I want to refer subnet (snet-vpg-dev) into virtual network gateway as a value of parameter called subnet_id
To get the Id of the subnet, you can take the subnet exported attribute of the vnet, convert it to a list and take the first element, like this
ip_configuration {
name = azurerm_public_ip.public_ip_address.name
public_ip_address_id = azurerm_public_ip.public_ip_address.id
private_ip_address_allocation = "Static"
subnet_id = tolist(azurerm_virtual_network.virtual_network.subnet)[0].id
}
Another solution is to use the azurerm_subnet resource rather than the inline subnet blocks.
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet
You can directly retrieve the id of the subnet since it has a dedicated resource
The template would be something like
Subnet
resource "azurerm_virtual_network" "virtual_network" {
name = "vNetVPN-Dev"
location = var.resource_group_location_north_europe
resource_group_name = var.resource_group_name
address_space = ["10.1.16.0/23", "10.2.0.0/16", "172.16.100.0/24"]
tags = {
environment = var.tag_dev
}
}
resource "azurerm_subnet" "subnet" {
name = "vNetVPN-Dev"
resource_group_name = var.resource_group_name
virtual_network_name = azurerm_virtual_network.virtual_network.name
address_prefixes = ["10.2.1.0/24"]
}
Virtual network gateway
resource "azurerm_virtual_network_gateway" "virtual_network_gateway" {
name = "vgw-vgp-dev"
location = var.resource_group_location_north_europe
resource_group_name = var.resource_group_name
type = "Vpn"
vpn_type = "RouteBased"
active_active = false
enable_bgp = false
sku = "Basic"
ip_configuration {
name = azurerm_public_ip.public_ip_address.name
public_ip_address_id = azurerm_public_ip.public_ip_address.id
private_ip_address_allocation = "Static"
subnet_id = azurerm_subnet.subnet.id
}
}
Im quite new to Terraform so maybe i make a very basic mistake but after multiple hours maybe here someone can help me out.
So i tried to peer to vlans together. I viewed multiple tutorials about it and the only difference between my configuration i can see is that i want to make a peering between 2 vlans that are in 2 different resource groups. I also noticed that if i put the peering in one of the 2 vlan ressource groups i have fever errors.
error
#Creating Resource Groups
resource "azurerm_resource_group" "network" {
name = "network"
location = "West Europe"
}
resource "azurerm_resource_group" "front" {
name = "front"
location = "West Europe"
}
resource "azurerm_resource_group" "middle" {
name = "middle"
location = "West Europe"
}
resource "azurerm_resource_group" "back" {
name = "back"
location = "West Europe"
}
resource "azurerm_resource_group" "peerings" {
name = "peerings"
location = "West Europe"
}
#Creating Virtual Networks
resource "azurerm_virtual_network" "network" {
name = "network"
location = azurerm_resource_group.network.location
resource_group_name = azurerm_resource_group.network.name
address_space = ["10.1.0.0/16"]
subnet {
name = "default"
address_prefix = "10.1.0.0/24"
}
subnet {
name = "gatewaysubnet"
address_prefix = "10.1.1.0/24"
}
subnet {
name = "azurefirewallsubnet"
address_prefix = "10.1.3.0/24"
}
subnet {
name = "azurebastionsubnet"
address_prefix = "10.1.2.0/24"
}
}
resource "azurerm_virtual_network" "front" {
name = "network"
location = azurerm_resource_group.front.location
resource_group_name = azurerm_resource_group.front.name
address_space = ["10.2.0.0/16"]
}
resource "azurerm_virtual_network" "middle" {
name = "network"
location = azurerm_resource_group.middle.location
resource_group_name = azurerm_resource_group.middle.name
address_space = ["10.3.0.0/16"]
}
resource "azurerm_virtual_network" "back" {
name = "network"
location = azurerm_resource_group.back.location
resource_group_name = azurerm_resource_group.back.name
address_space = ["10.4.0.0/16"]
}
#Create peerings
#network <--> front
resource "azurerm_virtual_network_peering" "networktofront" {
name = "networktofront"
resource_group_name = azurerm_resource_group.peerings.name
virtual_network_name = azurerm_virtual_network.network.name
remote_virtual_network_id = azurerm_virtual_network.front.id
}
resource "azurerm_virtual_network_peering" "fronttonetwork" {
name = "fronttonetwork"
resource_group_name = azurerm_resource_group.peerings.name
virtual_network_name = azurerm_virtual_network.front.name
remote_virtual_network_id = azurerm_virtual_network.network.id
}
#network <--> middle
resource "azurerm_virtual_network_peering" "networktomiddle" {
name = "networktomiddle"
resource_group_name = azurerm_resource_group.peerings.name
virtual_network_name = azurerm_virtual_network.network.name
remote_virtual_network_id = azurerm_virtual_network.middle.id
}
resource "azurerm_virtual_network_peering" "middletonetwork" {
name = "middletonetwork"
resource_group_name = azurerm_resource_group.peerings.name
virtual_network_name = azurerm_virtual_network.middle.name
remote_virtual_network_id = azurerm_virtual_network.network.id
}
#network <--> back
resource "azurerm_virtual_network_peering" "networktoback" {
name = "networktoback"
resource_group_name = azurerm_resource_group.peerings.name
virtual_network_name = azurerm_virtual_network.network.name
remote_virtual_network_id = azurerm_virtual_network.back.id
}
resource "azurerm_virtual_network_peering" "backtonetwork" {
name = "backtonetwork"
resource_group_name = azurerm_resource_group.peerings.name
virtual_network_name = azurerm_virtual_network.back.name
remote_virtual_network_id = azurerm_virtual_network.network.id
}
Virtual Network Peerings are a subset of the Virtual Network Resource (Microsoft.Network/virtualNetworks/network/virtualNetworkPeerings) and it is therefore not possible to carve these out into different resource groups.
Besides that, your code is accurate and should work as soon as you create the peerings in the corresponding virtual network resource groups:
#Creating Resource Groups
resource "azurerm_resource_group" "network" {
name = "network"
location = "West Europe"
}
resource "azurerm_resource_group" "front" {
name = "front"
location = "West Europe"
}
resource "azurerm_resource_group" "middle" {
name = "middle"
location = "West Europe"
}
resource "azurerm_resource_group" "back" {
name = "back"
location = "West Europe"
}
#Creating Virtual Networks
resource "azurerm_virtual_network" "network" {
name = "network"
location = azurerm_resource_group.network.location
resource_group_name = azurerm_resource_group.network.name
address_space = ["10.1.0.0/16"]
subnet {
name = "default"
address_prefix = "10.1.0.0/24"
}
subnet {
name = "gatewaysubnet"
address_prefix = "10.1.1.0/24"
}
subnet {
name = "azurefirewallsubnet"
address_prefix = "10.1.3.0/24"
}
subnet {
name = "azurebastionsubnet"
address_prefix = "10.1.2.0/24"
}
}
resource "azurerm_virtual_network" "front" {
name = "network"
location = azurerm_resource_group.front.location
resource_group_name = azurerm_resource_group.front.name
address_space = ["10.2.0.0/16"]
}
resource "azurerm_virtual_network" "middle" {
name = "network"
location = azurerm_resource_group.middle.location
resource_group_name = azurerm_resource_group.middle.name
address_space = ["10.3.0.0/16"]
}
resource "azurerm_virtual_network" "back" {
name = "network"
location = azurerm_resource_group.back.location
resource_group_name = azurerm_resource_group.back.name
address_space = ["10.4.0.0/16"]
}
#Create peerings
#network <--> front
resource "azurerm_virtual_network_peering" "networktofront" {
name = "networktofront"
resource_group_name = azurerm_resource_group.network.name
virtual_network_name = azurerm_virtual_network.network.name
remote_virtual_network_id = azurerm_virtual_network.front.id
}
resource "azurerm_virtual_network_peering" "fronttonetwork" {
name = "fronttonetwork"
resource_group_name = azurerm_resource_group.front.name
virtual_network_name = azurerm_virtual_network.front.name
remote_virtual_network_id = azurerm_virtual_network.network.id
}
#network <--> middle
resource "azurerm_virtual_network_peering" "networktomiddle" {
name = "networktomiddle"
resource_group_name = azurerm_resource_group.network.name
virtual_network_name = azurerm_virtual_network.network.name
remote_virtual_network_id = azurerm_virtual_network.middle.id
}
resource "azurerm_virtual_network_peering" "middletonetwork" {
name = "middletonetwork"
resource_group_name = azurerm_resource_group.middle.name
virtual_network_name = azurerm_virtual_network.middle.name
remote_virtual_network_id = azurerm_virtual_network.network.id
}
#network <--> back
resource "azurerm_virtual_network_peering" "networktoback" {
name = "networktoback"
resource_group_name = azurerm_resource_group.network.name
virtual_network_name = azurerm_virtual_network.network.name
remote_virtual_network_id = azurerm_virtual_network.back.id
}
resource "azurerm_virtual_network_peering" "backtonetwork" {
name = "backtonetwork"
resource_group_name = azurerm_resource_group.back.name
virtual_network_name = azurerm_virtual_network.back.name
remote_virtual_network_id = azurerm_virtual_network.network.id
}
I have a terraform script for creating a virtual network and subnets in azure. The code inherits a module which has the both creation of vnet and subnet. I am trying to create a VNET and two subnet, but want to enable service end point for a specific subnet only. Need help on how to do it
module "vnet" {
source = "./modules/VirtualNetwork"
VirtualNetwork_Name = "${var.prefix}-${var.resource_group_name}-VNET1"
Resource_Group_Name = azurerm_resource_group.resource_group.name
Location = azurerm_resource_group.resource_group.location
VirtualNetwork_AddressSpace = ["10.4.0.0/23"]
Subnet_Name = ["snet-1","snet-2"]
Subnet_Addresses = ["10.4.0.0/24","10.4.1.0/24"]
Service_Endpoints = vnet.Subnet_Name == "snet-1" ? ["Microsoft.AzureCosmosDB"] : [""]
if subnet=="snet-1" then ["Microsoft.AzureCosmosDB"] else ["nothing"]
Tags = {
environment = "prod"
resource = "VNET"
cost_center = "Test Cost Ceneter"
}
}
The below code is for network module
# Creates the virtual network for the resources
resource "azurerm_virtual_network" "vnet" {
name = var.VirtualNetwork_Name
location = var.Location
resource_group_name = var.Resource_Group_Name
address_space = var.VirtualNetwork_AddressSpace
tags = var.Tags
}
# Create two subnet for the vnet
resource "azurerm_subnet" "subnet" {
name = var.Subnet_Name[count.index]
address_prefix = var.Subnet_Addresses[count.index]
resource_group_name = var.Resource_Group_Name
virtual_network_name = azurerm_virtual_network.vnet.name
count = length(var.Subnet_Name)
# service_endpoints = ["Microsoft.AzureCosmosDB"]
service_endpoints = var.Service_Endpoints
}
According to your requirement, you just want to enable a service endpoint for a specific subnet only. You can set the conditional-expressions in the azurerm_subnet block.
You could change the code like this and I have validated it on my side.
main.if in the root directory.
variable "subnet_name" {
default = ["subnet1","subnet2"]
}
# retrieve a specific subnet via the index of subnet list.
locals {
subnet_name_enable_service_endpoint = element(var.subnet_name,0)
}
...
module "vnet" {
source = "./modules/VirtualNetwork"
VirtualNetwork_Name = "${var.prefix}-${var.resource_group_name}-VNET1"
Resource_Group_Name = azurerm_resource_group.main.name
Location = azurerm_resource_group.main.location
VirtualNetwork_AddressSpace = ["10.4.0.0/23"]
Subnet_Addresses = ["10.4.0.0/24","10.4.1.0/24"]
Subnet_Name = var.subnet_name
specfic_subnet_name = local.subnet_name_enable_service_endpoint
Service_Endpoints = ["Microsoft.AzureCosmosDB"]
Tags = {
environment = "prod"
resource = "VNET"
cost_center = "Test Cost Ceneter"
}
}
Network module configuration is in the path ./modules/VirtualNetwork.
# declare a variable for accepting the specific subnet.
variable "specfic_subnet_name" {
}
...
#Create Virtual Network in Primary Resource Group
resource "azurerm_virtual_network" "primary" {
name = var.VirtualNetwork_Name
resource_group_name = var.Resource_Group_Name
address_space = var.VirtualNetwork_AddressSpace
location = var.Location
tags = var.Tags
}
#Create Subnet in Virtual Network
resource "azurerm_subnet" "primary" {
count = length(var.Subnet_Name)
name = var.Subnet_Name[count.index]
resource_group_name = var.Resource_Group_Name
virtual_network_name = azurerm_virtual_network.primary.name
address_prefixes = [element(var.Subnet_Addresses,count.index)]
service_endpoints = element(var.Subnet_Name,count.index) == var.specfic_subnet_name ? var.Service_Endpoints : [""]
}
./modules/VirtualNetwork only the subnet creation part
# Create two subnet for the vnet
resource "azurerm_subnet" "subnet" {
name = var.Subnet_Name[count.index]
address_prefix = var.Subnet_Addresses[count.index]
resource_group_name = var.Resource_Group_Name
virtual_network_name = azurerm_virtual_network.vnet.name
count = length(var.Subnet_Name)
service_endpoints = element(var.Service_Endpoints,count.index)
}
main.tf
module "vnet" {
source = "./modules/VirtualNetwork"
VirtualNetwork_Name = "${var.prefix}-${var.resource_group_name}-VNET1"
Resource_Group_Name = azurerm_resource_group.resource_group.name
Location = azurerm_resource_group.resource_group.location
VirtualNetwork_AddressSpace = ["10.4.0.0/23"]
Subnet_Name = ["snet-1","snet-2"]
Subnet_Addresses = ["10.4.0.0/24","10.4.1.0/24"]
Service_Endpoints = [["Microsoft.AzureCosmosDB",""], [""]]
}
The key is to pass the service end point as a list Service_Endpoints = [["Microsoft.AzureCosmosDB",""], [""]]. Based on the index of the subnet it will assign the service end point
I want to create two vm's with terraform in Azure. I have configured two "azurerm_network_interface" but when I try to apply the changes, I receive an error. Do you have any idea? Is there any issue if I try to create them on different regions?
The error is something like: vm2-nic was not found azurerm_network_interface
# Configure the Azure Provider
provider "azurerm" {
subscription_id = var.subscription_id
tenant_id = var.tenant_id
version = "=2.10.0"
features {}
}
resource "azurerm_virtual_network" "main" {
name = "north-network"
address_space = ["10.0.0.0/16"]
location = "North Europe"
resource_group_name = var.azurerm_resource_group_name
}
resource "azurerm_subnet" "internal" {
name = "internal"
resource_group_name = var.azurerm_resource_group_name
virtual_network_name = azurerm_virtual_network.main.name
address_prefix = "10.0.2.0/24"
}
resource "azurerm_public_ip" "example" {
name = "test-pip"
location = "North Europe"
resource_group_name = var.azurerm_resource_group_name
allocation_method = "Static"
idle_timeout_in_minutes = 30
tags = {
environment = "dev01"
}
}
resource "azurerm_network_interface" "main" {
for_each = var.locations
name = "${each.key}-nic"
location = "${each.value}"
resource_group_name = var.azurerm_resource_group_name
ip_configuration {
name = "testconfiguration1"
subnet_id = azurerm_subnet.internal.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.example.id
}
}
resource "azurerm_virtual_machine" "main" {
for_each = var.locations
name = "${each.key}t-vm"
location = "${each.value}"
resource_group_name = var.azurerm_resource_group_name
network_interface_ids = [azurerm_network_interface.main[each.key].id]
vm_size = "Standard_D2s_v3"
...
Error:
Error: Error creating Network Interface "vm2-nic" (Resource Group "candidate-d7f5a2-rg"): network.InterfacesClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="InvalidResourceReference" Message="Resource /subscriptions/xxxxxxx/resourceGroups/xxxx/providers/Microsoft.Network/virtualNetworks/north-network/subnets/internal referenced by resource /subscriptions/xxxxx/resourceGroups/xxxxx/providers/Microsoft.Network/networkInterfaces/vm2-nic was not found. Please make sure that the referenced resource exists, and that both resources are in the same region." Details=[]
on environment.tf line 47, in resource "azurerm_network_interface" "main":
47: resource "azurerm_network_interface" "main" {
According to the documentation each NIC attached to a VM must exist in the same location (Region) and subscription as the VM. https://learn.microsoft.com/en-us/azure/virtual-machines/windows/network-overview.
If you can re-create the NIC in the same location as the VM or create the VM in the same location as the NIC that will likely solve your problem.
Since you have for_each and in the resource "azurerm_network_interface", it will create two NICs in the location = "${each.value}" while the subnet or VNet has a fixed region "North Europe". You need to create the NICs or other Azure VM related resources like subnets in the same region, you could change the codes like this,
resource "azurerm_resource_group" "test" {
name = "myrg"
location = "West US"
}
variable "locations" {
type = map(string)
default = {
vm1 = "North Europe"
vm2 = "West Europe"
}
}
resource "azurerm_virtual_network" "main" {
for_each = var.locations
name = "${each.key}-network"
address_space = ["10.0.0.0/16"]
location = "${each.value}"
resource_group_name = azurerm_resource_group.test.name
}
resource "azurerm_subnet" "internal" {
for_each = var.locations
name = "${each.key}-subnet"
resource_group_name = azurerm_resource_group.test.name
virtual_network_name = azurerm_virtual_network.main[each.key].name
address_prefix = "10.0.2.0/24"
}
resource "azurerm_public_ip" "example" {
for_each = var.locations
name = "${each.key}-pip"
location = "${each.value}"
resource_group_name = azurerm_resource_group.test.name
allocation_method = "Static"
idle_timeout_in_minutes = 30
}
resource "azurerm_network_interface" "main" {
for_each = var.locations
name = "${each.key}-nic"
location = "${each.value}"
resource_group_name = azurerm_resource_group.test.name
ip_configuration {
name = "testconfiguration1"
subnet_id = azurerm_subnet.internal[each.key].id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.example[each.key].id
}
}