Skip to content

Commit

Permalink
Add Fargate Spot option
Browse files Browse the repository at this point in the history
  • Loading branch information
huntharo committed Oct 27, 2024
1 parent 067ff6b commit 775558b
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 6 deletions.
42 changes: 37 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ npm install @pwrdrvr/lambda-dispatch-construct
```typescript
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import { LambdaConstruct, EcsConstruct } from '@pwrdrvr/lambda-dispatch-construct';

export class MyStack extends cdk.Stack {
Expand Down Expand Up @@ -64,10 +65,14 @@ export class MyStack extends cdk.Stack {
lambdaFunction: lambdaConstruct.function,
loadBalancer: alb,
httpsListener,
memoryLimitMiB: 2048, // Optional, defaults to 2048
cpu: 1024, // Optional, defaults to 1024
maxCapacity: 10, // Optional, defaults to 10
minCapacity: 1 // Optional, defaults to 1
// Optional configurations
memoryLimitMiB: 2048, // Default: 2048
cpu: 1024, // Default: 1024
maxCapacity: 10, // Default: 10
minCapacity: 1, // Default: 1
// Cost optimization options
useFargateSpot: true, // Default: false
cpuArchitecture: ecs.CpuArchitecture.AMD64 // Required for Fargate Spot
});
}
}
Expand All @@ -90,6 +95,30 @@ export class MyStack extends cdk.Stack {
- `cpu?`: CPU units for the ECS task (default: 1024)
- `maxCapacity?`: Maximum number of ECS tasks (default: 10)
- `minCapacity?`: Minimum number of ECS tasks (default: 1)
- `useFargateSpot?`: Whether to use Fargate Spot for cost savings (default: false)
- `cpuArchitecture?`: CPU architecture for ECS tasks (default: ARM64)

### Cost Optimization

The construct supports two main strategies for cost optimization:

1. **Fargate Spot**
- Enable with `useFargateSpot: true`
- Can reduce costs by up to 70% compared to regular Fargate
- Only supports AMD64 architecture
- Best for non-production or fault-tolerant workloads

2. **ARM64 Architecture**
- Default when not using Fargate Spot
- About 20% cheaper than AMD64
- Not compatible with Fargate Spot

Choose your configuration based on your needs:
- For maximum cost savings: Use Fargate Spot with AMD64
- For reliable ARM benefits: Use regular Fargate with ARM64
- For development: Either option works well

Note: When `useFargateSpot` is true, the construct automatically sets `cpuArchitecture` to AMD64 as required by Fargate Spot.

### Best Practices

Expand All @@ -99,7 +128,10 @@ export class MyStack extends cdk.Stack {

3. **Auto Scaling**: The ECS service includes CPU-based auto-scaling by default, scaling between min and max capacity based on a 50% CPU target.

4. **ARM64 Architecture**: Both Lambda and ECS tasks use ARM64 architecture by default for better cost efficiency.
4. **Cost Optimization**:
- Use Fargate Spot for non-critical or development environments
- Use ARM64 for production environments where consistent pricing is important
- Consider your application's fault tolerance when choosing between Spot and regular Fargate

5. **Health Checks**: The ECS service includes proper health checks configured on the target group.

Expand Down
30 changes: 29 additions & 1 deletion src/cdk-construct/src/ecs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ export interface EcsConstructProps {
* @default 1
*/
readonly minCapacity?: number;
/**
* Whether to use Fargate Spot capacity provider
* Note: Fargate Spot only supports AMD64 architecture
* @default false
*/
readonly useFargateSpot?: boolean;
/**
* CPU architecture to use for the ECS tasks
* Note: Fargate Spot only supports AMD64 architecture
* @default ARM64
*/
readonly cpuArchitecture?: ecs.CpuArchitecture;
}

/**
Expand Down Expand Up @@ -84,8 +96,18 @@ export class EcsConstruct extends Construct {
throw new Error("httpsListener is required in EcsConstructProps");
}

// Validate Fargate Spot and CPU architecture combination
if (
props.useFargateSpot &&
props.cpuArchitecture === ecs.CpuArchitecture.ARM64
) {
throw new Error("Fargate Spot only supports AMD64 architecture");
}

// Create cluster with appropriate capacity providers
const cluster = new ecs.Cluster(this, "EcsCluster", {
vpc: props.vpc,
enableFargateCapacityProviders: true,
});

const taskRole = new iam.Role(this, "EcsTaskRole", {
Expand All @@ -107,7 +129,7 @@ export class EcsConstruct extends Construct {
cpu: props.cpu ?? 1024,
taskRole: taskRole,
runtimePlatform: {
cpuArchitecture: ecs.CpuArchitecture.ARM64,
cpuArchitecture: props.cpuArchitecture ?? ecs.CpuArchitecture.ARM64,
operatingSystemFamily: ecs.OperatingSystemFamily.LINUX,
},
}
Expand Down Expand Up @@ -181,13 +203,19 @@ export class EcsConstruct extends Construct {
}
);

// Configure capacity provider strategy based on props
const capacityProviderStrategies = props.useFargateSpot
? [{ capacityProvider: "FARGATE_SPOT", weight: 1 }]
: [{ capacityProvider: "FARGATE", weight: 1 }];

this.service = new ecs.FargateService(this, "EcsService", {
cluster: cluster,
taskDefinition: taskDefinition,
desiredCount: props.minCapacity ?? 1,
assignPublicIp: false,
vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
securityGroups: [this.securityGroup],
capacityProviderStrategies,
});

// Add auto-scaling
Expand Down

0 comments on commit 775558b

Please sign in to comment.