Skip to content

Terraform で ACI 上に Route Leak 設定を含む Tenant を作成する

Terraform を使って Cisco ACI に「Route Leak 構成の Tenant を作成する」サンプルをメモしておきます。

構成

Terraform で以下の構成を設定します。

file

Terraform の設定ファイル

Terraform の設定ファイルは以下の通りです。

  1. variables.tf
  2. main.tf
  3. aci.tf

variables.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
variable "aci_url" { default = "https://10.0.0.1" }
variable "aci_username" { default = "admin" }
variable "aci_password" { default = "password" }
variable "tenant" { default = "Tenant1" }
variable "vrf1" { default = "1_VRF" }
variable "vrf2" { default = "2_VRF" }
variable "contract1" { default = "CT" }

variable "bd1" { default = "VL101_BD" }
variable "bd1_subnet" { default = "10.0.101.254/24" }
variable "bd2" { default = "VL102_BD" }
variable "bd2_subnet" { default = "10.0.102.254/24" }

variable "ap1" { default = "AP" }
variable "physdom" { default = "PhysDom" }
variable "epg1" { default = "VL101_EPG" }
variable "egp1_port1_tdn" { default = "topology/pod-1/paths-201/pathep-[eth1/1]" }
variable "egp1_port1_vlan" { default = "vlan-101" }
variable "epg1_contract1_type" { default = "consumer" }
variable "epg2" { default = "VL102_EPG" }
variable "egp2_port1_tdn" { default = "topology/pod-1/paths-201/pathep-[eth1/2]" }
variable "egp2_port1_vlan" { default = "vlan-102" }
variable "epg2_contract1_type" { default = "provider" }

main.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
terraform {
  required_providers {
    aci = {
      source  = "CiscoDevNet/aci"
      version = "0.5.4"
    }
  }
}

provider "aci" {
  username = var.aci_username
  password = var.aci_password
  url      = var.aci_url
  insecure = true
}

aci.tf

Route Leak 設定を行うには Application EPG に Subnet を設定しますが、現時点の Terraform には Application EPG Subnet を定義する Resource が有りません。 その為、Application EPG Subnet は aci_rest を使って設定します。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# Tenant
resource "aci_tenant" "tenant" {
  name = var.tenant
}

# VRF
resource "aci_vrf" "vrf1" {
  tenant_dn = aci_tenant.tenant.id
  name      = var.vrf1
}

resource "aci_vrf" "vrf2" {
  tenant_dn = aci_tenant.tenant.id
  name      = var.vrf2
}

# Contract / Subject / Filter
resource "aci_filter" "any" {
    tenant_dn = aci_tenant.tenant.id
    name      = "any_Filt"
}

resource "aci_filter_entry" "entry1" {
    name        = "0010"
    filter_dn   = aci_filter.any.id
    ether_t     = "unspecified"
}

resource "aci_contract" "contract1" {
    tenant_dn = aci_tenant.tenant.id
    name      = var.contract1
  scope     = "tenant"
}

resource "aci_contract_subject" "subject1" {
    contract_dn                  = aci_contract.contract1.id
    name                         = "${var.contract1}_Subj"
    relation_vz_rs_subj_filt_att = [aci_filter.any.id]
}

# BD1
resource "aci_bridge_domain" "bd1" {
  tenant_dn                = aci_tenant.tenant.id
  name                     = var.bd1
  relation_fv_rs_ctx       = aci_vrf.vrf1.id
}

resource "aci_subnet" "bd1_subnet" {
  parent_dn = aci_bridge_domain.bd1.id
  ip        = var.bd1_subnet
  scope     = ["private", "shared"]
}

# BD2
resource "aci_bridge_domain" "bd2" {
  tenant_dn                = aci_tenant.tenant.id
  name                     = var.bd2
  relation_fv_rs_ctx       = aci_vrf.vrf2.id
}

resource "aci_subnet" "bd2_subnet" {
  parent_dn = aci_bridge_domain.bd2.id
  ip        = var.bd2_subnet
  scope     = ["private", "shared"]
}

# Application Profile
resource "aci_application_profile" "ap1" {
  tenant_dn = aci_tenant.tenant.id
  name      = var.ap1
}

# Domain
data "aci_physical_domain" "physdom" {
  name = var.physdom
}

# EPG1
resource "aci_application_epg" "epg1" {
  application_profile_dn = aci_application_profile.ap1.id
  name                   = var.epg1
  relation_fv_rs_bd      = aci_bridge_domain.bd1.id
}

resource "aci_epg_to_domain" "epg1_physdom" {
  application_epg_dn = aci_application_epg.epg1.id
  tdn                = data.aci_physical_domain.physdom.id
}

resource "aci_epg_to_static_path" "egp1_port1" {
  application_epg_dn = aci_application_epg.epg1.id
  tdn                = var.egp1_port1_tdn
  encap              = var.egp1_port1_vlan
}

resource "aci_rest" "epg1_subnet" {
  path       = "/api/mo/uni/tn-${var.tenant}/ap-${var.ap1}/epg-${var.epg1}/subnet-[${var.bd1_subnet}].json"
  class_name = "fvSubnet"
  content = {
    ctrl  = "no-default-gateway"
    ip    = var.bd1_subnet
    scope = "private,shared"
  }
  depends_on = [
    aci_subnet.bd1_subnet,
    aci_application_epg.epg1
  ]
}

resource "aci_epg_to_contract" "epg1_contract1" {
    application_epg_dn = aci_application_epg.epg1.id
    contract_dn        = aci_contract.contract1.id
    contract_type      = var.epg1_contract1_type
}

# EPG2
resource "aci_application_epg" "epg2" {
  application_profile_dn = aci_application_profile.ap1.id
  name                   = var.epg2
  relation_fv_rs_bd      = aci_bridge_domain.bd2.id
}

resource "aci_epg_to_domain" "epg2_physdom" {
  application_epg_dn = aci_application_epg.epg2.id
  tdn                = data.aci_physical_domain.physdom.id
}

resource "aci_epg_to_static_path" "egp2_port1" {
  application_epg_dn = aci_application_epg.epg2.id
  tdn                = var.egp2_port1_tdn
  encap              = var.egp2_port1_vlan
}

resource "aci_rest" "epg2_subnet" {
  path       = "/api/mo/uni/tn-${var.tenant}/ap-${var.ap1}/epg-${var.epg2}/subnet-[${var.bd2_subnet}].json"
  class_name = "fvSubnet"
  content = {
    ctrl  = "no-default-gateway"
    ip    = var.bd2_subnet
    scope = "private,shared"
  }
  depends_on = [
    aci_subnet.bd2_subnet,
    aci_application_epg.epg2
  ]
}

resource "aci_epg_to_contract" "epg2_contract1" {
    application_epg_dn = aci_application_epg.epg2.id
    contract_dn        = aci_contract.contract1.id
    contract_type      = var.epg2_contract1_type
}