+ Details
+
+ Run on Apple M3 Pro with 12 cores, 18 GB RAM, arm64
+ Find the raw output of the benchmark tests, as well as the source code: https://gist.github.com/sreeram-venkitesh/f4aff1ae7957a5a3b9c6c53e869b7403
+ The following table provides an average performance analysis across CEL and JSONPath based additionalPrinterColumns:
+
+ | | CEL ([BenchmarkNew_CEL](https://gist.github.com/sreeram-venkitesh/f4aff1ae7957a5a3b9c6c53e869b7403#file-tableconvertor_test-go-L36-L75)) | JSONPath ([BenchmarkNew_JSONPath](https://gist.github.com/sreeram-venkitesh/f4aff1ae7957a5a3b9c6c53e869b7403#file-tableconvertor_test-go-L77-L116)) |
+ |--------------------------------------|--------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|
+ | **Column Definition** | `self.spec.servers.map(s, s.hosts.filter(h, h == "prod.example.com"))` | `.spec.servers[*].hosts[?(@ == "prod.example.com")]` |
+ | **Overall Performance**
(Compilation + Evaluation) | • Average iterations: 3,111
• Average time per operation: **382,914 ns/op** (~383 µs per op)
• Standard deviation: ±42,087 ns (±11%) | • Average iterations: 70,542 iterations
• Average time per operation: **17,654 ns/op** (~17.7 µs per op)
• Standard deviation: ±2,846 ns (±16%) |
+ | **Compilation Performance** | • Cold Start: 2.340 ms
• Warmed: 300–400 µs
◦ Most Expensive / Consistent Phases:
• Env & Cost Estimator: 160–220 µs avg
• CEL Compilation: 60–120 µs avg
• Program Generation: 50–80 µs avg
• 83% improvement (2.34 ms → ~400 µs)| • Cold Start: ~85 µs
• Warmed: 5–8 µs
◦ Most Expensive / Consistent Phases:
• JSONPath Parsing: 4–85 µs (occasional spikes)
• 90% improvement (85 µs → ~8 µs)|
+ | **Evaluation Performance** | **FindResults**
• Cold: 103.5 µs
• Warmed: 13.5 µs
• 81% improvement (103.5 → 13.5 µs)
**PrintResults**
• Cold: 3.9 µs
• Warmed: 1.5 µs
• 70% improvement (3.9 → 1.5 µs) | **FindResults**
• Cold: 1.4 µs
• Warmed: 0.85 µs
• 29% improvement (1.4 → 0.85 µs)
**PrintResults**
• Cold: 0.29 µs
• Warmed: 0.18 µs
• 58% improvement (0.29 → 0.18 µs) |
+
+
+- Scenario 2: Benchmarking evaluation (`findResults()`) performance.
+
+ Based on the review comment [here](https://github.com/kubernetes/enhancements/pull/4602#discussion_r2121919813) - `Benchmark an expensive JSON Path additionalPrinterColumns operation (just the part that finds a value using the JSON Path library)`.
+
+ Details
+
+ Run on a resource constraint VM - 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz, 4 CPU, 4GB RAM, X86_64
+ Find the raw output of the benchmark tests, as well as the source code: https://gist.github.com/Priyankasaggu11929/43cc9ece4d6215ee4cfe0d1523a919d6
+ The following table provides an average performance analysis across CEL and JSONPath based additionalPrinterColumns (only for the `findResults()` execution durations across the benchmark test iterations, along with the min, max, avg indexes):
+
+ | | CEL ([BenchmarkNew_CEL_DeepComplex](https://gist.github.com/Priyankasaggu11929/43cc9ece4d6215ee4cfe0d1523a919d6#file-tableconvertor_testgo)) | JSONPath ([BenchmarkNew_JSONPath_DeepComplex](https://gist.github.com/Priyankasaggu11929/43cc9ece4d6215ee4cfe0d1523a919d6#file-tableconvertor_testgo)) |
+ |--------------------------------------|--------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|
+ | **Column Definition** | `self.spec.environments.map(e, e.clusters.map(c, c.nodes.filter(n, n.metrics.memory > 8000).map(n, n.id)))` | `.spec.environments[*].clusters[*].nodes[?(@.metrics.memory > 8000)].id` |
+ | **Evaluation Performance** | **FindResults**
• Min: 30.91 µs
• Max: 1870.87 µs
• Average: 58.38 µs | **FindResults**
• Min: 2.19 µs
• Max: 1147.24 µs
• Average: 8.40 µs |
+
+
+
+_**Conclusion**_ —
+
+Overall performance (compilation + evaluation + cost calculation et.al) of CEL across our two scenarios above, is that CEL is about 20x slower than JSONPath.
+
+But since our focus for the performance analysis was to analyze the **evaluation cost** (refer scenario 2):
+
+- On average, CEL is about 7x slower than JSONPath (58.38 µs vs 8.40 µs)
+- In the worst cases scenario (most expensive run) CEL is 1.5x slower than JSONPath (1870.87 µs vs 1147.24 µs)
+
+
+
+
+### Test Plan
+
+
+
+[x] I/we understand the owners of the involved components may require updates to
+existing tests to make this code solid enough prior to committing the changes necessary
+to implement this enhancement.
+
+##### Prerequisite testing updates
+
+
+
+##### Unit tests
+
+
+
+
+
+Alpha:
+
+[staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation_test.go](https://github.com/kubernetes/kubernetes/blob/e54719bb6674fac228671e0786d19c2cf27b08a3/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation_test.go)
+
+- Test that validation passes when we create an additionalPrinterColumn with an expression field with valid CEL expression
+- Test that validation fails when we create an additionalPrinterColumn with an expression field with an invalid CEL expression
+- Test that existing behaviour of jsonPath is not altered when creating CRDs with only jsonPath additionalPrinterColumns
+- Test that validation fails when we create an additionalPrinterColumn with both jsonPath and expression fields
+- Test that validation passes when we create multiple additionalPrinterColumns with both jsonPath and expression fields
+- Test that validation fails when we try to create an additionalPrinterColumn with expression field when the feature gate is turned off
+
+[staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor_test.go](https://github.com/kubernetes/kubernetes/blob/bc302fa4144d21a338683cd83701661f97be4aba/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor_test.go)
+
+- Verify that CEL compilation errors are caught at the CRD validation phase
+- Verify that CEL compilation at the TableConvertor creation stage succeeds
+- Verify that TableConvertor is getting created for the CRD with both jsonPath and expression columns
+
+
+
+##### Integration tests
+
+
+
+
+[test/integration/apiserver/crd_additional_printer_columns_test.go](https://github.com/kubernetes/kubernetes/tree/bc302fa4144d21a338683cd83701661f97be4aba/test/integration/apiserver)
+
+- Verify that CRDs are getting created with additionalPrinterColumns with both jsonPath and expression fields
+- Verify that CEL compilation errors are caught at the CRD validation stage
+- Verify that existing behaviour is not altered when creating CRDs with only jsonPath additionalPrinterColumns
+
+
+
+##### e2e tests
+
+
+
+
+We will test all cases in integration test and unit test. If needed, we can add e2e tests before beta graduation. We are planning to extend the existing [e2e tests for CRDs](https://github.com/kubernetes/kubernetes/blob/3df3b83226530bda69ffcb7b4450026139b2cd11/test/e2e/apimachinery/custom_resource_definition.go).
+
+### Graduation Criteria
+
+#### Alpha
+
+- Feature implemented behind a feature flag
+- Initial benchmarks to compare performance of JSONPath with CEL columns and set an appropriate CEL cost (equivalent or at most 2x to the JSONPath cost - as discussed in the [June 11, 2025 SIG API Machinery meeting](https://docs.google.com/document/d/1x9RNaaysyO0gXHIr1y50QFbiL1x8OWnk2v3XnrdkT5Y/edit?tab=t.0#bookmark=id.epfys7yzizcn))
+- Unit tests and integration tests completed and enabled
+
+#### Beta
+
+- Gather feedback from developers and surveys
+- Add e2e tests
+- Add appropriate metrics for additionalPrinterColumns usage and CEL cost usage
+- More benchmarking to compare JSONPath and CEL execution and modify CEL cost if needed
+
+#### GA
+
+- N examples of real-world usage
+- Upgrade/downgrade e2e tests
+- Scalability tests
+- Allowing time for feedback
+
+### Upgrade / Downgrade Strategy
+
+
+
+
+
+
+
+No changes are required for a cluster to make an upgrade and maintain existing behavior.
+
+If the cluster is downgraded to a version which doesn't support CEL for additionalPrinterColumns:
+- Existing additionalPrinterColumns with CEL expressions would be ignored and those columns will not be printed. Any create or update operation to CRDs would fail if we try to use CEL for additionalPrinterColumns.
+- Existing additionalPrinterColumns with JSONPath would still work as expected.
+
+Once the cluster is upgraded back to a version supporting CEL for additionalPrinterColumns, users should be able to create CRDs with additionalPrinterColumns using CEL again.
+
+### Version Skew Strategy
+
+
+
+This feature is implemented in the kube-apiserver component, skew with other kubernetes components do not require coordinated behavior.
+
+Clients should ensure the kube-apiserver is fully rolled out before using the feature.
+
+## Production Readiness Review Questionnaire
+
+
+
+### Feature Enablement and Rollback
+
+
+
+###### How can this feature be enabled / disabled in a live cluster?
+
+
+
+- [x] Feature gate (also fill in values in `kep.yaml`)
+ - Feature gate name: `CRDAdditionalPrinterColumnCEL`
+ - Components depending on the feature gate: `apiextensions-apiserver`, `kube-apiserver`
+- [ ] Other
+ - Describe the mechanism:
+ - Will enabling / disabling the feature require downtime of the control
+ plane?
+ - Will enabling / disabling the feature require downtime or reprovisioning
+ of a node?
+
+###### Does enabling the feature change any default behavior?
+
+
+
+No default behaviour will be changed since we still support additionalPrinterColumns with JSONPath.
+
+###### Can the feature be disabled once it has been enabled (i.e. can we roll back the enablement)?
+
+
+
+Yes, if the feature is disabled after being used, the existing additionalPrinterColumns with JSONPath would work as expected. Existing resources with CEL expressions in their additionalPrinterColumn definition would be ignored and those columns will not be printed if the feature is disabled.
+
+###### What happens if we reenable the feature if it was previously rolled back?
+
+CRDs which had failed validation previously might now succeed if the CEL expression is valid. Existing CRDs additionalPrinterColumns defined with CEL expression would start working again after the feature has been reenabled.
+
+###### Are there any tests for feature enablement/disablement?
+
+
+
+We will have unit and integration tests to make sure that the feature enablement and disablement works as intended.
+
+### Rollout, Upgrade and Rollback Planning
+
+
+
+###### How can a rollout or rollback fail? Can it impact already running workloads?
+
+
+
+This feature will not impact rollouts or already-running workloads.
+
+###### What specific metrics should inform a rollback?
+
+
+
+If enabling this feature introduces an increase in the latency of the `kubectl get