Skip to content

Migrate EC2 metadata to SDKv2 - #1992

Merged
jefchien merged 1 commit into
feature/aws-sdk-v2from
aws-sdk-v2/ec2tagger
Jan 22, 2026
Merged

Migrate EC2 metadata to SDKv2#1992
jefchien merged 1 commit into
feature/aws-sdk-v2from
aws-sdk-v2/ec2tagger

Conversation

@jefchien

Copy link
Copy Markdown
Contributor

Description of the issue

The next one in the list after the exporters is the EC2 tagger.

Description of changes

internal/ec2metadataprovider

  • Migrated from aws-sdk-go/aws/ec2metadata to aws-sdk-go-v2/feature/ec2/imds
  • Replaced dual metadata client pattern (fallback enabled/disabled) with v2/v1 client pattern for clarity using EnableFallback ternary
  • Simplified metadata retrieval methods by consolidating fallback retry logic into a single getMetadata() helper
  • Enhanced test coverage with mock IMDS server

internal/retryer/v2/

  • Created new imdsretryer.go implementing AWS SDK v2 retry interface
  • Added comprehensive unit tests for IMDS-specific retry behavior
  • Maintains backward compatibility with existing retry logic while using v2 patterns
    • MaxAttempts = Retries + 1

plugins/processors/ec2tagger/

  • Updated ec2ProviderType to support v2 credential loading
  • Refactored volume operations to use v2 EC2 types throughout the internal volume package

extension/entitystore/

  • Updated to use cfg/aws/v2 credential configuration
  • Cleaned up unused ec2ProviderType and nativeCredential fields

License

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Tests

Kept unit tests as intact as possible while adding some additional coverage.

PR Build: https://github.com/aws/amazon-cloudwatch-agent/actions/runs/21230132305

Ran integration tests against branch: https://github.com/aws/amazon-cloudwatch-agent/actions/runs/21231010826

Ran the agent with metric collection enabled along with append_dimensions for volume, instance ID, and instance type. Can see it successfully send and can see metrics in CloudWatch.

Can see the entity store attempt to get the tags from IMDS

2026-01-21T22:20:26Z D! {"caller":"entitystore/retryer.go:75","msg":"attribute retrieval retry count","retry":1}
2026-01-21T22:20:26Z D! {"caller":"entitystore/retryer.go:80","msg":"there was an issue when retrieving entity attributes but will not affect agent functionality","error":"operation error ec2imds: GetMetadata, http response error StatusCode: 404, request to EC2 IMDS failed"}
2026-01-21T22:20:26Z D! Request
GET /latest/meta-data/tags/instance HTTP/1.1
Host: 169.254.169.254
User-Agent: aws-sdk-go-v2/1.41.1 ua/2.1 os/linux lang/go#1.25.5 md/GOOS#linux md/GOARCH#amd64 ft/ec2-imds
Amz-Sdk-Request: attempt=1; max=2
X-Aws-Ec2-Metadata-Token: <snip>
Accept-Encoding: gzip

2026-01-21T22:20:26Z D! Response
HTTP/1.1 404 Not Found
Connection: close
Content-Length: 339
Content-Type: text/html
Date: Wed, 21 Jan 2026 22:20:26 GMT
Server: EC2ws
X-Aws-Ec2-Metadata-Token-Ttl-Seconds: 238

2026-01-21T22:20:27Z D! Request
GET /latest/meta-data/tags/instance HTTP/1.1
Host: 169.254.169.254
User-Agent: aws-sdk-go-v2/1.41.1 ua/2.1 os/linux lang/go#1.25.5 md/GOOS#linux md/GOARCH#amd64 ft/ec2-imds
Amz-Sdk-Request: attempt=2; max=2
X-Aws-Ec2-Metadata-Token: <snip>
Accept-Encoding: gzip

2026-01-21T22:20:27Z D! Response
HTTP/1.1 404 Not Found
Connection: close
Content-Length: 339
Content-Type: text/html
Date: Wed, 21 Jan 2026 22:20:27 GMT
Server: EC2ws
X-Aws-Ec2-Metadata-Token-Ttl-Seconds: 237

