Skip to content
  • Products
    • Portfolio overview >

      Flexsave™

      Automatically manage cloud compute for optimized costs and agility

      Cloud Analytics

      Make sense of spend and chargeback to align with your business

      google cloud msp

      BigQuery Lens

      Optimize BigQuery costs with actionable recommendations and usage insights

      Spot Scaling

      Maximize AWS Spot savings and minimize disruptions for optimized scaling

      Anomaly Detection

      Autonomously identify cost spikes early, with zero configuration

      Platform overview >

      Organize your billing data for better business decisions

  • Services
    • Services overview >

      How we work

      Learn how we’re redefining support with our customer reliability engineering

      Stats

      View our live support and customer satisfaction statistics in real-time

      Cloud solutions

      Proven solutions to cloud complexity

      FinOps

      Learn how DoiT enables critical FinOps capabilities

      Areas of expertise

      Cloud Architecture

      Ensure your cloud architecture is future-ready and built for success

      Cloud Cost Optimization

      Identify opportunities to optimize costs and target spend for added value

      Cloud Migration

      Realize greater efficiency and innovation with successful cloud migration

      Cloud Security

      Center security in your cloud strategy to ensure ongoing efficacy and growth

      Data and Analytics

      Harness the potential of big data and analytics to gain a competitive edge

      Data Management

      Build your data practice with expert guidance tailored to your business goals

      DevOps Jump Start

      Accelerate your AWS workloads & release pipelines while also increasing automation, monitoring & reliability

      Infrastructure

      Maximize the full suite capabilities from your cloud infrastructure

      Kubernetes

      Manage the complexity of Kubernetes to enable innovation and scalability

      Location-Based Services

      Transform geolocational data into real-world, real-time intelligence

      Machine Learning

      Level-up key data with ML capabilities that accelerate innovation

      Multicloud

      Create meaningful business value with a robust multicloud strategy

      Training

      Build skills and capability across teams with certified, expert-led training

  • Partners
    • Alliances

      Proud to be an award‒winning multicloud partner to top‒tier cloud providers

      doit-together

      DoiT Together

      Enabling cloud growth and unlocking revenue through expert partnership

      ISV Go-Global

      Accelerate new customer growth and Marketplace integration on AWS and GCP

  • Resources
    • Resources hub >

      Blog

      Read the latest insights, tips and perspectives from our team of cloud experts

      Case Studies

      See how we’ve helped thousands of public cloud customers achieve their goals

      Cloud Masters Podcast

      Listen to our experts and customers share tangible tips for navigating the cloud.

      Ebooks and Guides

      Discover foundational expertise and future-ready recommendations for the cloud

      Events and Webinars

      Tech talks and interactive expert sessions delivered both virtually and in person

      GCPInstances.info

      Google Cloud Compute Engine instance comparison

      Help center

      Read documentation, product updates, and more

      Newsroom

      See what's new from DoiT in our latest news and announcements

      Trust Center

      How we focus on security, compliance, and privacy

      Videos

      Watch product demos, interviews and more from our cloud experts

  • About
    • About DoiT >

      Careers

      Browse our open positions and learn more about what it takes to be a Do’er

      Leadership

      Meet the team leading DoiT and our customers on a journey of hypergrowth

      Newsroom

      See what's new from DoiT in our latest news and announcements

  • Pricing
  • Contact us
  • Sign In
  • Products
    • Flexsave ™
    • Cloud Analytics
    • Spot Scaling
    • BigQuery Lens
    • Anomaly Detection
    • DoiT Platform
  • Services
    • How We Work
    • Stats
    • Cloud Solutions
    • FinOps
    • Areas of expertise
      • Cloud Architecture
      • Cloud Cost Optimization
      • Cloud Migration Consulting Services
      • Cloud Security
      • Data and Analytics
      • Data Management
      • DevOps with AWS & DoiT
      • Infrastructure
      • Kubernetes
      • Location Based Services
      • Machine Learning
      • Multicloud
      • Training
  • Partners
    • ISV Go-Global
    • Award-winning public cloud partner
    • DoiT Together
  • Resources
    • Blog
    • Case Studies
    • Cloud Masters Podcast
    • Ebooks and Guides
    • Events and Webinars
    • GCPInstances.info
    • Help center
    • Newsroom
    • Trust Center
    • Videos
  • Pricing
  • About
    • Careers
    • Leadership
    • Newsroom
  • Contact us
  • Sign In
Contact us
Sign in

Blog

Effortless In-Cluster Validation with Kubernetes: Introducing Validating Admission Policies

  • Eyal Zekaria Eyal Zekaria
  • Date: June 5, 2023

Streamlining Kubernetes Resource Validation with Validating Admission Policies and CEL

In-cluster validation offers many practical uses, such as preventing accidental or malicious deletion of resources, limiting the number of replicas a deployment can have for better resource management, and requiring certain annotations, labels, or environment variables to be present (or absent), among other things. Understanding the process of validating resources within a Kubernetes cluster is quite simple: every time a matching request is made to the API, a set of policies are run against it to determine whether it’s allowed or denied.

This can be incredibly valuable for cluster operators, as it helps enforce specific standards and rules on cluster users, such as developers. It’s no wonder that this has become a hot topic for many of our customers, and numerous products and companies have emerged to simplify the process of creating and running validation for Kubernetes resources.

By providing more information about the role of Dynamic Admission Control (DAC) in the validation process and the challenges faced by cluster operators, the article will help readers better appreciate the simplicity and benefits offered by Validating Admission Policies (VAP), Common Expression Language (CEL) and their RBAC-like syntax. This context will enable them to make more informed decisions about adopting these new features in their Kubernetes environments.

If you’re here for the actual code and examples, skip ahead to the Validating Admission Policies section. For more advanced use cases, take a look at the follow up post: Validating Admission Policies in Kubernetes: Advanced Use Cases.

Challenges with implementing Dynamic Admission Control

Cluster Validation with Kubernetes

Admission Controller Phases (source)

Implementing request validation within your cluster isn’t always a walk in the park. It involves using DAC — a powerful but not always user-friendly tool for cluster operators.

DAC is a critical component in the Kubernetes validation process. It allows cluster administrators to manage the admission of resources into the cluster by intercepting API requests and either allowing or rejecting them based on a set of predefined policies. This offers fine-grained control over the resources being created, updated, or deleted in the cluster, ensuring that they adhere to specific standards and rules.

However, using DAC currently can be challenging for cluster operators due to its complexity. In short, the process entails writing an admission webhook server, creating the webhook resource, configuring authentication to the API server if needed, and managing the certificate used for TLS. Furthermore, operators need to be well-versed in Kubernetes concepts and security best practices and be proficient in programming languages to create and maintain the validating logic.

Although tools like OPA Gatekeeper can streamline this process, cluster operators still need to deploy and manage the workload running in their cluster. But fear not! Kubernetes has introduced a new resource type called Validating Admission Policies (VAPs), available in alpha starting v1.26, which offers a simpler solution. Their simplicity, which demonstrate in the next sections, will likely make VAPs the de-facto standard way of performing in-cluster validation.

Introducing VAPs — a cluster operator’s best friend for resource validation

VAPs leverage Google’s CEL to define validation expressions that will be run against matching API requests. Because CEL expressions are evaluated directly in the API server, there’s no need to write or deploy custom workloads to evaluate your policies. This makes policy creation incredibly straightforward and accessible compared to alternative methods, such as the previously discussed Validating Admission Webhooks.

If you’re concerned about overloading the API and impacting other processes, don’t worry — CEL comes with resource constraints to keep things in check. It’s worth learning more about these safeguards by reading about CEL resource constraints in the official Kubernetes documentation.

CEL support was first introduced in Kubernetes v1.23 for inline validation of Custom Resource Definitions (CRD) — currently in beta starting v1.25. This has opened up numerous possibilities for CEL use cases within Kubernetes. For a deeper dive into the origins of CEL in Kubernetes and its potential, we recommend watching Cici Huang’s talk, “The Path to Self Contained CRDs,” which inspired our exploration of Validating Admission Policies.

Harnessing VAPs and CEL for Efficient Validation

One of the main advantages of using CEL and VAPs is their simplicity. Since the validation logic is evaluated directly within the API server, there’s no additional overhead from custom workloads, making it easier to scale the validation process as the cluster grows. Additionally, CEL provides a lightweight and efficient way to express validation rules, improving performance and reducing the risk of overloading the API server. Built-in resource constraints further ensure the stability and efficiency of the validation process.

By leveraging Validating Admission Policies and CEL, cluster operators can use a more straightforward and scalable validation process. This allows them to enforce standards and rules within the cluster more efficiently and effectively than with other methods. The ease of use, scalability, and performance benefits of VAPs and CEL make them a compelling alternative for cluster operators looking to streamline Kubernetes in-cluster validation.

Validating Admissions Policies

