Skip to content

Fix CloudWatch log group collision for multiple executor fleets - #211

Open
michaellzc wants to merge 2 commits into
mainfrom
michaellzc/investigate-slack-thread
Open

Fix CloudWatch log group collision for multiple executor fleets#211
michaellzc wants to merge 2 commits into
mainfrom
michaellzc/investigate-slack-thread

Conversation

@michaellzc

Copy link
Copy Markdown
Member

Problem

The executor (and docker-mirror) AMIs' CloudWatch agent ships host /var/log/syslog to a hard-coded log group — executors (and executors_docker_mirror). Running two executor fleets in one AWS account/region therefore collides on a single shared log group: the second terraform apply fails with ResourceAlreadyExistsException. This is the exact scenario in examples/multiple-executors (e.g. code-intel + batches). randomize_resource_names didn't help — it only changed the resource's tags.Name, never the real log group name or the on-host agent's target.

Fix (end-to-end name parameterization)

  • aws_cloudwatch_log_group.syslogs.name now uses the resolved name — randomized (unique) when randomize_resource_names = true, else the legacy fixed name for backward compatibility — in both modules/executors and modules/docker-mirror.
  • The resolved name is passed into the launch template / instance user_data, and the startup script reconfigures the on-host CloudWatch agent at boot to write to that group:
    • Prefers the AMI helper /usr/local/bin/configure-cloudwatch-agent-log-group when present (added in the matching AMI change).
    • Falls back to rewriting the agent config + fetch-config (works with existing/older AMIs). The fallback is gated on the agent binary, because fetch-config consumes the source config file at build time so it isn't present on running instances.
  • modules/docker-mirror/startup-script.shstartup-script.sh.tpl (templatefile) to receive the name.
  • Added cloudwatch_log_group_name outputs to both modules and documented the randomize_resource_names = true requirement for multi-fleet deployments.

Compatibility

  • Default (randomize_resource_names = false) keeps the legacy executors / executors_docker_mirror names → no replacement for existing single-fleet deployments.
  • The fallback path means this works with current AMIs immediately; the AMI helper (sourcegraph/sourcegraph) just makes the on-host reconfiguration cleaner once a new AMI ships.

Testing

Validated e2e on a real AWS account (two fleets + shared docker-mirror, all randomize_resource_names = true):

  • Both fleets terraform apply together with no collision.
  • Three distinct randomized log groups created; each host's running CloudWatch agent config points at its randomized group; all groups receive {instance_id}-syslog.
  • Verified against both a stock nightly AMI (fallback path) and a purpose-built AMI carrying the helper (helper path taken per cloud-init).

Companion AMI change: sourcegraph/sourcegraph (parameterized configure-cloudwatch-agent-log-group helper).

🤖 Generated with Claude Code

michaellzc and others added 2 commits July 22, 2026 19:38
The executor and docker-mirror AMIs' CloudWatch agent ships host syslog to
a hard-coded log group ("executors" / "executors_docker_mirror"). Running
two executor fleets in one account/region therefore collided on a single
shared log group: the second `terraform apply` failed with
ResourceAlreadyExistsException. `randomize_resource_names` only affected the
resource's tag, never the actual log group name or the on-host agent target.

Make the log group name configurable end to end:

- aws_cloudwatch_log_group.syslogs now uses the resolved name (randomized
  when randomize_resource_names=true, else the legacy fixed name for
  backward compatibility) in both modules.
- Pass the resolved name into the launch template / instance user_data and
  reconfigure the on-host CloudWatch agent at boot so it writes to the
  configured group. Prefer the AMI helper
  (/usr/local/bin/configure-cloudwatch-agent-log-group) when present, else
  fall back to rewriting the agent config and running fetch-config (works
  with existing AMIs). Gate the fallback on the agent binary, since
  fetch-config consumes the source config file at build time.
- docker-mirror startup-script.sh becomes a templatefile (.tpl) to receive
  the name.
- Add cloudwatch_log_group_name outputs to both modules and document the
  randomize_resource_names requirement for multi-fleet deployments.

Requires the matching AMI change (parameterized helper) to exercise the
helper path; the fallback keeps existing AMIs working immediately.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When not randomizing, the executor log group name fell back to the literal
"executors", so two fleets distinguished only by resource_prefix still
collided on it — even though every other non-randomized executor resource
(IAM role, launch template, ASG, security group, alarms) already includes the
prefix via local.prefix.

Make the non-randomized log group name include the prefix too:
  - randomize_resource_names: unique via random suffix (unchanged)
  - resource_prefix set:      "<prefix>_sourcegraph_executors" (now unique)
  - neither:                  legacy "executors" (single default fleet, unchanged)

Update the multiple-executors README: a distinct resource_prefix per fleet
(with or without randomize_resource_names) is sufficient to avoid the
collision.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@DaedalusG

Copy link
Copy Markdown
Contributor

@michaellzc these terraform repos don't have a "reease branch" concept since they only get releases during a minor/major sourcegraph release and theres currently no concept of a patch release in these repos

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants