Repository navigation
Releases: AkashiSN/node-rotation-controller
Release list
v0.7.0
What's Changed
Features
- feat(docs): publish the Scenario P validation report as a docs page (EN/JA) by @AkashiSN in #275
- feat(metrics): signal a maintenance window that closes with candidates unrotated by @AkashiSN in #319
- feat(metrics): export the in-backoff claim count so the in-window alert can match the lost-window counter by @AkashiSN in #323
- feat(selection): clamp the retry backoff to the maintenance window occurrence the failure happened in by @AkashiSN in #324
- feat(controller): name which surge path reserved the capacity by @AkashiSN in #325
- feat(surge): opt-in whole-node surge reservation, and announce the headroom block by @AkashiSN in #327
Fixes
- fix(deps): update module github.com/go-logr/logr to v1.4.4 - autoclosed by @renovate[bot] in #290
- fix(controller): count a rotation completion once per released anchor by @AkashiSN in #306
- fix(controller): refuse to start a rotation on a static NodePool by @AkashiSN in #308
- fix(controller): claim the transition on terminal NodeClaim writes by @AkashiSN in #309
- fix(controller): claim the transition on the two backward claim writes by @AkashiSN in #310
- fix(controller): let the startup sweep announce only what it wrote by @AkashiSN in #312
- fix(controller): let the startup sweep act on, and announce, what it selected by @AkashiSN in #314
- fix(controller): let the governance-lost reap announce what it has done by @AkashiSN in #316
Documentation
- docs(spec): rewrite specification, validation, and CI/CD docs per style guide by @AkashiSN in #276
- docs(contributing): unify documentation and release rules by @AkashiSN in #278
- docs(spec): name every emitted Event in the §4.3 table, and guard it by @AkashiSN in #318
- docs(spec): the clamp refusal settles what it reserves, not whether the placeholder is schedulable by @AkashiSN in #329
- docs(spec): record static NodePool support as rejected, not deferred by @AkashiSN in #331
- docs: state what the project is, not the order it got there by @AkashiSN in #339
- docs(controller): the claim-scoped emissions do own their transitions by @AkashiSN in #340
- docs(spec): record the whole-node reservation measurement in §7.2 by @AkashiSN in #345
- docs(contributing): the release section describes the repository it has by @AkashiSN in #344
Maintenance
- test(poc): tight-race expireAfter soak under a sub-daily window (Scenario P) by @AkashiSN in #272
- chore(deps): bump GitHub Actions to latest major versions by @AkashiSN in #281
- chore(deps): update Go modules and bump toolchain to 1.26.5 by @AkashiSN in #279
- chore(deps): refresh npm lockfile (vue 3.5.40, plugin-vue 6.0.8) by @AkashiSN in #280
- chore(deps): update aqua-pinned CLIs and track the registry ref with Renovate by @AkashiSN in #282
- chore(deps): update dependency aquaproj/aqua-registry to v4.538.1 by @renovate[bot] in #283
- chore(deps): update dependency aquaproj/aqua to v2.62.0 by @renovate[bot] in #284
- chore(deps): update dependency aws/aws-cli to v2.36.4 by @renovate[bot] in #286
- chore(deps): update dependency aquaproj/aqua-registry to v4.539.0 by @renovate[bot] in #287
- chore(deps): update gcr.io/distroless/static-debian12:nonroot docker digest to f5b485e by @renovate[bot] in #289
- chore(deps): update dependency happy-dom to v20.11.0 by @renovate[bot] in #288
- chore(deps): move the Go/Kubernetes stack to Go 1.27.1 and Kubernetes 1.37 by @AkashiSN in #335
- chore(renovate): group the dependency updates that can only land together by @AkashiSN in #332
- chore(deps): batch the docs-site npm updates by @AkashiSN in #334
- chore(deps): batch the aqua-pinned CLIs and the aqua installer by @AkashiSN in #333
- chore(deps): update dependency vitest to v5 by @renovate[bot] in #338
- chore(ci): parse the PromQL the chart's PrometheusRule ships by @AkashiSN in #341
- chore(deps): update dependency helm/helm to v4.3.0 by @renovate[bot] in #343
- chore(deps): update dependency happy-dom to v20.14.3 by @renovate[bot] in #346
- chore(deps): update dependency helm/helm to v4.3.0 by @renovate[bot] in #347
- chore(release): prepare v0.7.0 by @AkashiSN in #342
New Contributors
Full Changelog: v0.6.1...v0.7.0
v0.7.0-rc.1
What's Changed
Features
- feat(docs): publish the Scenario P validation report as a docs page (EN/JA) by @AkashiSN in #275
- feat(metrics): signal a maintenance window that closes with candidates unrotated by @AkashiSN in #319
- feat(metrics): export the in-backoff claim count so the in-window alert can match the lost-window counter by @AkashiSN in #323
- feat(selection): clamp the retry backoff to the maintenance window occurrence the failure happened in by @AkashiSN in #324
- feat(controller): name which surge path reserved the capacity by @AkashiSN in #325
- feat(surge): opt-in whole-node surge reservation, and announce the headroom block by @AkashiSN in #327
Fixes
- fix(deps): update module github.com/go-logr/logr to v1.4.4 - autoclosed by @renovate[bot] in #290
- fix(controller): count a rotation completion once per released anchor by @AkashiSN in #306
- fix(controller): refuse to start a rotation on a static NodePool by @AkashiSN in #308
- fix(controller): claim the transition on terminal NodeClaim writes by @AkashiSN in #309
- fix(controller): claim the transition on the two backward claim writes by @AkashiSN in #310
- fix(controller): let the startup sweep announce only what it wrote by @AkashiSN in #312
- fix(controller): let the startup sweep act on, and announce, what it selected by @AkashiSN in #314
- fix(controller): let the governance-lost reap announce what it has done by @AkashiSN in #316
Documentation
- docs(spec): rewrite specification, validation, and CI/CD docs per style guide by @AkashiSN in #276
- docs(contributing): unify documentation and release rules by @AkashiSN in #278
- docs(spec): name every emitted Event in the §4.3 table, and guard it by @AkashiSN in #318
- docs(spec): the clamp refusal settles what it reserves, not whether the placeholder is schedulable by @AkashiSN in #329
- docs(spec): record static NodePool support as rejected, not deferred by @AkashiSN in #331
- docs: state what the project is, not the order it got there by @AkashiSN in #339
- docs(controller): the claim-scoped emissions do own their transitions by @AkashiSN in #340
Maintenance
- test(poc): tight-race expireAfter soak under a sub-daily window (Scenario P) by @AkashiSN in #272
- chore(deps): bump GitHub Actions to latest major versions by @AkashiSN in #281
- chore(deps): update Go modules and bump toolchain to 1.26.5 by @AkashiSN in #279
- chore(deps): refresh npm lockfile (vue 3.5.40, plugin-vue 6.0.8) by @AkashiSN in #280
- chore(deps): update aqua-pinned CLIs and track the registry ref with Renovate by @AkashiSN in #282
- chore(deps): update dependency aquaproj/aqua-registry to v4.538.1 by @renovate[bot] in #283
- chore(deps): update dependency aquaproj/aqua to v2.62.0 by @renovate[bot] in #284
- chore(deps): update dependency aws/aws-cli to v2.36.4 by @renovate[bot] in #286
- chore(deps): update dependency aquaproj/aqua-registry to v4.539.0 by @renovate[bot] in #287
- chore(deps): update gcr.io/distroless/static-debian12:nonroot docker digest to f5b485e by @renovate[bot] in #289
- chore(deps): update dependency happy-dom to v20.11.0 by @renovate[bot] in #288
- chore(deps): move the Go/Kubernetes stack to Go 1.27.1 and Kubernetes 1.37 by @AkashiSN in #335
- chore(renovate): group the dependency updates that can only land together by @AkashiSN in #332
- chore(deps): batch the docs-site npm updates by @AkashiSN in #334
- chore(deps): batch the aqua-pinned CLIs and the aqua installer by @AkashiSN in #333
- chore(deps): update dependency vitest to v5 by @renovate[bot] in #338
- chore(ci): parse the PromQL the chart's PrometheusRule ships by @AkashiSN in #341
New Contributors
Full Changelog: v0.6.1...v0.7.0-rc.1
v0.6.1
v0.6.0
What's Changed
Features
- feat(schedule): forecast throughput from surge.drainEstimate, not the force-kill deadline by @AkashiSN in #217
- feat(observability): log every rotation state-machine transition by @AkashiSN in #223
- feat(observability): make
rotation completea self-contained line (surgeNode, total) by @AkashiSN in #229 - feat(schedule): model provisioning in t_rot_est, drop buffer (ADR-0003) by @AkashiSN in #232
- feat(policy): split surge.failurePause off cooldownAfter (ADR-0004) by @AkashiSN in #233
- feat(metrics): export layer-2 forecast inputs (C, t_rot_est, t_rot bound) (#218) by @AkashiSN in #234
- feat(sim): add the pure discrete-event rotation simulator core by @AkashiSN in #241
- feat(wasm): compile the policy simulator to wasm and guard its purity in CI by @AkashiSN in #242
- feat(docs): browser policy simulator page by @AkashiSN in #243
- feat(sim): return generations, rotations and window intervals; fix the partial-run sweep by @AkashiSN in #248
- feat(docs): redesign the simulator timeline by @AkashiSN in #249
- feat(docs): share a simulator run via a URL by @AkashiSN in #257
- feat(docs): make the simulator legible in dark mode and its minimap navigable by @AkashiSN in #262
- feat(docs): seed the simulator with defaults a visitor can read by @AkashiSN in #263
- feat(docs): explain the simulator's form, symbols and warnings by @AkashiSN in #264
- feat(docs): navigate the simulator by rotation occasion, not by rotation start by @AkashiSN in #265
- feat(docs): show the simulator's derivation, not only its result by @AkashiSN in #268
Fixes
- fix(schedule): count starts with ceil, replace ThroughputZero with a carry-over check by @AkashiSN in #214
- fix(chart): seal the RotationPolicy value subtree against typo'd keys by @AkashiSN in #222
- fix(metrics): observe duration histograms after the durable transition write by @AkashiSN in #226
- fix(surge): clamp placeholder requests to NodeClaim.status.allocatable by @AkashiSN in #227
- fix(controller): requeue benign rotationpolicy-status write conflicts instead of ERROR by @AkashiSN in #237
- fix(controller): recheck RotationPolicy status against caught-up caches by @AkashiSN in #245
- fix(docs): stop the simulator page overflowing and restore its typography by @AkashiSN in #251
- fix(docs): keep the mobile nav until the desktop layout arrives by @AkashiSN in #253
- fix(docs): align the simulator's right gutter with the nav bar's background by @AkashiSN in #255
- fix(docs): lower the simulator share-link ceiling below the host's request-line limit by @AkashiSN in #259
Maintenance
- refactor(schedule): right-size Buffer to 4·shortRequeue (2m) and keep it internal by @AkashiSN in #231
- test(poc): re-validate Scenario O forceful fallback under Buffer=2m by @AkashiSN in #235
- refactor(selection,controller): make the rotation decision layer pure (no karpv1) by @AkashiSN in #239
- chore(release): prepare v0.6.0 by @AkashiSN in #269
Other Changes
Full Changelog: v0.5.0...v0.6.0
v0.5.0
Upgrade notes
Three things need your attention before upgrading. The new forceful fallback itself is opt-in and off by default, so it requires no action from existing users.
Apply the CRD before helm upgrade. This release adds surge.forcefulFallback to the RotationPolicy CRD, and Helm does not upgrade CRDs — it only installs them on first install. Run kubectl apply -f charts/node-rotation-controller/crds/ (or apply the CRD from the packaged chart) before helm upgrade, otherwise a policy that sets the new field is rejected at admission.
Candidate selection now orders by deadline, not by age. The controller picks the eligible candidate with the earliest forceful-expiration deadline (creationTimestamp + expireAfter) rather than the oldest node. This only changes behavior when expireAfter is heterogeneous across NodeClaims, where a younger claim with a shorter expireAfter can reach forceful expiration before an older claim with a longer one. If every NodeClaim in a pool shares the same expireAfter, deadline order equals oldest-first and the pick is unchanged.
Nodes you have annotated karpenter.sh/do-not-disrupt are now excluded from candidate selection. The controller distinguishes its own transient do-not-disrupt (marked with noderotation.io/do-not-disrupt-owned) from one you applied yourself, and never rotates or unprotects the latter. If you were relying on the controller rotating such nodes, remove the annotation.
Verifying this release
Both the container image and the Helm chart are published with a keyless cosign signature and a GitHub build-provenance attestation bound to the release workflow's OIDC identity. The image also carries an in-registry SBOM and SLSA provenance, and an SPDX SBOM is attached to this release. See SECURITY.md for the cosign verify and gh attestation verify invocations.
What's Changed
Features
- feat(api): add reserved surge.forcefulFallback toggle (#156 D2) by @AkashiSN in #161
- feat(schedule): ThroughputBurstShortfall detection for synchronized batches (#156 D3) by @AkashiSN in #163
- feat(controller): window-bounded surge-less forceful fallback (#156 D4) by @AkashiSN in #165
- feat(selection): order candidates by earliest deadline (#157) by @AkashiSN in #169
- feat: exclude do-not-disrupt nodes from rotation candidate selection by @AkashiSN in #170
- feat(release): publish SBOM, provenance, and signatures for the image and chart by @AkashiSN in #208
- feat(chart): alert on rising noderotation_forceful_fallback_total by @AkashiSN in #205
Fixes
Documentation
- docs(adr): ADR-0001 window-bounded forceful fallback (relax surge-only) by @AkashiSN in #158
- docs(spec): forceful fallback + burst shortfall; accept ADR-0001 by @AkashiSN in #159
- docs: bilingual VitePress GitHub Pages site (spec/runbook/figures + developer CI/CD page) by @AkashiSN in #176
- docs: split specification into chapters, consolidate reference/, redesign nav by @AkashiSN in #178
- docs: fix mistranslations, omissions, and broken sentences (EN/JA parity) by @AkashiSN in #181
- docs: unify terminology across JA spec/runbook and add §1.4 glossary/symbol entries by @AkashiSN in #182
- docs: restructure dense spec/runbook/ci-cd paragraphs for readability (EN/JA) by @AkashiSN in #183
- docs(readme): fix JA omissions/overstatements, align PDB wording, restructure install by @AkashiSN in #184
- docs(spec): close EN spec/ADR consistency & completeness gaps by @AkashiSN in #188
- docs(site): add planned→validated status column to CoverageMatrix (#186) by @AkashiSN in #189
- docs(contributing): codify JA translation conventions (code-comment, stuck-drain) by @AkashiSN in #190
- docs: close remaining JA terminology/wording gaps from doc review Step 1 by @AkashiSN in #192
- docs: refresh the READMEs and the §6.2 roadmap for v0.5.0 by @AkashiSN in #204
- docs(ja): translate the perf notes and codify ADRs as English-only by @AkashiSN in #206
Maintenance
- test(e2e): KWOK surge-less forceful-fallback scenario (#156 D5) by @AkashiSN in #167
- test(e2e): trick-free real-EKS validation of forceful fallback / #157 / #170 (Scenario O) by @AkashiSN in #171
- chore(ci): skip heavy CI steps on docs-only changes via per-job change detection by @AkashiSN in #174
- chore: drop ConfigMap-era configuration references by @AkashiSN in #179
- chore(docker): pin base image digests for reproducible builds by @AkashiSN in #194
- test(controller): pin surgelessFallback threshold boundaries by @AkashiSN in #201
- chore(chart)!: remove the deprecated singular rotationPolicy value by @AkashiSN in #202
- chore(chart): bump to 0.5.0 and close the chart-side doc gaps by @AkashiSN in #203
- chore(github): categorize auto-generated release notes by @AkashiSN in #207
Full Changelog: v0.4.0...v0.5.0
v0.4.0
What's Changed
- feat(helm): render multiple RotationPolicy objects from rotationPolicies by @AkashiSN in #154
- chore(release): bump chart to v0.4.0 by @AkashiSN in #155
Full Changelog: v0.3.0...v0.4.0
v0.3.0
What's Changed
- docs(e2e): record v0.3.0-rc.2 EKS Auto Mode validation results by @AkashiSN in #142
- fix(reconciler): reap in-flight rotation when a NodePool leaves governance by @AkashiSN in #143
- test(metrics): cover ObservePolicyConflict gauge emission by @AkashiSN in #144
- docs(readme): sync Japanese README with English (#132, #139) by @AkashiSN in #145
- docs(chart): add Helm chart README by @AkashiSN in #146
- docs(spec): add mermaid diagrams, a TOC, and split long paragraphs by @AkashiSN in #147
- docs(runbook): add troubleshooting index, upgrade guidance, and diagrams by @AkashiSN in #148
- docs(examples): add RotationPolicy example manifests by @AkashiSN in #149
- docs(security): add SECURITY.md and a private-reporting contact link by @AkashiSN in #150
- docs(contributing): update compatibility surface to RotationPolicy CRD by @AkashiSN in #151
- chore(release): cut v0.3.0 GA by @AkashiSN in #152
Full Changelog: v0.3.0-rc.2...v0.3.0
v0.3.0-rc.2
What's Changed
- docs(release): document ghcr package visibility verification by @AkashiSN in #139
- fix(release): mark GitHub Release as prerelease for hyphenated semver tags by @AkashiSN in #138
- fix(test/e2e): migrate EKS Auto Mode harness to RotationPolicy CRD by @AkashiSN in #137
- chore(release): cut v0.3.0-rc.2 by @AkashiSN in #140
Full Changelog: v0.3.0-rc.1...v0.3.0-rc.2
v0.3.0-rc.1
What's Changed
- docs(spec): revise specification per five-round design review by @AkashiSN in #2
- feat: v0.2 skeleton — controller-runtime bootstrap, leader election, CI by @AkashiSN in #4
- feat(policy): add config schema, maintenance-window, and ageThreshold derivation by @AkashiSN in #6
- feat(selection): NodePool scope resolution + candidate selection (§3.2) by @AkashiSN in #8
- feat(surge): placeholder Pod builder + headroom gate (§3.3, §5.2 step 3) by @AkashiSN in #10
- feat(reconcile): rotation state machine — create/delete, freeze/cordon, drain (§5.2, §5.3) by @AkashiSN in #12
- feat(metrics): Prometheus wiring for the §4.2 observability surface by @AkashiSN in #16
- feat(chart): Helm chart for the v0.3 deployment surface (§4.3, §5.1, §5.4) by @AkashiSN in #18
- perf(reconcile): watch placeholder Pod and Node to cut surge-readiness latency by @AkashiSN in #19
- chore(ci): gate on gopls check (severity>=hint) by @AkashiSN in #20
- feat(metrics): drain-phase duration_seconds histogram (§4.2, §5.3) by @AkashiSN in #22
- fix(metrics): drop draining-at backfill; lock drain-anchor cleanup invariant (§4.2) by @AkashiSN in #23
- fix(chart): grant update on nodes to match controller writes by @AkashiSN in #32
- fix(controller): startup sweep for orphaned rotation artifacts (#25) by @AkashiSN in #33
- fix(controller): preserve operator-owned do-not-disrupt during cleanup (#26) by @AkashiSN in #38
- fix(controller): populate throughput inputs for schedule derivation by @AkashiSN in #39
- fix(controller): exclude terminating placeholder from surge readiness by @AkashiSN in #41
- fix(controller): include namespace in placeholder rollback exclusion by @AkashiSN in #42
- fix(policy): reject non-positive surge duration settings by @AkashiSN in #43
- fix(policy): reject explicit zero maxUnavailable in policy config by @AkashiSN in #44
- chore(security): disable service account token automount on placeholder pods by @AkashiSN in #45
- fix(surge): classify hostname affinity precisely for surge request sizing by @AkashiSN in #46
- feat(surge): tolerate candidate NodePool taints on the surge placeholder by @AkashiSN in #47
- fix(spec): drop reserved v2/v3 config fields from v1 examples by @AkashiSN in #51
- fix(surge): honor numeric Gt/Lt NodePool requirements in placeholder parity by @AkashiSN in #52
- fix(controller): surface non-fatal schedule findings and short-lead warnings by @AkashiSN in #53
- fix(selection): anchor rotation lead time on per-NodeClaim terminationGracePeriod by @AkashiSN in #63
- fix(surge): replicate candidate NodeClaim spec.requirements, not only node labels by @AkashiSN in #64
- fix(surge): support Gte and Lte NodePool requirements when building placeholders by @AkashiSN in #65
- fix(schedule): warn when E + tGP exceeds the Auto Mode 21d hard cap (§3.2 layer-1) by @AkashiSN in #66
- fix(window): collapse worst-case period to ~0 for a full-week union by @AkashiSN in #67
- feat(startup): fail fast when the required Karpenter v1 API surface is unavailable by @AkashiSN in #68
- docs(compat): document the Karpenter v1 compatibility policy for EKS Auto Mode by @AkashiSN in #69
- docs(readme): update project status for the v0.3 surge MVP by @AkashiSN in #70
- docs(agents): update project status to the v0.3 MVP by @AkashiSN in #71
- test(controller): cover the inducedClaim never-bound fallback by @AkashiSN in #83
- test(controller): cover warning Event dedup transitions and Forget by @AkashiSN in #82
- test(chart): assert rendered RBAC/PriorityClass and values.schema.json rejections by @AkashiSN in #84
- test(controller): exercise production SetupWithManager watches under envtest by @AkashiSN in #85
- test(chart): add expected-to-fail schema cases for placeholder.priorityClass.value=0 and warmup.enabled=true by @AkashiSN in #87
- test(controller): add a multi-step end-to-end rotation lifecycle test by @AkashiSN in #88
- perf(controller): benchmark and assess cluster-wide Pod list scalability by @AkashiSN in #89
- docs(runbook): add production runbook and optional PrometheusRule alerts by @AkashiSN in #90
- test: close defensive and boundary branch-coverage gaps by @AkashiSN in #91
- feat(e2e): add KWOK-based Karpenter e2e harness for the surge mechanism by @AkashiSN in #94
- feat(surge): make placeholder hostname exclusion a soft preference so Karpenter can provision new surge capacity by @AkashiSN in #97
- test(e2e): add ephemeral EKS Auto Mode Terraform for real-cluster PoC by @AkashiSN in #98
- chore: keep git worktrees under .worktrees/ inside the repo by @AkashiSN in #103
- fix(controller): use just-stamped started-at to avoid stale-read readyTimeout misfire by @AkashiSN in #99
- feat(controller): add debug-verbosity un-deduplicated reconcile/findings logging by @AkashiSN in #105
- test(e2e): decouple KWOK surge assertion budget from the aging sleep to fix load-induced flake by @AkashiSN in #104
- chore(tooling): pin CLI versions with aqua, replacing go install by @AkashiSN in #102
- test(e2e): deliver PoC controller image to EKS Auto Mode via ECR by @AkashiSN in #107
- docs(spec): record EKS Auto Mode PoC validation results in §7.2 by @AkashiSN in #108
- fix(test): fail make test when envtest assets cannot be resolved by @AkashiSN in #112
- docs(e2e): point EKS Auto Mode README invariant link to the spec by @AkashiSN in #113
- docs: reflect EKS Auto Mode PoC validation results by @AkashiSN in #115
- test(poc): validate capacity-absorb path on EKS Auto Mode (#109) by @AkashiSN in #116
- test(poc): validate remaining deterministic PoC items on EKS Auto Mode (#109) by @AkashiSN in #117
- chore(policy): drop warmup (v3) from roadmap and config schema by @AkashiSN in #121
- feat(api): RotationPolicy CRD types, deepcopy, and manifests (#119 deliverable 1) by @AkashiSN in #126
- feat(controller): read/watch RotationPolicy with targeting, conflict resolution, fallback (#119 deliverable 2) by @AkashiSN in #127
- feat(controller): populate RotationPolicy status subresource (#119 deliverable 3) by @AkashiSN in #128
- feat(helm): ship RotationPolicy CRD + sample, drop policy ConfigMap (#119 deliverable 4) by @AkashiSN in #129
- test(policy): harden RotationPolicy resolution and CRD-schema coverage by @AkashiSN in #130
- feat(release): tag-driven OCI distribution for cha...