如何使用 cidrsubnet Function 在 Terraform 中细分 CIDR 子网?
How to subdivide CIDR subnet in Terraform with cidrsubnet Function?
我想为 AWS 区域内的子网提供这样的地址:
10.0.0.0/21
10.0.8.0/21
10.0.16.0/21
10.0.24.0/21
10.0.32.0/21
...
基本上,将第二个数字递增 8。
我还将为每个区域设置一个 VPN,它们应该共享同一个网络。所以我希望他们像这样:
10.1.0.0/16
10.2.0.0/16
10.3.0.0/16
10.4.0.0/16
10.5.0.0/16
...
基本上每次将第 3 个数字递增 1。如果不可能每步走 1,那么也走 8。
我有read in depth about CIDR blocks,但还是不太清楚如何申请,具体在下面的上下文中。
我想要一套以 1 个 CIDR 块开头的嵌套 Terraform 模块,并将其子网划分为越来越小的块。首先,它将按区域(第三个数字)细分,然后按可用性区域(第二个数字)细分。一切都将是动态的,因此您只需按字面意思提供初始 CIDR 块。
看来我应该使用 cidrsubnet
:
cidrsubnet(prefix, newbits, netnum)
我得到了这样的结果:
cidrsubnet(var.cidr_block, 13, netnum?)
我知道 13
将从 /8
变为 /21
。但这直接进入可用性区域(我不知道如何处理 netnum
)。我想做这样的事情:
# main.tf
variable "cidr_block" {
default = "10.0.0.0/8"
}
module "region1" {
source = "./region" # ./region/main.tf
cidr_block = cidrsubnet(var.cidr_block, 8?, count.index?) # 10.0.0.0/16?
}
module "region2" {
source = "./region" # ./region/main.tf
cidr_block = cidrsubnet(var.cidr_block, 8?, count.index?) # 10.1.0.0/16?
}
// ...
然后在区域子模块中:
# region/main.tf
module "availability_zone1" {
source = "./availability_zone" # ./availability_zone/main.tf
cidr_block = cidrsubnet(var.cidr_block, 5?, count.index?) # 10.1.0.0/21
}
module "availability_zone2" {
source = "./availability_zone" # ./availability_zone/main.tf
cidr_block = cidrsubnet(var.cidr_block, 5?, count.index?) # 10.1.8.0/21
}
module "availability_zone3" {
source = "./availability_zone" # ./availability_zone/main.tf
cidr_block = cidrsubnet(var.cidr_block, 5?, count.index?) # 10.1.16.0/21
}
// ...
所以基本上,从 /8 -> /16
细分一次,然后再从 /16 -> /21
细分一次。 count.index
我还没有用过,但不知何故我想让它知道它在调用序列中的什么位置。如果不可能,那很好,我可以随模块一起传递一个索引。
如何使用 cidrsubnet
函数编写此代码?这个问题最重要的部分是我应该在函数的每个槽中放什么:cidrsubnet(prefix, newbits, netnum)
,我不知道具体 netnum
应该是什么样的。
你已经拥有的是正确的。 count.index
只会增加 1。
您可以按如下方式计算和验证块 (terraform 0.12):
provider "aws" {
region = "us-east-1"
}
variable "cidr_block" {
default = "10.0.0.0/8"
}
output "cidr1" {
value = [for index in range(8):
cidrsubnet(var.cidr_block, 8, index)]
}
output "cidr2" {
value = [for index in range(8):
cidrsubnet(var.cidr_block, 13, index)]
}
这些将输出:
cidr1 = [
"10.0.0.0/16",
"10.1.0.0/16",
"10.2.0.0/16",
"10.3.0.0/16",
"10.4.0.0/16",
"10.5.0.0/16",
"10.6.0.0/16",
"10.7.0.0/16",
]
cidr2 = [
"10.0.0.0/21",
"10.0.8.0/21",
"10.0.16.0/21",
"10.0.24.0/21",
"10.0.32.0/21",
"10.0.40.0/21",
"10.0.48.0/21",
"10.0.56.0/21",
]
要查看所有组合,您可以这样做:
provider "aws" {
region = "us-east-1"
}
variable "cidr_block" {
default = "10.0.0.0/8"
}
output "all_cidrs" {
value = [for index1 in range(8):
{
cidrsubnet(var.cidr_block, 8, index1) = [
for index2 in range(8): cidrsubnet(cidrsubnet(var.cidr_block, 8, index1), 5, index2)
]
}
]
}
给出:
all_cidrs = [
{
"10.0.0.0/16" = [
"10.0.0.0/21",
"10.0.8.0/21",
"10.0.16.0/21",
"10.0.24.0/21",
"10.0.32.0/21",
"10.0.40.0/21",
"10.0.48.0/21",
"10.0.56.0/21",
]
},
{
"10.1.0.0/16" = [
"10.1.0.0/21",
"10.1.8.0/21",
"10.1.16.0/21",
"10.1.24.0/21",
"10.1.32.0/21",
"10.1.40.0/21",
"10.1.48.0/21",
"10.1.56.0/21",
]
},
{
"10.2.0.0/16" = [
"10.2.0.0/21",
"10.2.8.0/21",
"10.2.16.0/21",
"10.2.24.0/21",
"10.2.32.0/21",
"10.2.40.0/21",
"10.2.48.0/21",
"10.2.56.0/21",
]
},
{
"10.3.0.0/16" = [
"10.3.0.0/21",
"10.3.8.0/21",
"10.3.16.0/21",
"10.3.24.0/21",
"10.3.32.0/21",
"10.3.40.0/21",
"10.3.48.0/21",
"10.3.56.0/21",
]
},
{
"10.4.0.0/16" = [
"10.4.0.0/21",
"10.4.8.0/21",
"10.4.16.0/21",
"10.4.24.0/21",
"10.4.32.0/21",
"10.4.40.0/21",
"10.4.48.0/21",
"10.4.56.0/21",
]
},
{
"10.5.0.0/16" = [
"10.5.0.0/21",
"10.5.8.0/21",
"10.5.16.0/21",
"10.5.24.0/21",
"10.5.32.0/21",
"10.5.40.0/21",
"10.5.48.0/21",
"10.5.56.0/21",
]
},
{
"10.6.0.0/16" = [
"10.6.0.0/21",
"10.6.8.0/21",
"10.6.16.0/21",
"10.6.24.0/21",
"10.6.32.0/21",
"10.6.40.0/21",
"10.6.48.0/21",
"10.6.56.0/21",
]
},
{
"10.7.0.0/16" = [
"10.7.0.0/21",
"10.7.8.0/21",
"10.7.16.0/21",
"10.7.24.0/21",
"10.7.32.0/21",
"10.7.40.0/21",
"10.7.48.0/21",
"10.7.56.0/21",
]
},
]
在我撰写此答案时,Terraform 0.13.0 处于候选发布版本 1,并将在几周内发布。 Terraform 0.13.0 包括对模块使用 for_each
和 count
的能力,这使得使用 the hashicorp/subnets/cidr
module 像这样的多级寻址计划更加直接。与直接进行单独的 cidrsubnet
调用相比,该模块的一个优点是它允许您为每个网络分配符号名称,并且它有一些约定来帮助弃用和稍后重用您的部分地址 space 无需重新分配所有相邻网络。
您在示例中提到了 AWS 区域和子网,因此为了展示这一点,我将使用 AWS 区域名称和可用性区域作为网络的符号名称,但您可以使用任何有意义的名称只要每个网络都以唯一标识符结尾,您的架构就可以了。
locals {
aws_region_zones = tolist([
{
region = "us-west-2"
zones = ["us-west-2a", "us-west-2b"]
},
{
region = "us-east-1"
zones = ["us-east-1a", "us-east-2f"]
},
# When allocating new regions or zones,
# always add them at the end of their
# respective list to avoid renumbering
# the existing address allocations.
])
}
module "regional" {
source = "hashicorp/subnets/cidr"
base_cidr_block = "10.0.0.0/8"
networks = [
for regional in local.aws_region_zones : {
name = regional.region
new_bits = 8
}
]
}
module "zonal" {
source = "hashicorp/subnets/cidr"
for_each = {
for net in module.regional.networks : net.name => net
}
base_cidr_block = each.value.cidr_block
networks = [
for zone_name in local.aws_region_zones[each.key].zones : {
name = regional.region
new_bits = 5
}
]
}
output "region_cidr_blocks" {
value = tomap({
for net in module.regional.networks : net.name => {
cidr_block = net.cidr_block
zones = tomap({
for subnet in module.zonal[net.name].networks : subnet.name => {
cidr_block = net.cidr_block
}
})
}
})
}
region_cidr_blocks
输出值将是一个对象映射,其中每个对象代表一个区域,然后是每个可用区的嵌套映射。
我想为 AWS 区域内的子网提供这样的地址:
10.0.0.0/21
10.0.8.0/21
10.0.16.0/21
10.0.24.0/21
10.0.32.0/21
...
基本上,将第二个数字递增 8。
我还将为每个区域设置一个 VPN,它们应该共享同一个网络。所以我希望他们像这样:
10.1.0.0/16
10.2.0.0/16
10.3.0.0/16
10.4.0.0/16
10.5.0.0/16
...
基本上每次将第 3 个数字递增 1。如果不可能每步走 1,那么也走 8。
我有read in depth about CIDR blocks,但还是不太清楚如何申请,具体在下面的上下文中。
我想要一套以 1 个 CIDR 块开头的嵌套 Terraform 模块,并将其子网划分为越来越小的块。首先,它将按区域(第三个数字)细分,然后按可用性区域(第二个数字)细分。一切都将是动态的,因此您只需按字面意思提供初始 CIDR 块。
看来我应该使用 cidrsubnet
:
cidrsubnet(prefix, newbits, netnum)
我得到了这样的结果:
cidrsubnet(var.cidr_block, 13, netnum?)
我知道 13
将从 /8
变为 /21
。但这直接进入可用性区域(我不知道如何处理 netnum
)。我想做这样的事情:
# main.tf
variable "cidr_block" {
default = "10.0.0.0/8"
}
module "region1" {
source = "./region" # ./region/main.tf
cidr_block = cidrsubnet(var.cidr_block, 8?, count.index?) # 10.0.0.0/16?
}
module "region2" {
source = "./region" # ./region/main.tf
cidr_block = cidrsubnet(var.cidr_block, 8?, count.index?) # 10.1.0.0/16?
}
// ...
然后在区域子模块中:
# region/main.tf
module "availability_zone1" {
source = "./availability_zone" # ./availability_zone/main.tf
cidr_block = cidrsubnet(var.cidr_block, 5?, count.index?) # 10.1.0.0/21
}
module "availability_zone2" {
source = "./availability_zone" # ./availability_zone/main.tf
cidr_block = cidrsubnet(var.cidr_block, 5?, count.index?) # 10.1.8.0/21
}
module "availability_zone3" {
source = "./availability_zone" # ./availability_zone/main.tf
cidr_block = cidrsubnet(var.cidr_block, 5?, count.index?) # 10.1.16.0/21
}
// ...
所以基本上,从 /8 -> /16
细分一次,然后再从 /16 -> /21
细分一次。 count.index
我还没有用过,但不知何故我想让它知道它在调用序列中的什么位置。如果不可能,那很好,我可以随模块一起传递一个索引。
如何使用 cidrsubnet
函数编写此代码?这个问题最重要的部分是我应该在函数的每个槽中放什么:cidrsubnet(prefix, newbits, netnum)
,我不知道具体 netnum
应该是什么样的。
你已经拥有的是正确的。 count.index
只会增加 1。
您可以按如下方式计算和验证块 (terraform 0.12):
provider "aws" {
region = "us-east-1"
}
variable "cidr_block" {
default = "10.0.0.0/8"
}
output "cidr1" {
value = [for index in range(8):
cidrsubnet(var.cidr_block, 8, index)]
}
output "cidr2" {
value = [for index in range(8):
cidrsubnet(var.cidr_block, 13, index)]
}
这些将输出:
cidr1 = [
"10.0.0.0/16",
"10.1.0.0/16",
"10.2.0.0/16",
"10.3.0.0/16",
"10.4.0.0/16",
"10.5.0.0/16",
"10.6.0.0/16",
"10.7.0.0/16",
]
cidr2 = [
"10.0.0.0/21",
"10.0.8.0/21",
"10.0.16.0/21",
"10.0.24.0/21",
"10.0.32.0/21",
"10.0.40.0/21",
"10.0.48.0/21",
"10.0.56.0/21",
]
要查看所有组合,您可以这样做:
provider "aws" {
region = "us-east-1"
}
variable "cidr_block" {
default = "10.0.0.0/8"
}
output "all_cidrs" {
value = [for index1 in range(8):
{
cidrsubnet(var.cidr_block, 8, index1) = [
for index2 in range(8): cidrsubnet(cidrsubnet(var.cidr_block, 8, index1), 5, index2)
]
}
]
}
给出:
all_cidrs = [
{
"10.0.0.0/16" = [
"10.0.0.0/21",
"10.0.8.0/21",
"10.0.16.0/21",
"10.0.24.0/21",
"10.0.32.0/21",
"10.0.40.0/21",
"10.0.48.0/21",
"10.0.56.0/21",
]
},
{
"10.1.0.0/16" = [
"10.1.0.0/21",
"10.1.8.0/21",
"10.1.16.0/21",
"10.1.24.0/21",
"10.1.32.0/21",
"10.1.40.0/21",
"10.1.48.0/21",
"10.1.56.0/21",
]
},
{
"10.2.0.0/16" = [
"10.2.0.0/21",
"10.2.8.0/21",
"10.2.16.0/21",
"10.2.24.0/21",
"10.2.32.0/21",
"10.2.40.0/21",
"10.2.48.0/21",
"10.2.56.0/21",
]
},
{
"10.3.0.0/16" = [
"10.3.0.0/21",
"10.3.8.0/21",
"10.3.16.0/21",
"10.3.24.0/21",
"10.3.32.0/21",
"10.3.40.0/21",
"10.3.48.0/21",
"10.3.56.0/21",
]
},
{
"10.4.0.0/16" = [
"10.4.0.0/21",
"10.4.8.0/21",
"10.4.16.0/21",
"10.4.24.0/21",
"10.4.32.0/21",
"10.4.40.0/21",
"10.4.48.0/21",
"10.4.56.0/21",
]
},
{
"10.5.0.0/16" = [
"10.5.0.0/21",
"10.5.8.0/21",
"10.5.16.0/21",
"10.5.24.0/21",
"10.5.32.0/21",
"10.5.40.0/21",
"10.5.48.0/21",
"10.5.56.0/21",
]
},
{
"10.6.0.0/16" = [
"10.6.0.0/21",
"10.6.8.0/21",
"10.6.16.0/21",
"10.6.24.0/21",
"10.6.32.0/21",
"10.6.40.0/21",
"10.6.48.0/21",
"10.6.56.0/21",
]
},
{
"10.7.0.0/16" = [
"10.7.0.0/21",
"10.7.8.0/21",
"10.7.16.0/21",
"10.7.24.0/21",
"10.7.32.0/21",
"10.7.40.0/21",
"10.7.48.0/21",
"10.7.56.0/21",
]
},
]
在我撰写此答案时,Terraform 0.13.0 处于候选发布版本 1,并将在几周内发布。 Terraform 0.13.0 包括对模块使用 for_each
和 count
的能力,这使得使用 the hashicorp/subnets/cidr
module 像这样的多级寻址计划更加直接。与直接进行单独的 cidrsubnet
调用相比,该模块的一个优点是它允许您为每个网络分配符号名称,并且它有一些约定来帮助弃用和稍后重用您的部分地址 space 无需重新分配所有相邻网络。
您在示例中提到了 AWS 区域和子网,因此为了展示这一点,我将使用 AWS 区域名称和可用性区域作为网络的符号名称,但您可以使用任何有意义的名称只要每个网络都以唯一标识符结尾,您的架构就可以了。
locals {
aws_region_zones = tolist([
{
region = "us-west-2"
zones = ["us-west-2a", "us-west-2b"]
},
{
region = "us-east-1"
zones = ["us-east-1a", "us-east-2f"]
},
# When allocating new regions or zones,
# always add them at the end of their
# respective list to avoid renumbering
# the existing address allocations.
])
}
module "regional" {
source = "hashicorp/subnets/cidr"
base_cidr_block = "10.0.0.0/8"
networks = [
for regional in local.aws_region_zones : {
name = regional.region
new_bits = 8
}
]
}
module "zonal" {
source = "hashicorp/subnets/cidr"
for_each = {
for net in module.regional.networks : net.name => net
}
base_cidr_block = each.value.cidr_block
networks = [
for zone_name in local.aws_region_zones[each.key].zones : {
name = regional.region
new_bits = 5
}
]
}
output "region_cidr_blocks" {
value = tomap({
for net in module.regional.networks : net.name => {
cidr_block = net.cidr_block
zones = tomap({
for subnet in module.zonal[net.name].networks : subnet.name => {
cidr_block = net.cidr_block
}
})
}
})
}
region_cidr_blocks
输出值将是一个对象映射,其中每个对象代表一个区域,然后是每个可用区的嵌套映射。