【问题标题】:How to subdivide CIDR subnet in Terraform with cidrsubnet Function?如何使用 cidrsubnet 函数在 Terraform 中细分 CIDR 子网?
【发布时间】:2020-11-20 02:12:03
【问题描述】:

我想为 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 模块,并将其子网化为越来越小的块。首先,它将按区域(第 3 个数字)细分,然后按可用区(第 2 个数字)细分。一切都是动态的,因此您只需按字面意思提供初始 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应该是什么样的。

【问题讨论】:

    标签: networking terraform ip-address subnet cidr


    【解决方案1】:

    在我撰写此答案时,Terraform 0.13.0 处于发布候选版本 1,并将在几周内发布。 Terraform 0.13.0 包括对模块使用for_eachcount 的能力,这使得使用the hashicorp/subnets/cidr module 进行这样的多级寻址计划更加简单。与直接进行单独的 cidrsubnet 调用相比,该模块的一个优点是它允许您为每个网络分配符号名称,并且它具有一些约定来帮助弃用和以后重用部分地址空间而无需重新分配所有的相邻网络。

    您在示例中提到了 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 输出值将是一个对象映射,其中每个对象代表一个区域,然后是每个可用区的嵌套映射。

    【讨论】:

      【解决方案2】:

      你已经拥有的是正确的。 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",
          ]
        },
      ]
      

      【讨论】:

        猜你喜欢
        • 2021-03-19
        • 1970-01-01
        • 2021-02-28
        • 2021-08-01
        • 2021-03-14
        • 1970-01-01
        • 1970-01-01
        • 2020-04-05
        • 2020-08-05
        相关资源
        最近更新 更多