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(eks): support Bottlerocket Nvidia AMIs #28287

Merged
merged 4 commits into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions packages/aws-cdk-lib/aws-eks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,17 @@ For example, if the Amazon EKS cluster version is `1.17`, the Bottlerocket AMI v

Please note Bottlerocket does not allow to customize bootstrap options and `bootstrapOptions` properties is not supported when you create the `Bottlerocket` capacity.

To create a Bottlerocket managed nodegroup with Nvidia-based EC2 instance types use the `BOTTLEROCKET_X86_64_NVIDIA` or
`BOTTLEROCKET_ARM_64_NVIDIA` AMIs:

```ts
declare const cluster: eks.Cluster;
cluster.addNodegroupCapacity('BottlerocketNvidiaNG', {
amiType: eks.NodegroupAmiType.BOTTLEROCKET_X86_64_NVIDIA,
instanceTypes: [new ec2.InstanceType('g4dn.xlarge')],
});
```

For more details about Bottlerocket, see [Bottlerocket FAQs](https://aws.amazon.com/bottlerocket/faqs/) and [Bottlerocket Open Source Blog](https://aws.amazon.com/blogs/opensource/announcing-the-general-availability-of-bottlerocket-an-open-source-linux-distribution-purpose-built-to-run-containers/).

### Endpoint Access
Expand Down
29 changes: 21 additions & 8 deletions packages/aws-cdk-lib/aws-eks/lib/managed-nodegroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@ export interface INodegroup extends IResource {
}

/**
* The AMI type for your node group. GPU instance types should use the `AL2_x86_64_GPU` AMI type, which uses the
* Amazon EKS-optimized Linux AMI with GPU support. Non-GPU instances should use the `AL2_x86_64` AMI type, which
* uses the Amazon EKS-optimized Linux AMI.
* The AMI type for your node group.
*
* GPU instance types should use the `AL2_x86_64_GPU` AMI type, which uses the
* Amazon EKS-optimized Linux AMI with GPU support or the `BOTTLEROCKET_ARM_64_NVIDIA` or `BOTTLEROCKET_X86_64_NVIDIA`
* AMI types, which uses the Amazon EKS-optimized Linux AMI with Nvidia-GPU support.
*
* Non-GPU instances should use the `AL2_x86_64` AMI type, which uses the Amazon EKS-optimized Linux AMI.
*/
export enum NodegroupAmiType {
/**
Expand All @@ -35,13 +39,21 @@ export enum NodegroupAmiType {
*/
AL2_ARM_64 = 'AL2_ARM_64',
/**
* Bottlerocket Linux(ARM-64)
* Bottlerocket Linux (ARM-64)
*/
BOTTLEROCKET_ARM_64 = 'BOTTLEROCKET_ARM_64',
/**
* Bottlerocket(x86-64)
* Bottlerocket (x86-64)
*/
BOTTLEROCKET_X86_64 = 'BOTTLEROCKET_x86_64',
/**
* Bottlerocket Linux with Nvidia-GPU support (ARM-64)
*/
BOTTLEROCKET_ARM_64_NVIDIA = 'BOTTLEROCKET_ARM_64_NVIDIA',
/**
* Bottlerocket with Nvidia-GPU support (x86-64)
*/
BOTTLEROCKET_X86_64_NVIDIA = 'BOTTLEROCKET_x86_64_NVIDIA',
/**
* Windows Core 2019 (x86-64)
*/
Expand Down Expand Up @@ -215,7 +227,7 @@ export interface NodegroupOptions {
/**
* The instance type to use for your node group. Currently, you can specify a single instance type for a node group.
* The default value for this parameter is `t3.medium`. If you choose a GPU instance type, be sure to specify the
* `AL2_x86_64_GPU` with the amiType parameter.
* `AL2_x86_64_GPU`, `BOTTLEROCKET_ARM_64_NVIDIA`, or `BOTTLEROCKET_x86_64_NVIDIA` with the amiType parameter.
*
* @default t3.medium
* @deprecated Use `instanceTypes` instead.
Expand Down Expand Up @@ -409,7 +421,7 @@ export class Nodegroup extends Resource implements INodegroup {

// if the user explicitly configured an ami type, make sure it's included in the possibleAmiTypes
if (props.amiType && !possibleAmiTypes.includes(props.amiType)) {
throw new Error(`The specified AMI does not match the instance types architecture, either specify one of ${possibleAmiTypes} or don't specify any`);
throw new Error(`The specified AMI does not match the instance types architecture, either specify one of ${possibleAmiTypes.join(', ')} or don't specify any`);
}

//if the user explicitly configured a Windows ami type, make sure the instanceType is allowed
Expand Down Expand Up @@ -550,7 +562,8 @@ const x8664AmiTypes: NodegroupAmiType[] = [NodegroupAmiType.AL2_X86_64, Nodegrou
const windowsAmiTypes: NodegroupAmiType[] = [NodegroupAmiType.WINDOWS_CORE_2019_X86_64,
NodegroupAmiType.WINDOWS_CORE_2022_X86_64, NodegroupAmiType.WINDOWS_FULL_2019_X86_64,
NodegroupAmiType.WINDOWS_FULL_2022_X86_64];
const gpuAmiTypes: NodegroupAmiType[] = [NodegroupAmiType.AL2_X86_64_GPU];
const gpuAmiTypes: NodegroupAmiType[] = [NodegroupAmiType.AL2_X86_64_GPU,
NodegroupAmiType.BOTTLEROCKET_X86_64_NVIDIA, NodegroupAmiType.BOTTLEROCKET_ARM_64_NVIDIA];

/**
* This function check if the instanceType is GPU instance.
Expand Down
42 changes: 39 additions & 3 deletions packages/aws-cdk-lib/aws-eks/test/nodegroup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ describe('node group', () => {
new ec2.InstanceType('p3.large'),
new ec2.InstanceType('g3.large'),
],
})).toThrow(/The specified AMI does not match the instance types architecture, either specify one of AL2_x86_64_GPU or don't specify any/);
})).toThrow(/The specified AMI does not match the instance types architecture, either specify one of AL2_x86_64_GPU, BOTTLEROCKET_x86_64_NVIDIA, BOTTLEROCKET_ARM_64_NVIDIA or don't specify any/);
});

/**
Expand All @@ -580,7 +580,7 @@ describe('node group', () => {
new ec2.InstanceType('c5.large'),
new ec2.InstanceType('m5.large'),
],
})).toThrow(/The specified AMI does not match the instance types architecture, either specify one of AL2_x86_64,BOTTLEROCKET_x86_64,WINDOWS_CORE_2019_x86_64,WINDOWS_CORE_2022_x86_64,WINDOWS_FULL_2019_x86_64,WINDOWS_FULL_2022_x86_64 or don't specify any/);
})).toThrow(/The specified AMI does not match the instance types architecture, either specify one of AL2_x86_64, BOTTLEROCKET_x86_64, WINDOWS_CORE_2019_x86_64, WINDOWS_CORE_2022_x86_64, WINDOWS_FULL_2019_x86_64, WINDOWS_FULL_2022_x86_64 or don't specify any/);
});

test('throws when AmiType is Windows and forbidden instanceType is selected', () => {
Expand Down Expand Up @@ -619,7 +619,43 @@ describe('node group', () => {
new ec2.InstanceType('c5.large'),
new ec2.InstanceType('m5.large'),
],
})).toThrow(/The specified AMI does not match the instance types architecture, either specify one of AL2_x86_64,BOTTLEROCKET_x86_64,WINDOWS_CORE_2019_x86_64,WINDOWS_CORE_2022_x86_64,WINDOWS_FULL_2019_x86_64,WINDOWS_FULL_2022_x86_64 or don't specify any/);
})).toThrow(/The specified AMI does not match the instance types architecture, either specify one of AL2_x86_64, BOTTLEROCKET_x86_64, WINDOWS_CORE_2019_x86_64, WINDOWS_CORE_2022_x86_64, WINDOWS_FULL_2019_x86_64, WINDOWS_FULL_2022_x86_64 or don't specify any/);
});

test('throws when LaunchTemplate is undefined, amiType is BOTTLEROCKET_ARM_64_NVIDIA and instanceTypes are not GPU', () => {
// GIVEN
const { stack, vpc } = testFixture();
const cluster = new eks.Cluster(stack, 'Cluster', {
vpc,
defaultCapacity: 0,
version: CLUSTER_VERSION,
});
// THEN
expect(() => cluster.addNodegroupCapacity('ng', {
amiType: NodegroupAmiType.BOTTLEROCKET_ARM_64_NVIDIA,
instanceTypes: [
new ec2.InstanceType('c5.large'),
new ec2.InstanceType('m5.large'),
],
})).toThrow(/The specified AMI does not match the instance types architecture, either specify one of AL2_x86_64, BOTTLEROCKET_x86_64, WINDOWS_CORE_2019_x86_64, WINDOWS_CORE_2022_x86_64, WINDOWS_FULL_2019_x86_64, WINDOWS_FULL_2022_x86_64 or don't specify any/);
});

test('throws when LaunchTemplate is undefined, amiType is BOTTLEROCKET_X86_64_NVIDIA and instanceTypes are not GPU', () => {
// GIVEN
const { stack, vpc } = testFixture();
const cluster = new eks.Cluster(stack, 'Cluster', {
vpc,
defaultCapacity: 0,
version: CLUSTER_VERSION,
});
// THEN
expect(() => cluster.addNodegroupCapacity('ng', {
amiType: NodegroupAmiType.BOTTLEROCKET_X86_64_NVIDIA,
instanceTypes: [
new ec2.InstanceType('c5.large'),
new ec2.InstanceType('m5.large'),
],
})).toThrow(/The specified AMI does not match the instance types architecture, either specify one of AL2_x86_64, BOTTLEROCKET_x86_64, WINDOWS_CORE_2019_x86_64, WINDOWS_CORE_2022_x86_64, WINDOWS_FULL_2019_x86_64, WINDOWS_FULL_2022_x86_64 or don't specify any/);
});

/**
Expand Down