Skip to content

OCPBUGS-98220: fix(cpo,hcco): prevent premature KAS convergence during KMS key rotation [release-4.22]#8972

Open
csrwng wants to merge 3 commits into
openshift:release-4.22from
csrwng:kms-rotation-fix-4.22
Open

OCPBUGS-98220: fix(cpo,hcco): prevent premature KAS convergence during KMS key rotation [release-4.22]#8972
csrwng wants to merge 3 commits into
openshift:release-4.22from
csrwng:kms-rotation-fix-4.22

Conversation

@csrwng

@csrwng csrwng commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

What this PR does / why we need it:

KMS key rotation fails because IsDeploymentReady returns true while old KAS pods are still terminating. Kubernetes deployment status fields explicitly exclude terminating pods ("non-terminating"), so all status counters look healthy while pods running the old encryption config are still serving requests. This causes ShouldPromoteTargetKey to fire prematurely, rewriting the encryption config and triggering another KAS rollout — resulting in 3 KAS pods with different encryption configs running simultaneously.

This PR:

  • Adds a hasTerminatingPods check to KASDeploymentConvergedWithEncryptionConfig that lists pods matching the deployment's selector and returns false if any have DeletionTimestamp set
  • Adds an encryption-config-hash annotation to the KAS pod template so convergence can verify the deployment rolled out with the correct config
  • Passes client.Reader to the convergence function from both the CPO and HCCO callers

The fix fails closed — if listing pods errors, convergence is not reported.

This is the release-4.22 backport of #8970.

Which issue(s) this PR fixes:

Fixes OCPBUGS-98086

Special notes for your reviewer:

  • Tested with HA control plane on AKS with two full KMS key rotations
  • Both rotations completed successfully with no premature state advancement
  • The hasTerminatingPods helper uses the deployment's own Spec.Selector to find its pods — no hardcoded labels

Checklist:

  • Subject and description added to both, commit and PR.
  • Relevant issues have been referenced.
  • This change includes docs.
  • This change includes unit tests.

csrwng and others added 2 commits July 9, 2026 10:00
Kubernetes deployment status fields exclude terminating pods, so
IsDeploymentReady returns true while old KAS pods are still running.
This causes ShouldPromoteTargetKey to fire prematurely during KMS key
rotation, triggering overlapping rollouts with multiple KAS pods
running different encryption configurations simultaneously.

Two fixes applied to KASDeploymentConvergedWithEncryptionConfig:

1. Add an encryption-config-hash annotation to the KAS pod template so
   both CPO and HCCO can verify the deployment has rolled out with the
   specific encryption config containing the target key, rather than
   observing readiness from a previous rollout.

2. Add a hasTerminatingPods check that lists pods matching the
   deployment selector and returns false if any have DeletionTimestamp
   set, ensuring convergence is only reported after old pods have fully
   terminated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Log errors before failing closed in hasTerminatingPods so operators
can diagnose unexpected failures in the terminating pod check.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: d9aabfc3-4504-4213-b04a-4cb0f06b47cf

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@openshift-ci

openshift-ci Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: csrwng

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci Bot added area/control-plane-operator Indicates the PR includes changes for the control plane operator - in an OCP release area/hypershift-operator Indicates the PR includes changes for the hypershift operator and API - outside an OCP release approved Indicates a PR has been approved by an approver from all required OWNERS files. and removed do-not-merge/needs-area labels Jul 9, 2026
@csrwng csrwng changed the title fix(cpo,hcco): prevent premature KAS convergence during KMS key rotation fix(cpo,hcco): prevent premature KAS convergence during KMS key rotation [release-4.22] Jul 9, 2026
@csrwng

csrwng commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

/jira cherry-pick OCPBUGS-98086

@csrwng csrwng added the backport-risk-assessed Indicates a PR to a release branch has been evaluated and considered safe to accept. label Jul 9, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@csrwng: Jira Issue OCPBUGS-98086 has been cloned as Jira Issue OCPBUGS-98220. Will retitle bug to link to clone.
/retitle OCPBUGS-98220: fix(cpo,hcco): prevent premature KAS convergence during KMS key rotation [release-4.22]

Details

In response to this:

/jira cherry-pick OCPBUGS-98086

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci Bot changed the title fix(cpo,hcco): prevent premature KAS convergence during KMS key rotation [release-4.22] OCPBUGS-98220: fix(cpo,hcco): prevent premature KAS convergence during KMS key rotation [release-4.22] Jul 9, 2026
@openshift-ci-robot openshift-ci-robot added jira/severity-critical Referenced Jira bug's severity is critical for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels Jul 9, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@csrwng: This pull request references Jira Issue OCPBUGS-98220, which is invalid:

  • release note text must be set and not match the template OR release note type must be set to "Release Note Not Required". For more information you can reference the OpenShift Bug Process.
  • expected dependent Jira Issue OCPBUGS-98086 to be in one of the following states: MODIFIED, ON_QA, VERIFIED, but it is POST instead

