aws / aws/containers-roadmap

[ECS EC2] Add cpuReservation parameter to separate scheduling from runtime limits

Open
#2,752 0 comments 1 reaction 0 assignees View on GitHub
ECS
Dominant language
Shell
Stars
5.4k
Forks
334
PR merge metrics
No merged PRs in 30d

Description

# Add CPU reservation parameter separate from CPU limit in ECS EC2

**Labels**: ECS, feature-request, EC2

## Problem

The `cpu` parameter in ECS EC2 does two things at once:
1. **Scheduling**: ECS uses it to decide if a task fits on an instance
2. **Runtime limit**: The container cannot exceed this CPU value

This forces users to choose between efficiency and protection.

## Current situation

**Memory works correctly** - it has two separate parameters:
```json
"memoryReservation": 256, // Used for scheduling
"memory": 1024 // Used as hard limit
```

**CPU does not** - it has only one parameter:
```json
"cpu": 512 // Used for BOTH scheduling AND limit
```

## The problem this creates

I have 28 services averaging 25% CPU usage with occasional spikes to 50%.

**If I set cpu limit** (`"cpu": 512`):
- ✅ One service cannot saturate the instance (protection works)
- ❌ Each service reserves 512 units even though it only uses ~100
- ❌ Instance appears "full" to the scheduler even though 75% CPU is idle
- ❌ Must provision 3x more instances than needed

**If I don't set cpu limit** (`"cpu": null`):
- ✅ Services share CPU efficiently
- ❌ One attacked/buggy service can use 100% CPU
- ❌ All other services on that instance become unresponsive
- ❌ Lose 5 services instead of 1 during incident

## Requested feature

Add `cpuReservation` parameter:
```json
{
"containerDefinitions": [{
"cpuReservation": 128, // ECS scheduler uses this for placement
"cpu": 512, // Runtime enforces this as maximum
"memoryReservation": 256,
"memory": 1024
}]
}
```

**How it would work:**
- Scheduler sees: "This task needs 128 CPU units minimum"
- Runtime enforces: "This task cannot exceed 512 CPU units"
- Result: Efficient packing + protection against runaway containers

## Real impact

**Current setup (with protection):**
- 6 instances × 2048 CPU units = 12,288 total
- Each service reserves: 512 units
- Maximum services: 12,288 ÷ 512 = 24 services
- Actual CPU usage: 25% (wasted capacity)

**With cpuReservation:**
- Same 6 instances = 12,288 total
- Each service reserves: 128 units (scheduling)
- Each service limited to: 512 units (protection)
- Maximum services: 12,288 ÷ 128 = 96 services
- Can safely run ~50 services with bursting
- **Cost savings: ~50%** (3 instances instead of 6)

## Why this matters

- **Cost**: Cannot efficiently pack containers without sacrificing protection
- **Feature parity**: Kubernetes has had this (requests vs limits) since the beginning
- **Consistency**: Memory already works this way in ECS
- **Production safety**: Forces choice between cost and reliability

## Current workarounds

None work properly:
1. **CPU shares only**: No hard limit, one service can still saturate instance
2. **Overprovision instances**: Expensive and wasteful
3. **No limits**: Unacceptable for production (noisy neighbor problem)

## Related

- Issue #1646 (same request, opened Jan 2022, no AWS response)
- Kubernetes documentation: resource requests vs limits

Contributor guide

Open the contributing guide

Research direction

Start by reviewing the ECS EC2 task-definition CPU semantics described here and compare them with the memoryReservation and memory parameters. Read related issue #1646 for prior context. Done would require an accepted design and AWS implementation or roadmap resolution for a separate cpuReservation parameter, but no repository files or tests are identified.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws
Domain
cloud, infrastructure
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.