ECS Fargate

View .md

ECS Fargate is the deploy target for a long-running webapi that should run as a container rather than a Lambda. Set deployTarget: "ecs-fargate" on the entry and kanject aws deploy builds the image, registers a task definition, and promotes it through CloudFormation. You deploy and roll back with the same commands as Lambda.

You'll learn
  • Turn an entry into an ECS Fargate service (deployTarget, webapi, image)
  • Configure the service — cpu/memory, autoscaling, ALB, IAM — in the stage file
  • Understand how a deploy promotes a task definition, and how rollback works
  • Know what's managed for you vs referenced, and the current limits

Make an entry ECS Fargate

An ECS service is exactly one entry, running one primary application container. doctor enforces the shape: runtimeMode must be webapi and packageType must be image.

json
// manifest.json → service.entryProjects[]{  "id": "web",  "projectPath": "src/Acme.Web/Acme.Web.csproj",  "runtimeMode": "webapi",  "packageType": "image",  "deployTarget": "ecs-fargate",  "build": { "kind": "container", "mode": "sdk-publish", "containerPort": 8080 }}
  • deployTarget — "ecs-fargate" (omit, or "lambda", for the Lambda path).
  • packageType — "image" is required; the service runs a container.
  • build — how the image is produced: mode: "sdk-publish" runs dotnet publish -t:PublishContainer (no Docker daemon), or "dockerfile" builds a Dockerfile. containerPort defaults to 8080.

Configure the service

The region-agnostic service shape lives in stages/<stage>.json → ecs:

json
// stages/<stage>.json"ecs": {  "cpu": 512,  "memory": 1024,  "desiredCount": 2,  "autoscaling": { "min": 2, "max": 10, "targetCpuPercent": 60 },  "circuitBreaker": { "enable": true, "rollback": true },  "alb": { "scheme": "public", "healthCheckPath": "/healthz", "port": 443 },  "assignPublicIp": false,  "taskRolePolicies": [],  "execRolePolicies": []}
  • cpu / memory / desiredCount (required) — Fargate task size and the baseline task count.
  • alb.healthCheckPath (required, KANCLI399) — the path the load balancer and the deploy's steady-state wait poll. A service that never reports healthy times out with KANCLI408.
  • autoscaling — min, max, targetCpuPercent for target-tracking; omit to hold desiredCount.
  • circuitBreaker — enable + rollback; ECS rolls a failed deployment back to the last good task definition.
  • alb — also scheme (public / internal) and port.
  • assignPublicIp, taskRolePolicies (your app's AWS permissions), execRolePolicies (image pull, secret read, logs).

Per-region references

Region-scoped resources — VPC, subnets, certificate, hosted zone, and an optional existing cluster — attach per target under targets[].ecs. They are referenced (Kanject CLI diagnoses them with KANCLI400–404 if missing, but never creates them).

json
// stages/<stage>.json — per-region references for an ECS target"targets": [  {    "region": "eu-west-2",    "ecs": {      "cluster": { "ref": "arn:aws:ecs:eu-west-2:111122223333:cluster/shared" },      "vpc": "vpc-0a1b2c3d",      "subnets": ["subnet-1111", "subnet-2222"],      "certificate": "arn:aws:acm:eu-west-2:111122223333:certificate/abc",      "hostedZone": "Z0123456789"    }  }]

Deploy and roll back

CloudFormation owns the durable parts: the cluster, service, load balancer, IAM roles and log groups. A deploy builds the image, pushes it to ECR pinned by digest (never a mutable tag), registers a task definition, points the service at it through a CloudFormation change set, and waits for steady state. A rollback is the same change set with the previous task definition.

bash
# Deploy: build the image, register a task definition, promote via CloudFormationkanject aws deploy --env prod​# Roll back to the previous task definition (a stack update — minutes, not seconds)kanject aws rollback --env prod

Managed vs referenced

  • Managed (CloudFormation creates): the ECS service, ALB + target group + listener, task & execution IAM roles, log groups, security groups, autoscaling. The cluster is managed by default, or you reference an existing one.
  • Referenced (must pre-exist): VPC + subnets, the ACM certificate, and the Route 53 hosted zone. Missing references are diagnosed before any change set runs.

Current limits

  • One entry — one primary application container — per ECS service. User-declared sidecars are a follow-up.
  • Deploys roll with the ECS circuit breaker by default. A stage rollout block can instead run a single-entry service as blue/green, or shift traffic in canary or linear steps behind an alarm gate; kanject doctor --env <stage> validates the block.
  • Migrating an existing Lambda to ECS creates a new, target-qualified stack and leaves the Lambda stack standing — opt in with --replace-target (refused when the stage carries an api.domain, to protect DNS).

Guidelines

  • Set autoscaling for anything production. desiredCount alone is a fixed floor; target-tracking handles load.
  • Keep secrets as references. The CLI checks they exist without reading them and passes them to the task definition as valueFrom, so ECS reads them at task start; secret values never enter the CLI process or the CloudFormation template.
  • Use --replace-target deliberately. It acknowledges that the old Lambda stack stays standing; remove it yourself once the new service is serving.
Recap
  • Set deployTarget: "ecs-fargate" (with webapi + image) to run an entry as a container service.
  • CloudFormation owns the durable infrastructure; each deploy registers a digest-pinned task definition and promotes it through a change set.
  • Configure the service in stages/<stage>.json → ecs; reference VPC / cert / zone per region under targets[].ecs.
  • Rollback re-promotes the previous task definition (minutes, preflighted). One entry per service; rolling deploys by default, blue/green or canary through a stage rollout block.
Was this page helpful?