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'],