Terraform で ACI 上に Route Leak 設定を含む Tenant を作成する
Terraform を使って Cisco ACI に「Route Leak 構成の Tenant を作成する」サンプルをメモしておきます。
構成
Terraform で以下の構成を設定します。
Terraform の設定ファイルは以下の通りです。
- variables.tf
- main.tf
- 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
}
|