Kyverno CEL Policy Model Migration
Migrate Kyverno policies from YAML-based rules to CEL expressions for type-safe, performant validation. Covers CEL syntax, migration patterns, and comparison
π‘ Quick Answer: Kyverno now supports CEL (Common Expression Language) as a policy expression engine alongside traditional YAML overlays, enabling type-safe, compile-time validated policies with better performance and alignment with Kubernetes ValidatingAdmissionPolicy.
The Problem
Traditional Kyverno YAML-based policies:
- Lack type safety (errors found at runtime, not authoring time)
- Limited expressiveness for complex conditions
- No compile-time validation of policy logic
- Difficult to express mathematical/string operations
- Separate syntax from Kubernetes-native ValidatingAdmissionPolicy
The Solution
Traditional YAML vs CEL Comparison
# Traditional Kyverno YAML pattern match
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-labels
spec:
validationFailureAction: Enforce
rules:
- name: check-team-label
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Label 'team' is required"
pattern:
metadata:
labels:
team: "?*"# New CEL-based Kyverno policy
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-labels-cel
spec:
validationFailureAction: Enforce
rules:
- name: check-team-label
match:
any:
- resources:
kinds:
- Pod
validate:
cel:
expressions:
- expression: "has(object.metadata.labels) && 'team' in object.metadata.labels"
message: "Label 'team' is required on all Pods"
- expression: "object.metadata.labels['team'].size() > 0"
message: "Label 'team' must not be empty"CEL Expression Patterns
# Resource limit validation with math
validate:
cel:
expressions:
- expression: |
object.spec.containers.all(c,
has(c.resources.limits) &&
has(c.resources.limits.memory) &&
quantity(c.resources.limits.memory).compareTo(quantity('4Gi')) <= 0
)
message: "Container memory limit must not exceed 4Gi"
- expression: |
object.spec.containers.all(c,
has(c.resources.requests) &&
has(c.resources.limits) &&
quantity(c.resources.requests.cpu).compareTo(
quantity(c.resources.limits.cpu)) <= 0
)
message: "CPU request must not exceed limit"CEL Variables and Bindings
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: image-policy-cel
spec:
rules:
- name: restrict-registries
match:
any:
- resources:
kinds:
- Pod
validate:
cel:
variables:
- name: allowedRegistries
expression: "['registry.example.com', 'gcr.io/my-project', 'nvcr.io']"
- name: containers
expression: "object.spec.containers + object.spec.?initContainers.orValue([])"
expressions:
- expression: |
variables.containers.all(c,
variables.allowedRegistries.exists(r, c.image.startsWith(r))
)
message: "Images must come from approved registries"Complex CEL Policies
# Enforce pod security standards via CEL
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: pod-security-cel
spec:
validationFailureAction: Enforce
rules:
- name: restrict-privilege-escalation
match:
any:
- resources:
kinds:
- Pod
validate:
cel:
expressions:
- expression: |
object.spec.containers.all(c,
!has(c.securityContext) ||
!has(c.securityContext.privileged) ||
c.securityContext.privileged == false
)
message: "Privileged containers are not allowed"
- expression: |
object.spec.containers.all(c,
has(c.securityContext) &&
has(c.securityContext.allowPrivilegeEscalation) &&
c.securityContext.allowPrivilegeEscalation == false
)
message: "Privilege escalation must be explicitly disabled"
- expression: |
!has(object.spec.hostNetwork) || object.spec.hostNetwork == false
message: "Host networking is not allowed"Migration Path from YAML to CEL
# Step 1: Identify policies to migrate
kubectl get cpol -o json | jq '.items[] | .metadata.name'
# Step 2: Test CEL expressions interactively
# Use cel-playground or kyverno CLI
kyverno test --policy cel-policy.yaml --resource test-pod.yaml
# Step 3: Run in Audit mode first
# validationFailureAction: Audit
# Step 4: Monitor policy reports
kubectl get policyreport -A --sort-by='.summary.fail'
# Step 5: Switch to Enforce after validationCEL vs YAML Decision Matrix
Feature YAML Overlay CEL Expression
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Type safety β runtime β
compile-time
Math operations β limited β
full arithmetic
String manipulation β basic regex β
full string ops
List comprehensions β no β
all/exists/map/filter
Cross-field validation β οΈ awkward β
natural
Performance β οΈ slower β
compiled
K8s VAP compatibility β no β
same syntax
Mutation support β
yes β validate only
Generation support β
yes β validate only
Learning curve β
familiar β οΈ new syntaxCommon Issues
CEL expression type error
- Cause: Accessing field that may not exist without
has()check - Fix: Always guard with
has(object.spec.field)before accessing
Policy not matching resources
- Cause: CEL expression returns wrong type (must be bool)
- Fix: Ensure all expressions evaluate to true/false
Performance regression with complex CEL
- Cause: Nested loops over large container lists
- Fix: Use variables to pre-compute; limit list operations
Best Practices
- Use
has()guards β fields may not exist in all resources - Define variables for reusable sub-expressions
- Test with
kyverno testbefore deploying - Start with Audit mode β never deploy Enforce untested
- Keep CEL expressions readable β use variables for complex logic
- Use CEL for validation, YAML for mutation β CEL doesnβt support mutate yet
Key Takeaways
- CEL provides type-safe, compile-time validated policy expressions
- Same syntax as Kubernetes ValidatingAdmissionPolicy (future-proof)
- Better performance than YAML overlay matching for complex conditions
- Use
has()+?optional chaining to handle missing fields - Variables enable readable, DRY policy expressions
- Migration: YAML for mutation/generation, CEL for complex validation
- Audit mode β Policy Reports β Enforce (safe rollout pattern)

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
