Skip to content

feat(ci3): diversify build-instance spot via EC2 create-fleet (v5-next) - #23966

Merged
charlielye merged 2 commits into
v5-nextfrom
ci3-spot-create-fleet-v5
Jun 9, 2026
Merged

feat(ci3): diversify build-instance spot via EC2 create-fleet (v5-next)#23966
charlielye merged 2 commits into
v5-nextfrom
ci3-spot-create-fleet-v5

Conversation

@charlielye

Copy link
Copy Markdown
Contributor

Important

Draft until the IAM policy is applied. Depends on AztecProtocol/github-aws-oidc-factory#21 (grants the pipeline-exec role ec2:CreateFleet/CreateLaunchTemplate/DeleteLaunchTemplate + describe/launch-template perms). Without it, provisioning hits UnauthorizedOperation. Marking ready once that policy is live.

v5-next port of #23963 (identical ci3 changes; the three files match between next and v5-next).

Problem

Build instances almost never won their spot bid. Two root causes:

  1. Diversification never ran. aws_request_instance looped m6a → m7a → m7i, but aws_request_instance_type fell back to on-demand inside the first pool's call, so m6a.32xlarge spot failed → m6a on-demand succeeded → returned. m7a/m7i spot was never tried (and m7i.32xlarge doesn't even exist).
  2. A single pool is the worst case. AWS Spot Placement Score for m6a.32xlarge in us-east-2 is 1/10 in every AZ.

Change

Replace the legacy request-spot-instances call with a single aws ec2 create-fleet --type instant per request:

  • capacity-optimized-prioritized across an expanded pool set spanning 192/128/64-vCPU sizes and all AZs. Priority prefers 128 → 192 → 64; 64 is still taken as spot before any on-demand.
  • Memory-safe families only (m + r, ≥4 GB/vCPU). Measured build peak ~1.9 GB/vCPU, so c-series (2 GB/vCPU) is excluded by default, gated behind CI_SPOT_INCLUDE_C.
  • Spot retry loop within a CI_SPOT_TIMEOUT budget (default 60s), preserving the historical "try spot ~1 min, then on-demand" behaviour.
  • On-demand fallback (lowest-price create-fleet) only after the spot budget expires.
  • An ephemeral launch template carries the common config and is deleted on exit; --type instant leaves no spot request or fleet to clean up.

bootstrap_ec2 now requests cores=192,128,64.

Files

  • ci3/aws_request_instance — override-list builder (size→priority, family pools, AWS_INSTANCE/CI_SPOT_INCLUDE_C).
  • ci3/aws_request_instance_type — create-fleet provisioning (LT, subnet lookup, spot retry loop, on-demand fallback, markers, LT cleanup); IP-wait/SSM/SSH tail unchanged.
  • ci3/bootstrap_ec2cores=192,128,64.

Validation

Exercised live against us-east-2 (on the next branch): create-fleet returned a spot m7i.48xlarge immediately; real script end-to-end acquired spot via the retry loop, wrote markers, reached SSM Online, deleted the launch template, clean exit; on-demand fallback (NO_SPOT=1) marks ondemand; no leaked instances, templates, or fleets.

Build instances almost never won their spot bid. Two causes: the request
hit a single pool (m6a.32xlarge, one AZ — Spot Placement Score 1/10 in
us-east-2), and the on-demand fallback fired inside the first pool's call,
so the m6a/m7a/m7i loop never actually diversified.

Replace the legacy request-spot-instances call with a single
`aws ec2 create-fleet --type instant` per request:

- capacity-optimized-prioritized across an expanded, memory-safe (>=4 GB/vCPU,
  m+r families) pool set spanning 192/128/64-vCPU sizes and all AZs. Priority
  prefers 128, then 192, then 64 (c-series is opt-in via CI_SPOT_INCLUDE_C
  pending build-parallelism throttling — measured peak ~1.9 GB/vCPU).
- spot attempts retry within a CI_SPOT_TIMEOUT budget (default 60s),
  preserving the historical "try spot ~1 min then on-demand" behaviour.
- on-demand create-fleet (lowest-price) only after the spot budget expires.
- an ephemeral launch template carries the common config and is deleted on
  exit; --type instant leaves no spot request or fleet to clean up.

Validated live: spot, spot-retry and on-demand paths all acquire and tear
down cleanly with no leaked instances, templates or fleets.

Requires the matching pipeline-exec IAM policy
(AztecProtocol/github-aws-oidc-factory#21) to be applied first.
Cosmetic only — the override list was built by appending " $t:$prio",
leaving a leading space that surfaced as a leading comma in the
"(pools: …)" log line. Word-splitting already discarded it when parsing,
so the fleet JSON was always correct (override count unchanged).
@charlielye
charlielye requested a review from ludamad June 9, 2026 14:36
@charlielye
charlielye marked this pull request as ready for review June 9, 2026 14:36
@charlielye
charlielye enabled auto-merge June 9, 2026 14:37
@charlielye
charlielye added this pull request to the merge queue Jun 9, 2026
Merged via the queue into v5-next with commit 2745c75 Jun 9, 2026
18 checks passed
@charlielye
charlielye deleted the ci3-spot-create-fleet-v5 branch June 9, 2026 15:29
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.

2 participants