Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ec2): Vpc supports allocating CIDR from AWS IPAM #22458

Merged
merged 36 commits into from Oct 27, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
fd7ec93
WIP
Oct 10, 2022
9e3fd7e
WIP
Oct 10, 2022
b9c13b3
Merge branch 'master' into nbaillie/ipam-provider
Oct 10, 2022
283812f
remove blocking issue from integ-test for now
nbaillie Oct 11, 2022
ffff217
Merge branch 'master' into nbaillie/ipam-provider
nbaillie Oct 11, 2022
bb51681
Merge branch 'main' into nbaillie/ipam-provider
nbaillie Oct 11, 2022
644ade8
Merge branch 'main' into nbaillie/ipam-provider
nbaillie Oct 18, 2022
dbe4e2a
Merge branch 'aws:main' into nbaillie/ipam-provider
nbaillie Oct 24, 2022
3bb5555
update based on comments from review
nbaillie Oct 24, 2022
0b6e993
--fix format
nbaillie Oct 24, 2022
96d1fee
update tests to remove dep prop cidr
nbaillie Oct 24, 2022
0815538
update cidr to ipAddressManager in other module tests
nbaillie Oct 24, 2022
45d7cb3
update cidr to ipAddressManager in other module tests
nbaillie Oct 24, 2022
75a967e
Merge branch 'main' into nbaillie/ipam-provider
nbaillie Oct 24, 2022
8eabd1d
Merge branch 'main' into nbaillie/ipam-provider
nbaillie Oct 24, 2022
73a5c39
Merge branch 'main' into nbaillie/ipam-provider
nbaillie Oct 24, 2022
d7c9ae5
vpc prop to ipAddresses
nbaillie Oct 24, 2022
454b449
rename ipam file to ip-addresses
nbaillie Oct 24, 2022
af38ad2
update error message test to reflect new message
nbaillie Oct 24, 2022
e57cece
Merge branch 'main' into nbaillie/ipam-provider
nbaillie Oct 25, 2022
fbee733
no public classes for ipam and cidr
nbaillie Oct 25, 2022
0e83d5b
pushing
nbaillie Oct 25, 2022
200eba4
Merge branch 'main' into nbaillie/ipam-provider
nbaillie Oct 25, 2022
2a929d7
internal for cidr and ipam
nbaillie Oct 25, 2022
c01d5bf
fix cidr inport in vpc
nbaillie Oct 25, 2022
ee1bb74
pushing
nbaillie Oct 25, 2022
1bfaabb
Merge branch 'main' into nbaillie/ipam-provider
nbaillie Oct 25, 2022
ce96c9d
Merge branch 'main' into nbaillie/ipam-provider
nbaillie Oct 26, 2022
cfb536a
Rename `awsIpam` -> `awsIpamAllocation`, rewrite README a bit
rix0rrr Oct 26, 2022
1369c2c
`IpAddresses` class is factory only, no need to have abstracts
rix0rrr Oct 26, 2022
d280483
Make examples compile
rix0rrr Oct 26, 2022
9c2b499
Merge branch 'aws:main' into nbaillie/ipam-provider
nbaillie Oct 26, 2022
6437005
Markdownlint
rix0rrr Oct 26, 2022
d686c3f
Merge branch 'nbaillie/ipam-provider' of github.com:nbaillie/aws-cdk …
rix0rrr Oct 26, 2022
e7136c5
Merge branch 'main' into nbaillie/ipam-provider
mergify[bot] Oct 26, 2022
132f18d
Merge branch 'main' into nbaillie/ipam-provider
mergify[bot] Oct 26, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
36 changes: 36 additions & 0 deletions packages/@aws-cdk/aws-ec2/README.md
Expand Up @@ -217,6 +217,42 @@ new ec2.Vpc(this, 'TheVPC', {
provider.connections.allowFrom(ec2.Peer.ipv4('1.2.3.4/8'), ec2.Port.tcp(80));
```

### Ip Address Management - IPAM
nbaillie marked this conversation as resolved.
Show resolved Hide resolved

To facilitate options for flexibility in the allocation and use of IP space within Vpc and Subnet including strategy and implementation for the allocation, Vpc utilizes an IpamProvider.

By default, the Vpc construct will create and use a StaticIpam for you if you do not pass an `ipamProvider` to Vpc. StaticIpam is an implementation of the Original CDK Vpc and Subnet IP address allocation strategy and implementation.
nbaillie marked this conversation as resolved.
Show resolved Hide resolved

You must supply at most one of ipamProvider or cidr to Vpc.

StaticIpam will first try to allocated space from the Vpc Cidr any Subnets that explicitly have a `cidrMask` as part of a SubnetConfiguration, this includes reserved subnets, after this any remaining space is divided between the rest of the required subnets.

When using StaticIpam concrete Cidr values are generated in the synthesized CloudFormation template.

```ts
new ec2.Vpc(stack, 'TheVPC', {
ipamProvider: new ec2.StaticIpam('10.0.1.0/20')
});
```

AwsIpam uses Amazon VPC IP Address Manager (IPAM) to allocated the Cidr for the Vpc. For information on Amazon VPC IP Address Manager please see the [official documentation](https://docs.aws.amazon.com/vpc/latest/ipam/what-it-is-ipam.html).

AWS Ipam requires a `ipv4IpamPoolId` be set to the Amazon VPC IP Address Manager Pool Id used for the Vpc Cidr allocation, additionally an `ipv4NetmaskLength` must be set, which defines the size of cidr that will be requested from the Pool at deploy time by the CloudFormation engine.

Subnets are allocated locally of a size defined by `defaultSubnetIpv4NetmaskLength` in the provider or by using any explicit `cidrMask` from a supplied SubnetConfiguration. The provider AwsIpam dose not attempt to allocated any remaining space in the Vpc's Cidr space.

```ts
new ec2.Vpc(stack, 'TheVPC', {
ipamProvider: new ec2.AwsIpam({
ipv4IpamPoolId: pool.ref,
ipv4NetmaskLength: 18,
defaultSubnetIpv4NetmaskLength: 24
})
});
```

When using AwsIpam the final Cidr allocation for Vpc and Subnets are unknown at synth time. Because of this Subnet Cidr values are synthesized as CloudFormation Intrinsic functions representing their offset within the Vpc Cidr space and not concrete values.

### Advanced Subnet Configuration

If the default VPC configuration (public and private subnets spanning the
Expand Down
77 changes: 77 additions & 0 deletions packages/@aws-cdk/aws-ec2/lib/cidr-splits.ts
@@ -0,0 +1,77 @@
/**
* Return the splits necessary to allocate the given sequence of cidrs in the given order
*
* The entire block is of size 'rootNetmask', and subsequent blocks will be allocated
* from it sized according to the sizes in the 'netmasks' array.
*
* The return value is a list of `CidrSplit` objects, which represent
* invocations of a pair of `Fn.select(Fn.cidr(...))` operations.
*
* Strategy: walk through the IP block space, clipping to the next possible
* start of a block of the given size, then allocate it. Here is an unrealistic
* example (with a weird ordering of the netmasks to show how clipping and hence
* space wasting plays out in practice):
*
* root space /16
* ┌──────────────────────────────────────────────────────────────────────────────────────────────┐
* │ │
* A /21 B /19
* ┌───┬───┬───┬───┬───────────────┬───────────────┬───┬───────────┬───────────────┬──────────────┐
* │ A │ A │ A │###│ B │ B │ A │###########│ B │ .... │
* └───┴───┴───┴───┴───────────────┴───────────────┴───┴───────────┴───────────────┴──────────────┘
* ^^^______ wasted space _________________^^^^^^
*/
export function calculateCidrSplits(rootNetmask: number, netmasks: number[]): CidrSplit[] {
const ret = new Array<CidrSplit>();

let offset = 0;
for (const netmask of netmasks) {
const size = Math.pow(2, 32 - netmask);

// Clip offset to the next block of the given size
offset = nextMultiple(offset, size);

const count = Math.pow(2, netmask - rootNetmask);
ret.push({
count,
netmask,
index: offset / size,
});

// Consume
offset += size;
}

if (offset > Math.pow(2, 32 - rootNetmask)) {
throw new Error(`IP space of size /${rootNetmask} not big enough to allocate subnets of sizes ${netmasks.map(x => `/${x}`)}`);
}

return ret;
}

function nextMultiple(current: number, multiple: number) {
return Math.ceil(current / multiple) * multiple;
}

/**
* A representation of a pair of `Fn.select(Fn.cidr())` invocations
*/
export interface CidrSplit {
/**
* The netmask of this block size
*
* This is the inverse number of what you need to pass to Fn.cidr (pass `32 -
* netmask` to Fn.cidr)`.
*/
readonly netmask: number;

/**
* How many parts the mask needs to be split into
*/
readonly count: number;

/**
* What subnet index to select from the split
*/
readonly index: number;
}
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-ec2/lib/index.ts
Expand Up @@ -27,6 +27,7 @@ export * from './client-vpn-endpoint-types';
export * from './client-vpn-endpoint';
export * from './client-vpn-authorization-rule';
export * from './client-vpn-route';
export * from './ipam';

// AWS::EC2 CloudFormation Resources:
export * from './ec2.generated';
Expand Down