Comment /jira refresh to re-evaluate validity if changes to the Jira bug are made, or edit the title of this pull request to link to a different bug.

The bug has been updated to refer to the pull request using the external bug tracker.

Details

In response to this:

What this PR does / why we need it:

KMS key rotation fails because IsDeploymentReady returns true while old KAS pods are still terminating. Kubernetes deployment status fields explicitly exclude terminating pods ("non-terminating"), so all status counters look healthy while pods running the old encryption config are still serving requests. This causes ShouldPromoteTargetKey to fire prematurely, rewriting the encryption config and triggering another KAS rollout — resulting in 3 KAS pods with different encryption configs running simultaneously.

This PR:

  • Adds a hasTerminatingPods check to KASDeploymentConvergedWithEncryptionConfig that lists pods matching the deployment's selector and returns false if any have DeletionTimestamp set
  • Adds an encryption-config-hash annotation to the KAS pod template so convergence can verify the deployment rolled out with the correct config
  • Passes client.Reader to the convergence function from both the CPO and HCCO callers

The fix fails closed — if listing pods errors, convergence is not reported.

This is the release-4.22 backport of #8970.

Which issue(s) this PR fixes:

Fixes OCPBUGS-98086

Special notes for your reviewer:

  • Tested with HA control plane on AKS with two full KMS key rotations
  • Both rotations completed successfully with no premature state advancement
  • The hasTerminatingPods helper uses the deployment's own Spec.Selector to find its pods — no hardcoded labels

Checklist:

  • Subject and description added to both, commit and PR.
  • Relevant issues have been referenced.
  • This change includes docs.
  • This change includes unit tests.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 54.76190% with 38 lines in your changes missing coverage. Please review.
✅ Project coverage is 35.86%. Comparing base (aa2d83b) to head (250dd74).
⚠️ Report is 2 commits behind head on release-4.22.

Files with missing lines Patch % Lines
support/secretencryption/encryptionconfig.go 54.54% 17 Missing and 3 partials ⚠️
...ontrollers/hostedcontrolplane/v2/kas/deployment.go 0.00% 8 Missing ⚠️
...lers/hostedcontrolplane/v2/kas/secretencryption.go 64.28% 4 Missing and 1 partial ⚠️
...goperator/controllers/reencryption/reencryption.go 72.22% 5 Missing ⚠️
Additional details and impacted files
@@               Coverage Diff                @@
##           release-4.22    #8972      +/-   ##
================================================
+ Coverage         35.85%   35.86%   +0.01%     
================================================
  Files               774      774              
  Lines             94736    94791      +55     