2026-01-21T22:20:27Z D! Could not perform operation without IMDS v1 fallback enabled. Enabling fallback.
2026-01-21T22:20:27Z D! Request
GET /latest/meta-data/tags/instance HTTP/1.1
Host: 169.254.169.254
User-Agent: aws-sdk-go-v2/1.41.1 ua/2.1 os/linux lang/go#1.25.5 md/GOOS#linux md/GOARCH#amd64 ft/ec2-imds
Amz-Sdk-Request: attempt=1; max=3
X-Aws-Ec2-Metadata-Token: <snip>
Accept-Encoding: gzip

2026-01-21T22:20:27Z D! Response
HTTP/1.1 404 Not Found
Connection: close
Content-Length: 339
Content-Type: text/html
Date: Wed, 21 Jan 2026 22:20:27 GMT
Server: EC2ws
X-Aws-Ec2-Metadata-Token-Ttl-Seconds: 238

2026-01-21T22:20:27Z D! {"caller":"entitystore/serviceprovider.go:275","msg":"Failed to get service name from instance tags. This is likely because instance tag is not enabled for IMDS but will not affect agent functionality."}

Can see it successfully get the instance identity document

2026-01-22T00:31:02Z D! Request
GET /latest/dynamic/instance-identity/document HTTP/1.1
Host: 169.254.169.254
User-Agent: aws-sdk-go-v2/1.41.1 ua/2.1 os/linux lang/go#1.25.5 md/GOOS#linux md/GOARCH#amd64 ft/ec2-imds
Amz-Sdk-Request: attempt=1; max=2
X-Aws-Ec2-Metadata-Token: <snip>
Accept-Encoding: gzip

2026-01-22T00:31:02Z D! Response
HTTP/1.1 200 OK
Connection: close
Content-Length: 478
Accept-Ranges: none
Content-Type: text/plain
Date: Thu, 22 Jan 2026 00:31:02 GMT
Last-Modified: Thu, 22 Jan 2026 00:14:41 GMT
Server: EC2ws
X-Aws-Ec2-Metadata-Token-Ttl-Seconds: 300

Requirements

Before commiting your code, please do the following steps.

  1. Run make fmt and make fmt-sh
  2. Run make lint

Integration Tests

To run integration tests against this PR, add the ready for testing label.

