Skip to content

AUTOSCALE-806: Introduce Karpenter API lifecycle object and controller#16

Draft
maxcao13 wants to merge 3 commits into
openshift:mainfrom
maxcao13:karpenter-crd
Draft

AUTOSCALE-806: Introduce Karpenter API lifecycle object and controller#16
maxcao13 wants to merge 3 commits into
openshift:mainfrom
maxcao13:karpenter-crd

Conversation

@maxcao13

@maxcao13 maxcao13 commented Jul 9, 2026

Copy link
Copy Markdown
Member

First commit:
This commit adds a new CRD and API to the autoscaling.openshift.io group with the kind Karpenter.
The full GVR is v1alpha1.karpenters.autoscaling.openshift.io.
This CRD will be used to manage the lifecycle of Karpenter in standalone OCP.
The operator will reconcile on this CR to control Karpenter settings, and scale up and down Karpenter.

Second commit:
Allows the existence of a Karpenter in the openshift-karpenter ns to reconcile Karpenter deployment.
This supersedes the previous implementation that the operator automatically created the operand.
From now on, the user is required to create the Karpenter object, in order to enable Karpenter in the cluster.
For now we only have logLevel as the only field to control from the Karpenter CR which controls the log level of the Karpenter deployment.

Additionally:
Improves the development workflow by adding an update make target. update is intended to do write operations to fix linting errors automatically. verify now serves as the full command to first do a read-only check of linting, formatting, etc., then perform update in the second half.

This PR also adds controller-gen to the project to automatically generate CRDs from the contents of pkg/apis and the kubebuilder annotations.

Finally this PR also substitutes a lot of magic numbers and strings with consts and variables.

Summary by CodeRabbit

  • New Features
    • Introduced a Karpenter singleton custom resource (Karpenter.autoscaling.openshift.io) with configurable log level and condition reporting.
    • Added an example manifest for easy deployment.
  • Bug Fixes
    • Updated the operator to reconcile using the Karpenter custom resource instead of an operator deployment.
    • Expanded RBAC and cluster-role permissions to support status subresources and required finalizers (karpenters, nodepools, nodeclaims, nodeoverlays).

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jul 9, 2026
@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 9, 2026
@openshift-ci

openshift-ci Bot commented Jul 9, 2026

Copy link
Copy Markdown

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@openshift-ci-robot

openshift-ci-robot commented Jul 9, 2026

Copy link
Copy Markdown

@maxcao13: This pull request references AUTOSCALE-806 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.0.0" version, but no target version was set.

Details

In response to this:

First commit:
This commit adds a new CRD and API to the autoscaling.openshift.io group with the kind Karpenter.
The full GVR is v1alpha1.karpenters.autoscaling.openshift.io.
This CRD will be used to manage the lifecycle of Karpenter in standalone OCP.
The operator will reconcile on this CR to control Karpenter settings, and scale up and down Karpenter.

Second commit:
Allows the existence of a Karpenter in the openshift-karpenter ns to reconcile Karpenter deployment.
This supersedes the previous implementation that the operator automatically created the operand.
From now on, the user is required to create the Karpenter object, in order to enable Karpenter in the cluster.
For now we only have logLevel as the only field to control from the Karpenter CR which controls the log level of the Karpenter deployment.

Additionally:
Improves the development workflow by adding an update make target. update is intended to do write operations to fix linting errors automatically. verify now serves as the full command to first do a read-only check of linting, formatting, etc., then perform update in the second half.

This PR also adds controller-gen to the project to automatically generate CRDs from the contents of pkg/apis and the kubebuilder annotations.

Finally this PR also substitutes a lot of magic numbers and strings with consts and variables.

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 commented Jul 9, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: maxcao13

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 the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jul 9, 2026
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Walkthrough

This PR introduces the Karpenter custom resource API, CRD, example manifest, and RBAC rules. It changes reconciliation ownership from the operator Deployment to the Karpenter singleton and propagates its log level to the operand. Makefile generation and clean-tree verification are also added.

Changes

Karpenter custom resource and reconciliation

