Monday 27 May 2024

AWS VPC and Terraform

 



Terraform provides two useful functions for calculating CIDR ranges for subnets: cidrsubnet and cidrsubnets.

 

cidrsubnet Function

cidrsubnet finds out the CIDR of the netnum-th subnet of prefix-defined (prefix is in form of CIDR) network by expanding its network mask by newbits bits. Here is the function's signature:

cidrsubnet(prefix, newbits, netnum)

Here are some examples:

$ terraform console

> cidrsubnet("192.168.0.0/16", 8, 0)
"192.168.0.0/24"
> cidrsubnet("192.168.0.0/16", 8, 1)
"192.168.1.0/24"
> cidrsubnet("192.168.0.0/16", 8, 2)
"192.168.2.0/24"
> cidrsubnet("192.168.0.0/16", 8, 3)

> cidrsubnet("192.168.0.0/16", 5, 0)
"192.168.0.0/21"
> cidrsubnet("192.168.0.0/16", 5, 1)
"192.168.8.0/21"
> cidrsubnet("192.168.0.0/16", 5, 2)
"192.168.16.0/21"
> cidrsubnet("192.168.0.0/16", 5, 3)
"192.168.24.0/21"

 

cidrsubnets Function

From official documentation:
 
cidrsubnets calculates a sequence of consecutive IP address ranges within a particular CIDR prefix.
 
So, the output of function is a list of IP address ranges (CIDRs) which are within a given CIDR. This sounds like a first choice tool to be used when we need to determine CIDRs for subnets of VPC defined by CIDR.
 
Here is the function's signature:
 
cidrsubnets(prefix, newbits...)

...which means that this function can take any number of newbits arguments. In fact, this number will match the number of IP ranges (subnets) we want to have. If we want to have S subnets, we'll have:

cidrsubnets(prefix, newbits1, newbits2, newbits3, ..., newbitsS)
 
newbitsN is the newbits number to be used for each IP range.
 
 
Example:
 
> cidrsubnets("192.168.0.0/16", 8, 9, 1)
tolist([
  "192.168.0.0/24",
  "192.168.1.0/25",
  "192.168.128.0/17",
])

 
So, how did we get this output?
 
We take first newbits number and add it to the original network bits (16): 16 + 8 = 24. So, the first IP range (subnet) is: 192.168.0.0/24. ipcalc shows that the maximum IP address in this range is 192.168.0.255.

$ ipcalc 192.168.0.0/24
Address:   192.168.0.0          11000000.10101000.00000000. 00000000
Netmask:   255.255.255.0 = 24   11111111.11111111.11111111. 00000000
Wildcard:  0.0.0.255            00000000.00000000.00000000. 11111111
=>
Network:   192.168.0.0/24       11000000.10101000.00000000. 00000000
HostMin:   192.168.0.1          11000000.10101000.00000000. 00000001
HostMax:   192.168.0.254        11000000.10101000.00000000. 11111110
Broadcast: 192.168.0.255        11000000.10101000.00000000. 11111111
Hosts/Net: 254                   Class C, Private Internet


So, the minimum IP address in the next IP range can be higher or equal to 192.168.1.0. 

The next IP range uses network mask 16 + 9  = 25. So this range will be 192.168.1.0/25. 

 
 $ ipcalc 192.168.1.0/25
Address:   192.168.1.0          11000000.10101000.00000001.0 0000000
Netmask:   255.255.255.128 = 25 11111111.11111111.11111111.1 0000000
Wildcard:  0.0.0.127            00000000.00000000.00000000.0 1111111
=>
Network:   192.168.1.0/25       11000000.10101000.00000001.0 0000000
HostMin:   192.168.1.1          11000000.10101000.00000001.0 0000001
HostMax:   192.168.1.126        11000000.10101000.00000001.0 1111110
Broadcast: 192.168.1.127        11000000.10101000.00000001.0 1111111
Hosts/Net: 126                   Class C, Private Internet


ipcalc shows that the max IP address in this range is 192.168.1.127 which means that next IP range can start with IP address higher or equal to 192.168.1.128.
 
Subnet mask is 16 + 1 = 17 which means 


How to get Default VPC details?



data "aws_vpc" "default" {
  default = true
}

output "default_vpc" {
  value = data.aws_vpc.default
}


terraform plan prints output vars:


Changes to Outputs:
  + defatul_vpc     = {
      + arn                                  = "arn:aws:ec2:eu-west-2:4xxxxxx18:vpc/vpc-06ecxxxxxxba9"
      + cidr_block                           = "172.31.0.0/16"
      + cidr_block_associations              = [
          + {
              + association_id = "vpc-cidr-assoc-0797xxxxxxxx87d"
              + cidr_block     = "172.31.0.0/16"
              + state          = "associated"
            },
        ]
      + default                              = true
      + dhcp_options_id                      = "dopt-0c2xxxxxx2c19"
      + enable_dns_hostnames                 = true
      + enable_dns_support                   = true
      + enable_network_address_usage_metrics = false
      + filter                               = null
      + id                                   = "vpc-06exxxxxxxba9"
      + instance_tenancy                     = "default"
      + ipv6_association_id                  = ""
      + ipv6_cidr_block                      = ""
      + main_route_table_id                  = "rtb-0axxxxx87"
      + owner_id                             = "471xxxx8"
      + state                                = null
      + tags                                 = {}
      + timeouts                             = null
    }


How to get a list of IDs of Default VPC subnets?



We can use data source defined above.

data "aws_subnets" "default" {
  filter {
    name   = "vpc-id"
    values = [data.aws_vpc.default.id]
  }
}

output "default_subnets" {
    value = data.aws_subnets.default
}

terraform plan output:

  + default_subnets = {
      + filter   = [
          + {
              + name   = "vpc-id"
              + values = [
                  + "vpc-06exxxxx9",
                ]
            },
        ]
      + id       = "eu-west-2"
      + ids      = [
          + "subnet-066xxxxxxxx241afc",
          + "subnet-023xxxxxx9e00c87",
          + "subnet-0571xxxxxa7fb176",
        ]
      + tags     = null
      + timeouts = null
    }

List of subnet IDs is: data.aws_subnets.default.ids

---

No comments: