Skip to content

Commit 47369d7

Browse files
committed
feat(rfc): Changes related to the latest explorations
Signed-off-by: Alex Snaps <[email protected]>
1 parent c4e1713 commit 47369d7

File tree

1 file changed

+52
-40
lines changed

1 file changed

+52
-40
lines changed

rfcs/0000-open-arch.md

Lines changed: 52 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,38 @@ higher-level abstraction to our existing policies.
3838
# Guide-level explanation
3939
[guide-level-explanation]: #guide-level-explanation
4040

41+
While this proposal does enable the work on `Metapolicy`ies as they are mostly understood today, it actually abstracts
42+
the very essence of what the Kuadrant controller already is, i.e. a metacontroller that knows about the so-called
43+
"State-of-the-World" (or SotW), the directed acyclic graph (or DAG) we use to represent the state of the different
44+
Gateway API network objects and how policies attach to them.
45+
46+
Aside that particularity of the SotW knowledge, certainly as far as the data-plane is concerned, the Kuadrant controller
47+
ingests `Auth-` and `RateLimit-` `Policy`ies and outputs `AuthConfig` and `Limit` CR respectively, while configuring the
48+
`Gateway`(s) as required, by configuring the wasm-shim they are running.
49+
4150
## What's a *Metapolicy*?
4251

43-
A *Metapolicy* is a policy just like any other [Gateway API Policy][2], other than it only produces one or more "core
52+
A *Metapolicy* is a policy just like any other [Gateway API Policy][2], other than it only affects one or more "core
4453
Kuadrant policies". A *Metapolicy* is managed by a `MetapolicyController` that will interact with the
4554
`KuadrantController` to integrate seamlessly in the ecosystem.
4655

4756
Think of a `MetapolicyController` being a pure function that takes the custom *Metapolicy* and the Gateway API network
48-
objects it targets as input, and outputs one or more Kuadrant Policies as a result.
57+
objects it targets as input, and alters one or more Kuadrant Policies as a result.
58+
59+
The simplest form will be a one-to-one match and their lifecycle will be the same. When creating the metapolicy, the
60+
resulting output `Policy` gets created; on updates, it is updated; and, finally, when the metapolicy is deleted, the
61+
matching core `Policy` also gets deleted.
62+
63+
In other cases tho, a metapolicy might depend directly or indirectly on the existence of another core `Policy`. Further
64+
more it may need to alter that policy in one way or another.
65+
66+
> [!NOTE]
67+
> An example of such a policy, would be the `PlanPolicy`. That policy points indirectly to an `AuthConfig`, that it'll use
68+
> as the source of data to match a request to a "plan". In abstract terms, it would need to alter the `AuthConfig` so that
69+
> it enriches the metadata available to the wasm-shim (and as such to other services it calls into), with the "plan"
70+
> identifier, so that limitador can apply the proper limits (and look up the proper counters). So while the `PlanPolicy`
71+
> would match straight to a `RateLimitPolicy`, it also would need to add, modify and remove that mapping function from,
72+
> ultimately, the `AuthConfig`.
4973
5074
## Implementing a custom *Metapolicy*
5175

@@ -56,10 +80,6 @@ Controller](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/
5680
it also needs to reconcile when changes to properties of the Gateway API it uses are observed. For that reason, the
5781
controller for a custom *Metapolicy* registers itself with the `KuadrantController`.
5882

59-
> [!TODO]
60-
> Some initial SDK usage example
61-
62-
6383
The example below is a modified example from the
6484
[controller-runtime's own example](https://github.com/kubernetes-sigs/controller-runtime/blob/main/examples/builtins/controller.go#L39).
6585

@@ -83,7 +103,7 @@ func (r *reconcileMetapolicy) Reconcile(ctx context.Context, request reconcile.R
83103
}
84104

85105
// resolve the CEL expression using the `KuadrantContext`
86-
label := kuadrant.evaluateExpression("kuadrant.gatewaysFor(self)[0].metadata.name")
106+
label := kuadrant.evaluateExpression("self.findGateways()[0].metadata.name")
87107

88108
if rs.Labels["gateway"] == label {
89109
return reconcile.Result{}, nil
@@ -103,8 +123,9 @@ It on differs in three ways from the original example:
103123

104124
1. The `Reconcile` signature takes an additional parameter, the `kuadrant *KuadrantContext`;
105125
1. It acts upon an hypothetical `user.MetaPolicy`;
106-
1. It uses the `evaluateExpression` to resolve the CEL expression `kuadrant.gatewaysFor(self)[0].metadata.name` instead
107-
of using a fixed string for the label's value.
126+
1. It uses the `evaluateExpression` to resolve the CEL expression `self.findGateways(self)[0].metadata.name` instead
127+
of using a fixed string for the label's value. Where `self` is the *Metapolicy* being reconciled.
128+
1. The Kuadrant CEL Library is the one providing the additional functionality needed to support the different use cases.
108129

109130
Because that expression is evaluated upon creation, the `KuadrantRuntime` will make sure to reconcile whenever that cel
110131
expression's evaluated result would change; in this particular example whenever the name of the first `Gateway` changes.
@@ -113,52 +134,43 @@ expression's evaluated result would change; in this particular example whenever
113134
> Below is the proposed inital integration point for `MetapolicyController`s. The idea is to keep the deployment model
114135
> fairly open moving forward. As of now, this would be the deployment model for _our own_ *Metapolicies*
115136
116-
To deploy our custom reconciler, we need to let the Kuadrant operator know about it, by adding it to the `Kuadrant` CR:
117-
118-
```yaml
119-
apiVersion: kuadrant.io/v1beta2
120-
kind: Kuadrant
121-
metadata:
122-
name: kuadrant-sample
123-
spec:
124-
plugins:
125-
userMetaPolicy:
126-
deployment: embedded
127-
```
128137

129138
The `UserMetaPolicy` will need to be packaged with a custom Docker image containing the plugin. It'll be automatically
130-
registered with the Kuadrant Controller from its own config file.
131-
132-
> [!TODO]
133-
> Support out-of-image deployments of plugins, i.e. ones running as their own container. Which then also means we need
134-
> to deal with failures et al, so probably adding the necessity for more configuration options for these plugins
139+
registered with the Kuadrant Controller when present.
135140

136141
# Reference-level explanation
137142
[reference-level-explanation]: #reference-level-explanation
138143

139144
## Plugin architecture
140145

141-
### gRPC to controller
146+
### Kuadrant's `MetapolicyControllerRuntime`
147+
148+
- [ ] Provides the layer around the standard [Kubernetes' Controller Runtime](https://github.com/kubernetes-sigs/controller-runtime)
149+
- [ ] Provides a logger to `stderr` for log forwarding, according to tbd formart
150+
- [ ] Provides a golang API that interfaces with the controller through gRPC (including streams for eventing)
151+
- [ ] Provides eventing for the changes triggered by the SotW DAG
152+
- [ ] Handles the lifecycling of the extension, `SIGTEM` handler
153+
- [ ] *Optional*: Readiness probe, tho looks like we don't need it
154+
- [ ] *Optional*: More advanced liveliness probe, tho again there probably is no reason
155+
156+
### Kuadrant Controller extension mechanism
142157

143158
- [ ] Unix socket for "in-pod/embedded" plugins
159+
- [ ] Monitors child processes and restarts them when needed
160+
- [ ] Forwards `stderr` to a per-extension logger at the appropriate log level
144161
- [ ] Declarative way to load plugins
145-
- [ ] Provide a decorated [Controller Runtime](https://github.com/kubernetes-sigs/controller-runtime) Golang that
146-
provides the changes triggered by the DAG
147-
148-
### gRPC streams for eventing on the DAG
149162

150-
- [ ] Subscriptions infered from CEL and the current CR being reconcilied
163+
### Extension services
151164

152-
### Typed DSL in CEL
165+
- [ ] API to query the SotW DAG, with subscriptions
166+
- [ ] API to add/modify/delete transformer functions to the DAG
167+
- [ ] metadata enrichment ("per action" ?)
168+
- [ ] others?
153169

154-
> [!IMPORTANT]
155-
> Provide both the `MetapolicyCR` & the `GwAPIContext` instances relative to a reconciliation
156-
> The `GwAPIContext` would not only be responsible for resolving the [CEL expressions][3] but also deriving the
157-
> necessary subscriptions needed to inform the controller when a reconciliation is needed because of changes to the
158-
> Gateway API objects queried
170+
### CEL Kuadrant Library
159171

160-
- [ ] Support existing `context`s in the CEL interpreter's `Env`
161-
- [ ] Find a way to express the `context`s present/set for each CEL
172+
- [ ] Support for all Gateway API types through protobuf
173+
- [ ] Add utility methods to `Policy` type for DAG navigation
162174

163175

164176
### Deployment

0 commit comments

Comments
 (0)