CEL Expressions Troubleshooting Guide
Introduction
This guide helps debug and troubleshoot Common Expression Language (CEL) expressions in Kyverno policies, based on actual implementation details and real user issues from the Kyverno codebase.
Verified CEL Variables
Based on the actual implementation, these are the confirmed CEL variables available:
Core Variables (Always Available)
object- The incoming Kubernetes resourceoldObject- The existing object (null for CREATE operations)request- The admission request information
Additional Variables (Implementation Status Verified)
namespaceObject- Available in policies (confirmed in codebase)authorizer- Limited availability (GitHub issue #8021 shows partial implementation)params- Available when using parameterized policies
Source: Issues #8021, #11060, and ValidatingPolicy documentation
Real Error Patterns (From GitHub Issues)
1. Variable Context Issues
Error from Issue #11060:
Creating configmaps in namespace '{{namespace}}' is not allowed
Root Cause: Variable syntax {{ }} doesn’t work in CEL expressions.
Verified Solution:
1# Wrong - from actual failing example
2validate:
3 cel:
4 expressions:
5 - expression: "namespaceObject.metadata.name == '{{namespace}}'"
6
7# Correct - working pattern
8validate:
9 cel:
10 expressions:
11 - expression: "namespaceObject.metadata.name == request.namespace"
2. CustomResource Matching Errors
Error from Issue #10313:
no unique match for kind MyCustomResource
Root Cause: CEL policies require explicit API group/version for CRDs.
Verified Solution:
1# Wrong - causes the error above
2match:
3 any:
4 - resources:
5 kinds:
6 - MyCustomResource
7
8# Correct - from issue resolution
9match:
10 any:
11 - resources:
12 kinds:
13 - example.com/v1/MyCustomResource
3. CEL Expression Warnings
From Issue #9605: Currently, Kyverno doesn’t block policy creation with CEL warnings due to ValidatingAdmissionPolicy variable bugs.
Current Behavior: Policies with CEL warnings are created but may not work as expected.
Workaround: Validate expressions manually before applying policies.
Debugging Strategies (Verified Working)
1. Enable Debug Logging
From Kyverno configuration documentation:
1# Increase logging verbosity to see CEL evaluation
2containers:
3- name: kyverno
4 args:
5 - -v=4 # Shows variable substitution details
2. Use dumpPayload for Request Inspection
From troubleshooting documentation:
1# Add to admission controller
2containers:
3- name: kyverno
4 args:
5 - --dumpPayload=true # Shows full AdmissionReview content
Note: This has performance impact - remove after debugging.
3. Progressive Expression Testing
Start with simple expressions and build complexity:
1# Step 1: Basic existence check
2expression: "has(object.spec)"
3
4# Step 2: Add specific field
5expression: "has(object.spec.containers)"
6
7# Step 3: Add validation logic
8expression: "has(object.spec.containers) && object.spec.containers.size() > 0"
Known Limitations (From Codebase)
1. Variable Composition Status
From Issue #8050: Variable composition in CEL expressions is planned but implementation details are evolving.
Current Status: Basic variables work, but complex composition may have limitations.
2. Context Variable Access
From Issue #11060: Context variables from apiCall cannot be directly used in CEL expressions.
Current Workaround: Use preconditions with traditional variable syntax, then simple CEL validation.
3. Built-in Variable Coverage
From Issue #11827: Several Kyverno built-in variables don’t have CEL equivalents yet:
serviceAccountName- Must be extracted fromrequest.userInfo.usernameserviceAccountNamespace- Must be parsed manuallyimages- CEL implementation in progress
Performance Considerations (From Codebase)
1. CEL Expression Caching
From Issue #10754: CEL expressions are compiled separately for each policy, even if identical.
Current Impact: Duplicate expressions across policies cause redundant compilation.
Planned Improvement: Expression caching and reuse (in development).
2. Webhook Timeouts
From installation documentation:
1spec:
2 webhookConfiguration:
3 timeoutSeconds: 30 # Default is 10s, max is 30s
Recommendation: Increase timeout for complex CEL expressions.
Testing Strategies (Verified Working)
1. CLI Testing
From Kyverno CLI documentation:
1# Test CEL policies before applying
2kyverno apply policy.yaml --resource test-resource.yaml
3
4# Validate policy syntax
5kyverno validate policy.yaml
2. Dry-Run Validation
1# Test against live cluster without applying
2kubectl apply -f test-resource.yaml --dry-run=server
3. Policy Reports Analysis
1# Check policy evaluation results
2kubectl get polr -A
3kubectl describe polr <policy-report-name>
Common Workarounds (From Community)
1. Complex Variable Access
Issue: CEL can’t access all context variables directly.
Workaround (from issue discussions):
1# Use preconditions for complex variable logic
2preconditions:
3 all:
4 - key: "{{ request.userInfo.username }}"
5 operator: NotEquals
6 value: "system:admin"
7validate:
8 cel:
9 expressions:
10 - expression: "object.spec.replicas > 0" # Simple CEL validation
2. Resource Library Alternative
Issue: Resource library access in CEL expressions has limitations.
Workaround: Use traditional context with apiCall:
1context:
2- name: configmap
3 configMap:
4 name: allowed-values
5 namespace: kyverno
6validate:
7 cel:
8 expressions:
9 - expression: "object.metadata.name != 'forbidden'" # Basic CEL check
Safe CEL Patterns (Verified Working)
1. Basic Field Validation
1# Confirmed working pattern
2validate:
3 cel:
4 expressions:
5 - expression: "has(object.metadata.labels.app)"
6 - expression: "object.spec.replicas >= 1"
7 - expression: "!object.spec.containers.exists(c, has(c.securityContext.privileged) && c.securityContext.privileged)"
2. Namespace Object Access
1# Confirmed working (from CLI tests)
2validate:
3 cel:
4 expressions:
5 - expression: "namespaceObject.metadata.name != 'default'"
6 - expression: "has(namespaceObject.metadata.labels.environment)"
3. Request Information
1# Verified available fields
2validate:
3 cel:
4 expressions:
5 - expression: "request.operation == 'CREATE'"
6 - expression: "request.userInfo.username != 'system:admin'"
Current Implementation Status
Fully Supported
- ✅ Basic object validation
- ✅ Simple field existence checks
- ✅ Namespace object access
- ✅ Request metadata access
- ✅ List operations (
all,exists,size)
Partially Supported
- ⚠️ Variable composition (basic cases work)
- ⚠️ Context variable access (limited)
- ⚠️ Resource library functions (some restrictions)
In Development
- 🔄 CEL expression caching (Issue #10754)
- 🔄 Built-in variable parity (Issue #11827)
- 🔄 Enhanced context access (Issue #11060)
Getting Help
When reporting CEL issues:
- Include Kyverno version: Check with
kubectl get pods -n kyverno - Provide policy YAML: Complete policy that reproduces the issue
- Share exact error: From policy reports or admission controller logs
- Reference similar issues: Check existing GitHub issues for patterns
Useful Commands for Bug Reports:
1# Get admission controller logs
2kubectl logs -n kyverno deployment/kyverno-admission-controller
3
4# Get policy reports
5kubectl get polr -A -o yaml
6
7# Check policy status
8kubectl describe cpol <policy-name>
Related Resources
- GitHub Issues: CEL-related issues
- ValidatingPolicy Docs: Official API reference
- Community Slack: #kyverno channel for real-time help
- CLI Documentation: Testing policies
Note: This guide reflects the current implementation status. Features marked as “in development” may change. Always test policies in non-production environments first.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.