Skip to content

Commit

Permalink
fix(aws-batch): Support omitting ComputeEnvironment security groups s…
Browse files Browse the repository at this point in the history
…o that they can be specified in Launch Template (#21579)

HPC Batch applications frequently require Elastic Fabric Adapters for low-latency networking.  Currently, the `ComputeEnvironment` construct always automatically defines a set of `SecurityGroupIds` in the CloudFormation it generates, and this prevents the stack deploying if the LaunchTemplate contains network interface definitions; Batch does not allow SecurityGroups at the `ComputeEnvironment` level if there are network interfaces defined in the `CfnLaunchTemplate`.

Since we do not currently have support for network interfaces this PR adds a new boolean property in `launchTemplate` called `useNetworkInterfaceSecurityGroups`. When this is enabled we will assume that security groups are being provided by the launch template.

A long term solution may be to:
- Add support for network interfaces in the L2 ec2.LaunchTemplate construct.
- Update the batch.ComputeEnvironment construct to take a ILaunchTemplate instead of the name/id.
- Check the ILaunchTemplate for whether the ComputeEnvironment needs to create any security groups.

closes #21577 

----

### All Submissions:

* [yes] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md)

### Adding new Unconventional Dependencies:

* [no] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-new-unconventional-dependencies)

### New Features

* [yes] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)?
	* [yes] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)?

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
tcutts committed Aug 23, 2022
1 parent 5ce0a09 commit 33b00dd
Show file tree
Hide file tree
Showing 10 changed files with 1,491 additions and 10 deletions.
37 changes: 37 additions & 0 deletions packages/@aws-cdk/aws-batch/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,43 @@ const myComputeEnv = new batch.ComputeEnvironment(this, 'ComputeEnv', {
});
```

Note that if your launch template explicitly specifies network interfaces,
for example to use an Elastic Fabric Adapter, you must use those security groups rather
than allow the `ComputeEnvironment` to define them. This is done by setting
`useNetworkInterfaceSecurityGroups` in the launch template property of the environment.
For example:

```ts
declare const vpc: ec2.Vpc;

const efaSecurityGroup = new ec2.SecurityGroup(this, 'EFASecurityGroup', {
vpc,
});

const launchTemplateEFA = new ec2.CfnLaunchTemplate(this, 'LaunchTemplate', {
launchTemplateName: 'LaunchTemplateName',
launchTemplateData: {
networkInterfaces: [{
deviceIndex: 0,
subnetId: vpc.privateSubnets[0].subnetId,
interfaceType: 'efa',
groups: [efaSecurityGroup.securityGroupId],
}],
},
});

const computeEnvironmentEFA = new batch.ComputeEnvironment(this, 'EFAComputeEnv', {
managed: true,
computeResources: {
vpc,
launchTemplate: {
launchTemplateName: launchTemplateEFA.launchTemplateName as string,
useNetworkInterfaceSecurityGroups: true,
},
},
});
```

### Importing an existing Compute Environment

To import an existing batch compute environment, call `ComputeEnvironment.fromComputeEnvironmentArn()`.
Expand Down
41 changes: 32 additions & 9 deletions packages/@aws-cdk/aws-batch/lib/compute-environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,19 @@ export interface LaunchTemplateSpecification {
* @default - the default version of the launch template
*/
readonly version?: string;
/**
* Use security groups defined in the launch template network interfaces
*
* In some cases, such as specifying Elastic Fabric Adapters,
* network interfaces must be used to specify security groups. This
* parameter tells the Compute Environment construct that this is your
* intention, and stops it from creating its own security groups. This
* parameter is mutually exclusive with securityGroups in the Compute
* Environment
*
* @default - false
*/
readonly useNetworkInterfaceSecurityGroups?: boolean;
}

/**
Expand Down Expand Up @@ -138,9 +151,11 @@ export interface ComputeResources {
readonly instanceTypes?: ec2.InstanceType[];

/**
* The EC2 security group(s) associated with instances launched in the compute environment.
* Up to 5 EC2 security group(s) associated with instances launched in the compute environment.
*
* This parameter is mutually exclusive with launchTemplate.useNetworkInterfaceSecurityGroups
*
* @default - AWS default security group.
* @default - Create a single default security group.
*/
readonly securityGroups?: ec2.ISecurityGroup[];

Expand Down Expand Up @@ -375,7 +390,9 @@ export class ComputeEnvironment extends Resource implements IComputeEnvironment,
const spotFleetRole = this.getSpotFleetRole(props);
let computeResources: CfnComputeEnvironment.ComputeResourcesProperty | undefined;

this.connections = this.buildConnections(props.computeResources?.vpc, props.computeResources?.securityGroups);
const useLaunchTemplateNetworkInterface = props.computeResources?.launchTemplate?.useNetworkInterfaceSecurityGroups ? true : false;

this.connections = this.buildConnections(useLaunchTemplateNetworkInterface, props.computeResources?.vpc, props.computeResources?.securityGroups);

// Only allow compute resources to be set when using MANAGED type
if (props.computeResources && this.isManaged(props)) {
Expand All @@ -388,7 +405,7 @@ export class ComputeEnvironment extends Resource implements IComputeEnvironment,
launchTemplate: props.computeResources.launchTemplate,
maxvCpus: props.computeResources.maxvCpus || 256,
placementGroup: props.computeResources.placementGroup,
securityGroupIds: this.getSecurityGroupIds(),
securityGroupIds: this.getSecurityGroupIds(useLaunchTemplateNetworkInterface),
spotIamFleetRole: spotFleetRole?.roleArn,
subnets: props.computeResources.vpc.selectSubnets(props.computeResources.vpcSubnets).subnetIds,
tags: props.computeResources.computeResourcesTags,
Expand Down Expand Up @@ -547,6 +564,12 @@ export class ComputeEnvironment extends Resource implements IComputeEnvironment,
throw new Error('You must specify either the launch template ID or launch template name in the request.');
}

// useNetworkInterfaceSecurityGroups cannot have securityGroups defined
if (props.computeResources.launchTemplate?.useNetworkInterfaceSecurityGroups &&
props.computeResources.securityGroups ) {
throw new Error('securityGroups cannot be specified if launchTemplate useNetworkInterfaceSecurityGroups is active');
}

// Setting a bid percentage is only allowed on SPOT resources +
// Cannot use SPOT_CAPACITY_OPTIMIZED when using ON_DEMAND
if (props.computeResources.type === ComputeResourceType.ON_DEMAND) {
Expand Down Expand Up @@ -584,9 +607,9 @@ export class ComputeEnvironment extends Resource implements IComputeEnvironment,
return instanceTypes.map((type: ec2.InstanceType) => type.toString());
}

private buildConnections(vpc?: ec2.IVpc, securityGroups?:ec2.ISecurityGroup[]): ec2.Connections {
private buildConnections(useLaunchTemplateNetworkInterface: boolean, vpc?: ec2.IVpc, securityGroups?:ec2.ISecurityGroup[]): ec2.Connections {

if (vpc === undefined) {
if (vpc === undefined || useLaunchTemplateNetworkInterface ) {
return new ec2.Connections({});
}

Expand All @@ -597,12 +620,12 @@ export class ComputeEnvironment extends Resource implements IComputeEnvironment,
],
});
}

return new ec2.Connections({ securityGroups });
};

private getSecurityGroupIds(): string[] | undefined {
if (this.connections === undefined) {
private getSecurityGroupIds(useLaunchTemplateInterface: boolean): string[] | undefined {
if (this.connections === undefined ||
useLaunchTemplateInterface ) {
return undefined;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Loading

0 comments on commit 33b00dd

Please sign in to comment.