From e0ca252acee8290558edddde137458a055ad0b9e Mon Sep 17 00:00:00 2001 From: Calvin Combs <66279577+comcalvi@users.noreply.github.com> Date: Fri, 11 Aug 2023 17:59:09 -0700 Subject: [PATCH] feat(batch): set default spot allocation strategy to `SPOT_PRICE_CAPACITY_OPTIMIZED` (#26731) https://aws.amazon.com/about-aws/whats-new/2023/08/aws-batch-price-capacity-optimized-allocation-strategy-spot-instances/ and https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-fleet-allocation-strategy.html `SPOT_PRICE_CAPACITY_OPTIMIZED` is now recommended over `SPOT_CAPACITY_OPTIMIZED`; make it the new default, while the construct is still in alpha. BREAKING CHANGE: if using spot instances on your Compute Environments, they will default to `SPOT_PRICE_CAPACITY_OPTIMIZED` instead of `SPOT_CAPACITY_OPTIMIZED` now. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/aws-batch-alpha/README.md | 21 +- .../lib/managed-compute-environment.ts | 13 +- ...efaultTestDeployAssertD4528F80.assets.json | 2 +- .../batch-stack.assets.json | 6 +- .../batch-stack.template.json | 227 +++++++++---- .../cdk.out | 2 +- .../integ.json | 2 +- .../manifest.json | 33 +- .../tree.json | 299 ++++++++++++++---- .../test/integ.managed-compute-environment.ts | 10 + .../test/managed-compute-environment.test.ts | 17 +- 11 files changed, 487 insertions(+), 145 deletions(-) diff --git a/packages/@aws-cdk/aws-batch-alpha/README.md b/packages/@aws-cdk/aws-batch-alpha/README.md index 6e76d196450db..d681ffb3ec86b 100644 --- a/packages/@aws-cdk/aws-batch-alpha/README.md +++ b/packages/@aws-cdk/aws-batch-alpha/README.md @@ -128,19 +128,23 @@ computeEnv.addInstanceClass(ec2.InstanceClass.R4); #### Allocation Strategies -| Allocation Strategy | Optimized for | Downsides | -| ----------------------- | ------------- | ----------------------------- | -| BEST_FIT | Cost | May limit throughput | -| BEST_FIT_PROGRESSIVE | Throughput | May increase cost | -| SPOT_CAPACITY_OPTIMIZED | Least interruption | Only useful on Spot instances | +| Allocation Strategy | Optimized for | Downsides | +| ----------------------- | ------------- | ----------------------------- | +| BEST_FIT | Cost | May limit throughput | +| BEST_FIT_PROGRESSIVE | Throughput | May increase cost | +| SPOT_CAPACITY_OPTIMIZED | Least interruption | Only useful on Spot instances | +| SPOT_PRICE_CAPACITY_OPTIMIZED | Least interruption + Price | Only useful on Spot instances | Batch provides different Allocation Strategies to help it choose which instances to provision. If your workflow tolerates interruptions, you should enable `spot` on your `ComputeEnvironment` -and use `SPOT_CAPACITY_OPTIMIZED` (this is the default if `spot` is enabled). +and use `SPOT_PRICE_CAPACITY_OPTIMIZED` (this is the default if `spot` is enabled). This will tell Batch to choose the instance types from the ones you’ve specified that have -the most spot capacity available to minimize the chance of interruption. +the most spot capacity available to minimize the chance of interruption and have the lowest price. To get the most benefit from your spot instances, you should allow Batch to choose from as many different instance types as possible. +If you only care about minimal interruptions and not want Batch to optimize for cost, use +`SPOT_CAPACITY_OPTIMIZED`. `SPOT_PRICE_CAPACITY_OPTIMIZED` is recommended over `SPOT_CAPACITY_OPTIMIZED` +for most use cases. If your workflow does not tolerate interruptions and you want to minimize your costs at the expense of potentially longer waiting times, use `AllocationStrategy.BEST_FIT`. @@ -189,7 +193,8 @@ const computeEnv = new batch.ManagedEc2EcsComputeEnvironment(this, 'myEc2Compute You can specify the maximum and minimum vCPUs a managed `ComputeEnvironment` can have at any given time. Batch will *always* maintain `minvCpus` worth of instances in your ComputeEnvironment, even if it is not executing any jobs, and even if it is disabled. Batch will scale the instances up to `maxvCpus` worth of instances as -jobs exit the JobQueue and enter the ComputeEnvironment. If you use `AllocationStrategy.BEST_FIT_PROGRESSIVE` or `AllocationStrategy.SPOT_CAPACITY_OPTIMIZED`, +jobs exit the JobQueue and enter the ComputeEnvironment. If you use `AllocationStrategy.BEST_FIT_PROGRESSIVE`, +`AllocationStrategy.SPOT_PRICE_CAPACITY_OPTIMIZED`, or `AllocationStrategy.SPOT_CAPACITY_OPTIMIZED`, batch may exceed `maxvCpus`; it will never exceed `maxvCpus` by more than a single instance type. This example configures a `minvCpus` of 10 and a `maxvCpus` of 100: diff --git a/packages/@aws-cdk/aws-batch-alpha/lib/managed-compute-environment.ts b/packages/@aws-cdk/aws-batch-alpha/lib/managed-compute-environment.ts index 42308bb025919..147e25082912a 100644 --- a/packages/@aws-cdk/aws-batch-alpha/lib/managed-compute-environment.ts +++ b/packages/@aws-cdk/aws-batch-alpha/lib/managed-compute-environment.ts @@ -452,6 +452,15 @@ export enum AllocationStrategy { * you should allow Batch to choose from as many different instance types as possible. */ SPOT_CAPACITY_OPTIMIZED = 'SPOT_CAPACITY_OPTIMIZED', + + /** + * The price and capacity optimized allocation strategy looks at both price and capacity + * to select the Spot Instance pools that are the least likely to be interrupted + * and have the lowest possible price. + * + * The Batch team recommends this over `SPOT_CAPACITY_OPTIMIZED` in most instances. + */ + SPOT_PRICE_CAPACITY_OPTIMIZED = 'SPOT_PRICE_CAPACITY_OPTIMIZED', } /** @@ -1145,7 +1154,9 @@ function createSpotFleetRole(scope: Construct): IRole { function determineAllocationStrategy(id: string, allocationStrategy?: AllocationStrategy, spot?: boolean): AllocationStrategy | undefined { let result = allocationStrategy; if (!allocationStrategy) { - result = spot ? AllocationStrategy.SPOT_CAPACITY_OPTIMIZED : AllocationStrategy.BEST_FIT_PROGRESSIVE; + result = spot ? AllocationStrategy.SPOT_PRICE_CAPACITY_OPTIMIZED : AllocationStrategy.BEST_FIT_PROGRESSIVE; + } else if (allocationStrategy === AllocationStrategy.SPOT_PRICE_CAPACITY_OPTIMIZED && !spot) { + throw new Error(`Managed ComputeEnvironment '${id}' specifies 'AllocationStrategy.SPOT_PRICE_CAPACITY_OPTIMIZED' without using spot instances`); } else if (allocationStrategy === AllocationStrategy.SPOT_CAPACITY_OPTIMIZED && !spot) { throw new Error(`Managed ComputeEnvironment '${id}' specifies 'AllocationStrategy.SPOT_CAPACITY_OPTIMIZED' without using spot instances`); } diff --git a/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/BatchManagedComputeEnvironmentTestDefaultTestDeployAssertD4528F80.assets.json b/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/BatchManagedComputeEnvironmentTestDefaultTestDeployAssertD4528F80.assets.json index c9ff88daa4353..446a5fb9c92bb 100644 --- a/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/BatchManagedComputeEnvironmentTestDefaultTestDeployAssertD4528F80.assets.json +++ b/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/BatchManagedComputeEnvironmentTestDefaultTestDeployAssertD4528F80.assets.json @@ -1,5 +1,5 @@ { - "version": "32.0.0", + "version": "33.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/batch-stack.assets.json b/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/batch-stack.assets.json index c479e894b1d84..2840c70f63e44 100644 --- a/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/batch-stack.assets.json +++ b/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/batch-stack.assets.json @@ -1,7 +1,7 @@ { - "version": "32.0.0", + "version": "33.0.0", "files": { - "81f3134124cef368d56ccabda586dbcbef39a78089edd14c9d641cbcb4e0bad2": { + "c107f22b1a273d6b3e98ae47d04dfc2c17295a01e96b0b2a69ceaaad3ec33905": { "source": { "path": "batch-stack.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "81f3134124cef368d56ccabda586dbcbef39a78089edd14c9d641cbcb4e0bad2.json", + "objectKey": "c107f22b1a273d6b3e98ae47d04dfc2c17295a01e96b0b2a69ceaaad3ec33905.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/batch-stack.template.json b/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/batch-stack.template.json index 2e86fbef42d62..6c452844a66bd 100644 --- a/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/batch-stack.template.json +++ b/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/batch-stack.template.json @@ -18,9 +18,6 @@ "vpcPublicSubnet1Subnet2E65531E": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "vpcA2121C38" - }, "AvailabilityZone": { "Fn::Select": [ 0, @@ -44,21 +41,24 @@ "Key": "Name", "Value": "batch-stack/vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "vpcA2121C38" + } } }, "vpcPublicSubnet1RouteTable48A2DF9B": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "vpcA2121C38" - }, "Tags": [ { "Key": "Name", "Value": "batch-stack/vpc/PublicSubnet1" } - ] + ], + "VpcId": { + "Ref": "vpcA2121C38" + } } }, "vpcPublicSubnet1RouteTableAssociation5D3F4579": { @@ -75,12 +75,12 @@ "vpcPublicSubnet1DefaultRoute10708846": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "vpcPublicSubnet1RouteTable48A2DF9B" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "vpcIGWE57CBDCA" + }, + "RouteTableId": { + "Ref": "vpcPublicSubnet1RouteTable48A2DF9B" } }, "DependsOn": [ @@ -102,15 +102,15 @@ "vpcPublicSubnet1NATGateway9C16659E": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "vpcPublicSubnet1Subnet2E65531E" - }, "AllocationId": { "Fn::GetAtt": [ "vpcPublicSubnet1EIPDA49DCBE", "AllocationId" ] }, + "SubnetId": { + "Ref": "vpcPublicSubnet1Subnet2E65531E" + }, "Tags": [ { "Key": "Name", @@ -126,9 +126,6 @@ "vpcPublicSubnet2Subnet009B674F": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "vpcA2121C38" - }, "AvailabilityZone": { "Fn::Select": [ 1, @@ -152,21 +149,24 @@ "Key": "Name", "Value": "batch-stack/vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "vpcA2121C38" + } } }, "vpcPublicSubnet2RouteTableEB40D4CB": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "vpcA2121C38" - }, "Tags": [ { "Key": "Name", "Value": "batch-stack/vpc/PublicSubnet2" } - ] + ], + "VpcId": { + "Ref": "vpcA2121C38" + } } }, "vpcPublicSubnet2RouteTableAssociation21F81B59": { @@ -183,12 +183,12 @@ "vpcPublicSubnet2DefaultRouteA1EC0F60": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "vpcPublicSubnet2RouteTableEB40D4CB" - }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "vpcIGWE57CBDCA" + }, + "RouteTableId": { + "Ref": "vpcPublicSubnet2RouteTableEB40D4CB" } }, "DependsOn": [ @@ -210,15 +210,15 @@ "vpcPublicSubnet2NATGateway9B8AE11A": { "Type": "AWS::EC2::NatGateway", "Properties": { - "SubnetId": { - "Ref": "vpcPublicSubnet2Subnet009B674F" - }, "AllocationId": { "Fn::GetAtt": [ "vpcPublicSubnet2EIP9B3743B1", "AllocationId" ] }, + "SubnetId": { + "Ref": "vpcPublicSubnet2Subnet009B674F" + }, "Tags": [ { "Key": "Name", @@ -234,9 +234,6 @@ "vpcPrivateSubnet1Subnet934893E8": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "vpcA2121C38" - }, "AvailabilityZone": { "Fn::Select": [ 0, @@ -260,21 +257,24 @@ "Key": "Name", "Value": "batch-stack/vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "vpcA2121C38" + } } }, "vpcPrivateSubnet1RouteTableB41A48CC": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "vpcA2121C38" - }, "Tags": [ { "Key": "Name", "Value": "batch-stack/vpc/PrivateSubnet1" } - ] + ], + "VpcId": { + "Ref": "vpcA2121C38" + } } }, "vpcPrivateSubnet1RouteTableAssociation67945127": { @@ -291,21 +291,18 @@ "vpcPrivateSubnet1DefaultRoute1AA8E2E5": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "vpcPrivateSubnet1RouteTableB41A48CC" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "vpcPublicSubnet1NATGateway9C16659E" + }, + "RouteTableId": { + "Ref": "vpcPrivateSubnet1RouteTableB41A48CC" } } }, "vpcPrivateSubnet2Subnet7031C2BA": { "Type": "AWS::EC2::Subnet", "Properties": { - "VpcId": { - "Ref": "vpcA2121C38" - }, "AvailabilityZone": { "Fn::Select": [ 1, @@ -329,21 +326,24 @@ "Key": "Name", "Value": "batch-stack/vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "vpcA2121C38" + } } }, "vpcPrivateSubnet2RouteTable7280F23E": { "Type": "AWS::EC2::RouteTable", "Properties": { - "VpcId": { - "Ref": "vpcA2121C38" - }, "Tags": [ { "Key": "Name", "Value": "batch-stack/vpc/PrivateSubnet2" } - ] + ], + "VpcId": { + "Ref": "vpcA2121C38" + } } }, "vpcPrivateSubnet2RouteTableAssociation007E94D3": { @@ -360,12 +360,12 @@ "vpcPrivateSubnet2DefaultRouteB0E07F99": { "Type": "AWS::EC2::Route", "Properties": { - "RouteTableId": { - "Ref": "vpcPrivateSubnet2RouteTable7280F23E" - }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { "Ref": "vpcPublicSubnet2NATGateway9B8AE11A" + }, + "RouteTableId": { + "Ref": "vpcPrivateSubnet2RouteTable7280F23E" } } }, @@ -383,11 +383,11 @@ "vpcVPCGW7984C166": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { - "VpcId": { - "Ref": "vpcA2121C38" - }, "InternetGatewayId": { "Ref": "vpcIGWE57CBDCA" + }, + "VpcId": { + "Ref": "vpcA2121C38" } } }, @@ -410,7 +410,6 @@ "minimalPropsFargate58449235": { "Type": "AWS::Batch::ComputeEnvironment", "Properties": { - "Type": "managed", "ComputeResources": { "MaxvCpus": 512, "SecurityGroupIds": [ @@ -434,6 +433,7 @@ }, "ReplaceComputeEnvironment": false, "State": "ENABLED", + "Type": "managed", "UpdatePolicy": {} } }, @@ -456,7 +456,6 @@ "maximalPropsFargate2D7D8138": { "Type": "AWS::Batch::ComputeEnvironment", "Properties": { - "Type": "managed", "ComputeEnvironmentName": "maxPropsFargateCE", "ComputeResources": { "MaxvCpus": 512, @@ -481,6 +480,7 @@ }, "ReplaceComputeEnvironment": true, "State": "ENABLED", + "Type": "managed", "UpdatePolicy": { "JobExecutionTimeoutMinutes": 30, "TerminateJobsOnUpdate": true @@ -547,7 +547,6 @@ "minimalPropsEc200AECC55": { "Type": "AWS::Batch::ComputeEnvironment", "Properties": { - "Type": "managed", "ComputeResources": { "AllocationStrategy": "BEST_FIT_PROGRESSIVE", "Ec2Configuration": [ @@ -590,6 +589,7 @@ }, "ReplaceComputeEnvironment": false, "State": "ENABLED", + "Type": "managed", "UpdatePolicy": {} } }, @@ -694,7 +694,6 @@ "LaunchTemplate04EC5460": { "Type": "AWS::Batch::ComputeEnvironment", "Properties": { - "Type": "managed", "ComputeResources": { "AllocationStrategy": "BEST_FIT", "Ec2Configuration": [ @@ -748,6 +747,7 @@ }, "ReplaceComputeEnvironment": true, "State": "ENABLED", + "Type": "managed", "UpdatePolicy": { "JobExecutionTimeoutMinutes": 60, "TerminateJobsOnUpdate": false @@ -831,9 +831,8 @@ "SpotEc2A0470C83": { "Type": "AWS::Batch::ComputeEnvironment", "Properties": { - "Type": "managed", "ComputeResources": { - "AllocationStrategy": "SPOT_CAPACITY_OPTIMIZED", + "AllocationStrategy": "SPOT_PRICE_CAPACITY_OPTIMIZED", "BidPercentage": 95, "Ec2Configuration": [ { @@ -881,6 +880,114 @@ }, "ReplaceComputeEnvironment": false, "State": "ENABLED", + "Type": "managed", + "UpdatePolicy": {} + } + }, + "AllocationStrategySPOTCAPACITYSecurityGroupA581EB8C": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "batch-stack/AllocationStrategySPOT_CAPACITY/SecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "vpcA2121C38" + } + } + }, + "AllocationStrategySPOTCAPACITYInstanceProfileRoleA6211395": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role" + ] + ] + } + ] + } + }, + "AllocationStrategySPOTCAPACITYInstanceProfile0B71F375": { + "Type": "AWS::IAM::InstanceProfile", + "Properties": { + "Roles": [ + { + "Ref": "AllocationStrategySPOTCAPACITYInstanceProfileRoleA6211395" + } + ] + } + }, + "AllocationStrategySPOTCAPACITYEE4582C5": { + "Type": "AWS::Batch::ComputeEnvironment", + "Properties": { + "ComputeResources": { + "AllocationStrategy": "SPOT_CAPACITY_OPTIMIZED", + "BidPercentage": 95, + "Ec2Configuration": [ + { + "ImageIdOverride": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestamznamihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "ImageType": "ECS_AL2" + } + ], + "InstanceRole": { + "Fn::GetAtt": [ + "AllocationStrategySPOTCAPACITYInstanceProfile0B71F375", + "Arn" + ] + }, + "InstanceTypes": [ + "optimal" + ], + "MaxvCpus": 256, + "MinvCpus": 0, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "AllocationStrategySPOTCAPACITYSecurityGroupA581EB8C", + "GroupId" + ] + } + ], + "Subnets": [ + { + "Ref": "vpcPrivateSubnet1Subnet934893E8" + }, + { + "Ref": "vpcPrivateSubnet2Subnet7031C2BA" + } + ], + "Type": "SPOT", + "UpdateToLatestImageVersion": true + }, + "ReplaceComputeEnvironment": false, + "State": "ENABLED", + "Type": "managed", "UpdatePolicy": {} } }, @@ -964,7 +1071,6 @@ "taggedCE5029E6F8": { "Type": "AWS::Batch::ComputeEnvironment", "Properties": { - "Type": "managed", "ComputeResources": { "AllocationStrategy": "BEST_FIT_PROGRESSIVE", "Ec2Configuration": [ @@ -1015,6 +1121,7 @@ "foo": "bar", "super": "salamander" }, + "Type": "managed", "UpdatePolicy": {} } } diff --git a/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/cdk.out b/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/cdk.out index f0b901e7c06e5..560dae10d018f 100644 --- a/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"32.0.0"} \ No newline at end of file +{"version":"33.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/integ.json b/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/integ.json index acb2eae98de06..e6786dca181e3 100644 --- a/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "32.0.0", + "version": "33.0.0", "testCases": { "BatchManagedComputeEnvironmentTest/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/manifest.json b/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/manifest.json index ef7e040db5067..56abc7f8ef4e1 100644 --- a/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "32.0.0", + "version": "33.0.0", "artifacts": { "batch-stack.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/81f3134124cef368d56ccabda586dbcbef39a78089edd14c9d641cbcb4e0bad2.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/c107f22b1a273d6b3e98ae47d04dfc2c17295a01e96b0b2a69ceaaad3ec33905.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -192,10 +192,7 @@ "/batch-stack/maximalPropsFargate/Resource": [ { "type": "aws:cdk:logicalId", - "data": "maximalPropsFargate2D7D8138", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "maximalPropsFargate2D7D8138" } ], "/batch-stack/minimalPropsEc2/SecurityGroup/Resource": [ @@ -294,6 +291,30 @@ "data": "SpotEc2A0470C83" } ], + "/batch-stack/AllocationStrategySPOT_CAPACITY/SecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "AllocationStrategySPOTCAPACITYSecurityGroupA581EB8C" + } + ], + "/batch-stack/AllocationStrategySPOT_CAPACITY/InstanceProfileRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "AllocationStrategySPOTCAPACITYInstanceProfileRoleA6211395" + } + ], + "/batch-stack/AllocationStrategySPOT_CAPACITY/InstanceProfile": [ + { + "type": "aws:cdk:logicalId", + "data": "AllocationStrategySPOTCAPACITYInstanceProfile0B71F375" + } + ], + "/batch-stack/AllocationStrategySPOT_CAPACITY/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "AllocationStrategySPOTCAPACITYEE4582C5" + } + ], "/batch-stack/taggedCE/SecurityGroup/Resource": [ { "type": "aws:cdk:logicalId", diff --git a/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/tree.json b/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/tree.json index 66d6744028e44..51fc04f4fc544 100644 --- a/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.js.snapshot/tree.json @@ -45,9 +45,6 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", "aws:cdk:cloudformation:props": { - "vpcId": { - "Ref": "vpcA2121C38" - }, "availabilityZone": { "Fn::Select": [ 0, @@ -71,7 +68,10 @@ "key": "Name", "value": "batch-stack/vpc/PublicSubnet1" } - ] + ], + "vpcId": { + "Ref": "vpcA2121C38" + } } }, "constructInfo": { @@ -93,15 +93,15 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", "aws:cdk:cloudformation:props": { - "vpcId": { - "Ref": "vpcA2121C38" - }, "tags": [ { "key": "Name", "value": "batch-stack/vpc/PublicSubnet1" } - ] + ], + "vpcId": { + "Ref": "vpcA2121C38" + } } }, "constructInfo": { @@ -134,12 +134,12 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Route", "aws:cdk:cloudformation:props": { - "routeTableId": { - "Ref": "vpcPublicSubnet1RouteTable48A2DF9B" - }, "destinationCidrBlock": "0.0.0.0/0", "gatewayId": { "Ref": "vpcIGWE57CBDCA" + }, + "routeTableId": { + "Ref": "vpcPublicSubnet1RouteTable48A2DF9B" } } }, @@ -174,15 +174,15 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", "aws:cdk:cloudformation:props": { - "subnetId": { - "Ref": "vpcPublicSubnet1Subnet2E65531E" - }, "allocationId": { "Fn::GetAtt": [ "vpcPublicSubnet1EIPDA49DCBE", "AllocationId" ] }, + "subnetId": { + "Ref": "vpcPublicSubnet1Subnet2E65531E" + }, "tags": [ { "key": "Name", @@ -212,9 +212,6 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", "aws:cdk:cloudformation:props": { - "vpcId": { - "Ref": "vpcA2121C38" - }, "availabilityZone": { "Fn::Select": [ 1, @@ -238,7 +235,10 @@ "key": "Name", "value": "batch-stack/vpc/PublicSubnet2" } - ] + ], + "vpcId": { + "Ref": "vpcA2121C38" + } } }, "constructInfo": { @@ -260,15 +260,15 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", "aws:cdk:cloudformation:props": { - "vpcId": { - "Ref": "vpcA2121C38" - }, "tags": [ { "key": "Name", "value": "batch-stack/vpc/PublicSubnet2" } - ] + ], + "vpcId": { + "Ref": "vpcA2121C38" + } } }, "constructInfo": { @@ -301,12 +301,12 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Route", "aws:cdk:cloudformation:props": { - "routeTableId": { - "Ref": "vpcPublicSubnet2RouteTableEB40D4CB" - }, "destinationCidrBlock": "0.0.0.0/0", "gatewayId": { "Ref": "vpcIGWE57CBDCA" + }, + "routeTableId": { + "Ref": "vpcPublicSubnet2RouteTableEB40D4CB" } } }, @@ -341,15 +341,15 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", "aws:cdk:cloudformation:props": { - "subnetId": { - "Ref": "vpcPublicSubnet2Subnet009B674F" - }, "allocationId": { "Fn::GetAtt": [ "vpcPublicSubnet2EIP9B3743B1", "AllocationId" ] }, + "subnetId": { + "Ref": "vpcPublicSubnet2Subnet009B674F" + }, "tags": [ { "key": "Name", @@ -379,9 +379,6 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", "aws:cdk:cloudformation:props": { - "vpcId": { - "Ref": "vpcA2121C38" - }, "availabilityZone": { "Fn::Select": [ 0, @@ -405,7 +402,10 @@ "key": "Name", "value": "batch-stack/vpc/PrivateSubnet1" } - ] + ], + "vpcId": { + "Ref": "vpcA2121C38" + } } }, "constructInfo": { @@ -427,15 +427,15 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", "aws:cdk:cloudformation:props": { - "vpcId": { - "Ref": "vpcA2121C38" - }, "tags": [ { "key": "Name", "value": "batch-stack/vpc/PrivateSubnet1" } - ] + ], + "vpcId": { + "Ref": "vpcA2121C38" + } } }, "constructInfo": { @@ -468,12 +468,12 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Route", "aws:cdk:cloudformation:props": { - "routeTableId": { - "Ref": "vpcPrivateSubnet1RouteTableB41A48CC" - }, "destinationCidrBlock": "0.0.0.0/0", "natGatewayId": { "Ref": "vpcPublicSubnet1NATGateway9C16659E" + }, + "routeTableId": { + "Ref": "vpcPrivateSubnet1RouteTableB41A48CC" } } }, @@ -498,9 +498,6 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", "aws:cdk:cloudformation:props": { - "vpcId": { - "Ref": "vpcA2121C38" - }, "availabilityZone": { "Fn::Select": [ 1, @@ -524,7 +521,10 @@ "key": "Name", "value": "batch-stack/vpc/PrivateSubnet2" } - ] + ], + "vpcId": { + "Ref": "vpcA2121C38" + } } }, "constructInfo": { @@ -546,15 +546,15 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", "aws:cdk:cloudformation:props": { - "vpcId": { - "Ref": "vpcA2121C38" - }, "tags": [ { "key": "Name", "value": "batch-stack/vpc/PrivateSubnet2" } - ] + ], + "vpcId": { + "Ref": "vpcA2121C38" + } } }, "constructInfo": { @@ -587,12 +587,12 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::Route", "aws:cdk:cloudformation:props": { - "routeTableId": { - "Ref": "vpcPrivateSubnet2RouteTable7280F23E" - }, "destinationCidrBlock": "0.0.0.0/0", "natGatewayId": { "Ref": "vpcPublicSubnet2NATGateway9B8AE11A" + }, + "routeTableId": { + "Ref": "vpcPrivateSubnet2RouteTable7280F23E" } } }, @@ -632,11 +632,11 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", "aws:cdk:cloudformation:props": { - "vpcId": { - "Ref": "vpcA2121C38" - }, "internetGatewayId": { "Ref": "vpcIGWE57CBDCA" + }, + "vpcId": { + "Ref": "vpcA2121C38" } } }, @@ -695,7 +695,6 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::Batch::ComputeEnvironment", "aws:cdk:cloudformation:props": { - "type": "managed", "computeResources": { "maxvCpus": 512, "type": "FARGATE", @@ -719,6 +718,7 @@ }, "replaceComputeEnvironment": false, "state": "ENABLED", + "type": "managed", "updatePolicy": {} } }, @@ -777,7 +777,6 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::Batch::ComputeEnvironment", "aws:cdk:cloudformation:props": { - "type": "managed", "computeEnvironmentName": "maxPropsFargateCE", "computeResources": { "maxvCpus": 512, @@ -802,6 +801,7 @@ }, "replaceComputeEnvironment": true, "state": "ENABLED", + "type": "managed", "updatePolicy": { "terminateJobsOnUpdate": true, "jobExecutionTimeoutMinutes": 30 @@ -938,7 +938,6 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::Batch::ComputeEnvironment", "aws:cdk:cloudformation:props": { - "type": "managed", "computeResources": { "maxvCpus": 256, "type": "EC2", @@ -981,6 +980,7 @@ }, "replaceComputeEnvironment": false, "state": "ENABLED", + "type": "managed", "updatePolicy": {} } }, @@ -1208,7 +1208,6 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::Batch::ComputeEnvironment", "aws:cdk:cloudformation:props": { - "type": "managed", "computeResources": { "maxvCpus": 512, "type": "EC2", @@ -1262,6 +1261,7 @@ }, "replaceComputeEnvironment": true, "state": "ENABLED", + "type": "managed", "updatePolicy": { "terminateJobsOnUpdate": false, "jobExecutionTimeoutMinutes": 60 @@ -1441,7 +1441,6 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::Batch::ComputeEnvironment", "aws:cdk:cloudformation:props": { - "type": "managed", "computeResources": { "maxvCpus": 256, "type": "SPOT", @@ -1478,6 +1477,183 @@ "Arn" ] }, + "allocationStrategy": "SPOT_PRICE_CAPACITY_OPTIMIZED", + "bidPercentage": 95, + "ec2Configuration": [ + { + "imageIdOverride": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestamznamihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "imageType": "ECS_AL2" + } + ] + }, + "replaceComputeEnvironment": false, + "state": "ENABLED", + "type": "managed", + "updatePolicy": {} + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_batch.CfnComputeEnvironment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-batch-alpha.ManagedEc2EcsComputeEnvironment", + "version": "0.0.0" + } + }, + "AllocationStrategySPOT_CAPACITY": { + "id": "AllocationStrategySPOT_CAPACITY", + "path": "batch-stack/AllocationStrategySPOT_CAPACITY", + "children": { + "SecurityGroup": { + "id": "SecurityGroup", + "path": "batch-stack/AllocationStrategySPOT_CAPACITY/SecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "batch-stack/AllocationStrategySPOT_CAPACITY/SecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "batch-stack/AllocationStrategySPOT_CAPACITY/SecurityGroup", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "vpcId": { + "Ref": "vpcA2121C38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSecurityGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.SecurityGroup", + "version": "0.0.0" + } + }, + "InstanceProfileRole": { + "id": "InstanceProfileRole", + "path": "batch-stack/AllocationStrategySPOT_CAPACITY/InstanceProfileRole", + "children": { + "ImportInstanceProfileRole": { + "id": "ImportInstanceProfileRole", + "path": "batch-stack/AllocationStrategySPOT_CAPACITY/InstanceProfileRole/ImportInstanceProfileRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "batch-stack/AllocationStrategySPOT_CAPACITY/InstanceProfileRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "InstanceProfile": { + "id": "InstanceProfile", + "path": "batch-stack/AllocationStrategySPOT_CAPACITY/InstanceProfile", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::InstanceProfile", + "aws:cdk:cloudformation:props": { + "roles": [ + { + "Ref": "AllocationStrategySPOTCAPACITYInstanceProfileRoleA6211395" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnInstanceProfile", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "batch-stack/AllocationStrategySPOT_CAPACITY/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Batch::ComputeEnvironment", + "aws:cdk:cloudformation:props": { + "computeResources": { + "maxvCpus": 256, + "type": "SPOT", + "updateToLatestImageVersion": true, + "securityGroupIds": [ + { + "Fn::GetAtt": [ + "AllocationStrategySPOTCAPACITYSecurityGroupA581EB8C", + "GroupId" + ] + } + ], + "subnets": [ + { + "Ref": "vpcPrivateSubnet1Subnet934893E8" + }, + { + "Ref": "vpcPrivateSubnet2Subnet7031C2BA" + } + ], + "minvCpus": 0, + "instanceRole": { + "Fn::GetAtt": [ + "AllocationStrategySPOTCAPACITYInstanceProfile0B71F375", + "Arn" + ] + }, + "instanceTypes": [ + "optimal" + ], "allocationStrategy": "SPOT_CAPACITY_OPTIMIZED", "bidPercentage": 95, "ec2Configuration": [ @@ -1491,6 +1667,7 @@ }, "replaceComputeEnvironment": false, "state": "ENABLED", + "type": "managed", "updatePolicy": {} } }, @@ -1644,7 +1821,6 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::Batch::ComputeEnvironment", "aws:cdk:cloudformation:props": { - "type": "managed", "computeResources": { "maxvCpus": 256, "type": "EC2", @@ -1695,6 +1871,7 @@ "foo": "bar", "super": "salamander" }, + "type": "managed", "updatePolicy": {} } }, @@ -1744,7 +1921,7 @@ "path": "BatchManagedComputeEnvironmentTest/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.2.26" + "version": "10.2.69" } }, "DeployAssert": { @@ -1790,7 +1967,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.2.26" + "version": "10.2.69" } } }, diff --git a/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.ts b/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.ts index a2976e021f3f6..ca3e04f1de04b 100644 --- a/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.ts +++ b/packages/@aws-cdk/aws-batch-alpha/test/integ.managed-compute-environment.ts @@ -59,6 +59,16 @@ new ManagedEc2EcsComputeEnvironment(stack, 'SpotEc2', { }), }); +new ManagedEc2EcsComputeEnvironment(stack, 'AllocationStrategySPOT_CAPACITY', { + vpc, + images: [{ + image: new ec2.AmazonLinuxImage(), + }], + spot: true, + spotBidPercentage: 95, + allocationStrategy: AllocationStrategy.SPOT_CAPACITY_OPTIMIZED, +}); + const taggedEc2Ecs = new ManagedEc2EcsComputeEnvironment(stack, 'taggedCE', { vpc, images: [{ diff --git a/packages/@aws-cdk/aws-batch-alpha/test/managed-compute-environment.test.ts b/packages/@aws-cdk/aws-batch-alpha/test/managed-compute-environment.test.ts index 37fa4113934c2..75ec0b8210dae 100644 --- a/packages/@aws-cdk/aws-batch-alpha/test/managed-compute-environment.test.ts +++ b/packages/@aws-cdk/aws-batch-alpha/test/managed-compute-environment.test.ts @@ -168,7 +168,7 @@ describe.each([ManagedEc2EcsComputeEnvironment, ManagedEc2EksComputeEnvironment] }); }); - test('spot => AllocationStrategy.SPOT_CAPACITY_OPTIMIZED', () => { + test('spot => AllocationStrategy.SPOT_PRICE_CAPACITY_OPTIMIZED', () => { // WHEN new ComputeEnvironment(stack, 'MyCE', { ...defaultProps, @@ -182,7 +182,7 @@ describe.each([ManagedEc2EcsComputeEnvironment, ManagedEc2EksComputeEnvironment] ComputeResources: { ...defaultComputeResources, Type: 'SPOT', - AllocationStrategy: 'SPOT_CAPACITY_OPTIMIZED', + AllocationStrategy: 'SPOT_PRICE_CAPACITY_OPTIMIZED', }, }); }); @@ -643,6 +643,17 @@ describe.each([ManagedEc2EcsComputeEnvironment, ManagedEc2EksComputeEnvironment] }).toThrow(/Managed ComputeEnvironment 'MyCE' specifies 'AllocationStrategy.SPOT_CAPACITY_OPTIMIZED' without using spot instances/); }); + test('throws error when AllocationStrategy.SPOT_PRICE_CAPACITY_OPTIMIZED is used without specfiying spot', () => { + // THEN + expect(() => { + new ComputeEnvironment(stack, 'MyCE', { + ...defaultProps, + vpc, + allocationStrategy: AllocationStrategy.SPOT_PRICE_CAPACITY_OPTIMIZED, + }); + }).toThrow(/Managed ComputeEnvironment 'MyCE' specifies 'AllocationStrategy.SPOT_PRICE_CAPACITY_OPTIMIZED' without using spot instances/); + }); + test('throws error when spotBidPercentage is specified without spot', () => { // THEN expect(() => { @@ -750,7 +761,7 @@ describe('ManagedEc2EcsComputeEnvironment', () => { ...pascalCaseExpectedEcsProps, ComputeResources: { ...defaultComputeResources, - AllocationStrategy: AllocationStrategy.SPOT_CAPACITY_OPTIMIZED, + AllocationStrategy: AllocationStrategy.SPOT_PRICE_CAPACITY_OPTIMIZED, Type: 'SPOT', SpotIamFleetRole: { 'Fn::GetAtt': ['SpotFleetRole6D4F7558', 'Arn'],