【问题标题】:Configure subnets using terraform cidrsubnet使用 terraform cidrsubnet 配置子网
【发布时间】:2021-03-19 03:34:20
【问题描述】:

我正在尝试使用 Terraform 支持的 cidrsubnet 函数创建两个子网。我拥有的 VPC cidr 是“10.32.0.0/16”。我正在尝试拥有子网 10.32.1.0/27 和 10.32.3.0/27。为了实现这一点,我在获取 cidrsubnet 功能时遇到了一些麻烦。到目前为止我所拥有的是:

cidrsubnet(10.32.0.0/16, 11, netnum???)

我不明白 netnum 需要什么值才能获得我想要的值。对这部分功能的任何解释都会有所帮助。我已尝试阅读有关此功能的文档,但似乎有限。

【问题讨论】:

    标签: amazon-web-services terraform subnet


    【解决方案1】:

    Netmasks and Subnets 文档部分试图提供足够的信息来了解此函数与 IP 地址约定的关系,并提到 Unix 命令ipcalc 作为一种可视化 CIDR 网络掩码表示方式的方法。

    让我们看看ipcalc 如何描述您的起始前缀和您的两个预期子网前缀:

    $ ipcalc 10.32.0.0/16
    Address:   10.32.0.0            00001010.00100000. 00000000.00000000
    Netmask:   255.255.0.0 = 16     11111111.11111111. 00000000.00000000
    Wildcard:  0.0.255.255          00000000.00000000. 11111111.11111111
    =>
    Network:   10.32.0.0/16         00001010.00100000. 00000000.00000000
    HostMin:   10.32.0.1            00001010.00100000. 00000000.00000001
    HostMax:   10.32.255.254        00001010.00100000. 11111111.11111110
    Broadcast: 10.32.255.255        00001010.00100000. 11111111.11111111
    Hosts/Net: 65534                 Class A, Private Internet
    
    $ ipcalc 10.32.1.0/27
    Address:   10.32.1.0            00001010.00100000.00000001.000 00000
    Netmask:   255.255.255.224 = 27 11111111.11111111.11111111.111 00000
    Wildcard:  0.0.0.31             00000000.00000000.00000000.000 11111
    =>
    Network:   10.32.1.0/27         00001010.00100000.00000001.000 00000
    HostMin:   10.32.1.1            00001010.00100000.00000001.000 00001
    HostMax:   10.32.1.30           00001010.00100000.00000001.000 11110
    Broadcast: 10.32.1.31           00001010.00100000.00000001.000 11111
    Hosts/Net: 30                    Class A, Private Internet
    
    $ ipcalc 10.32.3.0/27
    Address:   10.32.3.0            00001010.00100000.00000011.000 00000
    Netmask:   255.255.255.224 = 27 11111111.11111111.11111111.111 00000
    Wildcard:  0.0.0.31             00000000.00000000.00000000.000 11111
    =>
    Network:   10.32.3.0/27         00001010.00100000.00000011.000 00000
    HostMin:   10.32.3.1            00001010.00100000.00000011.000 00001
    HostMax:   10.32.3.30           00001010.00100000.00000011.000 11110
    Broadcast: 10.32.3.31           00001010.00100000.00000011.000 11111
    Hosts/Net: 30                    Class A, Private Internet
    

    ipcalc 的符号中,二进制表示中的空格表示地址的网络部分和主机部分之间的边界。我们可以看到,正如您在示例中所展示的那样,两个期望的结果在网络部分中的位比基地址多 11 位。

    让我们以其中一个为例来确定“netnum”是什么。我们将使用10.32.1.0/27,并将基地址和子网地址中的“地址”行放在一起,以便更清楚地看到区别:

    Address:   10.32.0.0            00001010.00100000. 00000000.00000000
    Address:   10.32.1.0            00001010.00100000.00000001.000 00000
    

    netnum 的值是在第二种情况下由这 11 个额外的二进制数字表示的数字:00000001000。该二进制数的十进制等效值为 8,因此该二进制数的 netnum 将是 8,我们可以通过在 terraform console 提示符下调用 cidrsubnet 来确认:

    > cidrsubnet("10.32.0.0/16", 11, 8)
    "10.32.1.0/27"
    

    为了概括这一点,请注意在 IP 地址中第三个十进制数字上方的二进制表示中,仅代表网络号的一部分:在00000001.000 中,我们可以看到有三个二进制数字属于第四个八位字节.因为第四个二进制位表示八位的数量,所以一般规则是要找到将为第三个八位字节提供特定值的netnum,您需要将该值乘以八。三乘以八是 24,所以如果我们将 netnum 设置为 24,那么我们会得到你想要的另一个前缀:

    > cidrsubnet("10.32.0.0/16", 11, 24)
    "10.32.3.0/27"
    

    话虽如此,值得注意的是,这种特殊的寻址方案正在“浪费”部分地址空间。如果您将最后三位始终设置为零,那么实际上您只有 8 位的网络编号,因此您只能拥有 256 个网络。如果您想利用网络编号空间的所有 11 位(2,048 个网络),您需要从零开始您的网络编号并从那里正常向上计数,这将密集地占用您的所有网络空间:

    > cidrsubnet("10.32.0.0/16", 11, 0)
    "10.32.0.0/27"
    > cidrsubnet("10.32.0.0/16", 11, 1)
    "10.32.0.32/27"
    > cidrsubnet("10.32.0.0/16", 11, 2)
    "10.32.0.64/27"
    > cidrsubnet("10.32.0.0/16", 11, 3)
    "10.32.0.96/27"
    > cidrsubnet("10.32.0.0/16", 11, 4)
    "10.32.0.128/27"
    > cidrsubnet("10.32.0.0/16", 11, 5)
    "10.32.0.160/27"
    > cidrsubnet("10.32.0.0/16", 11, 6)
    "10.32.0.192/27"
    > cidrsubnet("10.32.0.0/16", 11, 7)
    "10.32.0.224/27"
    > cidrsubnet("10.32.0.0/16", 11, 8)
    "10.32.1.0/27"
    

    因为传统的 IP 地址表示法是从 0 到 255 的四个十进制数字,所以上面的计数可能看起来违反直觉,但在底层二进制表示法中,这只是从零开始向上计数的正常计数,这样可以避免跳过网络编号 0到 7、9 到 15 等等。


    如果您正在为一组子网创建一个系统的网络寻址计划,每个子网都有一个特定的目的,您可能会发现使用the hashicorp/subnets/cidr module 提供的更高级别的抽象很有帮助,它只需要位数用于对每个网络进行编号并自行计算合适的 netnum 值:

    module "subnets" {
      source  = "hashicorp/subnets/cidr"
      version = "1.0.0"
    
      base_cidr_block = "10.32.0.0/16"
      networks = [
        {
          name     = "first",
          new_bits = 11
        },
        {
          name     = "second",
          new_bits = 11
        },
      ]
    }
    

    上面会产生一个像这样的network_cidr_blocks 映射:

    {
      first  = "10.32.0.0/27"
      second = "10.32.0.32/27"
    }
    

    您可以在配置的其他地方写module.subnets.network_cidr_blocks.first 来获取第一个地址。假设您选择有意义的名称而不是我做作的“第一”和“第二”,这将使您的其余配置更易于阅读,因为未来的读者不需要记住每个 IP 地址范围代表什么。

    【讨论】:

      猜你喜欢
      • 2020-11-20
      • 1970-01-01
      • 2021-02-28
      • 2021-01-02
      • 2021-02-28
      • 1970-01-01
      • 2021-07-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多