Layer / File(s) Summary
API contract and generated CRD
pkg/apis/autoscaling/v1alpha1/*, install/autoscaling.openshift.io_karpenters.yaml, examples/karpenter.yaml, pkg/operator/operator.go
Defines and registers the Karpenter API, adds its CRD schema and example resource, and registers the types in the operator scheme.
Karpenter-owned reconciliation
pkg/controllers/controllers.go, pkg/controllers/karpenter/controller.go
Reconciles the Karpenter singleton, uses it as the owner of managed resources, propagates its log level, watches the CR, and updates probe and metrics port handling.
RBAC permissions and assets
install/04_rbac.yaml, pkg/assets/operator/rbac.yaml, pkg/assets/karpenter/clusterrole-core.yaml
Adds Karpenter API permissions and finalizer permissions for operator and operand resources.

Generation and verification tooling

Layer / File(s) Summary
Manifest generation and verification
Makefile
Adds controller-gen installation, generation and manifest targets, an update workflow, and clean-tree verification wired into verify.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant KarpenterCR
  participant KarpenterController
  participant OperandResources
  KarpenterCR->>KarpenterController: enqueue singleton change
  KarpenterController->>KarpenterController: read spec and derive log level
  KarpenterController->>OperandResources: apply owned RBAC and Deployment
  KarpenterCR->>OperandResources: provide logLevel configuration
Loading

Possibly related PRs

Suggested labels: lgtm

Suggested reviewers: jkyros, joelsmith


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 2 warnings)

Check name Status Explanation Resolution
No-Sensitive-Data-In-Logs ❌ Error pkg/operator/operator.go logs cfg.ClusterEndpoint (and cluster metadata) in setup, which can expose internal hostnames. Remove the endpoint/cluster metadata from the info log, or redact/obfuscate it before logging.
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Microshift Test Compatibility ⚠️ Warning test/suites/operator/operator_test.go adds Ginkgo tests that read config.openshift.io/v1 ClusterOperator and has no MicroShift skip/tag guard. Add a MicroShift guard or tag (e.g. [Skipped:MicroShift] or [apigroup:config.openshift.io]), or skip the ClusterOperator checks on MicroShift.
✅ Passed checks (12 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding the Karpenter API lifecycle object and its controller.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed All Ginkgo titles found are static strings; no fmt.Sprintf, concatenation, or volatile identifiers appear in test names.
Test Structure And Quality ✅ Passed No Ginkgo test files were modified in this PR, so the test-structure check is not applicable.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the full diff only changes Makefile, API, RBAC, and controller files, with no It/Describe/Context/When additions.
Topology-Aware Scheduling Compatibility ✅ Passed New controller code adds no nodeSelector/affinity/tolerations; the control-plane selector in install/05_deployment.yaml predates this PR and wasn’t changed.
Ote Binary Stdout Contract ✅ Passed No process-level stdout writes were added; main uses controller-runtime zap which defaults to stderr, and init/suite files contain no print/output calls.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No new Ginkgo/e2e test files were changed; the commit only touches two RBAC YAML manifests, so IPv4/disconnected test risks are not applicable.
No-Weak-Crypto ✅ Passed No weak crypto, custom crypto, or secret/token comparisons were added in the PR diff; touched files only contain ordinary string/namespace checks.
Container-Privileges ✅ Passed No added/changed manifest or controller code sets privileged, hostPID/network/IPC, SYS_ADMIN, or allowPrivilegeEscalation=true; deployment uses runAsNonRoot=true and allowPrivilegeEscalation=false.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="Running error: context loading failed: failed to load packages: failed to load packages: failed to load with go/packages: err: exit status 1: stderr: go: inconsistent vendoring in :\n\tgithub.com/aws/aws-sdk-go-v2/config@v1.32.17: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt\n\tgithub.com/aws/aws-sdk-go-v2/service/ec2@v1.302.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt\n\tgithub.com/aws/karpenter-provider-aws@v1.9.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt\n\tgithub.com/onsi/ginkgo/v2@v2.27.5: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt\n\tgithub.com/onsi/gomega@v1.39.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt\n\tgithub.com/openshift/api@v0.0.0-20260107103503-6d35063ca179: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt\n\tgithub.com/

... [truncated 11763 characters] ...

tly required in go.mod, but not marked as explicit in vendor/modules.txt\n\tsigs.k8s.io/randfill@v1.0.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt\n\tsigs.k8s.io/structured-merge-diff/v6@v6.3.2-0.20260122202528-d9cc6641c482: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt\n\tsigs.k8s.io/yaml@v1.6.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt\n\tgithub.com/aws/karpenter-provider-aws: is replaced in go.mod, but not marked as replaced in vendor/modules.txt\n\tsigs.k8s.io/karpenter: is replaced in go.mod, but not marked as replaced in vendor/modules.txt\n\n\tTo ignore the vendor directory, use -mod=readonly or -mod=mod.\n\tTo sync the vendor directory, run:\n\t\tgo mod vendor\n"


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

@maxcao13

maxcao13 commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

/test images

checking if the tests in the other PR are just flaking for no reason or if there's an actual problem there.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@install/04_rbac.yaml`:
- Around line 73-75: The RBAC rule for the Karpenter CR currently grants write
access that the controller path does not use. Update the permission block for
the Karpenter resource in the RBAC manifest to read-only verbs for the
controller’s read path, and remove status/finalizer write permissions unless the
related reconciliation logic in the Karpenter controller actually performs those
updates in this PR.

In `@pkg/assets/operator/rbac.yaml`:
- Around line 54-56: The generated operator RBAC is too broad for the
controller’s actual usage; reduce the permissions in the mirrored RBAC asset so
the Karpenter singleton is read-only. Update the rule covering
autoscaling.openshift.io resources for karpenters, karpenters/status, and
karpenters/finalizers by removing write verbs and keeping only the read/watch
access needed by the controller code that fetches and watches the object. Ensure
the resulting rbac.yaml stays least-privilege and matches the controller’s
observed access pattern.

In `@pkg/controllers/karpenter/controller.go`:
- Around line 77-83: The controller is fetching the Karpenter singleton without
a namespace, so Reconcile can miss the namespaced CR and skip deployment
updates. Update Controller.Reconcile to use the operator namespace when building
the client.ObjectKey for the c.client.Get call, and make sure the synthetic
request enqueued by the controller also includes that namespace so the same
namespaced singleton is reconciled consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 26e51886-7254-464d-b65e-2ca18b68ca83

📥 Commits

Reviewing files that changed from the base of the PR and between 7a35066 and ca6f006.

⛔ Files ignored due to path filters (1)
  • pkg/apis/autoscaling/v1alpha1/zz_generated.deepcopy.go is excluded by !**/zz_generated*