Using this feature requires two main components to get going:

  • ValidatingAdmissionPolicy — defines the failure policy, request matches and CEL validation expressions. I.e. — the policy
  • ValidatingAdmissionPolicyBinding— defines the scope of the policy; it binds the policy to a set of matched resources

Even though this feature has been in Alpha since v1.26, some features are only present starting v1.27 (audit annotation, validation actions), so all of the following manifests were tested on a Kubernetes cluster running v1.27.1 (with alpha features and ValidatingAdmissionPolicyfeature gate enabled).

All examples in this post can also be found in a GitHub repository created for this purpose.

The first example comes straight from the documentation. We’ll create and use the demo namespace for running all the examples in this post:

 

$ echo 'apiVersion: v1
kind: Namespace
metadata:
  labels:
    environment: demo
  name: demo' | k apply -f-
namespace/demo created

$ k config set-context --current --namespace demo

Next, we will create a policy that prevents Deployments from having more than five replicas:

 

apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicy
metadata:
 name: "demo-policy.example.com"
spec:
 failurePolicy: Fail
 matchConstraints:
   resourceRules:
     - apiGroups:   ["apps"]
       apiVersions: ["v1"]
       operations:  ["CREATE", "UPDATE"]
       resources:   ["deployments"]
 validations:
   - expression: "object.spec.replicas <= 5"

The failurePolicyfield can be set to the following values:

Fail means that an error calling the ValidatingAdmissionPolicycauses the admission to fail and the API request to be rejected.
Ignore means that an error calling the ValidatingAdmissionPolicyis ignored and the API request is allowed to continue.

The matchConstraintsfield is used to match incoming requests and is configured so that the policy will only apply to API requests for Deployments in the apps/v1API, and only requests to CREATEor UPDATEa Deployment.

Lastly, the validationsfield contains the actual CEL expressions that will be run against the matched API requests. All expressions need to be evaluated to true in order for the request to be admitted.

We’ll create the following binding to complete the configuration:

apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicyBinding
metadata:
  name: "demo-binding-test.example.com"
spec:
  policyName: "demo-policy.example.com"
  validationActions: [Deny]
  matchResources:
    namespaceSelector:
      matchLabels:
        environment: demo

We’re binding the policy created earlier to any namespace that has the label environment=demoset — this is useful for configuring where we want to enforce the policy validation.

There are more options for matching namespace, such as matchExpressionsfor performing more granular matching, as well as other configuration options; excludeResourceRulesto exclude certain resources, objectSelectorto match certain objects (discouraged since developers can omit a label to avoid auditing). I’ll cover the more interesting options in later examples.

Once these manifests are applied to the cluster, trying to create a new Deployment that violates the policy will throw an error, as expected:

$ k create deployment nginx — image=nginx — replicas=10
error: failed to create deployment: deployments.apps "nginx" is forbidden: ValidatingAdmissionPolicy 'demo-policy.example.com' with binding 'demo-binding-test.example.com' denied request: failed expression: object.spec.replicas <= 5

This also works when trying to diff the resource:

 

$ k create deployment nginx --image=nginx --replicas=10 --dry-run=client -oyaml | k diff -f -
The deployments "nginx" is invalid: : ValidatingAdmissionPolicy 'demo-policy.example.com' with binding 'demo-binding-test.example.com' denied request: failed expression: object.spec.replicas <= 5

Multiple validation expressions

Sometimes you’d want to perform multiple validations on resources, consider the following validation expressions for Deployments:

apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicy
metadata:
  name: "demo-policy.example.com"
spec:
  failurePolicy: Fail
  matchConstraints:
    resourceRules:
      - apiGroups:   ["apps"]
        apiVersions: ["v1"]
        operations:  ["CREATE", "UPDATE"]
        resources:   ["deployments"]
  validations:
    # Deployments can't have more than 3 replicas
    - expression: "object.spec.replicas <= 3"
    # Deployment containers must be using images hosted in europe-west1 Artifact Registry in project test-eyal
    - expression: "object.spec.template.spec.containers.all(c, c.image.startsWith('europe-west1-docker.pkg.dev/test-eyal/'))"
    # Deployment cannot use emptyDir volumes
    - expression: "!has(object.spec.template.spec.volumes) || object.spec.template.spec.volumes.all(v, !has(v.emptyDir))"

A Deployment that is matched by this policy will need to have all expressions evaluated to truein order to be admitted to the cluster.

One thing to note is that the validations are executed sequentially. If one expression fails, it’ll return that failure to the client immediately — this means that if your resource violates more than one of the validation expressions, it will be an iterative process of getting denied, fixing the violation and trying again.

