Skip to content

feat(addons): add ACK backup-controller (Preview v0.1.1) as optional addon - #631

Draft
allamand wants to merge 3 commits into
aws-samples:mainfrom
allamand:feat/ack-backup-controller
Draft

feat(addons): add ACK backup-controller (Preview v0.1.1) as optional addon#631
allamand wants to merge 3 commits into
aws-samples:mainfrom
allamand:feat/ack-backup-controller

Conversation

@allamand

Copy link
Copy Markdown
Contributor

Summary

The EKS ACK capability is GA but does not currently bundle the aws-controllers-k8s/backup-controller (Preview v0.1.1, May 2026). This PR adds the backup-controller Helm chart as an optional GitOps-managed addon so users can declaratively create BackupPlan/BackupVault/BackupSelection resources from Kubernetes until AWS ships it inside the capability.

Motivation

Working on a cross-region EKS DR reference (AWS Backup + kro + ACK), I needed backup.services.k8s.aws CRDs on a PeEKS hub. Enabling the ACK capability on an EKS 1.31 cluster provisions ~180 *.services.k8s.aws CRDs, but none of the backup.services.k8s.aws group — confirmed live on eu-west-1. The only way to get them today is via the upstream Helm chart.

Changes

  • gitops/addons/bootstrap/default/addons.yaml — new ack-backup entry, modeled after ack-iam and ack-eks:
    • Chart: public.ecr.aws/aws-controllers-k8s/backup-chart:0.1.1
    • Namespace: ack-system
    • Sync-wave: -1 (post-kro RGD)
    • Selector: enable_ack_backup=true
    • Same CRD ignoreDifferences as other ACK controllers
    • SA: ack-backup-controller (override via ack_backup_service_account annotation)
  • platform/infra/terraform/hub-config.yamlenable_ack_backup: false seed added to the three cluster blocks, with a comment noting the Preview status.

Out of scope (follow-up)

  • IAM role / Pod Identity binding for the ack-backup-controller SA. Users must provide an ARN with AWSBackupFullAccess through the existing pod-identity annotation mechanism (same pattern as ack-iam, ack-eks).
  • Flip to EKS capability once AWS includes backup-controller in the bundled ACK capability — at that point enable_ack_backup should flip back to false and the capability flag should take over.

Validation

  • YAML parse OK on both files
  • helm template oci://public.ecr.aws/aws-controllers-k8s/backup-chart --version 0.1.1 --namespace ack-system renders cleanly
  • Deployed live on an EKS 1.31 Auto Mode hub → 3 CRDs present (backupplans, backupvaults, backupselections under backup.services.k8s.aws); controller pod starts (CrashLoops pending IRSA, as expected — out of scope here)

Related

Sebastien Allamand and others added 2 commits May 11, 2026 18:52
…addon

The EKS `ACK` capability is GA but does not currently bundle the
`aws-controllers-k8s/backup-controller` (Preview v0.1.1) as of May 2026.
Verified live on an EKS 1.31 hub cluster: enabling the `ACK` capability
provisions ~180 `*.services.k8s.aws` CRDs but none of
`backupplans/backupvaults/backupselections.backup.services.k8s.aws`.

This PR adds the backup-controller Helm chart as an optional addon so
users can deploy AWS Backup resources (BackupPlan/BackupVault/BackupSelection)
declaratively via GitOps until AWS ships it inside the `ACK` capability.

Changes:
- gitops/addons/bootstrap/default/addons.yaml: new `ack-backup` entry,
  modeled after `ack-iam`/`ack-eks`. Chart:
  public.ecr.aws/aws-controllers-k8s/backup-chart:0.1.1, namespace
  ack-system, sync-wave -1, selector `enable_ack_backup=true`, same
  CRD ignoreDifferences as other ACK controllers.
- platform/infra/terraform/hub-config.yaml: `enable_ack_backup: false`
  seed value added to the three cluster blocks, with a comment noting
  the Preview status.

Out of scope (follow-up):
- IAM role / Pod Identity binding for the `ack-backup-controller`
  ServiceAccount. Users must provide an ARN with AWSBackupFullAccess
  via the existing pod-identity annotation mechanism (same pattern as
  other ACK controllers).
- Flip to EKS capability once AWS includes backup-controller in the
  bundled `ACK` capability.

Signed-off-by: Sebastien Allamand <allamand@amazon.fr>
Adds a second pod-identity path in the application-sets chart, parallel
to the existing Crossplane path, using the kro RGD podidentity.kro.run.
When an addon sets enableACKKRO: true, the chart renders an additional
Argo source pointing at gitops/addons/charts/kro/instances/pod-identity,
which expands to:
  - iam.services.k8s.aws/Policy
  - iam.services.k8s.aws/Role (trust pods.eks.amazonaws.com)
  - eks.services.k8s.aws/PodIdentityAssociation

enableACK (Crossplane) and enableACKKRO (kro+ACK) are mutually exclusive;
enabling both triggers a helm template fail with a clear message.

The ack-backup addon is wired with enableACKKRO: true and ships a
least-privilege policyDocument covering backup:*, backup-storage:*,
iam:PassRole (scoped to role/*), and the KMS actions required for
cross-account encrypted snapshots (Decrypt, Encrypt, GenerateDataKey*,
DescribeKey, CreateGrant). This closes the IRSA gap that otherwise
leaves the backup-controller pod in CrashLoopBackOff.

Files:
  - gitops/addons/charts/application-sets/templates/_pod_identity_kro.tpl (new)
  - gitops/addons/charts/application-sets/templates/application-set.yaml (mutex + second guard)
  - gitops/addons/bootstrap/default/addons.yaml (enableACKKRO + podIdentity block)

Signed-off-by: Sebastien Allamand <allamand@amazon.com>
Signed-off-by: Sébastien Allamand <allamand@users.noreply.github.com>
@allamand

Copy link
Copy Markdown
Contributor Author

Update: Pod Identity wiring via kro + ACK

Second commit (795c45c1) completes the PR by wiring the backup-controller's Pod Identity via the existing kro + ACK path (not Crossplane).

Added

  • gitops/addons/charts/application-sets/templates/_pod_identity_kro.tpl — new template, mirrors _pod_identity.tpl but points at gitops/addons/charts/kro/instances/pod-identity (the existing kro-pi-instance chart backed by the podidentity.kro.run RGD).
  • Second guard in application-set.yaml triggered by enableACKKRO: true. Mutex with enableACK: setting both fails the helm template with an explicit error.
  • podIdentity block on ack-backup: namespace, service account, and least-privilege policyDocument.

IAM policy scope

  • backup:*, backup-storage:*
  • iam:PassRole scoped to arn:aws:iam::*:role/* (decoupled from backup-role naming)
  • KMS: Decrypt, Encrypt, GenerateDataKey*, DescribeKey, CreateGrant — required for cross-account encrypted snapshot copies.

Validation

  • helm template renders 3 Argo sources for ack-backup (values / pod-identity / chart) ✅
  • Mutex triggers fail as expected ✅
  • No change to existing addons using enableACK (Crossplane path untouched) ✅

Resolves the IRSA CrashLoopBackOff observed after deploying ack-backup-controller Helm chart standalone on an EKS Auto Mode cluster.

…path

The upstream ACK capability role grants workload-role management
(iam:CreateRole, PutRolePolicy, etc.) scoped per cluster, but is
missing the permissions needed by the kro+ACK pod-identity pattern:

  - iam:CreatePolicy/GetPolicyVersion/... (RGD creates a managed
    iam.services.k8s.aws/Policy, not an inline policy)
  - iam:PassRole (eks.services.k8s.aws/PodIdentityAssociation needs
    to pass the workload role to the EKS Pod Identity service)
  - eks:*PodIdentityAssociation (to create the association itself)

Also: the existing ManageIRSARoles policy was filtered to exclude
control-plane clusters. Renamed the comment (the IAM actions are
trust-policy-agnostic — same perms work for both IRSA and Pod
Identity) and removed the control-plane filter so the hub can run
kro+ACK-wired addons too (e.g. ack-backup-controller).

Changes:
  - ManageIRSARoles: removed environment != control-plane filter
  - ManageWorkloadPolicies (new): iam:CreatePolicy/... scoped to
    arn:aws:iam::ACCT:policy/${cluster.name}-*
  - ManagePodIdentityAssociations (new): iam:PassRole (constrained
    by iam:PassedToService = pods.eks.amazonaws.com) +
    eks:*PodIdentityAssociation scoped to
    cluster/${cluster.name} and
    podidentityassociation/${cluster.name}/*

Validated end-to-end on hub eu-west-1 (account 586794472760):
  - kro PodIdentity CR → RGD expands to ACK Policy + Role + PIA
  - All 3 ACK CRs SYNCED=True without manual IAM intervention
  - eks.list-pod-identity-associations returns the association
  - ack-backup-controller pod Running 1/1 (was CrashLoopBackOff)
  - BackupVault CR → AWS Backup vault created (ARN resolved)

Signed-off-by: Sebastien Allamand <allamand@amazon.com>
Signed-off-by: Sébastien Allamand <allamand@users.noreply.github.com>
@allamand

Copy link
Copy Markdown
Contributor Author

Commit 3 3d93e6bc — Terraform: extend ACK capability role for kro+ACK Pod Identity path

Root cause discovered during end-to-end validation on hub eu-west-1: the upstream aws_iam_role.eks_capability_ack role (in platform/infra/terraform/cluster/main.tf) was missing the IAM permissions needed by the kro+ACK pod-identity pattern introduced in commit 2. Symptom: kro PodIdentity CR stuck — ACK iam.Policy / iam.Role / PodIdentityAssociation reconciliation failed with AccessDenied.

Gaps (confirmed via runtime testing):

  • iam:CreatePolicy / GetPolicyVersion / CreatePolicyVersion / ... — the kro RGD creates a managed iam.services.k8s.aws/Policy (not inline on the role), so ManageIRSARoles perms were insufficient
  • iam:PassRole — needed so eks.services.k8s.aws/PodIdentityAssociation can pass the workload role to the EKS Pod Identity service
  • eks:*PodIdentityAssociation* + eks:TagResource/UntagResource/ListTagsForResource — the PodIdentityAssociation CRUD itself
  • ManageIRSARoles filter environment != "control-plane" — excluded the hub, blocking kro+ACK-wired addons on the capability cluster

Fix (3 policies on aws_iam_role.eks_capability_ack):

  1. ManageIRSARoles — removed control-plane filter + clarifying comment (IAM actions are trust-policy-agnostic, same perms work for IRSA and Pod Identity)
  2. ManageWorkloadPolicies (new)iam:CreatePolicy/DeletePolicy/GetPolicy/GetPolicyVersion/ListPolicyVersions/CreatePolicyVersion/DeletePolicyVersion/TagPolicy/UntagPolicy scoped to policy/${cluster.name}-*
  3. ManagePodIdentityAssociations (new)iam:PassRole (condition iam:PassedToService = pods.eks.amazonaws.com, scoped to role/${cluster.name}-*) + eks:*PodIdentityAssociation* scoped to cluster/${cluster.name} + podidentityassociation/${cluster.name}/*

Validation end-to-end on hub eu-west-1 (account 586794472760), workarounds removed:

  • kro PodIdentity CR kro-pi-instance-ack-backup-controllerSTATE=ACTIVE READY=True
  • ACK Policy hub-backup-chart-pod-policySYNCED=True (ARN resolved)
  • ACK Role hub-backup-chart-roleSYNCED=True (trust pods.eks.amazonaws.com)
  • ACK PodIdentityAssociationSYNCED=True, aws eks list-pod-identity-associations returns the association
  • ack-backup-controller-backup-chart pod → Running 1/1 (was CrashLoopBackOff)
  • BackupVault CR → AWS Backup vault created, deleted cleanly

terraform plan diff: 3 to add, 0 to change, 0 to destroy (one per cluster key — spoke clusters already had ManageIRSARoles, this just adds the 2 new Pod-Identity policies; hub gets all 3).

allamand added a commit to allamand/appmod-blueprints that referenced this pull request May 15, 2026
Wire a new 'enableACKKRO' flag on per-addon chart configs in the
appset-chart. When set, the addon ApplicationSet gets a second source
pointing to gitops/addons/charts/kro/instances/pod-identity, which
materializes ACK iam.Role + iam.Policy + eks.PodIdentityAssociation via
the podidentity.kro.run RGD instead of the legacy Crossplane path.

- 'enableACKKRO' and 'enableAckPodIdentity' are mutually exclusive;
  the template fails fast if both are set on the same addon.
- All existing addons keep their behavior (no flag flip).
- Required for ACK controllers not yet bundled in the EKS ACK
  capability (e.g. ack-backup, currently in preview at v0.1.1).

Adapted from upstream PR aws-samples#631 to fit the
appset-chart structure on the feature/platform-cluster-kro-ack base
(PR aws-samples#642). Credit to the upstream author.
allamand added a commit to allamand/appmod-blueprints that referenced this pull request May 15, 2026
Register the ack-backup-controller (chart oci://public.ecr.aws/aws-controllers-k8s/backup-chart:0.1.1)
as a regular addon in gitops/addons/registry/platform.yaml.

Why an addon and not the EKS ACK capability?
The backup ACK controller is in PREVIEW (v0.1.1, May 2026) and is NOT
yet bundled in the managed 'ACK' capability. Until AWS ships it as part
of the capability, it is deployed via Helm.

How does it get its IAM?
Through the new enableACKKRO=true path on appset-chart (previous commit).
That path renders gitops/addons/charts/kro/instances/pod-identity, which
expands via the podidentity.kro.run RGD to ACK iam.Role + iam.Policy +
eks.PodIdentityAssociation for SA ack-backup-controller in ack-system.

Policy follows least-privilege:
- backup:* + backup-storage:* on all resources
- iam:PassRole scoped to role/* (controller passes backup service roles)
- kms:Decrypt/Encrypt/GenerateDataKey/CreateGrant for encrypted vaults

Enabled only on the hub cluster via 'enable_ack_backup: true' in
hub-config.yaml; spokes keep it false.

Required prerequisite for the BackupPolicy RGD (PR aws-samples#644) to materialize
its referenced backup.services.k8s.aws CRDs (BackupVault, BackupPlan,
BackupSelection).

Adapted from upstream PR aws-samples#631.
allamand added a commit to allamand/appmod-blueprints that referenced this pull request May 15, 2026
Wire a new 'enableACKKRO' flag on per-addon chart configs in the
appset-chart. When set, the addon ApplicationSet gets a second source
pointing to gitops/addons/charts/kro/instances/pod-identity, which
materializes ACK iam.Role + iam.Policy + eks.PodIdentityAssociation via
the podidentity.kro.run RGD instead of the legacy Crossplane path.

- 'enableACKKRO' and 'enableAckPodIdentity' are mutually exclusive;
  the template fails fast if both are set on the same addon.
- All existing addons keep their behavior (no flag flip).
- Required for ACK controllers not yet bundled in the EKS ACK
  capability (e.g. ack-backup, currently in preview at v0.1.1).

Adapted from upstream PR aws-samples#631 to fit the
appset-chart structure on the feature/platform-cluster-kro-ack base
(PR aws-samples#642). Credit to the upstream author.
allamand added a commit to allamand/appmod-blueprints that referenced this pull request May 15, 2026
Register the ack-backup-controller (chart oci://public.ecr.aws/aws-controllers-k8s/backup-chart:0.1.1)
as a regular addon in gitops/addons/registry/platform.yaml.

Why an addon and not the EKS ACK capability?
The backup ACK controller is in PREVIEW (v0.1.1, May 2026) and is NOT
yet bundled in the managed 'ACK' capability. Until AWS ships it as part
of the capability, it is deployed via Helm.

How does it get its IAM?
Through the new enableACKKRO=true path on appset-chart (previous commit).
That path renders gitops/addons/charts/kro/instances/pod-identity, which
expands via the podidentity.kro.run RGD to ACK iam.Role + iam.Policy +
eks.PodIdentityAssociation for SA ack-backup-controller in ack-system.

Policy follows least-privilege:
- backup:* + backup-storage:* on all resources
- iam:PassRole scoped to role/* (controller passes backup service roles)
- kms:Decrypt/Encrypt/GenerateDataKey/CreateGrant for encrypted vaults

Enabled only on the hub cluster via 'enable_ack_backup: true' in
hub-config.yaml; spokes keep it false.

Required prerequisite for the BackupPolicy RGD (PR aws-samples#644) to materialize
its referenced backup.services.k8s.aws CRDs (BackupVault, BackupPlan,
BackupSelection).

Adapted from upstream PR aws-samples#631.
@allamand
allamand marked this pull request as draft May 18, 2026 15:57
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.

1 participant