Common Expression Language in Kubernetes

    CEL expressions are evaluated directly in the API server, making CEL a convenient alternative to out-of-process mechanisms, such as webhooks, for many extensibility use cases. Your CEL expressions continue to execute so long as the control plane’s API server component remains available.

    The CEL language has a straightforward syntax that is similar to the expressions in C, C++, Java, JavaScript and Go.

    CEL was designed to be embedded into applications. Each CEL “program” is a single expression that evaluates to a single value. CEL expressions are typically short “one-liners” that inline well into the string fields of Kubernetes API resources.

    Inputs to a CEL program are “variables”. Each Kubernetes API field that contains CEL declares in the API documentation which variables are available to use for that field. For example, in the field of CustomResourceDefinitions, the self and oldSelf variables are available and refer to the previous and current state of the custom resource data to be validated by the CEL expression. Other Kubernetes API fields may declare different variables. See the API documentation of the API fields to learn which variables are available for that field.

    Example CEL expressions:

    CEL community libraries

    Kubernetes CEL expressions have access to the following CEL community libraries:

    In additional to the CEL community libraries, Kubernetes includes CEL libraries that are available everywhere CEL is used in Kubernetes.

    The list library includes indexOf and lastIndexOf, which work similar to the strings functions of the same names. These functions either the first or last positional index of the provided element in the list.

    The list library also includes min, max and sum. Sum is supported on all number types as well as the duration type. Min and max are supported on all comparable types.

    isSorted is also provided as a convenience function and is supported on all comparable types.

    Examples:

    Examples of CEL expressions using list library functions
    CEL ExpressionPurpose
    names.isSorted()Verify that a list of names is kept in alphabetical order
    items.map(x, x.weight).sum() == 1.0Verify that the “weights” of a list of objects sum to 1.0
    lowPriorities.map(x, x.priority).max() < highPriorities.map(x, x.priority).min()Verify that two sets of priorities do not overlap
    names.indexOf(‘should-be-first’) == 1Require that the first name in a list if a specific value

    In addition to the matches function provided by the CEL standard library, the regex library provides find and findAll, enabling a much wider range of regex operations.

    Examples:

    See the Kubernetes regex library godoc for more information.

    To make it easier and safer to process URLs, the following functions have been added:

    • isURL(string) checks if a string is a valid URL according to the Go’s net/url package. The string must be an absolute URL.
    • url(string) URL converts a string to a URL or results in an error if the string is not a valid URL.

    Once parsed via the function, the resulting URL object has getScheme, getHost, getHostname, getPort, getEscapedPath and getQuery accessors.

    Examples:

    Examples of CEL expressions using URL library functions
    CEL ExpressionPurpose
    url(‘)Get the ‘example.com:80’ host part of the URL.
    url(‘https://example.com/path with spaces/‘).getEscapedPath()Returns ‘/path%20with%20spaces/‘

    See the godoc for more information.

    Type checking

    CEL is a .

    Some Kubernetes API fields contain fully type checked CEL expressions. For example, CustomResourceDefinitions Validation Rules are fully type checked.

    Some Kubernetes API fields contain partially type checked CEL expressions. A partially type checked expression is an experessions where some of the variables are statically typed but others are dynamically typed. For example, in the CEL expressions of the request variable is typed, but the object variable is dynamically typed. As a result, an expression containing request.namex would fail type checking because the namex field is not defined. However, object.namex would pass type checking even when the namex field is not defined for the resource kinds that object refers to, because object is dynamically typed.

    The has() macro in CEL may be used in CEL expressions to check if a field of a dynamically typed variable is accessible before attempting to access the field’s value. For example:

    Equality comparison for arrays with x-kubernetes-list-type of set or map ignores element order. For example [1, 2] == [2, 1] if the arrays represent Kubernetes set values.

    Concatenation on arrays with x-kubernetes-list-type use the semantics of the list type:

    • map: X + Y performs a merge where the array positions of all keys in X are preserved but the values are overwritten by values in Y when the key sets of X and Y intersect. Elements in Y with non-intersecting keys are appended, retaining their partial order.

    Escaping

    Only Kubernetes resource property names of the form [a-zA-Z_.-/][a-zA-Z0-9_.-/]* are accessible from CEL. Accessible property names are escaped according to the following rules when accessed in the expression:

    Table of CEL identifier escaping rules
    escape sequenceproperty name equivalent
    underscores
    dot.
    dash-
    slash/
    {keyword}__CEL RESERVED keyword

    When you escape any of CEL’s RESERVED keywords you need to match the exact property name use the underscore escaping (for example, int in the word sprint would not be escaped and nor would it need to be).

    Examples on escaping:

    CEL is non-Turing complete and offers a variety of production safety controls to limit execution time. CEL’s resource constraint features provide feedback to developers about expression complexity and help protect the API server from excessive resource consumption during evaluation. CEL’s resource constraint features are used to prevent CEL evaluation from consuming excessive API server resources.

    A key element of the resource constraint features is a cost unit that CEL defines as a way of tracking CPU utilization. Cost units are independent of system load and hardware. Cost units are also deterministic; for any given CEL expression and input data, evaluation of the expression by the CEL interpreter will always result in the same cost.

    Many of CEL’s core operations have fixed costs. The simplest operations, such as comparisons (e.g. <) have a cost of 1. Some have a higher fixed cost, for example list literal declarations have a fixed base cost of 40 cost units.

    Calls to functions implemented in native code approximate cost based on the time complexity of the operation. For example: operations that use regular expressions, such as match and , are estimated using an approximated cost of length(regexString)*length(inputString). The approximated cost reflects the worst case time complexity of Go’s RE2 implementation.

    All CEL expressions evaluated by Kubernetes are constrained by a runtime cost budget. The runtime cost budget is an estimate of actual CPU utilization computed by incrementing a cost unit counter while interpreting a CEL expression. If the CEL interpreter executes too many instructions, the runtime cost budget will be exceeded, execution of the expressions will be halted, and an error will result.

    Some Kubernetes resources define an additional runtime cost budget that bounds the execution of multiple expressions. If the sum total of the cost of expressions exceed the budget, execution of the expressions will be halted, and an error will result. For example the validation of a custom resource has a per-validation runtime cost budget for all evaluated to validate the custom resource.