Skip to content

fix(runners): make dedicated-host (mac/windows) ASG deploys resilient to metal capacity - #1113

Open
coderbirju wants to merge 1 commit into
mainfrom
fix/mac-runner-capacity-durability
Open

fix(runners): make dedicated-host (mac/windows) ASG deploys resilient to metal capacity#1113
coderbirju wants to merge 1 commit into
mainfrom
fix/mac-runner-capacity-durability

Conversation

@coderbirju

Copy link
Copy Markdown
Contributor

Problem

FinchPipeline deploys of the macOS/Windows runner ASGs intermittently wedge and block Finch releases. The rolling update terminates an instance before its replacement is InService (minInstancesInService: 0), and dedicated hosts are auto-released between deploys (auto-release-host: true). On scarce mac2.metal capacity this creates a gap: the old instance is gone, the replacement can't launch (Insufficient capacity. Launching EC2 instance failed.), the batch never stabilizes, and the CloudFormation update fails — sometimes wedging the stack in UPDATE_ROLLBACK_FAILED (observed on Production-ASG-mac-finch-15-armStack, which blocked the Prod wave and prevented the Release wave from running).

The prior maxCapacity = desiredInstances also means a bad instance cannot be replaced without deadlocking (no room to launch a replacement).

Fix (dedicated-host runners only; non-metal Linux ASGs unchanged)

  • N+1 headroom: maxCapacity = desiredInstances + 1 so a replacement can launch before the old instance is terminated, and a bad instance can always be replaced.
  • Launch-before-terminate: rollingUpdate.minInstancesInService = desiredInstances — never drop below desired healthy during a rollout.
  • Retain hosts: host resource group auto-release-host = false so the reserved host slot persists between deploys instead of re-competing for metal capacity (macOS hosts have a ~24h min allocation regardless, so retaining adds little effective cost).

Together these guarantee a reserved slot for the replacement, eliminating the capacity gap and the resulting wedge, while still allowing instance replacement.

Capacity / quota

Requires N+1 dedicated-host quota headroom. In Prod us-west-2 the mac2 dedicated-host quota (L-5D8DADF5) is 10 with 7 in use → sufficient for the +1 per mac arm stack. Recommend bumping to 12 for comfort during host recycle churn (separate quota request, not in this PR).

Testing

  • npm run build clean.
  • Unit tests pass (5/5). Added assertions that dedicated-host ASGs synthesize MaxSize = desired+1, MinInstancesInService = desired, MaxBatchSize = 1, and host resource group auto-release-host: false; and that non-metal (Linux) ASGs keep MaxSize = desired.

Rollout note

This changes the ASG capacity + host retention; first deploy will allocate the extra retained host. Should be rolled out when mac2.metal capacity is available. Does not fix an already-wedged stack (recover that separately via continue-update-rollback).

… to metal capacity

Rolling updates of the macOS/Windows runner ASGs terminate an instance
before its replacement is InService (minInstancesInService: 0), and hosts
are auto-released between deploys (auto-release-host: true). On scarce
mac2.metal capacity this causes a wedge: the old instance is gone, the
replacement can't launch ("Insufficient capacity"), the batch never
stabilizes, and the CloudFormation update fails and can get stuck in
UPDATE_ROLLBACK_FAILED - blocking Finch releases.

Changes (dedicated-host runners only; non-metal Linux ASGs unchanged):
- maxCapacity = desiredInstances + 1 (N+1 headroom) so a replacement can
  launch before the old instance is terminated, and so a bad instance can
  always be replaced without deadlocking.
- rollingUpdate.minInstancesInService = desiredInstances
  (launch-before-terminate) to avoid the capacity gap.
- host resource group auto-release-host = false to retain the reserved
  host slot between deploys instead of re-competing for metal capacity
  (macOS hosts have a ~24h min allocation anyway).

Requires N+1 dedicated-host quota headroom (mac2 quota L-5D8DADF5 in
us-west-2 is 10, 7 in use - sufficient). Adds unit tests asserting the
N+1 capacity, launch-before-terminate policy, and host retention for
dedicated-host runners, and that non-metal ASGs keep maxCapacity=desired.

Signed-off-by: Arjun Yogidas <arjunry@amazon.com>
@coderbirju
coderbirju marked this pull request as ready for review September 4, 2026 07:47
@coderbirju
coderbirju requested a review from a team as a code owner September 4, 2026 07:47
coderbirju added a commit that referenced this pull request Sep 4, 2026
…lock Prod wave (#1115)

mac2.metal ARM capacity in us-west-2 is exhausted: only 1 healthy instance exists and AWS cannot allocate a 2nd (all available mac2 hosts at 0 free capacity). The Production-ASG-mac-finch-15-armStack ASG wants DesiredCapacity=2, so CloudFormation cannot stabilize and the stack wedges (UPDATE_ROLLBACK_FAILED), blocking the Prod wave and the downstream Release wave (which carries the Windows update).

Reduce runnerProd mac/15.7/arm/finch desiredInstances 2 -> 1 to match currently available capacity so the deploy stabilizes on the single existing instance.

TEMPORARY: restore to 2 (and/or rely on the N+1 durability fix in #1113) once mac2.metal capacity is healthy. Complementary to #1113, which ADDS N+1 headroom (needs more capacity); this REDUCES demand to match current capacity.

Signed-off-by: Arjun Yogidas <arjunry@amazon.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant