published

Terraform ACI L3Out Module

Manages ACI L3Out
Location in GUI:
Tenants/Networking/L3Outs

Examples

Minimal L3Out config

module "aci_l3out" {
  source  = "qzx/l3out/aci"
  version = "1.0.0"

  name        = "example-l3out"
  tenant_name = "example"
  vrf         = "example"
  l3_domain   = "example-l3out-domain"

  paths = {
    primary = {
      name                = "eth1/2"
      pod_id              = 1
      nodes               = [101]
      is_vpc              = false
      vlan_id             = 301
      mtu                 = 1500
      interconnect_subnet = "172.16.0.0/30"
    }
  }

  static_routes = ["0.0.0.0/0"]
}

L3Out over dual VPC in two pods with OSPF

module "aci_vpc_l3out" {
  source  = "qzx/l3out/aci"
  version = "1.0.0"

  name        = "example-l3out"
  tenant_name = "example"
  vrf         = "example"
  l3_domain   = "example-l3out-domain"

  paths = {
    primary = {
      name                = "EXAMPLE-VPC"
      pod_id              = 1
      nodes               = [101, 102]
      is_vpc              = true
      vlan_id             = 301
      mtu                 = 1500
      interconnect_subnet = "172.16.0.1/29"
    },
    secondary = {
      name                = "EXAMPLE-VPC"
      pod_id              = 2
      nodes               = [103, 104]
      is_vpc              = true
      vlan_id             = 301
      mtu                 = 1500
      interconnect_subnet = "172.16.0.1/29"
    }
  }

  ospf_enable = false

  ospf_timers = {
    hello_interval      = 5
    dead_interval       = 25
    retransmit_interval = 3
    transmit_delay      = 1
    priority            = 1
  }

  ospf_area = {
    id   = 1
    type = "nssa"
    cost = 1
  }
}

Dual L3Out with BGP

module "aci_ha_mpls_l3out" {
  source  = "qzx/l3out/aci"
  version = "1.0.0"

  name        = "example-l3out"
  tenant_name = "example"
  vrf         = "example"
  l3_domain   = "MPLS-Provider-L3-Domain"


  router_id_as_loopback = true

  paths = {
    primary = {
      name                = "eth1/22"
      pod_id              = 1
      nodes               = [101]
      is_vpc              = false
      vlan_id             = 301
      mtu                 = 1500
      interconnect_subnet = "172.16.1.0/29"
    },
    secondary = {
      name                = "eth1/22"
      pod_id              = 1
      nodes               = [102]
      is_vpc              = false
      vlan_id             = 301
      mtu                 = 1500
      interconnect_subnet = "172.16.1.4/29"
    }
  }

  external_epgs = {
    FW-Subnets = {
      subnets = ["0.0.0.0/0"]
      scope   = ["import-security"]
    }
    Servers = {
      subnets = ["10.0.0.0/8", "192.168.0.0/16", "172.16.0.0/12"]
      scope   = ["shared-rtctrl", "shared-security", "import-security"]
    }
  }

  bgp_peers = {
    primary = {
      address   = "172.16.1.1"
      local_as  = 10
      remote_as = 200
      password  = "provider-password-1"
    },
    secondary = {
      address   = "172.16.1.5"
      local_as  = 10
      remote_as = 300
      password  = "provider-password-2"
    }
  }
}

Requirements

Name Version
terraform ~> 1.2.9
aci ~> 2.5.2

Providers

Name Version
aci ~> 2.5.2

Inputs

Name Description Type Default Required
name Name of our new L3Out string n/a yes
tenant_name The tenant we want to deploy our L3Out into string n/a yes
vrf The associated VRF we are deploying into string n/a yes
vrf_id The ID of the VRF being used, this is required for the router ID generation if the module is already managing an L3Out in the same tenant but different VRF number 1 no
l3_domain The Layer3 domain this L3Out belongs to string n/a yes
router_id_as_loopback Set to true if router IDs should be installed as loopback addresses to respective switches bool false no
paths The interface path to which we will deploy the L3Out
map(object({
name = string,
pod_id = number,
nodes = list(number),
is_vpc = bool,
vlan_id = number,
mtu = number,
interconnect_subnet = string,
}))
n/a yes
pathsv6 The interface path to which we will deploy the L3Out IPv6 Address
map(object({
name = string,
pod_id = number,
nodes = list(number),
is_vpc = bool,
vlan_id = number,
mtu = number,
interconnect_subnet = string,
}))
{} no
external_epgs Map of external EPGs to create as network objects
map(object({
subnets = list(string),
scope = list(string),
}))
{
"default": {
"scope": [
"import-security"
],
"subnets": [
"0.0.0.0/0"
]
}
}
no
static_routes List of subnets in CIDR notation to be statically routed to the first IP address of the interconnect subnet list(string) [] no
ospf_enable Enable OSPF, timers and area settings can be over written with ospf_area and ospf_timers bool false no
ospf_area OSPF Area settings
object({
id = string,
type = string,
cost = number,
})
{
"cost": 1,
"id": "backbone",
"type": "regular"
}
no
ospf_timers Optional ospf timing configuration to pass on, sensible defaults are provided
object({
hello_interval = number,
dead_interval = number,
retransmit_interval = number,
transmit_delay = number,
priority = number,
})
{
"dead_interval": 40,
"hello_interval": 10,
"priority": 1,
"retransmit_interval": 5,
"transmit_delay": 1
}
no
ospf_auth OSPF authentication settings if ospf is enabled, key_id can range from 1-255 and key_type can be: md5, simple or none
object({
key = string,
key_id = number,
type = string,
})
{
"key": "",
"key_id": 1,
"type": "none"
}
no
bgp_peers BGP Neighbour configuration, having a neighbour causes BGP to be enabled, nodes must have loopbacks (enable router_id_as_loopback)
map(object({
address = string,
local_as = number,
remote_as = number,
password = string,
}))
{} no
intf_bgp_peers BGP Neighbour configuration for interface bound profiles. no loopback required
map(object({
address = string,
local_as = number,
remote_as = number,
password = string,
}))
{} no
inbound_filter If enabled the module will create inbound filter lists based on the subnets in the EPGs provided and enforce inbound filtering bool false no

Outputs

Name Description
l3out_epgs List of external EPGs created

Resources

Name Type
aci_bgp_peer_connectivity_profile.intf_this resource
aci_bgp_peer_connectivity_profile.this resource
aci_external_network_instance_profile.this resource
aci_l3_ext_subnet.this resource
aci_l3_outside.this resource
aci_l3out_bgp_external_policy.this resource
aci_l3out_ospf_external_policy.this resource
aci_l3out_ospf_interface_profile.this resource
aci_l3out_path_attachment.this resource
aci_l3out_path_attachment.thisv6 resource
aci_l3out_path_attachment_secondary_ip.this resource
aci_l3out_path_attachment_secondary_ip.thisv6 resource
aci_l3out_static_route.this resource
aci_l3out_static_route_next_hop.this resource
aci_l3out_vpc_member.this resource
aci_l3out_vpc_member.thisv6 resource
aci_logical_interface_profile.this resource
aci_logical_interface_profile.thisv6 resource
aci_logical_node_profile.this resource
aci_logical_node_to_fabric_node.this resource
aci_ospf_interface_policy.this resource
View code on GitHub

Code Exchange Community

Get help, share code, and collaborate with other developers in the Code Exchange community.View Community
Disclaimer:
Cisco provides Code Exchange for convenience and informational purposes only, with no support of any kind. This page contains information and links from third-party websites that are governed by their own separate terms. Reference to a project or contributor on this page does not imply any affiliation with or endorsement by Cisco.