📒 Files selected for processing (10)
  • Makefile
  • examples/karpenter.yaml
  • install/04_rbac.yaml
  • install/autoscaling.openshift.io_karpenters.yaml
  • pkg/apis/autoscaling/v1alpha1/doc.go
  • pkg/apis/autoscaling/v1alpha1/karpenter.go
  • pkg/assets/operator/rbac.yaml
  • pkg/controllers/controllers.go
  • pkg/controllers/karpenter/controller.go
  • pkg/operator/operator.go

Comment thread install/04_rbac.yaml
Comment thread pkg/assets/operator/rbac.yaml
Comment thread pkg/controllers/karpenter/controller.go
@openshift-ci

openshift-ci Bot commented Jul 10, 2026

Copy link
Copy Markdown

@maxcao13: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/images ca6f006 link true /test images

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.

maxcao13 added 3 commits July 10, 2026 13:31
This commit adds a new CRD and API to the autoscaling.openshift.io group.
The full GVR is v1alpha1.karpenters.autoscaling.openshift.io.
This CRD will be used to manage the lifecycle of Karpenter in standalone OCP.
The operator will reconcile on this CR to control Karpenter settings, and scale up and down Karpenter.

Refer to openshift/enhancements#2007 for details.

Signed-off-by: Max Cao <macao@redhat.com>
Allows the existence of a Karpenter in the openshift-karpenter ns to reconcile Karpenter deployment.
This supersedes the previous implementation that the operator automatically created the operand.
From now on, the user is required to create the Karpenter object, in order to enable Karpenter in the cluster.

