Skip to content

Commit

Permalink
Add subnet calculation explanation to README.md (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
const-bon authored Sep 1, 2017
1 parent bd43a1a commit 7e5ab3f
Showing 1 changed file with 81 additions and 0 deletions.
81 changes: 81 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,84 @@ module "subnets" {
| cidr_block | `` | The base CIDR block which will be divided into subnet CIDR blocks (e.g. `10.0.0.0/16`) | Yes |
| vpc_default_route_table_id | `` | The default route table for public subnets. Provides access to the Internet. If not set here, will be created. (e.g. `rtb-f4f0ce12`) | No |
| availability_zones | [] | The list of Availability Zones where subnets will be created (e.g. `["us-eas-1a", "us-eas-1b"]`) | Yes |


## TL;DR

`tf_subnets` creates a set of subnets based on `${var.cidr_block}` input
and amount of Availability Zones in a region.

For subnet set calculation `tf_subnets` uses TF
[cidrsubnet](https://www.terraform.io/docs/configuration/interpolation.html#cidrsubnet-iprange-newbits-netnum-)
interpolation.

### Calculation logic

```
${
cidrsubnet(
signum(length(var.cidr_block)) == 1 ?
var.cidr_block : data.aws_vpc.default.cidr_block,
ceil(log(length(data.aws_availability_zones.available.names) * 2, 2)),
count.index)
}
```


1. Use `${var.cidr_block}` input (if specified) or
use a VPC CIDR block `data.aws_vpc.default.cidr_block` (e.g. `10.0.0.0/16`)
2. Get number of available AZ in the region (e.g. `length(data.aws_availability_zones.available.names)`)
3. Calculate `newbits`. `newbits` number tells on how many subnets will
be CIDR block (input or VPC) divided. `newbits` is an amount of `binary digits`.

Example:

`newbits = 1` - 2 subnets are available (`1 binary digit` allows to count up to `2`)

`newbits = 2` - 4 subnets are available (`2 binary digits` allows to count up to `4`)

`newbits = 3` - 8 subnets are available (`3 binary digits` allows to count up to `8`)


etc.


1. We know, that we have `6` AZs in a `us-east-1` region (see step 2).
2. We need to create `1 public` subnet and `1 private` subnet in each AZ,
thus we need to create `12 subnets` in total (`6` AZs * (`1 public` + `1 private`)).
3. We need `4 binary digits` for that ( 2<sup>4</sup> = 16 ).
In order to calculate amount of `binary digits` we should use `logarithm`
function. We should use logarithm for `base 2` because decimal numbers
can be calculated as `powers` of binary number.
See [Wiki](https://en.wikipedia.org/wiki/Binary_number#Decimal)
for more details

Example:

For `12 subnets` we need `3.58` amount `binary digits` (log<sub>2</sub>12)

For `16 subnets` we need `4` amount `binary digits` (log<sub>2</sub>16)

For `7 subnets` we need `2.81` amount `binary digits` (log<sub>2</sub>7)

etc.

4. We can't calculate amount `binary digits` using fractional values.
We can't round it down because smaller amount `binary digits` is
insufficient for required number calculation.
Thus we should round it up. See TF [ceil](https://www.terraform.io/docs/configuration/interpolation.html#ceil-float-).

Example:

For `12 subnets` we need `4` amount `binary digits` (ceil(log<sub>2</sub>12))

For `16 subnets` we need `4` amount `binary digits` (ceil(log<sub>2</sub>16))

For `7 subnets` we need `3` amount `binary digits` (ceil(log<sub>2</sub>7))

etc.

5. Assign private subnets according to AZ number (we're using `count.index` for that).
6. Assign public subnets according to AZ number but with shift.
Using shift number according to amount of AZs in a region (see step 2)
(we're using `length(data.aws_availability_zones.available.names) + count.index` for that)

0 comments on commit 7e5ab3f

Please sign in to comment.