 I'm going to be talking about the Common Expression Language in Kubernetes. My name is David Eads. I've been a SIG lead and chair for API machinery for, I don't know, about eight years or so now. So we're going to jump right in. So what is CEL? It is a Common Expression Language. And it's basically a way to write statements like this about your custom resource definitions. So you create a custom resource definition, and you create a schema for it. And then you say, well, I have this other things that I want to do. And the other things that you might want to do are things like for a platform extension author. You want to be able to write controllers for your CRDs. And that means you need to have certain guarantees about them. Maybe a field needs to be in a range. Maybe it needs to be compared against another field that you can't do with OpenAPI today. And then on the other hand, you have cluster admins. And cluster admins are trying to build policy and conformance tools for their particular clusters. They're going to be making rules that are for their clusters in particular. So it still conforms to the ones that a platform extension author wrote. But there's additional things, like maybe you can't make a privileged version, or maybe you can't scale past six. And so they want to be able to do that. And they want to be able to do it in a way that's reliable and resilient and ideally easy. And so this is the path to get the parity that you have with native Kubernetes resources. And so when we launched CRDs, they covered those three things. It was at the very beginning. It was the minimal, do we have enough to be able to read things off the type system and interpret them? We have to have that to write a controller. And then we built the very end. If you have custom code, I have my own custom validation. I want to do whatever it is I want to do. You could write an admission webhook. And so we had the beginning and the end. And it gave you all the power you technically needed. Wasn't easy, but it lets you do it. And then we later built out in the path to v1, these other things related to type schemas, be sure that the string is really a string, that the int is really an int, basic defaulting. Now what we discovered is that there are two items left. And what we're talking about now are these last two items. I want to be able to do static validation of my object based on other fields in that object. So I'm still looking only at the object in question, what was submitted. And then I also want to be able to say, I want to define a policy object in a particular spot and use information like who is requesting this particular item, who's creating it, who's updating it to make decisions about whether or not it is allowed in my cluster. And so why bother to do it? I mean, we can already have the mutating and validating admission webhooks. You technically have all the power that you need. And the answer comes down to deployment model. So when you look at a deployment model for an admission webhook, it has these basic parts. You have a QAPI server. There's some configuration that you have with command line flags, configuration that you have in the resource itself where you define that. And then trust built in both directions to the admission webhook pod itself and then keeping it up to date. It's contacting the server. It's running authentication. Server needs to trust it. There's a decent amount to keep track of. And because we're currently processing it right there, if you have any problem in your network, say you can't reach the service network for some reason, you can't reach a pod endpoint, well, now you can't create your resources. And that ends up being a very frustrating problem for someone trying to maintain reliability on their platform. So what we want to do is be able to provide most of the functionality people write into these webhooks. And we want to be able to process it in the QAPI server. And doing it like that is going to let us eliminate the complexity of writing your own app, building it, creating your image, creating your pod, maintaining the serving certs and the client certificates, and making sure that your service network works all the time, and setting your exclusion rules properly so that if you self host, you can reboot strap yourself. So we can eliminate a lot of complexity if we can figure out how to move it to the QAPI server. And so that's why we brought in Cell, another expression language, one where you can compare fields. And the reason Cell was chosen primarily was due to its sandbox abilities and its cost estimation. So if we flip back here, when you move something to the QAPI server, suddenly the cost of running it is on the QAPI server. If you use too much CPU, you'll destroy the API server, and nothing will work. And so that quality in particular was very important. If it's too expensive, we won't run it. So there are two different sets of items. And I am afraid you're only at 10 minutes. So this is going to be a lot about what and why and less about the hows. We will hit a few examples along the way. But for detailed reading, you're going to have to refer to the docs. The validation here is for platform extension authors. People who want to be able to say that if this field is set, then this other thing must be true. And that will be true for every instance of this custom resource created on any cluster. And the reason that's important is when you're a platform extension author, you need to be able to write the docs of how to use it. You need to be able to write the controllers to implement it. And so running through a few examples here, one common one is map must contain a particular key. I've just thrown this up as an example. The yaml that is being validated is on your left. And the expression that actually does the validation is on the right. And so this is a simple example where its map key must contain my value, another one where it's I have a min, a max, and a current. And you can see that I can compare the values to each other. And you can't do this with the open API validation. You can do it with cell, but you can't do it with the standard open API validation that already existed. And then another final example here is just I have a custom resource. I'm tracking broken clusters and working clusters. It can't be broken and working at the same time. And so my validation makes sure that can't happen, again, inexpressible in standard open API. So the other category of thing is one where you can start taking in external systems into account. What should happen based on the user that's coming in, for instance? And this one is particularly useful for cluster admins. It lets them do things like on my cluster it requires this permission to do. And to make this work, we have these three parts. Your first thought is, David, this didn't make it easier. I still have three things. But the advantage of these three things is that they are all on the QAPI server itself. So they're never going to disappear. They are going to be here. That makes availability a lot easier to guarantee. And so starting on the left, we have validating admission policy. And this is where you might write, I have an expression, or I have this field, and it must be less than some value that a cluster admin might want to set. And then to actually use it, a cluster admin will create a binding. And the reason you might want to create a binding is because it gives you another secondary spot to filter by namespace or by resource. So maybe you have a pre-existing cluster, and you want to enforce something new, but you don't want to instantly break everything. So you need to separate your namespaces into those where, if a new thing is created, it will fail. And those that are pre-existing, and I have to accept the bad thing until it's fixed, and I just want to audit it. And that's what the binding allows you to do. And then finally, you have a parameter. It lets you set a value where you might say, my max replicas is six, just the example I threw up here. And so you have the simple example, hardcoding it right in there. And then you have another example where you have a parameter, CRD created separately, so you can manage them independently. And then this is a slightly more interesting one. You have some users who are special. And so I'm looking at the request, and depending on who made it, that request is going to be allowed or not. And so because the request is by David, it's going to work, because David is awesome. He gets to bypass the requirement. But everybody else is stuck with the requirement. And then the final one that I think is going to be really useful for people is to have an authorization check. So I want to create something that's privileged. And the only people who are allowed to do that are people who have the use verb on the security assignment resource with a particular name that matches the node. And that's the example that I threw up here. So you can now have RBAC rules to create your own custom secondary auth z. And I'm going to close up with what comes next. So right now, some of these are in alpha. Some of these are in beta. And they're pushing their way through. But because CEL is now built in, we're seeing it being included in lots of different resources, different things people want to do with it. I'm afraid I'm going to have to take questions sometime down in the break room, because I believe I have expended the time. But hopefully this was a good introduction for everybody, and you get some sense of what this is for and what you can use it to do.