Skip to content

Detect cloud-init failure at startup to prevent silent cluster miscon… - #4988

Merged
amogh09 merged 1 commit into
aws:devfrom
amogh09:amoghr/cloudinit-check
Jun 9, 2026
Merged

amogh09 merged 1 commit into
aws:devfrom
amogh09:amoghr/cloudinit-check

Conversation

@amogh09

@amogh09 amogh09 commented Jun 2, 2026 •

Copy link
Copy Markdown
Contributor

Summary

When IMDS is transiently unreachable during instance boot (e.g., ENI initialization failure), cloud-init falls back to DataSourceNone and skips userdata execution. The ECS agent then starts with default config which is undesirable.

This adds a best-effort check at agent startup that detects this condition and terminally exits (code 5) so Agent does not run with default configuration.

Implementation details

Detection logic:

  1. Read /var/lib/cloud/data/result.json (bind-mounted by ecs-init)
  2. If datasource is DataSourceNone AND IMDS /latest/user-data returns non-empty content → cloud-init failed to execute userdata
  3. Agent logs CRITICAL and exits with code 5 (terminal, no restart)

Fail-open design: Any failure to read or parse the file causes the check to be skipped. The check can never incorrectly prevent the agent from starting.

Changes:

  • ecs-init/docker/docker_config.go: Optional read-only bind mount of /var/lib/cloud/data/result.json (skipped in External mode, logs warning if file missing)
  • agent/config/cloudinit_check_linux.go: CheckCloudInitFailure() function with fail-open semantics
  • agent/config/cloudinit_check_unsupported.go: No-op stub for non-Linux
  • agent/app/agent.go: Call the check in doStart() before Docker version verification (skipped in External mode)

Testing

  • Unit tests cover all branches: file missing, invalid JSON, DataSourceEc2, DataSourceNone + IMDS error, DataSourceNone + empty userdata, DataSourceNone + non-empty userdata (detection fires)
  • E2E test (MACIS): two-phase instance test — install agent on first boot, cloud-init clean + IMDS disable on second boot, verify agent exits 5 with "Cloud-init failure detected" in logs
  • Verified on AL2023 ECS-Optimized AMI
  • Verified detection does NOT fire on normally-booted instances

New tests cover the changes: yes

Description for the changelog

Feature - Detect cloud-init failure at startup to prevent silent cluster misconfiguration when IMDS is transiently unreachable during boot

Additional Information

Does this PR include breaking model changes? No

Does this PR include the addition of new environment variables in the README? No

Licensing

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@amogh09
amogh09 force-pushed the amoghr/cloudinit-check branch from d151b94 to eea8c52 Compare June 4, 2026 23:12
@amogh09
amogh09 marked this pull request as ready for review June 5, 2026 00:37
@amogh09
amogh09 requested a review from a team as a code owner June 5, 2026 00:37
@amogh09
amogh09 force-pushed the amoghr/cloudinit-check branch from eea8c52 to 48f01ca Compare June 5, 2026 01:07
@amogh09
amogh09 force-pushed the amoghr/cloudinit-check branch from 48f01ca to c7e91f3 Compare June 5, 2026 19:26
Comment thread agent/config/cloudinit_check_linux.go Outdated

userData, err := ec2Client.GetUserData()
if err != nil {
seelog.Infof("cloud-init used DataSourceNone; unable to verify if userdata exists on IMDS, skipping check: %v", err)

@mye956 mye956 Jun 5, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: thinking more on this now, why do we not want to throw a terminal error if we're unable to get the userdata? is this for the edge case where IMDS is not available on the host or something else?

@gitesh-tyagi gitesh-tyagi Jun 5, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, along similar lines, I want to understand.

what happens for no userdata case? will it be an error or empty userdata?

what happens for IMDS not reachable case? agent should always be able to reach to IMDS else why start on broken host for unreliable failures/config down the line?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My intention for this check is to catch the narrow case where cloud-init failed to fetch userdata but it is available now. That is why this check skips when it cannot establish if userdata is available now. Also it is possible to have Agent run with IMDS disabled (by providing everything that Agent needs from IMDS via env vars instead), so failing here would block such use cases. It is okay if this check has some leaks but I don't want it to break any legitimate setups.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove this check altogether. It only exists to allow Agent to run in cases when there was no userdata to begin with thus making cloud-init failure a no-op from ECS config POV.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens for no userdata case? will it be an error or empty userdata?

In that case err is non-nil due to a 404 response from IMDS and we don't block Agent.

what happens for IMDS not reachable case? agent should always be able to reach to IMDS else why start on broken host for unreliable failures/config down the line?

It is possible to configure Agent to run without IMDS access by providing overrides for region, credentials etc. using environment variables or a custom credentials file (/rotatingcreds/credentials), so failing here can break such setups. If Agent is configured to require IMDS then it will fail regardless of whether we fail in this branch or not.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove this check altogether. It only exists to allow Agent to run in cases when there was no userdata to begin with thus making cloud-init failure a no-op from ECS config POV.

This is a legitimate case though, no? Wouldn't that mean if no userdata is specified and IMDS is transiently unreachable during instance boot (but then possibly reachable later), that ECS Agent would fail to start up? I expect that customers who don't specify userdata wouldn't want ECS Agent to fail to start up in this case.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also it is possible to have Agent run with IMDS disabled (by providing everything that Agent needs from IMDS via env vars instead), so failing here would block such use cases.

Ah gotcha, mainly for external/ECS Anywhere scenarios iiuc. Although, there isn't anything blocking anyone from doing it on EC2 hosts as well. Thanks for clarifying.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah gotcha, mainly for external/ECS Anywhere scenarios iiuc.

Yes but for external mode this check is not even invoked.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a legitimate case though, no? Wouldn't that mean if no userdata is specified and IMDS is transiently unreachable during instance boot (but then possibly reachable later), that ECS Agent would fail to start up? I expect that customers who don't specify userdata wouldn't want ECS Agent to fail to start up in this case.

Yep.

mye956
mye956 previously approved these changes Jun 8, 2026
danehlim
danehlim previously approved these changes Jun 8, 2026
@amogh09
amogh09 dismissed stale reviews from danehlim and mye956 via df76918 June 8, 2026 20:07
@amogh09
amogh09 force-pushed the amoghr/cloudinit-check branch 3 times, most recently from 75ac162 to e8c15c9 Compare June 8, 2026 20:20
…figuration

When IMDS is transiently unreachable during instance boot, cloud-init
falls back to DataSourceNone and skips userdata execution. The agent then
starts with default config and silently registers to the wrong cluster.

Add a best-effort check at agent startup: if cloud-init's result.json
reports DataSourceNone and userdata exists on IMDS, the agent terminally
exits (code 5) so ASG replaces the instance. The check is fail-open —
any error reading or parsing the file causes it to be skipped.

Changes:
- ecs-init: bind mount /var/lib/cloud/data/result.json into agent container
- agent: add CheckCloudInitFailure() in config package (Linux only)
- agent: call the check in doStart() before Docker version verification
@amogh09
amogh09 force-pushed the amoghr/cloudinit-check branch from e8c15c9 to 07efcae Compare June 8, 2026 20:29
@amogh09
amogh09 merged commit aa4092a into aws:dev Jun 9, 2026
45 checks passed
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.

5 participants