Signed-off-by: Max Cao <macao@redhat.com>
Signed-off-by: Max Cao <macao@redhat.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
install/04_rbac.yaml (1)

149-151: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

nodeclaims/finalizers in the read rule is a no-op grant.

A */finalizers subresource is only meaningfully accessed via update/patch; get/list/watch on it grant nothing useful, and finalizer writes are already covered by the write rule at Lines 170-171. Drop it here to keep the read rule minimal.

As per path instructions, "RBAC: least privilege; no cluster-admin for workloads."

Suggested read-rule trim
   - apiGroups: ["karpenter.sh"]
-    resources: ["nodepools", "nodepools/status", "nodeclaims", "nodeclaims/status", "nodeclaims/finalizers", "nodeoverlays", "nodeoverlays/status"]
+    resources: ["nodepools", "nodepools/status", "nodeclaims", "nodeclaims/status", "nodeoverlays", "nodeoverlays/status"]
     verbs: ["get", "list", "watch"]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@install/04_rbac.yaml` around lines 149 - 151, Remove "nodeclaims/finalizers"
from the resources list in the read RBAC rule, while leaving finalizer access
covered by the existing write rule.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Makefile`:
- Line 144: Serialize the prerequisites of the Makefile verify target so update
completes before manifest-diff and verify-git-clean run. Adjust the verify
target or its recipe while preserving the existing vet, lint, and test checks,
ensuring parallel make cannot read files during update.

---

Nitpick comments:
In `@install/04_rbac.yaml`:
- Around line 149-151: Remove "nodeclaims/finalizers" from the resources list in
the read RBAC rule, while leaving finalizer access covered by the existing write
rule.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 8de356ed-c3af-4a5b-9714-ffd066f1fc08

📥 Commits

Reviewing files that changed from the base of the PR and between ca6f006 and fe9b6be.

⛔ Files ignored due to path filters (1)
  • pkg/apis/autoscaling/v1alpha1/zz_generated.deepcopy.go is excluded by !**/zz_generated*
📒 Files selected for processing (11)
  • Makefile
  • examples/karpenter.yaml
  • install/04_rbac.yaml
  • install/autoscaling.openshift.io_karpenters.yaml
  • pkg/apis/autoscaling/v1alpha1/doc.go
  • pkg/apis/autoscaling/v1alpha1/karpenter.go
  • pkg/assets/karpenter/clusterrole-core.yaml
  • pkg/assets/operator/rbac.yaml
  • pkg/controllers/controllers.go
  • pkg/controllers/karpenter/controller.go
  • pkg/operator/operator.go
✅ Files skipped from review due to trivial changes (3)
  • pkg/operator/operator.go
  • pkg/assets/karpenter/clusterrole-core.yaml
  • examples/karpenter.yaml
🚧 Files skipped from review as they are similar to previous changes (6)
  • pkg/apis/autoscaling/v1alpha1/doc.go
  • install/autoscaling.openshift.io_karpenters.yaml
  • pkg/controllers/controllers.go
  • pkg/assets/operator/rbac.yaml
  • pkg/apis/autoscaling/v1alpha1/karpenter.go
  • pkg/controllers/karpenter/controller.go

Comment thread Makefile

.PHONY: verify
verify: vet fmt lint manifest-diff verify-deps test ## Run all verification checks.
verify: vet lint manifest-diff update verify-git-clean test ## Run all verification checks.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

sed -n '1,240p' Makefile

Repository: openshift/karpenter-operator

Length of output: 7594


🏁 Script executed:

rg -n "\bmake\b.*\bverify\b|^\s*verify:" .github Makefile

Repository: openshift/karpenter-operator

Length of output: 319


Serialize the verify steps in Makefile:144.

update, manifest-diff, and verify-git-clean are independent, so make -j verify can let update rewrite files while the diff checks read them. Run update before manifest-diff and verify-git-clean, or move them into a sequential recipe to avoid flaky partial-state reads.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Makefile` at line 144, Serialize the prerequisites of the Makefile verify
target so update completes before manifest-diff and verify-git-clean run. Adjust
the verify target or its recipe while preserving the existing vet, lint, and
test checks, ensuring parallel make cannot read files during update.

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. do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants