Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions website/docs/guides/feature-gates.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ ACK controllers support feature gates that enable or disable specific functional
| **ResourceAdoption** | Beta | Enabled | Import existing AWS resources into ACK management using adoption annotations. [Learn more](/guides/adoption) |
| **ReadOnlyResources** | Beta | Enabled | Observe AWS resources without ACK managing them using read-only annotation. [Learn more](/guides/readonly) |
| **IAMRoleSelector** | Alpha | Disabled | Use IAMRoleSelector CRD for dynamic IAM role mapping to namespaces and resources. [Learn more](/guides/cross-account) |
| **IgnoreFieldDrift** | Alpha | Disabled | Stop reconciling drift on specific fields using the ignore-field-drift annotation. [Learn more](/guides/ignore-field-drift) |
| **ServiceLevelCARM** | Alpha | Disabled | Enable CARM (Cross-Account Resource Management) for service-level resources |
| **TeamLevelCARM** | Alpha | Disabled | Enable CARM (Cross-Account Resource Management) for team-level resources |

Expand Down Expand Up @@ -53,4 +54,5 @@ Enabling IAMRoleSelector disables CARM features. These features cannot be used t

- [Resource adoption](/guides/adoption) - Import existing AWS resources
- [ReadOnly resources](/guides/readonly) - Observe resources without managing them
- [Ignore field drift](/guides/ignore-field-drift) - Stop reconciling drift on specific fields
- [Advanced IAM roles](/guides/cross-account) - Configure IAMRoleSelector for multi-account management
89 changes: 89 additions & 0 deletions website/docs/guides/ignore-field-drift.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
---
title: Ignore Field Drift
---

# Ignore Field Drift

By default, an ACK controller treats the resource spec as the source of truth: on every reconcile it compares your spec against the live AWS state and drives AWS back to match. The `services.k8s.aws/ignore-field-drift` annotation lets you tell ACK to **stop reconciling drift on specific fields**, while still creating and managing the rest of the resource.

This is useful when part of a resource is legitimately managed outside of ACK — for example, when organization tooling applies dynamic tags that ACK would otherwise keep trying to remove.

:::info Feature Status
Ignore Field Drift is gated by the **`IgnoreFieldDrift`** feature gate — an **Alpha** feature that is **disabled by default**. An operator must enable it on the controller before the annotation has any effect:

```bash
helm install ... --set featureGates.IgnoreFieldDrift=true
```

See [Feature Gates](/guides/feature-gates).
:::

## What it does

For each field listed in the annotation, ACK:

- **Still creates** the field from your spec (the create-time value is the baseline).
- **Still late-initializes** it if configured (an unset field is populated once from AWS).
- **Stops reconciling drift** — if the field changes on the AWS side out-of-band, ACK does **not** reset it to your spec.
- **Retains your declared value** in the resource spec — ACK never overwrites it with the AWS-observed value.

The resource stays `ACK.ResourceSynced=True`: you have declared that you don't want these fields managed, so the resource is in its desired managed state. Drift on ignored fields is recorded in the controller logs.

## Using the annotation

The annotation value is a comma-separated list of dotted, JSON-style field paths (the paths you see in your resource YAML):

```yaml
apiVersion: iam.services.k8s.aws/v1alpha1
kind: Role
metadata:
name: app-role
annotations:
services.k8s.aws/ignore-field-drift: "spec.tags"
spec:
name: app-role
policies:
- arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
tags:
- key: team
value: payments
```

With this in place:

1. At create, ACK applies your declared tag (`team=payments`) — the baseline.
2. External tooling adds other tags to the role in AWS. On the next reconcile, ACK observes them but, because `spec.tags` drift is ignored, does **not** remove them.
3. You can still change **other** fields (e.g. `spec.policies`) — those are reconciled normally. The role remains fully managed for everything except tag drift.

## Example: tags managed by an external system

The motivating scenario ([community#2367](https://github.com/aws-controllers-k8s/community/issues/2367)): an organization auto-applies dynamic tags to every IAM role (a session ID, a creation timestamp), and a Service Control Policy denies `iam:UntagRole`. Without this feature, ACK repeatedly tries to remove the org tags, the `UntagRole` call is denied, and the resource is stuck `ACK.ResourceSynced=False`.

Annotating the role with `services.k8s.aws/ignore-field-drift: "spec.tags"` stops ACK from fighting the external tags: no `UntagRole` call, no stuck reconcile, and the role is still managed for its policies and other fields.

## Removing the annotation

Removing the annotation (or dropping a path from it) is **non-destructive**: because your declared value was never cleared from the spec, ACK resumes reconciling the field toward whatever your spec currently holds.

```bash
kubectl annotate role app-role services.k8s.aws/ignore-field-drift-
```

:::note Removal is not immediate
ACK watches resources with a generation-changed filter, so editing an annotation alone does not trigger a reconcile — the field is re-enforced on the next spec change or on the periodic resync (default 10 hours). To resume management immediately, remove the annotation **and** make any spec change in the same edit (which bumps the resource generation and triggers a reconcile).
:::

If instead you want the current AWS value to become the new desired state, set your spec field to that value (before or after removing the annotation) — ACK never silently adopts a drifted value.

## Notes and limitations

- **Whole-field only.** A field is either fully managed or fully ignored. Ignoring only a sub-field inside a list entry (e.g. one element's weight) is not supported.
- **Applies to drift, not create.** The field is still sent at create and still late-initialized; only *subsequent* drift is ignored. Adding a *new* value and the annotation in the same edit on an existing resource will not apply the new value — set the value first (or at create), then add the annotation.
- **Paths are validated for syntax only.** A malformed path (illegal characters, empty segments) is logged as a warning. A well-formed but incorrect path (e.g. a typo like `spec.tagz`) silently has no effect — double-check the path matches your resource's spec.
- **Observability is log-only in this release** — there is no dedicated status condition for ignored-field drift yet.

## Next Steps

- [Feature Gates](/guides/feature-gates) - Enable `IgnoreFieldDrift`
- [ReadOnly Resources](/guides/readonly) - Observe a resource without managing any field
- [Deletion Policy](/guides/deletion-policy) - Control deletion behavior for managed resources
5 changes: 5 additions & 0 deletions website/sidebars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ const sidebars: SidebarsConfig = {
id: 'guides/readonly',
label: 'ReadOnly Resources',
},
{
type: 'doc',
id: 'guides/ignore-field-drift',
label: 'Ignore Field Drift',
},
{
type: 'doc',
id: 'guides/deletion-policy',
Expand Down