Due to the limitations of time in this lab, we have constructed a repository that contains a terraform module that will deploy a VXLAN/EVPN network. This module is designed to show what is possible with Terraform and how it can be used to deploy complex network topologies.
Terraform modules are reusable components that encapsulate a set of resources and their configurations. They allow you to define infrastructure in a modular way, making it easier to manage and reuse code across different projects or environments. Modules can be used to create complex infrastructure setups, such as networks, virtual machines, databases by grouping related resources together.
The overall structure of Terraform is at the root is a project. The project contains a set of modules and data files.
The first step is to clone the repository that contains the Terraform module. This repository is hosted on GitHub and can be cloned using the following command:
cd /home/pod14/workspace/nxapilab
mkdir -p terraform-nxos
cd terraform-nxos
The first step is to clone the repository that contains the Terraform module. This repository is hosted on GitHub and can be cloned using the following command:
git clone https://github.com/rafmuller/ltrdcn-3903-terra.git
This will create a directory called ltrdcn-3903-terra
in your home directory. The repository contains
two separate directories, one that is the module and the second a preset configuration files in YAML.
ls -l ltrdcn-3903-terra/
(nxapilab) pod14 ~/workspace/nxapilab/terraform-nxos $: ls -l ltrdcn-3903-terra/ total 20 drwxr-xr-x 3 pod01 pod01 4096 Jun 5 15:57 data -rw-r--r-- 1 pod01 pod01 1070 Jun 5 15:57 LICENSE -rw-r--r-- 1 pod01 pod01 1261 Jun 5 15:57 main.tf -rw-r--r-- 1 pod01 pod01 2058 Jun 5 15:57 README.md drwxr-xr-x 2 pod01 pod01 4096 Jun 5 15:57 vxlan
We have left out from the module some code for you to complete. Inside of the module you are going to complete the ports resource. In this case we will be adding two componenents. Data that we need to build for the resources and then the resources themselves.
There is an empty file called nxos_interfaces_ports.tf
inside of the module directory vxlan
.
First you need to open this file in the code editor.
code-server -r /home/pod14/workspace/nxapilab/terraform-nxos/ltrdcn-3903-terra/vxlan/nxos_interfaces_ports.tf
The first step is to add the Layer2 Access Ports inside of the locals
block. This
code is a variable definition created by an iteration over various points of the configuration
built inside of the data
directory.
# .______ ______ .______ .___________. _______.
# | _ \ / __ \ | _ \ | | / |
# | |_) | | | | | | |_) | `---| |----` | (----`
# | ___/ | | | | | / | | \ \
# | | | `--' | | |\ \----. | | .----) |
# | _| \______/ | _| `._____| |__| |_______/
#
# These reources are used to create the phyiscal interface ports that connect to the
# switches.
locals{
l2_access_ports = flatten([
for device in try(local.devices, []) : [
for interface in try(device.interfaces, []) : {
key = format("%s-%s", device.name, interface.id)
device = device.name
id = interface.id
description = try(interface.description, "Configured by Terraform")
mtu = try(interface.mtu, 9216)
speed = try(interface.speed, "auto")
admin_state = try(interface.admin_state, "up")
layer = "Layer2"
l2_mode = "access"
vlan = interface.vlans
} if interface.link_type == "service-l2" && try(interface.l2_mode, null) == "access"
]
])
}
The first step is to add the Layer2 Access Ports inside of the locals
block. This
code is a variable definition created by an iteration over various points of the configuration
built inside of the data
directory.
# .______ ______ .______ .___________. _______.
# | _ \ / __ \ | _ \ | | / |
# | |_) | | | | | | |_) | `---| |----` | (----`
# | ___/ | | | | | / | | \ \
# | | | `--' | | |\ \----. | | .----) |
# | _| \______/ | _| `._____| |__| |_______/
#
# These reources are used to create the phyiscal interface ports that connect to the
# switches.
locals{
l2_access_ports = flatten([
for device in try(local.devices, []) : [
for interface in try(device.interfaces, []) : {
key = format("%s-%s", device.name, interface.id)
device = device.name
id = interface.id
description = try(interface.description, "Configured by Terraform")
mtu = try(interface.mtu, 9216)
speed = try(interface.speed, "auto")
admin_state = try(interface.admin_state, "up")
layer = "Layer2"
l2_mode = "access"
vlan = interface.vlans
} if interface.link_type == "service-l2" && try(interface.l2_mode, null) == "access"
]
])
l2_trunk_ports = flatten([
for device in try(local.devices, []) : [
for interface in try(device.interfaces, []) : {
key = format("%s-%s", device.name, interface.id)
device = device.name
id = interface.id
description = try(interface.description, "Configured by Terraform")
mtu = try(interface.mtu, 9216)
admin_state = try(interface.admin_state, "up")
speed = try(interface.speed, "auto")
layer = "Layer2"
l2_mode = "trunk"
trunk_vlans = interface.vlans
} if interface.link_type == "service-l2" && try(interface.l2_mode, null) == "trunk"
]
])
}
You may be asking why we have two different variables for the Layer2 ports. The reason is that we will be using two separate resources. For the Terraform NXOS provider to configure the access ports and trunk ports require different resources.
Instead of building logic in the resources to pick through the different types, we just build the data structure required for each port indedpendently. This also allows easier parameter control since access ports have less values than trunk ports.
The next step is to add the resources that will create the Layer2 Access and Trunk ports.
These resources will use the data defined in the locals
block.
resource "nxos_physical_interface" "vxlan_access_port_service_interface" {
for_each = { for interface in try(local.l2_access_ports, []) : interface.key => interface }
device = each.value.device
interface_id = each.value.id
description = each.value.description
mode = "access"
mtu = each.value.mtu
access_vlan = "vlan-${each.value.vlan}"
admin_state = each.value.admin_state
speed = each.value.speed
layer = "Layer2"
}
resource "nxos_physical_interface" "vxlan_trunk_port_service_interface" {
for_each = { for interface in try(local.l2_trunk_ports, []) : interface.key => interface }
device = each.value.device
interface_id = each.value.id
description = each.value.description
mode = "trunk"
mtu = each.value.mtu
admin_state = each.value.admin_state
speed = each.value.speed
layer = "Layer2"
trunk_vlans = each.value.trunk_vlans
depends_on = [nxos_feature_lacp.lacp]
}