Skip to content

Commit

Permalink
feat(aws-ecs): support runtime platform property for create fargate w…
Browse files Browse the repository at this point in the history
…indows runtime. (aws#17622)

feat(aws-ecs): support runtime platform property for create fargate windows and Graviton2 runtime.

close aws#17242
----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
neilkuan authored and TikiTDO committed Feb 21, 2022
1 parent 1685a1c commit 52b99bc
Show file tree
Hide file tree
Showing 8 changed files with 1,097 additions and 1 deletion.
44 changes: 44 additions & 0 deletions packages/@aws-cdk/aws-ecs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,50 @@ taskDefinition.addContainer('container', {
});
```

### Using Windows containers on Fargate

AWS Fargate supports Amazon ECS Windows containers. For more details, please see this [blog post](https://aws.amazon.com/tw/blogs/containers/running-windows-containers-with-amazon-ecs-on-aws-fargate/)

```ts
// Create a Task Definition for the Windows container to start
const taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDef', {
runtimePlatform: {
operatingSystemFamily: ecs.OperatingSystemFamily.WINDOWS_SERVER_2019_CORE,
cpuArchitecture: ecs.CpuArchitecture.X86_64,
},
cpu: 1024,
memoryLimitMiB: 2048,
});

taskDefinition.addContainer('windowsservercore', {
logging: ecs.LogDriver.awsLogs({ streamPrefix: 'win-iis-on-fargate' }),
portMappings: [{ containerPort: 80 }],
image: ecs.ContainerImage.fromRegistry('mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019'),
});
```

### Using Graviton2 with Fargate

AWS Graviton2 supports AWS Fargate. For more details, please see this [blog post](https://aws.amazon.com/blogs/aws/announcing-aws-graviton2-support-for-aws-fargate-get-up-to-40-better-price-performance-for-your-serverless-containers/)

```ts
// Create a Task Definition for running container on Graviton Runtime.
const taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDef', {
runtimePlatform: {
operatingSystemFamily: ecs.OperatingSystemFamily.LINUX,
cpuArchitecture: ecs.CpuArchitecture.ARM64,
},
cpu: 1024,
memoryLimitMiB: 2048,
});

