feat(pod-identity): add Argo Rollouts IAM role for AMP query (IRSA, #42) - #831
feat(pod-identity): add Argo Rollouts IAM role for AMP query (IRSA, #42)#831allamand wants to merge 8 commits into
Conversation
…sters Adds an `argo-rollouts` identity entry to both pod-identity charts (ack and crossplane mirrors) and enables it in the dev and prod spoke overlays. ## Problem (Issue #42) The Argo Rollouts controller needs to query Amazon Managed Prometheus (AMP) to run the `metrics` analysis gate in Phase 30.5 (Metrics Driven Decisions). The `AnalysisTemplate` uses Prometheus `sigv4` auth — the controller signs requests with AWS SigV4 credentials from the default AWS credential chain. The SA annotation in `gitops/addons/registry/gitops.yaml` already points to `<clusterName>-argo-rollouts` but that role was never created by any chart, so the Pod Identity Agent had nothing to inject → SigV4 calls failed. ## Fix - Adds `argo-rollouts` identity (disabled by default) to both chart mirrors with an inline `ArgoRolloutsAMPQueryPolicy` (aps:QueryMetrics and read-only APS actions). Role name pattern follows the charts' convention: `<aws.clusterName>-argo-rollouts` (matches the gitops.yaml SA annotation). - Enables the identity in the `dev` and `prod` spoke environment overlays (spoke clusters are where Argo Rollouts runs; hub/control-plane excluded). - Chart comment explains the Pod Identity flow — no OIDC/IRSA required; the AWS SDK v1 default chain picks up `AWS_CONTAINER_CREDENTIALS_FULL_URI` that the Pod Identity Agent injects once the PIA exists. ## Validation plan Apply to kro-c1 live (peeks-spoke-dev) and verify: 1. ACK creates IAM Role `peeks-spoke-dev-argo-rollouts` and PIA 2. Argo Rollouts pod restarts → `AWS_CONTAINER_CREDENTIALS_FULL_URI` present 3. Phase 30.5 metrics AnalysisRun succeeds (SigV4 AMP query returns > 0) Fixes #42 (platform-engineering-on-eks issue tracker)
Live test results + Root cause analysis✅ What works
❌ What doesn't work yet (upstream bug)
EKS Pod Identity injects the file path variant, not the env var. So the SDK v1.38.35 credential chain fails with Fix optionsOption A (upstream fix) — Update Option B (Helm workaround) — Add an initContainer or sidecar to copy the token file content into Option C (use IRSA annotation instead of PIA) — The SA already has the IRSA annotation ( RecommendationThis PR is still valuable — it creates the IAM Role + PIA correctly. But a companion change is needed to make the credentials actually work:
Option C is the path of least resistance given the SA annotation already uses IRSA format. |
✅ Live test VALIDATED on kro-c1SummaryAfter resolving two additional issues, the metrics gate works end-to-end: AnalysisRun result: Issue 1 — Pod Identity vs IRSA (aws-sdk-go v1 incompatibility)
Fix: Remove the PodIdentityAssociation for argo-rollouts. The SA already has the PR action: This chart creates the IAM role via ACK and a PodIdentityAssociation. The PIA needs to be removed from the ACK template — we want IRSA injection, not Pod Identity injection. Update Issue 2 — AMP URL must NOT include /api/v1/query (Bug #38 extension)The ExternalSecret The Prometheus client appends Fix: Store only the workspace base URL: This needs to be fixed in the bootstrap process that creates Next steps for this PR
|
…ead of Pod Identity Adds a `skipPIA: true` opt-out field to the pod-identity charts. When set, the PodIdentityAssociation CR is not created (only IAM Role + Policy are). This is required for Argo Rollouts because: - The SA annotation `eks.amazonaws.com/role-arn` uses the IRSA mechanism - `prometheus/common/sigv4 v0.1.0` (used by Argo Rollouts for AMP SigV4 auth) depends on `aws-sdk-go v1.38.35` which supports `AWS_WEB_IDENTITY_TOKEN_FILE` (IRSA) but NOT `AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE` (Pod Identity) - Creating a PIA would inject Pod Identity tokens which the old SDK cannot read, causing `NoCredentialProviders` errors With `skipPIA: true` + OIDC provider registered + IRSA trust policy on the role, the pod gets `AWS_WEB_IDENTITY_TOKEN_FILE` injected → SigV4 AMP queries work. Validated live on kro-c1 (peeks-spoke-dev): AnalysisRun Successful with `value=[1,1,1,1,...]` — AMP queries returning real metrics. Note: Also revealed a second bug (AMP URL format) — the `peeks/platform/amp` Secrets Manager secret must store the workspace base URL WITHOUT the `/api/v1/query` suffix. The Prometheus client appends it automatically. Correct: `https://aps-workspaces.us-west-2.amazonaws.com/workspaces/${ws-id}` Wrong: `https://...workspaces/${ws-id}/api/v1/query` → 404 on every query
…mirror of ack fix)
… not Pod Identity Clarify that argo-rollouts uses IRSA (not Pod Identity) because prometheus/common/sigv4 v0.1.0 only supports AWS_WEB_IDENTITY_TOKEN_FILE. References argoproj/argo-rollouts#5010 for the upstream fix.
…true When an identity has skipPIA=true (no PodIdentityAssociation created), the IAM role needs an IRSA trust policy instead of a Pod Identity trust policy. Changes: - role.yaml: conditionally generates IRSA trust (sts:AssumeRoleWithWebIdentity with OIDC condition) when skipPIA=true AND aws.oidcIssuer is set, otherwise falls back to Pod Identity trust (pods.eks.amazonaws.com) - core.yaml: injects aws.oidcIssuer from cluster secret annotation eks_oidc_issuer into the ack_pod_identities chart values This completes the argo-rollouts fix: the role now has the correct trust policy for IRSA injection (AWS_WEB_IDENTITY_TOKEN_FILE) which is required because prometheus/common/sigv4 v0.1.0 does not support Pod Identity. Note: aws.oidcIssuer requires the OIDC provider to be registered in IAM. On EKS, this is done automatically since EKS 1.25 at cluster creation time. The EksCluster RGD writes eks_oidc_issuer to the cluster secret.
Temporary workaround for argoproj/argo-rollouts#4536: Argo Rollouts' SigV4 provider (prometheus/common/sigv4 v0.1.0 / aws-sdk-go v1.38) supports IRSA but not Pod Identity. IRSA requires the EKS OIDC issuer to be registered as an IAM OpenID Connect provider — EKS creates the endpoint automatically but does NOT register it in IAM. Changes: - cluster-providers/kind-kro-ack/Taskfile.yaml: new task 'spokes:register-oidc-providers' — discovers spoke clusters from fleet/members, reads each cluster's OIDC issuer, and creates the IAM OIDC provider if missing. Idempotent (skips if already registered). Only runs on kind-kro-ack. - workshop/Taskfile.yaml: call the new task after wait-for-spokes (spokes are ACTIVE at that point) but only when PROVIDER=kind-kro-ack. - gitops/addons/registry/core.yaml: inject aws.oidcIssuer from the cluster secret annotation into ack-pod-identity chart values (used by role.yaml to build the IRSA trust policy for skipPIA identities). Together with PR #831 (argo-rollouts IAM role + skipPIA IRSA trust policy), this makes the OIDC provider available so the role's trust policy can be satisfied and IRSA injection (`AWS_WEB_IDENTITY_TOKEN_FILE`) works. This workaround will be removed once argoproj/argo-rollouts#5010 is merged.
…ke scrapers The initial seed-observability runs in the background during hub install, before spoke clusters (peeks-spoke-dev/prod) exist. The spoke scraper loop finds no clusters → spoke_dev_cluster_arn/subnet/sg annotations are empty in the hub Secrets Manager secret → ESO propagates empty values to the ArgoCD cluster secret → observability-aws chart generates no spoke Crossplane Scrapers. Fix: re-run seed-observability after wait-for-spokes (spokes are ACTIVE at that point) so spoke cluster ARN/SG/subnets are correctly seeded into SM and the observability-aws chart generates spoke scrapers on the next sync. Verified: Team 10 (ADIDAS PEEKS, fresh WS account) confirms the bug — only peeks-peeks-hub scraper present, no peeks-spoke-dev scraper. Phase 30.5 metrics gate fails because Rust application metrics (team-rust namespace) are not in AMP.
…y seed
The seed-observability task used hardcoded 'spoke-dev'/'spoke-prod' cluster
names when calling 'aws eks describe-cluster'. The actual cluster names are
'<prefix>-spoke-dev' / '<prefix>-spoke-prod' (e.g. 'peeks-spoke-dev').
This caused:
WARN: Cluster spoke-dev not found in us-west-2. Scraper skipped.
WARN: Cluster spoke-prod not found in us-west-2. Scraper skipped.
So the spoke_dev_cluster_arn/subnet/sg annotations were never written to the
hub Secrets Manager secret → observability-aws chart generated no spoke
Crossplane Scrapers → Phase 30.5 metrics gate always fails (no spoke metrics
in AMP).
The peeks-observability-seed.timer runs every 20min and kept overwriting any
manually-set annotations with empty values.
Fix: replace 'spoke-dev spoke-prod' with
'{{.RESOURCE_PREFIX}}-spoke-dev {{.RESOURCE_PREFIX}}-spoke-prod' in both
kind-kro-ack and kind-crossplane Taskfiles.
Verified on Team 10 (ADIDAS PEEKS, account 795798215864): log showed
exactly the WARN message above on every timer run.
Problem
The Argo Rollouts controller needs to query Amazon Managed Prometheus (AMP) to run the
metricsanalysis gate in Phase 30.5. The SA annotation ingitops/addons/registry/gitops.yamlalready points toarn:aws:iam::<account>:role/<clusterName>-argo-rollouts, but that role was never created and the OIDC provider was never registered.Root cause: IRSA required, Pod Identity won't work
prometheus/common/sigv4 v0.1.0(used by Argo Rollouts for AMP SigV4 auth) usesaws-sdk-go v1.38.35which supportsAWS_WEB_IDENTITY_TOKEN_FILE(IRSA) but notAWS_CONTAINER_AUTHORIZATION_TOKEN_FILE(Pod Identity token file).Upstream tracking: argoproj/argo-rollouts#4536
Upstream fix PR (migrate to aws-sdk-go-v2): argoproj/argo-rollouts#5010
Complete fix (all 5 pieces)
1. IAM Role + Policy (ack-pod-identity chart)
New
argo-rolloutsidentity withskipPIA: trueand AMP query policy.skipPIAprevents creating a PodIdentityAssociation (which would trigger Pod Identity injection instead of IRSA).2. IRSA trust policy in role.yaml (new)
When
skipPIA: trueANDaws.oidcIssueris set, the role gets an IRSA trust policy (sts:AssumeRoleWithWebIdentitywith OIDC condition) instead of the default Pod Identity trust (pods.eks.amazonaws.com).3. oidcIssuer injected into chart values (core.yaml)
The
ack_pod_identitiesApplicationSet now injectsaws.oidcIssuerfrom the cluster secret annotationeks_oidc_issuer(written by the EksCluster RGD at cluster-creation time).4. OIDC provider registration at bootstrap (kind-kro-ack Taskfile)
New task
spokes:register-oidc-providers— discovers spoke clusters fromfleet/members, reads each cluster's OIDC issuer, and registers it as an IAM OpenID Connect provider if not already present. This is the missing piece: EKS creates the OIDC endpoint automatically but does NOT register the provider in IAM, which is required for IRSA to work.Called from
workshop/Taskfile.yamlafterwait-for-spokes(clusters are ACTIVE at that point), only whenPROVIDER=kind-kro-ack.5. Mirror in crossplane-pod-identity (drift test requirement)
Same
skipPIAflag andoidcIssuersupport mirrored to the Crossplane chart.Files changed
ack-pod-identity/values.yamlargo-rolloutsidentity:skipPIA: true, AMP policyack-pod-identity/templates/role.yamlskipPIA=true+oidcIssuersetack-pod-identity/templates/pod-identity-association.yamlskipPIA: truecrossplane-pod-identity/values.yamlcrossplane-pod-identity/templates/pod-identity-association.yamloverlays/environments/dev/pod-identities/values.yamloverlays/environments/prod/pod-identities/values.yamlgitops/addons/registry/core.yamlaws.oidcIssuerfrom cluster secretcluster-providers/kind-kro-ack/Taskfile.yamlspokes:register-oidc-providersworkshop/Taskfile.yamlwait-for-spokesFuture state
Once argoproj/argo-rollouts#5010 is merged and released (aws-sdk-go-v2, Pod Identity support):
skipPIA: true→ use Pod Identity normallyspokes:register-oidc-providerscall from workshop TaskfileValidation
Tested on kro-c1 (586794472760), spoke cluster
peeks-spoke-dev:AWS_WEB_IDENTITY_TOKEN_FILE✅phase=Successful,value=[1,1,1...]✅Fixes Issue #42 in platform-engineering-on-eks tracker.