@jefchien
jefchien requested a review from a team as a code owner January 22, 2026 00:33
var getMetaDataProvider = func(ctx context.Context) ec2metadataprovider.MetadataProvider {
mdCredentialConfig := &configaws.CredentialsConfig{}
cfg, err := mdCredentialConfig.LoadConfig(ctx)
if err != nil {

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.

should log the error?

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.

It's already logged in config/aws/v2/credentials.go.

type metadataClient struct {
metadataFallbackDisabled *ec2metadata.EC2Metadata
metadataFallbackEnabled *ec2metadata.EC2Metadata
v2Client *imds.Client

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.

a comment or todo would be nice for why to keep both and what to do later on.

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.

I don't think there is a TODO unless we want to mention that we're going to remove the v1Client once IMDSv1 is removed.

Comment on lines +33 to +35
Standard: retry.NewStandard(func(options *retry.StandardOptions) {
options.MaxAttempts = retries + 1 // MaxAttempts include the first attempt
}),

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.

Is the reason for this custom retryer so that we can update the max attempts? Otherwise, I don't think we would need one. NewFromConfig for IMDS has the "standard" retryer already: https://github.com/aws/aws-sdk-go-v2/blob/dcbed91b6c6235022f15eda6ea526dbb91e1cb81/feature/ec2/imds/api_client.go#L117-L119.

If that is also the case, we can use the pattern described in https://docs.aws.amazon.com/sdk-for-go/v2/developer-guide/configure-retries-timeouts.html#customizing-behavior under Limiting the max number of attempts. This is more of a nit; I'm not opposed to what you have already.

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.

The custom IMDS retryer is to allow retries for not just the default retryable codes/errors, but basically any AWS error from IMDS. In SDKv2, IMDS returns https://github.com/aws/aws-sdk-go-v2/blob/dcbed91b6c6235022f15eda6ea526dbb91e1cb81/feature/ec2/imds/request_middleware.go#L185-L191, which may or may not fall under the standard retryables.

I'll try changing the pattern in the next PR.

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.

Tried it out and remembered why I couldn't use it. retry.AddWithMaxAttempts returns an aws.Retryer. The new IMDS retryer and retry.Standard both implement the aws.RetryerV2 interface, so it wouldn't satisfy the new functions it needs to cover.

@jefchien
jefchien merged commit aa4b305 into feature/aws-sdk-v2 Jan 22, 2026
559 of 574 checks passed
@jefchien
jefchien deleted the aws-sdk-v2/ec2tagger branch January 22, 2026 22:06
jefchien added a commit that referenced this pull request Feb 4, 2026
jefchien added a commit that referenced this pull request Feb 6, 2026
sky333999 pushed a commit that referenced this pull request Jun 18, 2026
Squashed application of the aws-sdk-v2 migration (feature/aws-sdk-v2) onto
latest main. Replaces the SDKv1 credential chain, service clients, retryers,
and request handlers with SDKv2 equivalents, and removes the hand-vendored
SDKv1 cloudwatch/cloudwatchlogs services (~44k lines).

Source PRs (Jeffrey Chien):
- #1981 Support credential chain for AWS SDK Go v2
- #1985 Migrate CloudWatch exporter to SDKv2
- #1989 Migrate CloudWatch logs output plugin to SDKv2
- #1992 Migrate EC2 metadata to SDKv2
- #1994 Migrate ECS service discovery to SDKv2
- #1995 Migrate wizard, downloader, and translator to SDKv2
- #2001 Remove SDKv1 direct dependencies
- Use a shared HTTP client to reduce file descriptor usage

aws-sdk-go (v1) is no longer a direct dependency. cfg/aws now exposes the v2
credential chain (CredentialsConfig.LoadConfig), STS regional->partitional
fallback, smithy custom-header middleware, and a shared BuildableClient.
sky333999 pushed a commit that referenced this pull request Jun 29, 2026
Squashed application of the aws-sdk-v2 migration (feature/aws-sdk-v2) onto
latest main. Replaces the SDKv1 credential chain, service clients, retryers,
and request handlers with SDKv2 equivalents, and removes the hand-vendored
SDKv1 cloudwatch/cloudwatchlogs services (~44k lines).

Source PRs (Jeffrey Chien):
- #1981 Support credential chain for AWS SDK Go v2
- #1985 Migrate CloudWatch exporter to SDKv2
- #1989 Migrate CloudWatch logs output plugin to SDKv2
- #1992 Migrate EC2 metadata to SDKv2
- #1994 Migrate ECS service discovery to SDKv2
- #1995 Migrate wizard, downloader, and translator to SDKv2
- #2001 Remove SDKv1 direct dependencies
- Use a shared HTTP client to reduce file descriptor usage

aws-sdk-go (v1) is no longer a direct dependency. cfg/aws now exposes the v2
credential chain (CredentialsConfig.LoadConfig), STS regional->partitional
fallback, smithy custom-header middleware, and a shared BuildableClient.
sky333999 pushed a commit that referenced this pull request Jul 30, 2026
Squashed application of the aws-sdk-v2 migration (feature/aws-sdk-v2) onto
latest main. Replaces the SDKv1 credential chain, service clients, retryers,
and request handlers with SDKv2 equivalents, and removes the hand-vendored
SDKv1 cloudwatch/cloudwatchlogs services (~44k lines).

Source PRs (Jeffrey Chien):
- #1981 Support credential chain for AWS SDK Go v2
- #1985 Migrate CloudWatch exporter to SDKv2
- #1989 Migrate CloudWatch logs output plugin to SDKv2
- #1992 Migrate EC2 metadata to SDKv2
- #1994 Migrate ECS service discovery to SDKv2
- #1995 Migrate wizard, downloader, and translator to SDKv2
- #2001 Remove SDKv1 direct dependencies
- Use a shared HTTP client to reduce file descriptor usage

aws-sdk-go (v1) is no longer a direct dependency. cfg/aws now exposes the v2
credential chain (CredentialsConfig.LoadConfig), STS regional->partitional
fallback, smithy custom-header middleware, and a shared BuildableClient.
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.

3 participants