================================================
+ Hits              33969    33999      +30     
- Misses            57986    58007      +21     
- Partials           2781     2785       +4     
Files with missing lines Coverage Δ
...lers/hostedcontrolplane/v2/kas/secretencryption.go 53.07% <64.28%> (-0.53%) ⬇️
...goperator/controllers/reencryption/reencryption.go 69.34% <72.22%> (+0.31%) ⬆️
...ontrollers/hostedcontrolplane/v2/kas/deployment.go 25.71% <0.00%> (-0.15%) ⬇️
support/secretencryption/encryptionconfig.go 76.04% <54.54%> (-18.19%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Fix gci import group ordering. Regenerate KAS deployment fixture to
include the new encryption-config-hash annotation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@csrwng csrwng force-pushed the kms-rotation-fix-4.22 branch from 2ca875c to 250dd74 Compare July 9, 2026 15:48
@ahitacat

Copy link
Copy Markdown

/verified by ahitacat

I have verify this test using the following annotation:
hypershift.openshift.io/control-plane-operator-image: quay.io/redhat-user-workloads/crt-redhat-acm-tenant/control-plane-operator-4-22:on-pr-250dd743772fd0f9582359151d6dcf4cd85d3f48

To verify this works I have update twice the key version (on completion of the first one):

Create a cluster
Update activeKey version
Wait for completion
Update activeKey version (to a new one)
During the second update I can verified that the kas pods are recreating without issue:

NAME                              READY   STATUS        RESTARTS   AGE
kube-apiserver-7d7d474fc-4g572    7/7     Running       0          8m14s
kube-apiserver-7d7d474fc-bl4kg    5/7     Terminating   0          6m34s
kube-apiserver-7dd69b59d7-27z8s   0/7     Pending       0          96s
kube-apiserver-7dd69b59d7-62jnf   7/7     Running       0          3m7s
Once it finished the second update the history of the activeKey in the hostedCluster RC looks like this:
history:
      - completionTime: "2026-07-13T08:36:00Z"
        from:
          fingerprint: 1f7cf75a26047f7f4bb0a59c57d47796c44e84cfb04ab126b4ca91531d3d82b3
          provider: Azure
        startedTime: "2026-07-13T08:25:29Z"
        state: Completed
        to:
          fingerprint: 722926100ce3aaf2de826a6fd08ac19fb1ee667d514f7822b8218c503e9a24ee
          provider: Azure
      - completionTime: "2026-07-13T08:13:43Z"
        from:
          fingerprint: 99ad754c2a0576b6f6a0f13af601ebc750e7d56d653f904e99042e392a3e3fc7
          provider: Azure
        startedTime: "2026-07-13T07:59:47Z"
        state: Completed
        to:
          fingerprint: 1f7cf75a26047f7f4bb0a59c57d47796c44e84cfb04ab126b4ca91531d3d82b3
          provider: Azure

With this we can see it succeeded of re-encrypt the second time with a new version. And cluster is healthy.

@openshift-ci-robot openshift-ci-robot added the verified Signifies that the PR passed pre-merge verification criteria label Jul 13, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@ahitacat: This PR has been marked as verified by ahitacat.

Details

In response to this:

/verified by ahitacat

I have verify this test using the following annotation:
hypershift.openshift.io/control-plane-operator-image: quay.io/redhat-user-workloads/crt-redhat-acm-tenant/control-plane-operator-4-22:on-pr-250dd743772fd0f9582359151d6dcf4cd85d3f48

To verify this works I have update twice the key version (on completion of the first one):

Create a cluster
Update activeKey version
Wait for completion
Update activeKey version (to a new one)
During the second update I can verified that the kas pods are recreating without issue:

NAME                              READY   STATUS        RESTARTS   AGE
kube-apiserver-7d7d474fc-4g572    7/7     Running       0          8m14s
kube-apiserver-7d7d474fc-bl4kg    5/7     Terminating   0          6m34s
kube-apiserver-7dd69b59d7-27z8s   0/7     Pending       0          96s
kube-apiserver-7dd69b59d7-62jnf   7/7     Running       0          3m7s
Once it finished the second update the history of the activeKey in the hostedCluster RC looks like this:
history:
     - completionTime: "2026-07-13T08:36:00Z"
       from:
         fingerprint: 1f7cf75a26047f7f4bb0a59c57d47796c44e84cfb04ab126b4ca91531d3d82b3
         provider: Azure
       startedTime: "2026-07-13T08:25:29Z"
       state: Completed
       to:
         fingerprint: 722926100ce3aaf2de826a6fd08ac19fb1ee667d514f7822b8218c503e9a24ee
         provider: Azure
     - completionTime: "2026-07-13T08:13:43Z"
       from:
         fingerprint: 99ad754c2a0576b6f6a0f13af601ebc750e7d56d653f904e99042e392a3e3fc7
         provider: Azure
       startedTime: "2026-07-13T07:59:47Z"
       state: Completed
       to:
         fingerprint: 1f7cf75a26047f7f4bb0a59c57d47796c44e84cfb04ab126b4ca91531d3d82b3
         provider: Azure

With this we can see it succeeded of re-encrypt the second time with a new version. And cluster is healthy.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@jparrill

Copy link
Copy Markdown
Contributor

/jira refresh

@openshift-ci-robot

Copy link
Copy Markdown

@jparrill: This pull request references Jira Issue OCPBUGS-98220, which is invalid:

  • release note text must be set and not match the template OR release note type must be set to "Release Note Not Required". For more information you can reference the OpenShift Bug Process.
  • expected dependent Jira Issue OCPBUGS-98086 to be in one of the following states: MODIFIED, ON_QA, VERIFIED, but it is ASSIGNED instead

Comment /jira refresh to re-evaluate validity if changes to the Jira bug are made, or edit the title of this pull request to link to a different bug.

Details

In response to this:

/jira refresh

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@jparrill

Copy link
Copy Markdown
Contributor

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Jul 13, 2026
@csrwng csrwng added jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. and removed jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels Jul 14, 2026
@csrwng

csrwng commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

/hold
/pipeline required

@openshift-ci openshift-ci Bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jul 14, 2026
@csrwng

csrwng commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

/test e2e-aws
/test e2e-aks

@openshift-ci

openshift-ci Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

@csrwng: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. area/control-plane-operator Indicates the PR includes changes for the control plane operator - in an OCP release area/hypershift-operator Indicates the PR includes changes for the hypershift operator and API - outside an OCP release backport-risk-assessed Indicates a PR to a release branch has been evaluated and considered safe to accept. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. jira/severity-critical Referenced Jira bug's severity is critical for the branch this PR is targeting. jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged. verified Signifies that the PR passed pre-merge verification criteria

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants