From 78717a70c67a23037482daa4f5d39cd82d2fe017 Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Wed, 9 Dec 2020 15:38:45 +0000 Subject: [PATCH 01/21] Fixes aws/aws-cdk#11827 --- packages/@aws-cdk/aws-eks/lib/cluster.ts | 2 +- .../@aws-cdk/aws-eks/lib/legacy-cluster.ts | 2 +- .../@aws-cdk/aws-eks/lib/managed-nodegroup.ts | 40 +++- .../test/integ.eks-cluster.expected.json | 210 +++++++++++++----- .../aws-eks/test/integ.eks-cluster.ts | 19 +- .../@aws-cdk/aws-eks/test/test.cluster.ts | 4 +- .../@aws-cdk/aws-eks/test/test.nodegroup.ts | 95 +++++--- 7 files changed, 271 insertions(+), 101 deletions(-) diff --git a/packages/@aws-cdk/aws-eks/lib/cluster.ts b/packages/@aws-cdk/aws-eks/lib/cluster.ts index 54cbeb9379d02..d1fd36d2ae9eb 100644 --- a/packages/@aws-cdk/aws-eks/lib/cluster.ts +++ b/packages/@aws-cdk/aws-eks/lib/cluster.ts @@ -1059,7 +1059,7 @@ export class Cluster extends ClusterBase { this.addAutoScalingGroupCapacity('DefaultCapacity', { instanceType, minCapacity }) : undefined; this.defaultNodegroup = props.defaultCapacityType !== DefaultCapacityType.EC2 ? - this.addNodegroupCapacity('DefaultCapacity', { instanceType, minSize: minCapacity }) : undefined; + this.addNodegroupCapacity('DefaultCapacity', { instanceType: [instanceType], minSize: minCapacity }) : undefined; } const outputConfigCommand = props.outputConfigCommand === undefined ? true : props.outputConfigCommand; diff --git a/packages/@aws-cdk/aws-eks/lib/legacy-cluster.ts b/packages/@aws-cdk/aws-eks/lib/legacy-cluster.ts index 27014e73871ef..25ca0372c12fe 100644 --- a/packages/@aws-cdk/aws-eks/lib/legacy-cluster.ts +++ b/packages/@aws-cdk/aws-eks/lib/legacy-cluster.ts @@ -234,7 +234,7 @@ export class LegacyCluster extends Resource implements ICluster { this.addCapacity('DefaultCapacity', { instanceType, minCapacity }) : undefined; this.defaultNodegroup = props.defaultCapacityType !== DefaultCapacityType.EC2 ? - this.addNodegroup('DefaultCapacity', { instanceType, minSize: minCapacity }) : undefined; + this.addNodegroup('DefaultCapacity', { instanceType: [instanceType], minSize: minCapacity }) : undefined; } const outputConfigCommand = props.outputConfigCommand === undefined ? true : props.outputConfigCommand; diff --git a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts index ea7e7a448e4f8..5361adfbcd809 100644 --- a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts @@ -37,6 +37,20 @@ export enum NodegroupAmiType { AL2_ARM_64 = 'AL2_ARM_64' } +/** + * Capacity type of the managed node group + */ +export enum CapacityType { + /** + * spot instances + */ + SPOT = 'SPOT', + /** + * on-demand instances + */ + ON_DEMAND = 'ON_DEMAND' +} + /** * The remote access (SSH) configuration to use with your node group. * @@ -139,7 +153,7 @@ export interface NodegroupOptions { * * @default t3.medium */ - readonly instanceType?: InstanceType; + readonly instanceType?: InstanceType[]; /** * The Kubernetes labels to be applied to the nodes in the node group when they are created. * @@ -183,6 +197,12 @@ export interface NodegroupOptions { * @default - no launch template */ readonly launchTemplateSpec?: LaunchTemplateSpec; + /** + * The capacity type of the nodegroup. + * + * @default - ON_DEMAND + */ + readonly capacityType?: CapacityType; } /** @@ -271,11 +291,11 @@ export class Nodegroup extends Resource implements INodegroup { nodegroupName: props.nodegroupName, nodeRole: this.role.roleArn, subnets: this.cluster.vpc.selectSubnets(props.subnets).subnetIds, - amiType: props.amiType ?? (props.instanceType ? getAmiTypeForInstanceType(props.instanceType).toString() : + amiType: props.amiType ?? (props.instanceType ? getAmiTypeForInstanceType(props.instanceType[0]).toString() : undefined), diskSize: props.diskSize, forceUpdateEnabled: props.forceUpdate ?? true, - instanceTypes: props.instanceType ? [props.instanceType.toString()] : undefined, + instanceTypes: props.instanceType ? props.instanceType.map(t => t.toString()) : undefined, labels: props.labels, releaseVersion: props.releaseVersion, remoteAccess: props.remoteAccess ? { @@ -291,17 +311,21 @@ export class Nodegroup extends Resource implements INodegroup { tags: props.tags, }); + if (props.capacityType) { + resource.addPropertyOverride('CapacityType', props.capacityType.valueOf()); + } + if (props.launchTemplateSpec) { if (props.diskSize) { // see - https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html // and https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-nodegroup.html#cfn-eks-nodegroup-disksize throw new Error('diskSize must be specified within the launch template'); } - if (props.instanceType) { - // see - https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html - // and https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-nodegroup.html#cfn-eks-nodegroup-disksize - throw new Error('Instance types must be specified within the launch template'); - } + /** + * Instance types can be specified either in `instanceType` or launch template but not both. AS we can not check the content of + * the provided launch template and the `instanceType` property is preferrable. We allow users to define `instanceType` property here. + * see - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-nodegroup.html#cfn-eks-nodegroup-instancetypes + */ // TODO: update this when the L1 resource spec is updated. resource.addPropertyOverride('LaunchTemplate', { Id: props.launchTemplateSpec.id, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json index 7e5d81152c4d8..e24fed74e83b6 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json @@ -1251,6 +1251,13 @@ ] }, "\\\",\\\"username\\\":\\\"system:node:{{EC2PrivateDNSName}}\\\",\\\"groups\\\":[\\\"system:bootstrappers\\\",\\\"system:nodes\\\"]},{\\\"rolearn\\\":\\\"", + { + "Fn::GetAtt": [ + "ClusterNodegroupextrangspotNodeGroupRoleB53B4857", + "Arn" + ] + }, + "\\\",\\\"username\\\":\\\"system:node:{{EC2PrivateDNSName}}\\\",\\\"groups\\\":[\\\"system:bootstrappers\\\",\\\"system:nodes\\\"]},{\\\"rolearn\\\":\\\"", { "Fn::GetAtt": [ "ClusterNodegroupextrangarmNodeGroupRoleADF5749F", @@ -3206,11 +3213,7 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], - "AmiType": "AL2_x86_64", "ForceUpdateEnabled": true, - "InstanceTypes": [ - "t3.small" - ], "ScalingConfig": { "DesiredSize": 1, "MaxSize": 1, @@ -3218,6 +3221,109 @@ } } }, + "ClusterNodegroupextrangspotNodeGroupRoleB53B4857": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": { + "Fn::Join": [ + "", + [ + "ec2.", + { + "Ref": "AWS::URLSuffix" + } + ] + ] + } + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonEKSWorkerNodePolicy" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonEKS_CNI_Policy" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" + ] + ] + } + ] + } + }, + "ClusterNodegroupextrangspotB327AE6B": { + "Type": "AWS::EKS::Nodegroup", + "Properties": { + "ClusterName": { + "Ref": "Cluster9EE0221C" + }, + "NodeRole": { + "Fn::GetAtt": [ + "ClusterNodegroupextrangspotNodeGroupRoleB53B4857", + "Arn" + ] + }, + "Subnets": [ + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + }, + { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + }, + { + "Ref": "VpcPrivateSubnet3SubnetF258B56E" + } + ], + "AmiType": "AL2_x86_64", + "ForceUpdateEnabled": true, + "InstanceTypes": [ + "c5.large", + "c5a.large", + "c5d.large" + ], + "ScalingConfig": { + "DesiredSize": 3, + "MaxSize": 3, + "MinSize": 3 + }, + "CapacityType": "SPOT" + } + }, "ClusterNodegroupextrangarmNodeGroupRoleADF5749F": { "Type": "AWS::IAM::Role", "Properties": { @@ -3927,7 +4033,7 @@ } } }, - "AWSCDKCfnUtilsProviderCustomResourceProviderRoleFE0EE867": { + "CustomAWSCDKOpenIdConnectProviderCustomResourceProviderRole517FED65": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { @@ -3946,15 +4052,36 @@ { "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Resource": "*", + "Action": [ + "iam:CreateOpenIDConnectProvider", + "iam:DeleteOpenIDConnectProvider", + "iam:UpdateOpenIDConnectProviderThumbprint", + "iam:AddClientIDToOpenIDConnectProvider", + "iam:RemoveClientIDFromOpenIDConnectProvider" + ] + } + ] + } + } ] } }, - "AWSCDKCfnUtilsProviderCustomResourceProviderHandlerCF82AA57": { + "CustomAWSCDKOpenIdConnectProviderCustomResourceProviderHandlerF2C543E0": { "Type": "AWS::Lambda::Function", "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParametersb075459e6bf309093fbd4b9a9e576a5f172b91c14d84eedb0f069566f6abb0deS3Bucket055DC235" + "Ref": "AssetParametersb075459e6bf309093fbd4b9a9e576a5f172b91c14d84eedb0f069566f6abb0deS3Bucket14156880" }, "S3Key": { "Fn::Join": [ @@ -3967,7 +4094,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParametersb075459e6bf309093fbd4b9a9e576a5f172b91c14d84eedb0f069566f6abb0deS3VersionKey2FFFA299" + "Ref": "AssetParametersb075459e6bf309093fbd4b9a9e576a5f172b91c14d84eedb0f069566f6abb0deS3VersionKey5225BCA4" } ] } @@ -3980,7 +4107,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParametersb075459e6bf309093fbd4b9a9e576a5f172b91c14d84eedb0f069566f6abb0deS3VersionKey2FFFA299" + "Ref": "AssetParametersb075459e6bf309093fbd4b9a9e576a5f172b91c14d84eedb0f069566f6abb0deS3VersionKey5225BCA4" } ] } @@ -3995,17 +4122,17 @@ "Handler": "__entrypoint__.handler", "Role": { "Fn::GetAtt": [ - "AWSCDKCfnUtilsProviderCustomResourceProviderRoleFE0EE867", + "CustomAWSCDKOpenIdConnectProviderCustomResourceProviderRole517FED65", "Arn" ] }, "Runtime": "nodejs12.x" }, "DependsOn": [ - "AWSCDKCfnUtilsProviderCustomResourceProviderRoleFE0EE867" + "CustomAWSCDKOpenIdConnectProviderCustomResourceProviderRole517FED65" ] }, - "CustomAWSCDKOpenIdConnectProviderCustomResourceProviderRole517FED65": { + "AWSCDKCfnUtilsProviderCustomResourceProviderRoleFE0EE867": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { @@ -4024,36 +4151,15 @@ { "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" } - ], - "Policies": [ - { - "PolicyName": "Inline", - "PolicyDocument": { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Resource": "*", - "Action": [ - "iam:CreateOpenIDConnectProvider", - "iam:DeleteOpenIDConnectProvider", - "iam:UpdateOpenIDConnectProviderThumbprint", - "iam:AddClientIDToOpenIDConnectProvider", - "iam:RemoveClientIDFromOpenIDConnectProvider" - ] - } - ] - } - } ] } }, - "CustomAWSCDKOpenIdConnectProviderCustomResourceProviderHandlerF2C543E0": { + "AWSCDKCfnUtilsProviderCustomResourceProviderHandlerCF82AA57": { "Type": "AWS::Lambda::Function", "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters952bd1c03e8201c4c1c67d6de0f3fdaaf88fda05f89a1232c3f6364343cd5344S3Bucket14156880" + "Ref": "AssetParameters952bd1c03e8201c4c1c67d6de0f3fdaaf88fda05f89a1232c3f6364343cd5344S3Bucket055DC235" }, "S3Key": { "Fn::Join": [ @@ -4066,7 +4172,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters952bd1c03e8201c4c1c67d6de0f3fdaaf88fda05f89a1232c3f6364343cd5344S3VersionKey5225BCA4" + "Ref": "AssetParameters952bd1c03e8201c4c1c67d6de0f3fdaaf88fda05f89a1232c3f6364343cd5344S3VersionKey2FFFA299" } ] } @@ -4079,7 +4185,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters952bd1c03e8201c4c1c67d6de0f3fdaaf88fda05f89a1232c3f6364343cd5344S3VersionKey5225BCA4" + "Ref": "AssetParameters952bd1c03e8201c4c1c67d6de0f3fdaaf88fda05f89a1232c3f6364343cd5344S3VersionKey2FFFA299" } ] } @@ -4094,14 +4200,14 @@ "Handler": "__entrypoint__.handler", "Role": { "Fn::GetAtt": [ - "CustomAWSCDKOpenIdConnectProviderCustomResourceProviderRole517FED65", + "AWSCDKCfnUtilsProviderCustomResourceProviderRoleFE0EE867", "Arn" ] }, "Runtime": "nodejs12.x" }, "DependsOn": [ - "CustomAWSCDKOpenIdConnectProviderCustomResourceProviderRole517FED65" + "AWSCDKCfnUtilsProviderCustomResourceProviderRoleFE0EE867" ] }, "WebServiceSecurityGroupA556AEB5": { @@ -4545,18 +4651,6 @@ "Type": "String", "Description": "Artifact hash for asset \"b7d8a9750f8bfded8ac76be100e3bee1c3d4824df006766110d023f42952f5c2\"" }, - "AssetParameters952bd1c03e8201c4c1c67d6de0f3fdaaf88fda05f89a1232c3f6364343cd5344S3Bucket055DC235": { - "Type": "String", - "Description": "S3 bucket for asset \"952bd1c03e8201c4c1c67d6de0f3fdaaf88fda05f89a1232c3f6364343cd5344\"" - }, - "AssetParameters952bd1c03e8201c4c1c67d6de0f3fdaaf88fda05f89a1232c3f6364343cd5344S3VersionKey2FFFA299": { - "Type": "String", - "Description": "S3 key for asset version \"952bd1c03e8201c4c1c67d6de0f3fdaaf88fda05f89a1232c3f6364343cd5344\"" - }, - "AssetParameters952bd1c03e8201c4c1c67d6de0f3fdaaf88fda05f89a1232c3f6364343cd5344ArtifactHash1AB042BC": { - "Type": "String", - "Description": "Artifact hash for asset \"952bd1c03e8201c4c1c67d6de0f3fdaaf88fda05f89a1232c3f6364343cd5344\"" - }, "AssetParametersb075459e6bf309093fbd4b9a9e576a5f172b91c14d84eedb0f069566f6abb0deS3Bucket14156880": { "Type": "String", "Description": "S3 bucket for asset \"b075459e6bf309093fbd4b9a9e576a5f172b91c14d84eedb0f069566f6abb0de\"" @@ -4569,6 +4663,18 @@ "Type": "String", "Description": "Artifact hash for asset \"b075459e6bf309093fbd4b9a9e576a5f172b91c14d84eedb0f069566f6abb0de\"" }, + "AssetParameters952bd1c03e8201c4c1c67d6de0f3fdaaf88fda05f89a1232c3f6364343cd5344S3Bucket055DC235": { + "Type": "String", + "Description": "S3 bucket for asset \"952bd1c03e8201c4c1c67d6de0f3fdaaf88fda05f89a1232c3f6364343cd5344\"" + }, + "AssetParameters952bd1c03e8201c4c1c67d6de0f3fdaaf88fda05f89a1232c3f6364343cd5344S3VersionKey2FFFA299": { + "Type": "String", + "Description": "S3 key for asset version \"952bd1c03e8201c4c1c67d6de0f3fdaaf88fda05f89a1232c3f6364343cd5344\"" + }, + "AssetParameters952bd1c03e8201c4c1c67d6de0f3fdaaf88fda05f89a1232c3f6364343cd5344ArtifactHash1AB042BC": { + "Type": "String", + "Description": "Artifact hash for asset \"952bd1c03e8201c4c1c67d6de0f3fdaaf88fda05f89a1232c3f6364343cd5344\"" + }, "AssetParameters2acc31b34c05692ab3ea9831a27e5f241cffb21857e633d8256b8f0ebf5f3f43S3BucketB43AFE04": { "Type": "String", "Description": "S3 bucket for asset \"2acc31b34c05692ab3ea9831a27e5f241cffb21857e633d8256b8f0ebf5f3f43\"" @@ -4626,4 +4732,4 @@ "Default": "/aws/service/eks/optimized-ami/1.14/amazon-linux-2/recommended/image_id" } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.ts index d8522eb543619..14841e7c553c4 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.ts +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.ts @@ -53,6 +53,8 @@ class EksClusterStack extends TestStack { this.assertNodeGroupX86(); + this.assertNodeGroupSpot(); + this.assertNodeGroupArm(); this.assertNodeGroupCustomAmi(); @@ -140,12 +142,25 @@ class EksClusterStack extends TestStack { private assertNodeGroupX86() { // add a extra nodegroup this.cluster.addNodegroupCapacity('extra-ng', { - instanceType: new ec2.InstanceType('t3.small'), minSize: 1, // reusing the default capacity nodegroup instance role when available nodeRole: this.cluster.defaultCapacity ? this.cluster.defaultCapacity.role : undefined, }); } + private assertNodeGroupSpot() { + // add a extra nodegroup + this.cluster.addNodegroupCapacity('extra-ng-spot', { + instanceType: [ + new ec2.InstanceType('c5.large'), + new ec2.InstanceType('c5a.large'), + new ec2.InstanceType('c5d.large'), + ], + minSize: 3, + // reusing the default capacity nodegroup instance role when available + nodeRole: this.cluster.defaultCapacity ? this.cluster.defaultCapacity.role : undefined, + capacityType: eks.CapacityType.SPOT, + }); + } private assertNodeGroupCustomAmi() { // add a extra nodegroup const userData = ec2.UserData.forLinux(); @@ -173,7 +188,7 @@ class EksClusterStack extends TestStack { private assertNodeGroupArm() { // add a extra nodegroup this.cluster.addNodegroupCapacity('extra-ng-arm', { - instanceType: new ec2.InstanceType('m6g.medium'), + instanceType: [new ec2.InstanceType('m6g.medium')], minSize: 1, // reusing the default capacity nodegroup instance role when available nodeRole: this.cluster.defaultCapacity ? this.cluster.defaultCapacity.role : undefined, diff --git a/packages/@aws-cdk/aws-eks/test/test.cluster.ts b/packages/@aws-cdk/aws-eks/test/test.cluster.ts index facdf1880d426..6f367eaa1654d 100644 --- a/packages/@aws-cdk/aws-eks/test/test.cluster.ts +++ b/packages/@aws-cdk/aws-eks/test/test.cluster.ts @@ -1252,7 +1252,7 @@ export = { version: CLUSTER_VERSION, defaultCapacityInstance: new ec2.InstanceType('m6g.medium'), }).addNodegroupCapacity('ng', { - instanceType: new ec2.InstanceType('m6g.medium'), + instanceType: [new ec2.InstanceType('m6g.medium')], }); // THEN @@ -1272,7 +1272,7 @@ export = { version: CLUSTER_VERSION, defaultCapacityInstance: new ec2.InstanceType('t4g.medium'), }).addNodegroupCapacity('ng', { - instanceType: new ec2.InstanceType('t4g.medium'), + instanceType: [new ec2.InstanceType('t4g.medium')], }); // THEN diff --git a/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts b/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts index c21f81ded307a..f63cc9a6ac4fa 100644 --- a/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts @@ -193,7 +193,7 @@ export = { }); new eks.Nodegroup(stack, 'Nodegroup', { cluster, - instanceType: new ec2.InstanceType('m5.large'), + instanceType: [new ec2.InstanceType('m5.large')], }); // THEN @@ -205,6 +205,65 @@ export = { )); test.done(); }, + 'create nodegroup with on-demand capacity type'(test: Test) { + // GIVEN + const { stack, vpc } = testFixture(); + + // WHEN + const cluster = new eks.Cluster(stack, 'Cluster', { + vpc, + kubectlEnabled: true, + defaultCapacity: 0, + version: CLUSTER_VERSION, + }); + new eks.Nodegroup(stack, 'Nodegroup', { + cluster, + instanceType: [new ec2.InstanceType('m5.large')], + capacityType: eks.CapacityType.ON_DEMAND, + }); + + // THEN + expect(stack).to(haveResourceLike('AWS::EKS::Nodegroup', { + InstanceTypes: [ + 'm5.large', + ], + CapacityType: 'ON_DEMAND', + }, + )); + test.done(); + }, + 'create nodegroup with spot capacity type'(test: Test) { + // GIVEN + const { stack, vpc } = testFixture(); + + // WHEN + const cluster = new eks.Cluster(stack, 'Cluster', { + vpc, + kubectlEnabled: true, + defaultCapacity: 0, + version: CLUSTER_VERSION, + }); + new eks.Nodegroup(stack, 'Nodegroup', { + cluster, + instanceType: [ + new ec2.InstanceType('m5.large'), + new ec2.InstanceType('t3.large'), + new ec2.InstanceType('c5.large'), + ], + capacityType: eks.CapacityType.SPOT, + }); + // THEN + expect(stack).to(haveResourceLike('AWS::EKS::Nodegroup', { + InstanceTypes: [ + 'm5.large', + 't3.large', + 'c5.large', + ], + CapacityType: 'SPOT', + }, + )); + test.done(); + }, 'remoteAccess without security group provided'(test: Test) { // GIVEN const { stack, vpc } = testFixture(); @@ -409,38 +468,4 @@ export = { }), /diskSize must be specified within the launch template/); test.done(); }, - 'throws when both instanceType and launch template specified'(test: Test) { - // GIVEN - const { stack, vpc } = testFixture(); - - // WHEN - const cluster = new eks.Cluster(stack, 'Cluster', { - vpc, - kubectlEnabled: true, - defaultCapacity: 0, - version: CLUSTER_VERSION, - }); - const userData = ec2.UserData.forLinux(); - userData.addCommands( - 'set -o xtrace', - `/etc/eks/bootstrap.sh ${cluster.clusterName}`, - ); - const lt = new ec2.CfnLaunchTemplate(stack, 'LaunchTemplate', { - launchTemplateData: { - imageId: new eks.EksOptimizedImage().getImage(stack).imageId, - instanceType: new ec2.InstanceType('t3.small').toString(), - userData: cdk.Fn.base64(userData.render()), - }, - }); - // THEN - test.throws(() => - cluster.addNodegroupCapacity('ng-lt', { - instanceType: new ec2.InstanceType('c5.large'), - launchTemplateSpec: { - id: lt.ref, - version: lt.attrDefaultVersionNumber, - }, - }), /Instance types must be specified within the launch template/); - test.done(); - }, }; From 554d0a413f02c61997907b040868971c80ff05b8 Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Wed, 9 Dec 2020 16:04:31 +0000 Subject: [PATCH 02/21] chore(doc): update README --- packages/@aws-cdk/aws-eks/README.md | 31 +++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/aws-eks/README.md b/packages/@aws-cdk/aws-eks/README.md index 1b09a3ac995e5..116c8cd51a18d 100644 --- a/packages/@aws-cdk/aws-eks/README.md +++ b/packages/@aws-cdk/aws-eks/README.md @@ -201,7 +201,7 @@ const cluster = new eks.Cluster(this, 'HelloEKS', { }); cluster.addNodegroupCapacity('custom-node-group', { - instanceType: new ec2.InstanceType('m5.large'), + instanceType: [new ec2.InstanceType('m5.large')], minSize: 4, diskSize: 100, amiType: eks.NodegroupAmiType.AL2_X86_64_GPU, @@ -209,6 +209,27 @@ cluster.addNodegroupCapacity('custom-node-group', { }); ``` +#### Spot Instances Support + +Use `capacityType` to create the Spot managed node groups. To maximize the availability of your applications while using +Spot Instances, we recommend that you configure a Spot managed node group to use multiple instance types. + +> For more details visit [Managed node group capacity types ](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html#managed-node-group-capacity-types). + + +```ts +cluster.addNodegroupCapacity('extra-ng-spot', { + instanceType: [ + new ec2.InstanceType('c5.large'), + new ec2.InstanceType('c5a.large'), + new ec2.InstanceType('c5d.large'), + ], + minSize: 3, + capacityType: eks.CapacityType.SPOT, +}); + +``` + #### Launch Template Support You can specify a launch template that the node group will use. Note that when using a custom AMI, Amazon EKS doesn't merge any user data. @@ -236,7 +257,9 @@ cluster.addNodegroupCapacity('extra-ng', { }); ``` -> For more details visit [Launch Template Support](https://docs.aws.amazon.com/en_ca/eks/latest/userguide/launch-templates.html). +You may specify one or multiple instance types in either `instanceType` property of `NodeGroup` or in the launch template but not both. + +> For more details visit [Launch Template Support](https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html). Graviton 2 instance types are supported including `c6g`, `m6g`, `r6g` and `t4g`. @@ -504,13 +527,13 @@ Amazon Linux 2 AMI for ARM64 will be automatically selected. ```ts // add a managed ARM64 nodegroup cluster.addNodegroupCapacity('extra-ng-arm', { - instanceType: new ec2.InstanceType('m6g.medium'), + instanceType: [new ec2.InstanceType('m6g.medium')], minSize: 2, }); // add a self-managed ARM64 nodegroup cluster.addAutoScalingGroupCapacity('self-ng-arm', { - instanceType: new ec2.InstanceType('m6g.medium'), + instanceType: [new ec2.InstanceType('m6g.medium')], minCapacity: 2, }) ``` From 93d300ac0a281d0a34237a5991183100135137e3 Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Wed, 9 Dec 2020 16:21:55 +0000 Subject: [PATCH 03/21] chore(doc): minor --- packages/@aws-cdk/aws-eks/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-eks/README.md b/packages/@aws-cdk/aws-eks/README.md index 116c8cd51a18d..045eae44a2f37 100644 --- a/packages/@aws-cdk/aws-eks/README.md +++ b/packages/@aws-cdk/aws-eks/README.md @@ -214,7 +214,7 @@ cluster.addNodegroupCapacity('custom-node-group', { Use `capacityType` to create the Spot managed node groups. To maximize the availability of your applications while using Spot Instances, we recommend that you configure a Spot managed node group to use multiple instance types. -> For more details visit [Managed node group capacity types ](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html#managed-node-group-capacity-types). +> For more details visit [Managed node group capacity types](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html#managed-node-group-capacity-types). ```ts From af765cd91be940d77b15ef911ad2389b2517ff47 Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Wed, 16 Dec 2020 08:38:11 +0000 Subject: [PATCH 04/21] use instanceTypes instead --- packages/@aws-cdk/aws-eks/README.md | 12 +++--- packages/@aws-cdk/aws-eks/lib/cluster.ts | 2 +- .../@aws-cdk/aws-eks/lib/legacy-cluster.ts | 2 +- .../@aws-cdk/aws-eks/lib/managed-nodegroup.ts | 37 ++++++++++++++++--- .../test/integ.eks-cluster.expected.json | 4 ++ .../aws-eks/test/integ.eks-cluster.ts | 5 ++- .../@aws-cdk/aws-eks/test/test.cluster.ts | 4 +- .../@aws-cdk/aws-eks/test/test.nodegroup.ts | 6 +-- 8 files changed, 51 insertions(+), 21 deletions(-) diff --git a/packages/@aws-cdk/aws-eks/README.md b/packages/@aws-cdk/aws-eks/README.md index 186414ac9fa28..aa4112dd7845c 100644 --- a/packages/@aws-cdk/aws-eks/README.md +++ b/packages/@aws-cdk/aws-eks/README.md @@ -201,7 +201,7 @@ const cluster = new eks.Cluster(this, 'HelloEKS', { }); cluster.addNodegroupCapacity('custom-node-group', { - instanceType: [new ec2.InstanceType('m5.large')], + instanceTypes: [new ec2.InstanceType('m5.large')], minSize: 4, diskSize: 100, amiType: eks.NodegroupAmiType.AL2_X86_64_GPU, @@ -212,14 +212,14 @@ cluster.addNodegroupCapacity('custom-node-group', { #### Spot Instances Support Use `capacityType` to create the Spot managed node groups. To maximize the availability of your applications while using -Spot Instances, we recommend that you configure a Spot managed node group to use multiple instance types. +Spot Instances, we recommend that you configure a Spot managed node group to use multiple instance types with `instanceTypes`. > For more details visit [Managed node group capacity types](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html#managed-node-group-capacity-types). ```ts cluster.addNodegroupCapacity('extra-ng-spot', { - instanceType: [ + instanceTypes: [ new ec2.InstanceType('c5.large'), new ec2.InstanceType('c5a.large'), new ec2.InstanceType('c5d.large'), @@ -257,7 +257,7 @@ cluster.addNodegroupCapacity('extra-ng', { }); ``` -You may specify one or multiple instance types in either `instanceType` property of `NodeGroup` or in the launch template but not both. +You may specify one or multiple instance types in either `instanceTypes` property of `NodeGroup` or in the launch template but not both. > For more details visit [Launch Template Support](https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html). @@ -550,13 +550,13 @@ Amazon Linux 2 AMI for ARM64 will be automatically selected. ```ts // add a managed ARM64 nodegroup cluster.addNodegroupCapacity('extra-ng-arm', { - instanceType: [new ec2.InstanceType('m6g.medium')], + instanceTypes: [new ec2.InstanceType('m6g.medium')], minSize: 2, }); // add a self-managed ARM64 nodegroup cluster.addAutoScalingGroupCapacity('self-ng-arm', { - instanceType: [new ec2.InstanceType('m6g.medium')], + instanceType: new ec2.InstanceType('m6g.medium'), minCapacity: 2, }) ``` diff --git a/packages/@aws-cdk/aws-eks/lib/cluster.ts b/packages/@aws-cdk/aws-eks/lib/cluster.ts index 40d944c5371e4..772f388ca6bf4 100644 --- a/packages/@aws-cdk/aws-eks/lib/cluster.ts +++ b/packages/@aws-cdk/aws-eks/lib/cluster.ts @@ -1119,7 +1119,7 @@ export class Cluster extends ClusterBase { this.addAutoScalingGroupCapacity('DefaultCapacity', { instanceType, minCapacity }) : undefined; this.defaultNodegroup = props.defaultCapacityType !== DefaultCapacityType.EC2 ? - this.addNodegroupCapacity('DefaultCapacity', { instanceType: [instanceType], minSize: minCapacity }) : undefined; + this.addNodegroupCapacity('DefaultCapacity', { instanceTypes: [instanceType], minSize: minCapacity }) : undefined; } const outputConfigCommand = props.outputConfigCommand === undefined ? true : props.outputConfigCommand; diff --git a/packages/@aws-cdk/aws-eks/lib/legacy-cluster.ts b/packages/@aws-cdk/aws-eks/lib/legacy-cluster.ts index 3e644fcc52fe6..2193ec301de3c 100644 --- a/packages/@aws-cdk/aws-eks/lib/legacy-cluster.ts +++ b/packages/@aws-cdk/aws-eks/lib/legacy-cluster.ts @@ -236,7 +236,7 @@ export class LegacyCluster extends Resource implements ICluster { this.addCapacity('DefaultCapacity', { instanceType, minCapacity }) : undefined; this.defaultNodegroup = props.defaultCapacityType !== DefaultCapacityType.EC2 ? - this.addNodegroup('DefaultCapacity', { instanceType: [instanceType], minSize: minCapacity }) : undefined; + this.addNodegroup('DefaultCapacity', { instanceType, minSize: minCapacity }) : undefined; } const outputConfigCommand = props.outputConfigCommand === undefined ? true : props.outputConfigCommand; diff --git a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts index 5361adfbcd809..7c8eea1517f20 100644 --- a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts @@ -109,7 +109,7 @@ export interface NodegroupOptions { /** * The AMI type for your node group. * - * @default - auto-determined from the instanceType property. + * @default - auto-determined from the instanceTypes property. */ readonly amiType?: NodegroupAmiType; /** @@ -149,11 +149,16 @@ 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` with the amiType parameter. This property will be ignored if `instanceTypes` is defined. * * @default t3.medium + * @deprecated Use `instanceTypes` instead. */ - readonly instanceType?: InstanceType[]; + readonly instanceType?: InstanceType; + /** + * The instance types to use for your node group. + */ + readonly instanceTypes?: InstanceType[]; /** * The Kubernetes labels to be applied to the nodes in the node group when they are created. * @@ -254,6 +259,7 @@ export class Nodegroup extends Resource implements INodegroup { private readonly desiredSize: number; private readonly maxSize: number; private readonly minSize: number; + private readonly instanceType: InstanceType[]; constructor(scope: Construct, id: string, props: NodegroupProps) { super(scope, id, { @@ -266,6 +272,8 @@ export class Nodegroup extends Resource implements INodegroup { this.maxSize = props.maxSize ?? this.desiredSize; this.minSize = props.minSize ?? 1; + const DEFAULT_INSTANCE_TYPE = new InstanceType('t3.medium'); + if (this.desiredSize > this.maxSize) { throw new Error(`Desired capacity ${this.desiredSize} can't be greater than max size ${this.maxSize}`); } @@ -273,6 +281,13 @@ export class Nodegroup extends Resource implements INodegroup { throw new Error(`Minimum capacity ${this.minSize} can't be greater than desired size ${this.desiredSize}`); } + this.instanceType = props.instanceTypes ?? (props.instanceType ? [props.instanceType] : [DEFAULT_INSTANCE_TYPE]); + // console.log(this.instanceType); + const determinedAmiType = determineAmiTypes(this.instanceType); + if (props.amiType && props.amiType !== determinedAmiType) { + throw new Error(`amiType is not correct - should be ${determinedAmiType}`); + } + if (!props.nodeRole) { const ngRole = new Role(this, 'NodeGroupRole', { assumedBy: new ServicePrincipal('ec2.amazonaws.com'), @@ -291,11 +306,12 @@ export class Nodegroup extends Resource implements INodegroup { nodegroupName: props.nodegroupName, nodeRole: this.role.roleArn, subnets: this.cluster.vpc.selectSubnets(props.subnets).subnetIds, - amiType: props.amiType ?? (props.instanceType ? getAmiTypeForInstanceType(props.instanceType[0]).toString() : - undefined), + // AmyType is not allowed by CFN when specifying an image id in your launch template. + amiType: props.launchTemplateSpec == undefined ? determinedAmiType : undefined, diskSize: props.diskSize, forceUpdateEnabled: props.forceUpdate ?? true, - instanceTypes: props.instanceType ? props.instanceType.map(t => t.toString()) : undefined, + instanceTypes: props.instanceTypes ? props.instanceTypes.map(t => t.toString()) : + props.instanceType ? [props.instanceType.toString()] : undefined, labels: props.labels, releaseVersion: props.releaseVersion, remoteAccess: props.remoteAccess ? { @@ -364,3 +380,12 @@ function getAmiTypeForInstanceType(instanceType: InstanceType) { NodegroupAmiType.AL2_X86_64; } +function determineAmiTypes(instanceType: InstanceType[]) { + const amiTypes = instanceType.map(i =>getAmiTypeForInstanceType(i)); + const uniq = [...new Set(amiTypes)]; + if (uniq.length > 1) { + throw new Error('instanceTypes of different CPU architectures not allowed'); + } else { + return uniq[0]; + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json index 1f795022cb611..4b3aab27a6a6f 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json @@ -3216,7 +3216,11 @@ "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], + "AmiType": "AL2_x86_64", "ForceUpdateEnabled": true, + "InstanceTypes": [ + "t3.small" + ], "ScalingConfig": { "DesiredSize": 1, "MaxSize": 1, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.ts index 14841e7c553c4..c88e4b97369c6 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.ts +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.ts @@ -142,6 +142,7 @@ class EksClusterStack extends TestStack { private assertNodeGroupX86() { // add a extra nodegroup this.cluster.addNodegroupCapacity('extra-ng', { + instanceType: new ec2.InstanceType('t3.small'), minSize: 1, // reusing the default capacity nodegroup instance role when available nodeRole: this.cluster.defaultCapacity ? this.cluster.defaultCapacity.role : undefined, @@ -150,7 +151,7 @@ class EksClusterStack extends TestStack { private assertNodeGroupSpot() { // add a extra nodegroup this.cluster.addNodegroupCapacity('extra-ng-spot', { - instanceType: [ + instanceTypes: [ new ec2.InstanceType('c5.large'), new ec2.InstanceType('c5a.large'), new ec2.InstanceType('c5d.large'), @@ -188,7 +189,7 @@ class EksClusterStack extends TestStack { private assertNodeGroupArm() { // add a extra nodegroup this.cluster.addNodegroupCapacity('extra-ng-arm', { - instanceType: [new ec2.InstanceType('m6g.medium')], + instanceType: new ec2.InstanceType('m6g.medium'), minSize: 1, // reusing the default capacity nodegroup instance role when available nodeRole: this.cluster.defaultCapacity ? this.cluster.defaultCapacity.role : undefined, diff --git a/packages/@aws-cdk/aws-eks/test/test.cluster.ts b/packages/@aws-cdk/aws-eks/test/test.cluster.ts index 5b4da0d41e1d0..d57c18561c2b4 100644 --- a/packages/@aws-cdk/aws-eks/test/test.cluster.ts +++ b/packages/@aws-cdk/aws-eks/test/test.cluster.ts @@ -1278,7 +1278,7 @@ export = { prune: false, defaultCapacityInstance: new ec2.InstanceType('m6g.medium'), }).addNodegroupCapacity('ng', { - instanceType: [new ec2.InstanceType('m6g.medium')], + instanceType: new ec2.InstanceType('m6g.medium'), }); // THEN @@ -1299,7 +1299,7 @@ export = { prune: false, defaultCapacityInstance: new ec2.InstanceType('t4g.medium'), }).addNodegroupCapacity('ng', { - instanceType: [new ec2.InstanceType('t4g.medium')], + instanceType: new ec2.InstanceType('t4g.medium'), }); // THEN diff --git a/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts b/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts index a8869bd4a856f..0693d73235e78 100644 --- a/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts @@ -194,7 +194,7 @@ export = { }); new eks.Nodegroup(stack, 'Nodegroup', { cluster, - instanceType: [new ec2.InstanceType('m5.large')], + instanceType: new ec2.InstanceType('m5.large'), }); // THEN @@ -219,7 +219,7 @@ export = { }); new eks.Nodegroup(stack, 'Nodegroup', { cluster, - instanceType: [new ec2.InstanceType('m5.large')], + instanceType: new ec2.InstanceType('m5.large'), capacityType: eks.CapacityType.ON_DEMAND, }); @@ -246,7 +246,7 @@ export = { }); new eks.Nodegroup(stack, 'Nodegroup', { cluster, - instanceType: [ + instanceTypes: [ new ec2.InstanceType('m5.large'), new ec2.InstanceType('t3.large'), new ec2.InstanceType('c5.large'), From 1d12a0528c25d8f76e130355f65f890f382ac822 Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Wed, 16 Dec 2020 09:03:29 +0000 Subject: [PATCH 05/21] add integ tests --- .../@aws-cdk/aws-eks/lib/managed-nodegroup.ts | 2 + .../@aws-cdk/aws-eks/test/test.nodegroup.ts | 151 ++++++++++++++++++ 2 files changed, 153 insertions(+) diff --git a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts index 7c8eea1517f20..7e1bfb8b9a777 100644 --- a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts @@ -157,6 +157,8 @@ export interface NodegroupOptions { readonly instanceType?: InstanceType; /** * The instance types to use for your node group. + * @default t3.medium will be used according to the cloudformation document. + * @see - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-nodegroup.html#cfn-eks-nodegroup-instancetypes */ readonly instanceTypes?: InstanceType[]; /** diff --git a/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts b/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts index 0693d73235e78..6847761d108ba 100644 --- a/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts @@ -181,6 +181,27 @@ export = { expect(stack).to(countResources('AWS::EKS::Nodegroup', 2)); test.done(); }, + 'create nodegroup with minimal property provided'(test: Test) { + // GIVEN + const { stack, vpc } = testFixture(); + + // WHEN + const cluster = new eks.Cluster(stack, 'Cluster', { + vpc, + kubectlEnabled: true, + defaultCapacity: 0, + version: CLUSTER_VERSION, + }); + new eks.Nodegroup(stack, 'Nodegroup', { + cluster, + }); + + // THEN + expect(stack).to(haveResourceLike('AWS::EKS::Nodegroup', { + }, + )); + test.done(); + }, 'create nodegroup with instanceType provided'(test: Test) { // GIVEN const { stack, vpc } = testFixture(); @@ -265,6 +286,136 @@ export = { )); test.done(); }, + 'create nodegroup with ondemand capacity type'(test: Test) { + // GIVEN + const { stack, vpc } = testFixture(); + + // WHEN + const cluster = new eks.Cluster(stack, 'Cluster', { + vpc, + kubectlEnabled: true, + defaultCapacity: 0, + version: CLUSTER_VERSION, + }); + new eks.Nodegroup(stack, 'Nodegroup', { + cluster, + instanceTypes: [ + new ec2.InstanceType('m5.large'), + new ec2.InstanceType('t3.large'), + new ec2.InstanceType('c5.large'), + ], + capacityType: eks.CapacityType.ON_DEMAND, + }); + // THEN + expect(stack).to(haveResourceLike('AWS::EKS::Nodegroup', { + InstanceTypes: [ + 'm5.large', + 't3.large', + 'c5.large', + ], + CapacityType: 'ON_DEMAND', + }, + )); + test.done(); + }, + 'create nodegroup with both instanceTypes and instanceType defined'(test: Test) { + // GIVEN + const { stack, vpc } = testFixture(); + + // WHEN + const cluster = new eks.Cluster(stack, 'Cluster', { + vpc, + kubectlEnabled: true, + defaultCapacity: 0, + version: CLUSTER_VERSION, + }); + new eks.Nodegroup(stack, 'Nodegroup', { + cluster, + instanceType: new ec2.InstanceType('m5.large'), + instanceTypes: [ + new ec2.InstanceType('m5.large'), + new ec2.InstanceType('t3.large'), + new ec2.InstanceType('c5.large'), + ], + capacityType: eks.CapacityType.SPOT, + }); + // THEN + expect(stack).to(haveResourceLike('AWS::EKS::Nodegroup', { + InstanceTypes: [ + 'm5.large', + 't3.large', + 'c5.large', + ], + CapacityType: 'SPOT', + }, + )); + test.done(); + }, + 'create nodegroup with either instanceTypes or instanceType defined'(test: Test) { + // GIVEN + const { stack, vpc } = testFixture(); + + // WHEN + const cluster = new eks.Cluster(stack, 'Cluster', { + vpc, + kubectlEnabled: true, + defaultCapacity: 0, + version: CLUSTER_VERSION, + }); + new eks.Nodegroup(stack, 'Nodegroup', { + cluster, + capacityType: eks.CapacityType.SPOT, + }); + // THEN + expect(stack).to(haveResourceLike('AWS::EKS::Nodegroup', { + CapacityType: 'SPOT', + }, + )); + test.done(); + }, + 'throws when instanceTypes provided with different CPU architrcture'(test: Test) { + // GIVEN + const { stack, vpc } = testFixture(); + const cluster = new eks.Cluster(stack, 'Cluster', { + vpc, + kubectlEnabled: true, + defaultCapacity: 0, + version: CLUSTER_VERSION, + }); + // THEN + test.throws(() => cluster.addNodegroupCapacity('ng', { + instanceTypes: [ + // X86 + new ec2.InstanceType('c5.large'), + new ec2.InstanceType('c5a.large'), + // ARM64 + new ec2.InstanceType('m6g.large'), + ], + }), /instanceTypes of different CPU architectures not allowed/); + test.done(); + }, + 'throws when amiType provided is incorrect'(test: Test) { + // GIVEN + const { stack, vpc } = testFixture(); + const cluster = new eks.Cluster(stack, 'Cluster', { + vpc, + kubectlEnabled: true, + defaultCapacity: 0, + version: CLUSTER_VERSION, + }); + // THEN + test.throws(() => cluster.addNodegroupCapacity('ng', { + instanceTypes: [ + new ec2.InstanceType('c5.large'), + new ec2.InstanceType('c5a.large'), + new ec2.InstanceType('c5d.large'), + ], + // incorrect amiType + amiType: eks.NodegroupAmiType.AL2_ARM_64, + }), /amiType is not correct - should be/); + test.done(); + }, + 'remoteAccess without security group provided'(test: Test) { // GIVEN const { stack, vpc } = testFixture(); From ef1dff440f11e3f26ded81943279920e50f1a284 Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Wed, 16 Dec 2020 11:26:41 +0000 Subject: [PATCH 06/21] minor --- packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts index 7e1bfb8b9a777..9c9ca1b925325 100644 --- a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts @@ -284,7 +284,6 @@ export class Nodegroup extends Resource implements INodegroup { } this.instanceType = props.instanceTypes ?? (props.instanceType ? [props.instanceType] : [DEFAULT_INSTANCE_TYPE]); - // console.log(this.instanceType); const determinedAmiType = determineAmiTypes(this.instanceType); if (props.amiType && props.amiType !== determinedAmiType) { throw new Error(`amiType is not correct - should be ${determinedAmiType}`); From 53c7c35d1876f48c9d462f3cfcd645a8ea5495b5 Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Wed, 16 Dec 2020 11:38:03 +0000 Subject: [PATCH 07/21] minor --- packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts index 9c9ca1b925325..a481c26099922 100644 --- a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts @@ -261,7 +261,6 @@ export class Nodegroup extends Resource implements INodegroup { private readonly desiredSize: number; private readonly maxSize: number; private readonly minSize: number; - private readonly instanceType: InstanceType[]; constructor(scope: Construct, id: string, props: NodegroupProps) { super(scope, id, { @@ -283,8 +282,8 @@ export class Nodegroup extends Resource implements INodegroup { throw new Error(`Minimum capacity ${this.minSize} can't be greater than desired size ${this.desiredSize}`); } - this.instanceType = props.instanceTypes ?? (props.instanceType ? [props.instanceType] : [DEFAULT_INSTANCE_TYPE]); - const determinedAmiType = determineAmiTypes(this.instanceType); + const instanceType = props.instanceTypes ?? (props.instanceType ? [props.instanceType] : [DEFAULT_INSTANCE_TYPE]); + const determinedAmiType = determineAmiTypes(instanceType); if (props.amiType && props.amiType !== determinedAmiType) { throw new Error(`amiType is not correct - should be ${determinedAmiType}`); } From 0e78865990ce441747a959b1a1de6347847981e4 Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Wed, 16 Dec 2020 11:40:46 +0000 Subject: [PATCH 08/21] minor --- packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts index a481c26099922..8a9dcc27a3bbc 100644 --- a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts @@ -282,8 +282,8 @@ export class Nodegroup extends Resource implements INodegroup { throw new Error(`Minimum capacity ${this.minSize} can't be greater than desired size ${this.desiredSize}`); } - const instanceType = props.instanceTypes ?? (props.instanceType ? [props.instanceType] : [DEFAULT_INSTANCE_TYPE]); - const determinedAmiType = determineAmiTypes(instanceType); + const instanceTypes = props.instanceTypes ?? (props.instanceType ? [props.instanceType] : [DEFAULT_INSTANCE_TYPE]); + const determinedAmiType = determineAmiTypes(instanceTypes); if (props.amiType && props.amiType !== determinedAmiType) { throw new Error(`amiType is not correct - should be ${determinedAmiType}`); } From d2d9ca5cf8d35318010536a326e7ad365867a288 Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Wed, 16 Dec 2020 13:31:51 +0000 Subject: [PATCH 09/21] add annotations --- packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts index 8a9dcc27a3bbc..4e3b2ff0e632d 100644 --- a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts @@ -1,6 +1,6 @@ import { InstanceType, ISecurityGroup, SubnetSelection } from '@aws-cdk/aws-ec2'; import { IRole, ManagedPolicy, Role, ServicePrincipal } from '@aws-cdk/aws-iam'; -import { IResource, Resource } from '@aws-cdk/core'; +import { IResource, Resource, Annotations } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { Cluster, ICluster } from './cluster'; import { CfnNodegroup } from './eks.generated'; @@ -282,6 +282,9 @@ export class Nodegroup extends Resource implements INodegroup { throw new Error(`Minimum capacity ${this.minSize} can't be greater than desired size ${this.desiredSize}`); } + if (props.instanceType) { + Annotations.of(this).addWarning('instanceType will be deprecated, remember to use instanceTypes instead.'); + } const instanceTypes = props.instanceTypes ?? (props.instanceType ? [props.instanceType] : [DEFAULT_INSTANCE_TYPE]); const determinedAmiType = determineAmiTypes(instanceTypes); if (props.amiType && props.amiType !== determinedAmiType) { From 1a023925758df9fd75478d9f629695d25195c597 Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Thu, 17 Dec 2020 10:19:00 +0000 Subject: [PATCH 10/21] minor --- packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts index 4e3b2ff0e632d..1da073d7c1ff4 100644 --- a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts @@ -226,6 +226,10 @@ export interface NodegroupProps extends NodegroupOptions { * The Nodegroup resource class */ export class Nodegroup extends Resource implements INodegroup { + /** + * Default instanceTypes + */ + public static readonly DEFAULT_INSTANCE_TYPES = [new InstanceType('t3.medium')]; /** * Import the Nodegroup from attributes */ @@ -273,8 +277,6 @@ export class Nodegroup extends Resource implements INodegroup { this.maxSize = props.maxSize ?? this.desiredSize; this.minSize = props.minSize ?? 1; - const DEFAULT_INSTANCE_TYPE = new InstanceType('t3.medium'); - if (this.desiredSize > this.maxSize) { throw new Error(`Desired capacity ${this.desiredSize} can't be greater than max size ${this.maxSize}`); } @@ -285,7 +287,7 @@ export class Nodegroup extends Resource implements INodegroup { if (props.instanceType) { Annotations.of(this).addWarning('instanceType will be deprecated, remember to use instanceTypes instead.'); } - const instanceTypes = props.instanceTypes ?? (props.instanceType ? [props.instanceType] : [DEFAULT_INSTANCE_TYPE]); + const instanceTypes = props.instanceTypes ?? (props.instanceType ? [props.instanceType] : Nodegroup.DEFAULT_INSTANCE_TYPES); const determinedAmiType = determineAmiTypes(instanceTypes); if (props.amiType && props.amiType !== determinedAmiType) { throw new Error(`amiType is not correct - should be ${determinedAmiType}`); @@ -310,7 +312,7 @@ export class Nodegroup extends Resource implements INodegroup { nodeRole: this.role.roleArn, subnets: this.cluster.vpc.selectSubnets(props.subnets).subnetIds, // AmyType is not allowed by CFN when specifying an image id in your launch template. - amiType: props.launchTemplateSpec == undefined ? determinedAmiType : undefined, + amiType: props.launchTemplateSpec === undefined ? determinedAmiType : undefined, diskSize: props.diskSize, forceUpdateEnabled: props.forceUpdate ?? true, instanceTypes: props.instanceTypes ? props.instanceTypes.map(t => t.toString()) : @@ -391,4 +393,4 @@ function determineAmiTypes(instanceType: InstanceType[]) { } else { return uniq[0]; } -} \ No newline at end of file +} From 481e6f12eabb6647127c740a8d1d4a4b8649ccd4 Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Fri, 18 Dec 2020 11:25:57 +0800 Subject: [PATCH 11/21] Update packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts Co-authored-by: Eli Polonsky --- packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts index 1da073d7c1ff4..c0764a769e937 100644 --- a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts @@ -285,7 +285,7 @@ export class Nodegroup extends Resource implements INodegroup { } if (props.instanceType) { - Annotations.of(this).addWarning('instanceType will be deprecated, remember to use instanceTypes instead.'); + Annotations.of(this).addWarning(`'instanceType' is deprecated and will be removed in the next major version. please use 'instanceTypes' instead`); } const instanceTypes = props.instanceTypes ?? (props.instanceType ? [props.instanceType] : Nodegroup.DEFAULT_INSTANCE_TYPES); const determinedAmiType = determineAmiTypes(instanceTypes); From f05ddbbde8c33f34dae2a91fa11f3e4865355463 Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Fri, 18 Dec 2020 11:28:29 +0800 Subject: [PATCH 12/21] Update packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts Co-authored-by: Eli Polonsky --- packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts index c0764a769e937..fe2912633d406 100644 --- a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts @@ -290,7 +290,7 @@ export class Nodegroup extends Resource implements INodegroup { const instanceTypes = props.instanceTypes ?? (props.instanceType ? [props.instanceType] : Nodegroup.DEFAULT_INSTANCE_TYPES); const determinedAmiType = determineAmiTypes(instanceTypes); if (props.amiType && props.amiType !== determinedAmiType) { - throw new Error(`amiType is not correct - should be ${determinedAmiType}`); + throw new Error(`The specified AMI does not match the instance types architecture, either specify ${determinedAmiType} or dont specify any`); } if (!props.nodeRole) { From fb136560f64e5d42b07392a9a26ea5de96d3091f Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Fri, 18 Dec 2020 12:38:06 +0000 Subject: [PATCH 13/21] update the helper function --- .../@aws-cdk/aws-eks/lib/managed-nodegroup.ts | 26 ++++++++++++------- .../@aws-cdk/aws-eks/test/test.nodegroup.ts | 22 +++++----------- 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts index fe2912633d406..d475e69574fb3 100644 --- a/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/lib/managed-nodegroup.ts @@ -149,7 +149,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. This property will be ignored if `instanceTypes` is defined. + * `AL2_x86_64_GPU` with the amiType parameter. * * @default t3.medium * @deprecated Use `instanceTypes` instead. @@ -284,11 +284,21 @@ export class Nodegroup extends Resource implements INodegroup { throw new Error(`Minimum capacity ${this.minSize} can't be greater than desired size ${this.desiredSize}`); } + if (props.instanceType && props.instanceTypes) { + throw new Error('"instanceType is deprecated, please use "instanceTypes" only.'); + } + if (props.instanceType) { - Annotations.of(this).addWarning(`'instanceType' is deprecated and will be removed in the next major version. please use 'instanceTypes' instead`); + Annotations.of(this).addWarning('"instanceType" is deprecated and will be removed in the next major version. please use "instanceTypes" instead'); } const instanceTypes = props.instanceTypes ?? (props.instanceType ? [props.instanceType] : Nodegroup.DEFAULT_INSTANCE_TYPES); - const determinedAmiType = determineAmiTypes(instanceTypes); + // get unique AMI types from instanceTypes + const uniqAmiTypes = getAmiTypes(instanceTypes); + // uniqAmiTypes.length should be at least 1 + if (uniqAmiTypes.length > 1) { + throw new Error('instanceTypes of different CPU architectures is not allowed'); + } + const determinedAmiType = uniqAmiTypes[0]; if (props.amiType && props.amiType !== determinedAmiType) { throw new Error(`The specified AMI does not match the instance types architecture, either specify ${determinedAmiType} or dont specify any`); } @@ -385,12 +395,8 @@ function getAmiTypeForInstanceType(instanceType: InstanceType) { NodegroupAmiType.AL2_X86_64; } -function determineAmiTypes(instanceType: InstanceType[]) { +function getAmiTypes(instanceType: InstanceType[]) { const amiTypes = instanceType.map(i =>getAmiTypeForInstanceType(i)); - const uniq = [...new Set(amiTypes)]; - if (uniq.length > 1) { - throw new Error('instanceTypes of different CPU architectures not allowed'); - } else { - return uniq[0]; - } + // retuen unique AMI types + return [...new Set(amiTypes)]; } diff --git a/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts b/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts index 6847761d108ba..13f8a414613a7 100644 --- a/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts @@ -318,7 +318,7 @@ export = { )); test.done(); }, - 'create nodegroup with both instanceTypes and instanceType defined'(test: Test) { + 'throws when both instanceTypes and instanceType defined'(test: Test) { // GIVEN const { stack, vpc } = testFixture(); @@ -329,8 +329,8 @@ export = { defaultCapacity: 0, version: CLUSTER_VERSION, }); - new eks.Nodegroup(stack, 'Nodegroup', { - cluster, + // THEN + test.throws(() => cluster.addNodegroupCapacity('ng', { instanceType: new ec2.InstanceType('m5.large'), instanceTypes: [ new ec2.InstanceType('m5.large'), @@ -338,17 +338,7 @@ export = { new ec2.InstanceType('c5.large'), ], capacityType: eks.CapacityType.SPOT, - }); - // THEN - expect(stack).to(haveResourceLike('AWS::EKS::Nodegroup', { - InstanceTypes: [ - 'm5.large', - 't3.large', - 'c5.large', - ], - CapacityType: 'SPOT', - }, - )); + }), /"instanceType is deprecated, please use "instanceTypes" only/); test.done(); }, 'create nodegroup with either instanceTypes or instanceType defined'(test: Test) { @@ -391,7 +381,7 @@ export = { // ARM64 new ec2.InstanceType('m6g.large'), ], - }), /instanceTypes of different CPU architectures not allowed/); + }), /instanceTypes of different CPU architectures is not allowed/); test.done(); }, 'throws when amiType provided is incorrect'(test: Test) { @@ -412,7 +402,7 @@ export = { ], // incorrect amiType amiType: eks.NodegroupAmiType.AL2_ARM_64, - }), /amiType is not correct - should be/); + }), /The specified AMI does not match the instance types architecture/); test.done(); }, From 9888f2f2ee88f4e57b89b03565f4c8988cb6cc68 Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Fri, 18 Dec 2020 23:53:13 +0800 Subject: [PATCH 14/21] Update packages/@aws-cdk/aws-eks/test/test.nodegroup.ts Co-authored-by: Eli Polonsky --- packages/@aws-cdk/aws-eks/test/test.nodegroup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts b/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts index 13f8a414613a7..8d34fbbe71dc1 100644 --- a/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts @@ -341,7 +341,7 @@ export = { }), /"instanceType is deprecated, please use "instanceTypes" only/); test.done(); }, - 'create nodegroup with either instanceTypes or instanceType defined'(test: Test) { + 'create nodegroup with neither instanceTypes nor instanceType defined'(test: Test) { // GIVEN const { stack, vpc } = testFixture(); From cdd304f0402416896d33e38f60ad9ee3600092ba Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Fri, 18 Dec 2020 15:55:22 +0000 Subject: [PATCH 15/21] fix tests --- packages/@aws-cdk/aws-eks/test/test.nodegroup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts b/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts index 8d34fbbe71dc1..3034feb4dd2e2 100644 --- a/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts @@ -286,7 +286,7 @@ export = { )); test.done(); }, - 'create nodegroup with ondemand capacity type'(test: Test) { + 'create nodegroup with on-demand capacity type and multiple instances'(test: Test) { // GIVEN const { stack, vpc } = testFixture(); From 50c2ac6a821699a343b8946104b4240a4c0092da Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Fri, 18 Dec 2020 16:01:30 +0000 Subject: [PATCH 16/21] minor --- packages/@aws-cdk/aws-eks/test/test.nodegroup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts b/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts index 3034feb4dd2e2..8b32053fa43a8 100644 --- a/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts @@ -286,7 +286,7 @@ export = { )); test.done(); }, - 'create nodegroup with on-demand capacity type and multiple instances'(test: Test) { + 'create nodegroup with on-demand capacity type and multiple instance types'(test: Test) { // GIVEN const { stack, vpc } = testFixture(); From 47725adebe0fe16b39a5491c9ffc502384b75ef9 Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Tue, 22 Dec 2020 14:55:36 +0000 Subject: [PATCH 17/21] fix tests --- .../@aws-cdk/aws-eks/test/test.nodegroup.ts | 45 ------------------- 1 file changed, 45 deletions(-) diff --git a/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts b/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts index f9287189e2f9c..1dedc66fc105a 100644 --- a/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts @@ -161,43 +161,6 @@ export = { )); test.done(); }, - 'create nodegroups with kubectlEnabled is false'(test: Test) { - // GIVEN - const { stack, vpc } = testFixture(); - - // WHEN - const cluster = new eks.LegacyCluster(stack, 'Cluster', { - vpc, - defaultCapacity: 2, - version: CLUSTER_VERSION, - }); - // add a extra nodegroup - cluster.addNodegroup('extra-ng'); - // THEN - expect(stack).to(countResources('AWS::EKS::Nodegroup', 2)); - test.done(); - }, - 'create nodegroup with minimal property provided'(test: Test) { - // GIVEN - const { stack, vpc } = testFixture(); - - // WHEN - const cluster = new eks.Cluster(stack, 'Cluster', { - vpc, - kubectlEnabled: true, - defaultCapacity: 0, - version: CLUSTER_VERSION, - }); - new eks.Nodegroup(stack, 'Nodegroup', { - cluster, - }); - - // THEN - expect(stack).to(haveResourceLike('AWS::EKS::Nodegroup', { - }, - )); - test.done(); - }, 'create nodegroup with instanceType provided'(test: Test) { // GIVEN const { stack, vpc } = testFixture(); @@ -229,7 +192,6 @@ export = { // WHEN const cluster = new eks.Cluster(stack, 'Cluster', { vpc, - kubectlEnabled: true, defaultCapacity: 0, version: CLUSTER_VERSION, }); @@ -256,7 +218,6 @@ export = { // WHEN const cluster = new eks.Cluster(stack, 'Cluster', { vpc, - kubectlEnabled: true, defaultCapacity: 0, version: CLUSTER_VERSION, }); @@ -288,7 +249,6 @@ export = { // WHEN const cluster = new eks.Cluster(stack, 'Cluster', { vpc, - kubectlEnabled: true, defaultCapacity: 0, version: CLUSTER_VERSION, }); @@ -320,7 +280,6 @@ export = { // WHEN const cluster = new eks.Cluster(stack, 'Cluster', { vpc, - kubectlEnabled: true, defaultCapacity: 0, version: CLUSTER_VERSION, }); @@ -343,8 +302,6 @@ export = { // WHEN const cluster = new eks.Cluster(stack, 'Cluster', { vpc, - kubectlEnabled: true, - defaultCapacity: 0, version: CLUSTER_VERSION, }); new eks.Nodegroup(stack, 'Nodegroup', { @@ -363,7 +320,6 @@ export = { const { stack, vpc } = testFixture(); const cluster = new eks.Cluster(stack, 'Cluster', { vpc, - kubectlEnabled: true, defaultCapacity: 0, version: CLUSTER_VERSION, }); @@ -384,7 +340,6 @@ export = { const { stack, vpc } = testFixture(); const cluster = new eks.Cluster(stack, 'Cluster', { vpc, - kubectlEnabled: true, defaultCapacity: 0, version: CLUSTER_VERSION, }); From a20441f74c03c4dcc68403f1b574108c932aadc8 Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Tue, 22 Dec 2020 15:31:47 +0000 Subject: [PATCH 18/21] fix tests --- .../@aws-cdk/aws-eks/test/test.nodegroup.ts | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts b/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts index 1dedc66fc105a..ff962572a6f92 100644 --- a/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts +++ b/packages/@aws-cdk/aws-eks/test/test.nodegroup.ts @@ -555,37 +555,4 @@ export = { }), /diskSize must be specified within the launch template/); test.done(); }, - 'throws when both instanceType and launch template specified'(test: Test) { - // GIVEN - const { stack, vpc } = testFixture(); - - // WHEN - const cluster = new eks.Cluster(stack, 'Cluster', { - vpc, - defaultCapacity: 0, - version: CLUSTER_VERSION, - }); - const userData = ec2.UserData.forLinux(); - userData.addCommands( - 'set -o xtrace', - `/etc/eks/bootstrap.sh ${cluster.clusterName}`, - ); - const lt = new ec2.CfnLaunchTemplate(stack, 'LaunchTemplate', { - launchTemplateData: { - imageId: new eks.EksOptimizedImage().getImage(stack).imageId, - instanceType: new ec2.InstanceType('t3.small').toString(), - userData: cdk.Fn.base64(userData.render()), - }, - }); - // THEN - test.throws(() => - cluster.addNodegroupCapacity('ng-lt', { - instanceType: new ec2.InstanceType('c5.large'), - launchTemplateSpec: { - id: lt.ref, - version: lt.attrDefaultVersionNumber, - }, - }), /Instance types must be specified within the launch template/); - test.done(); - }, }; From ef0ccd9c04decfc195486d4886bb01a234790251 Mon Sep 17 00:00:00 2001 From: Eli Polonsky Date: Tue, 22 Dec 2020 21:23:12 +0200 Subject: [PATCH 19/21] Some rephrasing --- packages/@aws-cdk/aws-eks/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-eks/README.md b/packages/@aws-cdk/aws-eks/README.md index 8ec6a33519697..3c7f8b341c441 100644 --- a/packages/@aws-cdk/aws-eks/README.md +++ b/packages/@aws-cdk/aws-eks/README.md @@ -211,7 +211,7 @@ cluster.addNodegroupCapacity('custom-node-group', { #### Spot Instances Support -Use `capacityType` to create the Spot managed node groups. To maximize the availability of your applications while using +Use `capacityType` to create managed node groups comprised of spot instances. To maximize the availability of your applications while using Spot Instances, we recommend that you configure a Spot managed node group to use multiple instance types with `instanceTypes`. > For more details visit [Managed node group capacity types](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html#managed-node-group-capacity-types). From 265ffae4cc4233fce7802814e51738a6ceac7b9c Mon Sep 17 00:00:00 2001 From: Eli Polonsky Date: Tue, 22 Dec 2020 21:23:28 +0200 Subject: [PATCH 20/21] Some rephrasing --- packages/@aws-cdk/aws-eks/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-eks/README.md b/packages/@aws-cdk/aws-eks/README.md index 3c7f8b341c441..c469dca92633d 100644 --- a/packages/@aws-cdk/aws-eks/README.md +++ b/packages/@aws-cdk/aws-eks/README.md @@ -212,7 +212,7 @@ cluster.addNodegroupCapacity('custom-node-group', { #### Spot Instances Support Use `capacityType` to create managed node groups comprised of spot instances. To maximize the availability of your applications while using -Spot Instances, we recommend that you configure a Spot managed node group to use multiple instance types with `instanceTypes`. +Spot Instances, we recommend that you configure a Spot managed node group to use multiple instance types with the `instanceTypes` property. > For more details visit [Managed node group capacity types](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html#managed-node-group-capacity-types). From 61044769e446827c915909913c304912df657762 Mon Sep 17 00:00:00 2001 From: Eli Polonsky Date: Tue, 22 Dec 2020 21:23:37 +0200 Subject: [PATCH 21/21] Some rephrasing --- packages/@aws-cdk/aws-eks/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-eks/README.md b/packages/@aws-cdk/aws-eks/README.md index c469dca92633d..26dfa0991a243 100644 --- a/packages/@aws-cdk/aws-eks/README.md +++ b/packages/@aws-cdk/aws-eks/README.md @@ -257,7 +257,7 @@ cluster.addNodegroupCapacity('extra-ng', { }); ``` -You may specify one or multiple instance types in either `instanceTypes` property of `NodeGroup` or in the launch template but not both. +You may specify one or instance types in either the `instanceTypes` property of `NodeGroup` or in the launch template, **but not both**. > For more details visit [Launch Template Support](https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html).