如何使用 Terraform 选择未使用的 VPC CIDR 块?
How do you choose an unused VPC CIDR Block with Terraform?
设置: 我将使用 terraform 以编程方式创建环境。已经存在一些 VPC,我想确保在使用 terraform 创建新 VPC 时它不会与现有 VPC 冲突。
第一步,我可以用这个获取世界的当前状态
data "aws_vpcs" "current" { }
但我不确定如何选择不在列表中的 IP 地址。例如,我们使用 172.x.0.0/16
作为格式。
在 terraform 中,如何选择当前未使用的最低 x?
单独使用 Terraform 不适合此动态分配任务,因为结果会不稳定:如果您假设编写 Terraform 配置以查找分配最高的 CIDR 块,然后将其用于新的 aws_vpc
那么下次你 运行 Terraform 时,它会发现最高分配的 CIDR 块已经改变,然后计划用更高的数字替换 VPC,并继续这样做直到 IP 地址 space 耗尽. Terraform 数据资源在 运行 之间没有任何“记忆”,因为它们旨在让 Terraform 配置适应周围不断变化的环境。
要做什么取决于您是喜欢自上而下的手动分配方法还是动态的“按需分配”方法。从你的问题听起来你更喜欢其中的第二个,但我将首先讨论第一个,因为它是我更常见且更直接的。
对于自上而下的手动分配,您可以编写一个 Terraform 模块,其唯一目的是描述来自您的 IP 地址的分配 space。每次你想分配一个新地址 space 时,你首先要更改该模块以包含对其地址 space 的新分配,然后将其结果用于 select 适当的基地址当前配置的范围。 Terraform Registry 中有一个名为 hashicorp/subnets/cidr
that aims to make it easier to build a module like that, by defining some simple rules for backward-compatible changes to allocations later.
的模块
(上述的一个变体是使用专为编目网络地址 spaces 而设计的专门系统,如 NetBox,但最终这些归结为同一件事:集中管理人类和软件可以参考的地址 space 分配的注册表。)
对于“按请求分配”方法,您需要一些单独的系统来响应分配请求并记住分配给每个系统的地址 space 以便它可以保证始终 return 在未来的 Terraform 运行s 上对每个调用者进行相同的分配。这样的系统可能需要一个持久的数据存储,以便它可以为每个调用者召回一个地址范围是否已经分配给它,如果是,return 相同的分配而不是创建一个新的分配。
我个人并不知道有任何专门的软件可以完成这项任务,但是您可以自己构建一个简单的服务,它通过 returning 地址范围来响应包含系统标识符的 HTTP 请求,该地址范围是使用系统标识符作为唯一键的新分配或先前分配:
data "http" "cidr_block" {
url = "https://example.com/cidr-block-allocation/example-system"
}
locals {
cidr_block = chomp(data.http.cidr_block.body)
}
在上面,我假设这个假设的端点 return 是一个 text/plain
响应,仅包含 CIDR 表示法中的地址范围,但它可能是一个 JSON 使用 Terraform 解析的响应jsondecode
函数,例如。
此 data
块与您原始问题中的块之间的重要区别在于,已分配内容的持久记录存在于服务器 运行ning 的 example.com
独立于AWS 中存在哪些 VPC,因此在指定地址范围内创建新 VPC 不会更改未来请求的答案。
不确定您是否还需要这个答案,但我刚刚完成了一个解决方案。
它在 172.16.0.0/16 和 172.31.0.0/16 之间创建 /16 个 VPC。
要正常工作,VPC 必须具有唯一名称,并且 172.* 中的所有 VPC 必须是 /16。
如果16个CIDR都被占用,则默认为“10.254.0.0/16”
variable "vpc_name" {
type = string
description = "VPC name"
default = "test"
}
locals {
cidr_base = "172.16.0.0/12"
cidr_fail = "10.254.0.0/16"
vpc_max = 16
cidr_available = [for index, x in data.aws_vpcs.all: cidrsubnet(local.cidr_base, 4, "${index}") if length(x.ids) == 0]
}
#Check if self exists
data "aws_vpcs" "self" {
tags = {
Name = var.vpc_name
}
}
#Get self data
data "aws_vpc" "self" {
count = length(data.aws_vpcs.self.ids) > 0 ? 1 : 0
id = data.aws_vpcs.self.ids[0]
}
#Get all VPCs
data "aws_vpcs" "all" {
count = local.vpc_max
filter {
name = "cidr"
values = [cidrsubnet(local.cidr_base, 4, count.index)]
}
}
#Use self CIDR or look for unused CIDR
resource "aws_vpc" "main" {
cidr_block = "${
length(data.aws_vpcs.self.ids) > 0 ? data.aws_vpc.self[0].cidr_block :
length(local.cidr_available) > 0 ? local.cidr_available[0] :
local.cidr_fail
}"
tags = {
Name = var.vpc_name
}
}
如果您需要更多的 VPC,您可以更改变量以在 10.*** 私有块中创建 VPC,这将为您提供 255 个 VPC
设置: 我将使用 terraform 以编程方式创建环境。已经存在一些 VPC,我想确保在使用 terraform 创建新 VPC 时它不会与现有 VPC 冲突。
第一步,我可以用这个获取世界的当前状态
data "aws_vpcs" "current" { }
但我不确定如何选择不在列表中的 IP 地址。例如,我们使用 172.x.0.0/16
作为格式。
在 terraform 中,如何选择当前未使用的最低 x?
单独使用 Terraform 不适合此动态分配任务,因为结果会不稳定:如果您假设编写 Terraform 配置以查找分配最高的 CIDR 块,然后将其用于新的 aws_vpc
那么下次你 运行 Terraform 时,它会发现最高分配的 CIDR 块已经改变,然后计划用更高的数字替换 VPC,并继续这样做直到 IP 地址 space 耗尽. Terraform 数据资源在 运行 之间没有任何“记忆”,因为它们旨在让 Terraform 配置适应周围不断变化的环境。
要做什么取决于您是喜欢自上而下的手动分配方法还是动态的“按需分配”方法。从你的问题听起来你更喜欢其中的第二个,但我将首先讨论第一个,因为它是我更常见且更直接的。
对于自上而下的手动分配,您可以编写一个 Terraform 模块,其唯一目的是描述来自您的 IP 地址的分配 space。每次你想分配一个新地址 space 时,你首先要更改该模块以包含对其地址 space 的新分配,然后将其结果用于 select 适当的基地址当前配置的范围。 Terraform Registry 中有一个名为 hashicorp/subnets/cidr
that aims to make it easier to build a module like that, by defining some simple rules for backward-compatible changes to allocations later.
(上述的一个变体是使用专为编目网络地址 spaces 而设计的专门系统,如 NetBox,但最终这些归结为同一件事:集中管理人类和软件可以参考的地址 space 分配的注册表。)
对于“按请求分配”方法,您需要一些单独的系统来响应分配请求并记住分配给每个系统的地址 space 以便它可以保证始终 return 在未来的 Terraform 运行s 上对每个调用者进行相同的分配。这样的系统可能需要一个持久的数据存储,以便它可以为每个调用者召回一个地址范围是否已经分配给它,如果是,return 相同的分配而不是创建一个新的分配。
我个人并不知道有任何专门的软件可以完成这项任务,但是您可以自己构建一个简单的服务,它通过 returning 地址范围来响应包含系统标识符的 HTTP 请求,该地址范围是使用系统标识符作为唯一键的新分配或先前分配:
data "http" "cidr_block" {
url = "https://example.com/cidr-block-allocation/example-system"
}
locals {
cidr_block = chomp(data.http.cidr_block.body)
}
在上面,我假设这个假设的端点 return 是一个 text/plain
响应,仅包含 CIDR 表示法中的地址范围,但它可能是一个 JSON 使用 Terraform 解析的响应jsondecode
函数,例如。
此 data
块与您原始问题中的块之间的重要区别在于,已分配内容的持久记录存在于服务器 运行ning 的 example.com
独立于AWS 中存在哪些 VPC,因此在指定地址范围内创建新 VPC 不会更改未来请求的答案。
不确定您是否还需要这个答案,但我刚刚完成了一个解决方案。
它在 172.16.0.0/16 和 172.31.0.0/16 之间创建 /16 个 VPC。
要正常工作,VPC 必须具有唯一名称,并且 172.* 中的所有 VPC 必须是 /16。 如果16个CIDR都被占用,则默认为“10.254.0.0/16”
variable "vpc_name" {
type = string
description = "VPC name"
default = "test"
}
locals {
cidr_base = "172.16.0.0/12"
cidr_fail = "10.254.0.0/16"
vpc_max = 16
cidr_available = [for index, x in data.aws_vpcs.all: cidrsubnet(local.cidr_base, 4, "${index}") if length(x.ids) == 0]
}
#Check if self exists
data "aws_vpcs" "self" {
tags = {
Name = var.vpc_name
}
}
#Get self data
data "aws_vpc" "self" {
count = length(data.aws_vpcs.self.ids) > 0 ? 1 : 0
id = data.aws_vpcs.self.ids[0]
}
#Get all VPCs
data "aws_vpcs" "all" {
count = local.vpc_max
filter {
name = "cidr"
values = [cidrsubnet(local.cidr_base, 4, count.index)]
}
}
#Use self CIDR or look for unused CIDR
resource "aws_vpc" "main" {
cidr_block = "${
length(data.aws_vpcs.self.ids) > 0 ? data.aws_vpc.self[0].cidr_block :
length(local.cidr_available) > 0 ? local.cidr_available[0] :
local.cidr_fail
}"
tags = {
Name = var.vpc_name
}
}
如果您需要更多的 VPC,您可以更改变量以在 10.*** 私有块中创建 VPC,这将为您提供 255 个 VPC