如何在Terraform中用cidrsubnet函数分层细分CIDR子网
Hey there! Let's walk through exactly how to use Terraform's cidrsubnet function to build your desired subnet hierarchy step by step. First, let's clarify the three parameters of cidrsubnet since that's your core question:
Breaking Down cidrsubnet(prefix, newbits, netnum)
prefix: The parent CIDR block you're splitting (e.g., your default10.0.0.0/8).newbits: The number of additional bits to add to the parent's prefix length. Calculate this asnew_prefix_length - parent_prefix_length(e.g., going from/8to/16requires16-8=8new bits).netnum: The zero-based index of the subnet you want to create within the parent block. This is what controls which specific subnet you get—start at 0 and increment for each new subnet.
Step 1: Root Module (Region Level)
Instead of manually defining region1, region2, etc., we'll use count to dynamically generate regions. This keeps your code clean and scalable.
# root/main.tf variable "cidr_block" { description = "Root CIDR block to split into regions and AZs" type = string default = "10.0.0.0/8" } variable "number_of_regions" { description = "Total number of regions to provision" type = number default = 3 } # Dynamically create region modules module "regions" { source = "./region" count = var.number_of_regions # Split /8 into /16: newbits = 16 - 8 = 8; netnum = count.index (0,1,2...) cidr_block = cidrsubnet(var.cidr_block, 8, count.index) }
This will generate:
- Region 0:
10.0.0.0/16 - Region 1:
10.1.0.0/16 - Region 2:
10.2.0.0/16
... which matches your VPN network requirement perfectly.
Step 2: Region Submodule (AZ Level)
Now inside the region module, we'll split the region's /16 block into /21 AZ subnets. Again, use count for dynamic AZ generation.
First, define variables for the region module:
# region/variables.tf variable "cidr_block" { description = "CIDR block for this region (e.g., 10.0.0.0/16)" type = string } variable "number_of_azs" { description = "Number of availability zones per region" type = number default = 3 }
Then create the AZ modules:
# region/main.tf # Dynamically create AZ modules module "availability_zones" { source = "./availability_zone" count = var.number_of_azs # Split /16 into /21: newbits = 21 - 16 = 5; netnum = count.index (0,1,2...) cidr_block = cidrsubnet(var.cidr_block, 5, count.index) }
This will generate for each region:
- AZ 0:
10.x.0.0/21 - AZ 1:
10.x.8.0/21 - AZ 2:
10.x.16.0/21
... exactly the AZ subnet pattern you need. The third octet increments by 8 automatically because a/21block covers 2048 addresses (8*256), so each subsequent subnet starts 8 octets higher.
If You Prefer Manual Module Calls
If you don't want dynamic generation and prefer to explicitly define each region/AZ, you can hardcode the netnum values:
Root Module (Manual Regions):
module "region1" { source = "./region" cidr_block = cidrsubnet(var.cidr_block, 8, 0) # 10.0.0.0/16 } module "region2" { source = "./region" cidr_block = cidrsubnet(var.cidr_block, 8, 1) # 10.1.0.0/16 }
Region Module (Manual AZs):
module "availability_zone1" { source = "./availability_zone" cidr_block = cidrsubnet(var.cidr_block, 5, 0) # 10.x.0.0/21 } module "availability_zone2" { source = "./availability_zone" cidr_block = cidrsubnet(var.cidr_block, 5, 1) # 10.x.8.0/21 } module "availability_zone3" { source = "./availability_zone" cidr_block = cidrsubnet(var.cidr_block, 5, 2) # 10.x.16.0/21 }
Key Takeaways
newbitsis always the difference between the new prefix length and the parent's prefix length (e.g.,/8→/16= 8 new bits;/16→/21=5 new bits).netnumis your zero-based subnet index—usecount.indexfor dynamic scaling, or hardcode values for explicit control.- The octet increments (1 for regions, 8 for AZs) are handled automatically by the CIDR math in
cidrsubnet—you don't need to calculate octet values manually.
内容的提问来源于stack exchange,提问作者Lance Pollard




