From 6aa1b1b02ab3782b0e6419f8d5a340663cb47c81 Mon Sep 17 00:00:00 2001 From: Luca Pizzini Date: Fri, 8 Dec 2023 18:48:03 +0100 Subject: [PATCH] feat(eks): support Bottlerocket Nvidia AMIs (#28287) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds support for `BOTTLEROCKET_ARM_64_NVIDIA` and `BOTTLEROCKET_x86_64_NVIDIA` AMI types. Closes #28241. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/aws-cdk-lib/aws-eks/README.md | 11 +++++ .../aws-eks/lib/managed-nodegroup.ts | 29 +++++++++---- .../aws-eks/test/nodegroup.test.ts | 42 +++++++++++++++++-- 3 files changed, 71 insertions(+), 11 deletions(-) diff --git a/packages/aws-cdk-lib/aws-eks/README.md b/packages/aws-cdk-lib/aws-eks/README.md index fba788290d009..262a3758b1dd9 100644 --- a/packages/aws-cdk-lib/aws-eks/README.md +++ b/packages/aws-cdk-lib/aws-eks/README.md @@ -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 diff --git a/packages/aws-cdk-lib/aws-eks/lib/managed-nodegroup.ts b/packages/aws-cdk-lib/aws-eks/lib/managed-nodegroup.ts index b59b941318323..be4bd439f727f 100644 --- a/packages/aws-cdk-lib/aws-eks/lib/managed-nodegroup.ts +++ b/packages/aws-cdk-lib/aws-eks/lib/managed-nodegroup.ts @@ -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 { /** @@ -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) */ @@ -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. @@ -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 @@ -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. diff --git a/packages/aws-cdk-lib/aws-eks/test/nodegroup.test.ts b/packages/aws-cdk-lib/aws-eks/test/nodegroup.test.ts index 585c682b60958..51a58b6ab2e73 100644 --- a/packages/aws-cdk-lib/aws-eks/test/nodegroup.test.ts +++ b/packages/aws-cdk-lib/aws-eks/test/nodegroup.test.ts @@ -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/); }); /** @@ -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', () => { @@ -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/); }); /**