Customize the validation message

It is also possible to supply a custom messageto be returned to the client in case of a failed validation. You can even perform interpolation if necessary by using a messageExpression. A message expression has access to object, oldObject, request, and params.

Let’s update our last policy with custom messages rather than comments:

apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicy
metadata:
  name: "demo-policy.example.com"
spec:
  failurePolicy: Fail
  matchConstraints:
    resourceRules:
      - apiGroups:   ["apps"]
        apiVersions: ["v1"]
        operations:  ["CREATE", "UPDATE"]
        resources:   ["deployments"]
  validations:
    - expression: "object.spec.replicas <= 3"
      messageExpression: "'Deployments cannot have more than 3 replicas, this one has ' + string(object.spec.replicas)"
    - expression: "object.spec.template.spec.containers.all(c, c.image.startsWith('europe-west1-docker.pkg.dev/test-eyal/'))"
      message: "Deployment containers must be using images hosted in europe-west1 Artifact Registry in project test-eyal"
    - expression: "!has(object.spec.template.spec.volumes) || object.spec.template.spec.volumes.all(v, !has(v.emptyDir))"
      messageExpression: "'Deployment cannot use emptyDir volumes, change the following volume: ' + object.spec.template.spec.volumes.filter(v, has(v.emptyDir)).map(v, v.name)[0]"

It’s important to note that any interpolated values in the messageExpressionfield would need to be of type string, otherwise the message will return an error for the failed evaluation instead.

Without setting a custom message, a deployment with an emptyDirvolume would have failed with the following:

The deployments “nginx” is invalid: : ValidatingAdmissionPolicy ‘demo-policy.example.com’ with binding ‘demo-binding-test.example.com’ denied request: failed expression: !has(object.spec.template.spec.volumes) || object.spec.template.spec.volumes.all(v, !has(v.emptyDir))

This might be somewhat hard to understand from a client's perspective. With the custom message expression, we would get the following:

 

The deployments “nginx” is invalid: : ValidatingAdmissionPolicy ‘demo-policy.example.com’ with binding ‘demo-binding-test.example.com’ denied request: Deployment cannot use emptyDir volumes, change the following volumes: test

Note that I’m using a messageExpressionrather than a normal messagefor this validation in order to demonstrate the power of CEL. The fact that you can do something doesn’t always mean that you should!

Final Thoughts

As Kubernetes continues to evolve, CEL support is set to introduce more exciting capabilities in future releases. We encourage you to explore Validating Admission Policies and become acquainted with this powerful feature, as it’s likely to become a go-to tool for cluster operators.

Remember that the Validating Admission Policy feature gate is currently in Alpha, which means changes and improvements are expected as it progresses toward General Availability. Stay informed by following updates in the Kubernetes changelog and documentation to ensure you’re up to speed with the latest developments.

Given the ongoing nature of this feature, the content of this article may need to be updated over time. If you come across an example that no longer works or a statement that is no longer accurate, please reach out to us, and we’ll review and update the information accordingly.

 

 

Subscribe to updates, news and more.

Subscribe

Subscribe to updates, news and more.

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Related blogs

Using predefined IAM roles for enhanced Google Maps Platform governance

Examining using predefined Google Cloud IAM roles dedicated to Google Maps usage to enhance the governance of these activities.

Keep reading 
Ramp Plans Resource Hub Header1

Monitor your cloud commit attainment with DoiT Ramp Plans

DoiT Ramp Plans help you visualize, manage, and track your commit attainment so you can make sure you spend what you committed to, and act proactively.

Keep reading 
DoiT-Google-Kubernetes-Engine-Troubleshooting-Made-Simple-with-Interactive-Playbooks

Google Kubernetes Engine Troubleshooting Made Simple with Interactive Playbooks

In modern application management, Kubernetes is the foundation of container orchestration. It automates software deployment, scaling, and management, revolutionising delivery. However, growing complexity and scale pose challenges in troubleshooting and maintaining dynamic ecosystems.

Keep reading 
View all blogs
Let’s do it

From cost optimization to cloud migration, machine learning and CloudOps, we’re here to make the public cloud easy — without the costs.

Ready to get started?

Get in touch

Company

  • About us
  • Blog
  • Careers
  • MS-HT statement
  • Newsroom
  • Privacy policy
  • Terms

Offering

  • Compliance
  • Products
  • Services
  • Solutions
  • Resources

Support

  • Sign in
  • Help center
  • Open ticket
  • Contact us

Never miss an update.

Subscribe to our newsletter

Subscribe to updates, news and more.