taskDefinition.addContainer('webarm64', {
logging: ecs.LogDriver.awsLogs({ streamPrefix: 'graviton2-on-fargate' }),
portMappings: [{ containerPort: 80 }],
image: ecs.ContainerImage.fromRegistry('public.ecr.aws/nginx/nginx:latest-arm64v8'),
});
```

## Service

A `Service` instantiates a `TaskDefinition` on a `Cluster` a given number of
Expand Down
47 changes: 47 additions & 0 deletions packages/@aws-cdk/aws-ecs/lib/base/task-definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { FirelensLogRouter, FirelensLogRouterDefinitionOptions, FirelensLogRoute
import { AwsLogDriver } from '../log-drivers/aws-log-driver';
import { PlacementConstraint } from '../placement';
import { ProxyConfiguration } from '../proxy-configuration/proxy-configuration';
import { RuntimePlatform } from '../runtime-platform';
import { ImportedTaskDefinition } from './_imported-task-definition';

/**
Expand Down Expand Up @@ -208,6 +209,15 @@ export interface TaskDefinitionProps extends CommonTaskDefinitionProps {
* @default - Undefined, in which case, the task will receive 20GiB ephemeral storage.
*/
readonly ephemeralStorageGiB?: number;

/**
* The operating system that your task definitions are running on.
* A runtimePlatform is supported only for tasks using the Fargate launch type.
*
*
* @default - Undefined.
*/
readonly runtimePlatform?: RuntimePlatform;
}

/**
Expand Down Expand Up @@ -369,6 +379,8 @@ export class TaskDefinition extends TaskDefinitionBase {

private _referencesSecretJsonField?: boolean;

private runtimePlatform?: RuntimePlatform;

/**
* Constructs a new instance of the TaskDefinition class.
*/
Expand Down Expand Up @@ -405,6 +417,10 @@ export class TaskDefinition extends TaskDefinitionBase {
throw new Error(`External tasks can only have Bridge network mode, got: ${this.networkMode}`);
}

if (!this.isFargateCompatible && props.runtimePlatform) {
throw new Error('Cannot specify runtimePlatform in non-Fargate compatible tasks');
}

this._executionRole = props.executionRole;

this.taskRole = props.taskRole || new iam.Role(this, 'TaskRole', {
Expand All @@ -417,6 +433,15 @@ export class TaskDefinition extends TaskDefinitionBase {

this.ephemeralStorageGiB = props.ephemeralStorageGiB;

// validate the cpu and memory size for the Windows operation system family.
if (props.runtimePlatform?.operatingSystemFamily?._operatingSystemFamily.includes('WINDOWS')) {
// We know that props.cpu and props.memoryMiB are defined because an error would have been thrown previously if they were not.
// But, typescript is not able to figure this out, so using the `!` operator here to let the type-checker know they are defined.
this.checkFargateWindowsBasedTasksSize(props.cpu!, props.memoryMiB!, props.runtimePlatform!);
}

this.runtimePlatform = props.runtimePlatform;

const taskDef = new CfnTaskDefinition(this, 'Resource', {
containerDefinitions: Lazy.any({ produce: () => this.renderContainers() }, { omitEmptyArray: true }),
volumes: Lazy.any({ produce: () => this.renderVolumes() }, { omitEmptyArray: true }),
Expand Down Expand Up @@ -445,6 +470,10 @@ export class TaskDefinition extends TaskDefinitionBase {
ephemeralStorage: this.ephemeralStorageGiB ? {
sizeInGiB: this.ephemeralStorageGiB,
} : undefined,
runtimePlatform: this.isFargateCompatible && this.runtimePlatform ? {
cpuArchitecture: this.runtimePlatform?.cpuArchitecture?._cpuArchitecture,
operatingSystemFamily: this.runtimePlatform?.operatingSystemFamily?._operatingSystemFamily,
} : undefined,
});

if (props.placementConstraints) {
Expand Down Expand Up @@ -697,6 +726,24 @@ export class TaskDefinition extends TaskDefinitionBase {

return this.containers.map(x => x.renderContainerDefinition());
}

private checkFargateWindowsBasedTasksSize(cpu: string, memory: string, runtimePlatform: RuntimePlatform) {
if (Number(cpu) === 1024) {
if (Number(memory) < 1024 || Number(memory) > 8192 || (Number(memory)% 1024 !== 0)) {
throw new Error(`If provided cpu is ${cpu}, then memoryMiB must have a min of 1024 and a max of 8192, in 1024 increments. Provided memoryMiB was ${Number(memory)}.`);
}
} else if (Number(cpu) === 2048) {
if (Number(memory) < 4096 || Number(memory) > 16384 || (Number(memory) % 1024 !== 0)) {
throw new Error(`If provided cpu is ${cpu}, then memoryMiB must have a min of 4096 and max of 16384, in 1024 increments. Provided memoryMiB ${Number(memory)}.`);
}
} else if (Number(cpu) === 4096) {
if (Number(memory) < 8192 || Number(memory) > 30720 || (Number(memory) % 1024 !== 0)) {
throw new Error(`If provided cpu is ${ cpu }, then memoryMiB must have a min of 8192 and a max of 30720, in 1024 increments.Provided memoryMiB was ${ Number(memory) }.`);
}
} else {
throw new Error(`If operatingSystemFamily is ${runtimePlatform.operatingSystemFamily!._operatingSystemFamily}, then cpu must be in 1024 (1 vCPU), 2048 (2 vCPU), or 4096 (4 vCPU). Provided value was: ${cpu}`);
}
};
}

/**
Expand Down
10 changes: 10 additions & 0 deletions packages/@aws-cdk/aws-ecs/lib/fargate/fargate-task-definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
NetworkMode,
TaskDefinition,
} from '../base/task-definition';
import { RuntimePlatform } from '../runtime-platform';

/**
* The properties for a task definition.
Expand Down Expand Up @@ -59,6 +60,15 @@ export interface FargateTaskDefinitionProps extends CommonTaskDefinitionProps {
* @default 20
*/
readonly ephemeralStorageGiB?: number;

/**
* The operating system that your task definitions are running on.
*
* A runtimePlatform is supported only for tasks using the Fargate launch type.
*
* @default - Undefined.
*/
readonly runtimePlatform?: RuntimePlatform;
}

/**
Expand Down
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-ecs/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export * from './log-drivers/log-drivers';
export * from './proxy-configuration/app-mesh-proxy-configuration';
export * from './proxy-configuration/proxy-configuration';
export * from './proxy-configuration/proxy-configurations';
export * from './runtime-platform';

// AWS::ECS CloudFormation Resources:
//
Expand Down
111 changes: 111 additions & 0 deletions packages/@aws-cdk/aws-ecs/lib/runtime-platform.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/**
* The CpuArchitecture for Fargate Runtime Platform.
*/
export class CpuArchitecture {
/**
* ARM64
*/
public static readonly ARM64 = CpuArchitecture.of('ARM64');

/**
* X86_64
*/
public static readonly X86_64 = CpuArchitecture.of('X86_64');

/**
* Other cpu architecture.
*
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-taskdefinition-runtimeplatform.html#cfn-ecs-taskdefinition-runtimeplatform-cpuarchitecture for all available cpu architecture.
*
* @param cpuArchitecture cpu architecture.
*
*/
public static of(cpuArchitecture: string) { return new CpuArchitecture(cpuArchitecture); }

/**
*
* @param _cpuArchitecture The CPU architecture.
*/
private constructor(public readonly _cpuArchitecture: string) { }
}

/**
* The operating system for Fargate Runtime Platform.
*/
export class OperatingSystemFamily {
/**
* LINUX
*/
public static readonly LINUX = OperatingSystemFamily.of('LINUX');

/**
* WINDOWS_SERVER_2004_CORE
*/
public static readonly WINDOWS_SERVER_2004_CORE = OperatingSystemFamily.of('WINDOWS_SERVER_2004_CORE');

/**
* WINDOWS_SERVER_2016_FULL
*/
public static readonly WINDOWS_SERVER_2016_FULL = OperatingSystemFamily.of('WINDOWS_SERVER_2016_FULL');

/**
* WINDOWS_SERVER_2019_CORE
*/
public static readonly WINDOWS_SERVER_2019_CORE = OperatingSystemFamily.of('WINDOWS_SERVER_2019_CORE');

/**
* WINDOWS_SERVER_2019_FULL
*/
public static readonly WINDOWS_SERVER_2019_FULL = OperatingSystemFamily.of('WINDOWS_SERVER_2019_FULL');

/**
* WINDOWS_SERVER_2022_CORE
*/
public static readonly WINDOWS_SERVER_2022_CORE = OperatingSystemFamily.of('WINDOWS_SERVER_2022_CORE');

/**
* WINDOWS_SERVER_2022_FULL
*/
public static readonly WINDOWS_SERVER_2022_FULL = OperatingSystemFamily.of('WINDOWS_SERVER_2022_FULL');

/**
* WINDOWS_SERVER_20H2_CORE
*/
public static readonly WINDOWS_SERVER_20H2_CORE = OperatingSystemFamily.of('WINDOWS_SERVER_20H2_CORE');

/**
* Other operating system family.
*
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-taskdefinition-runtimeplatform.html#cfn-ecs-taskdefinition-runtimeplatform-operatingsystemfamily for all available operating system family.
*
* @param family operating system family.
*
*/
public static of(family: string) { return new OperatingSystemFamily(family); }

/**
*
* @param _operatingSystemFamily The operating system family.
*/
private constructor(public readonly _operatingSystemFamily: string) { }
}


/**
* The interface for Runtime Platform.
*/
export interface RuntimePlatform {
/**
* The CpuArchitecture for Fargate Runtime Platform.
*
* @default - Undefined.
*/
readonly cpuArchitecture?: CpuArchitecture,

/**
* The operating system for Fargate Runtime Platform.
*
* @default - Undefined.
*/
readonly operatingSystemFamily?: OperatingSystemFamily,
}

0 comments on commit 52b99bc

Please sign in to comment.