-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update (rewrite) eventing specs #25
Conversation
/assign @vaikas @n3wscott @lionelvillard |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!!
specs/eventing/control-plane.md
Outdated
the `spec.subscriber.ref` field points to a resource which does not exist or | ||
cannot be resolved via [Addressable resolution](#addressable-resolution), the | ||
Trigger MUST set the `Ready` condition to `false`, and at least one condition | ||
should indicate the reason for the error. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just jotting this down so I don't forget, but we should also mention about the Dependency Annotation errors.
Specifying the annotation: knative.dev/dependency
This never made it to spec :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you point to either code or doc for this?
I'm guessing this is knative/eventing#4486 ?
How critical is it to have this in the spec, vs it being a documented addition by the OSS software? i.e. is this a foundational part of the interface, or a make-things-easier for the current implementation?
specs/eventing/control-plane.md
Outdated
[metav1.ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#objectmeta-v1-meta) | ||
resource. | ||
|
||
### Spec: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's also the dependency annotation that I think I mentioned in the other PR or somewhere else here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(which is still open)
If it's important, I'm willing to enforce it on all specs.
specs/eventing/control-plane.md
Outdated
## duckv1.Destination | ||
|
||
Destination is used to indicate the destination for event delivery. This is an | ||
exclusive union; excatly one field MUST be set. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit, typo: excatly => exactly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice eyes!
specs/eventing/control-plane.md
Outdated
## duckv1.Destination | ||
|
||
Destination is used to indicate the destination for event delivery. This is an | ||
exclusive union; excatly one field MUST be set. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not an exclusive union.
https://github.com/knative/pkg/blob/main/apis/duck/v1/destination.go#L25
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops, thanks!
specs/eventing/control-plane.md
Outdated
<tr> | ||
<td><code>attributes</code></td> | ||
<td>map[string]string</td> | ||
<td>Event filter using exact match on event context attributes. Each key in the map is compared with the equivalent key in the event context. An event passes the filter if the event attribute values are equal to the specified values.</td> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there's an empty string, it means match like '*'
knative/eventing#4847
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, done.
specs/eventing/data-plane.md
Outdated
|
||
- Knative Eventing aims to enable highly-reliable event processing workflows. As | ||
such, it prefers duplicate delivery to discarded events. The CloudEvents spec | ||
does not take a stance here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found this a bit too restrictive. In particular, the IMC-based broker offers no such guarantees.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does prefer them :) They are just not persisted anywhere, but point taken :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The in-memory-controller SHOULD do the best it can to prefer duplicate delivery to discarded events. This means that it should implement retry, dead-letter, etc to the best of its ability.
Of course, its durability is limited by the backing storage, but that's true of other platforms like Kafka, too (i.e. if you run Kafka with default.replication.factor=1
and lose a drive, there's also data loss).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And it's even harder to have guarantees if you have to worry about flooding, meteor strikes, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are use cases for at-most-once delivery guarantee, which prefer losing events to duplicate delivery.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are such use cases, but Knative eventing doesn't particularly design for that use case, which is different.
specs/eventing/data-plane.md
Outdated
|
||
Event recipients MUST use the HTTP response code to indicate acceptance of an | ||
event. The recipient MUST NOT return a response accepting the event until it has | ||
handled event (processed the event or stored in stable storage). The following |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know how this can be enforced and IMO it's too restrictive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that it might be hard to prove that an implementation was playing fast and loose. I can switch this to SHOULD if you'd prefer.
I think the objection about IMC is a red herring; there are a lot of other decisions (retry, timeout, etc) which could have a higher impact on failure rate than the pod lifetime, depending on the environment.
specs/eventing/control-plane.md
Outdated
1. Attempt delivery to the `status.subscriberUri` URL following the | ||
[data plane contract](./data-plane.md). | ||
|
||
1. If the event delivery fails with a retriable error, it SHOULD be retried |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MUST? Should this SHOULD
be a MUST
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. I'm happy to promote this to a MUST, but I wasn't sure how e.g. crashing in the middle of a delivery attempt might affect these parameters.
I just discovered that I (somehow) flubbed |
…es *server-side* requirements.
I updated the language in |
I opened issue #28 about supporting future upgrades, version mixing and version detection. It seems it is not supported today? What happens in future when Knative is upgraded and event processor were built to support 1.0 (sources, cloud apps that act sinks etc.) - can Knative adapt to mixed 1.0 and newer event processors? |
I owe cleaning up (per KTC notes): Outstanding big discussions
|
On the TM call today we agreed to merge the PR (once Evan gives me the "ok") and then work on the outstanding items in follow-on PRs. Evan (speaking for Brenda) gave VMware's approval |
HUGE thanks to @evankanderson for all his work and patience in this process!!!! |
I think the 1.1 spec needs to take 1.0 compatibility into account; I don't think there's anything we can do today to ensure that any 1.1 would be compatible with this 1.0. |
I updated:
|
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: duglin, evankanderson The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know I am late to the party and this looks like a very late review so I'm gonna leave my comments fwiw. Late better than never. I only reached 1/4th of the control plane. Will keep adding my comments in batches.
example_ of the minimal profile rather than a requirement. This Role is | ||
sufficient to develop, deploy, and manage event routing for an application | ||
within a single namespace. Knative Conformance tests against "MUST", "MUST NOT", | ||
"SHALL", "SHALL NOT", and "REQUIRED" conditions are expected to pass when using |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does expected
here mean? is it a "SHOULD" ? Would this affect conformance? i.e. if the RBAC profile needed is different or stricter, would it still be compliant with this spec? specially given that it states above that this is an example
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kubernetes RBAC is not a requirement for Knative Eventing. The conformance requirement is that there is a cluster and a user set up (with a KUBECONFIG file for auth) which the tests execute aginst.
It would be possible (for example) to have a conformant cluster which implemented no access control, only resource validation. On the other hand, a cluster where Channel / Subscription are forbidden to all users can't pass the conformance tests and so isn't conformant, even if it's running code which might otherwise be conformant.
and MUST attempt to forward the received events for filtering to each associated | ||
Trigger whose `Ready` condition is `true`. As described in the | ||
[Trigger Lifecycle](#trigger-lifecycle) section, a Broker MAY forward events to | ||
an associated Trigger destination which which does not currently have a `true` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
an associated Trigger destination which which does not currently have a `true` | |
an associated Trigger destination which does not currently have a `true` |
`Ready` condition, including events received by the Broker before the Trigger | ||
was created. | ||
|
||
The annotation `eventing.knative.dev/broker.class` SHOULD be used to select a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does that mean that a platform which ignores the annotation and forces users to use a specific Broker regardless of other installed Knative brokers is considered Knative compliant? Is there a reason this is not a MUST ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
In particular, there's been discussion at KTC about alternate implementations which might or might not use the OSS code. You can imagine an implementation which only offers a single Broker type and ignores the annotation.
It's not clear how, from a conformance-testing point of view, we'd enforce a MUST here.
`spec.delivery.deadLetterSink` as described in | ||
[Destination resolution](#destination-resolution) before setting the `Ready` | ||
condition to `true`. If any of the addressable fields fails resolution, the | ||
Subscription MUST set the `Ready` condition to `false`, and at least one |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason here false
is used while on 219:220 MUST NOT be true
is used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
219-220 says:
if the channel does not exist or its
Ready
condition is nottrue
, the Subscription'sReady
condition MUST NOT betrue
.
There are three values for a condition: true
, false
, and ""
(unknown). If a Channel's Ready
status is unknown, a Subscription's Ready
status could also reasonably be unknown.
Here, we definitively know that there is a problem (resolution failed, i.e. it's not in progress anymore), so we should affirmatively set Ready
to false
, rather than allowing it to be unknown.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question, my the way -- this tri-state nature of conditions is subtle!
`status.physicalSubscription` URIs to the empty string if the corresponding | ||
`spec` reference cannot be resolved. | ||
|
||
At least one of `spec.subscriber` and `spec.reply` MUST be set; if only |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the behavior is equivalent to setting
spec.subscriber
Does that mean that it's a MUST? i.e. the channel controller MUST append to the subscribers the one specified in reply? if so, is there a reason MUST is not used here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once created, the Subscription's `spec.channel` MUST NOT permit updates; to | ||
change the `spec.channel`, the Subscription MUST be deleted and re-created. This | ||
pattern is chosen to make it clear that changing the `spec.channel` is not an | ||
atomic operation, as it might span multiple storage systems. Changes to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I may ask, what do you mean by it might span multiple storage systems here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you change:
spec:
channel:
apiVersion: messaging.knative.dev/v1
kind: Channel
name: foo-kafka
...
to
spec:
channel:
apiVersion: messaging.knative.dev/v1
kind: Channel
name: foo-in-memory
...
Even if the same events are delivered to foo-kafka
and foo-in-memory
, changing the Subscription from one to the other may cause duplicate or missed events from the logical stream.
We could cut this justification, since there's nothing required in that block.
the Subscription or the Channel), the Subscription MUST only set the `Ready` | ||
condition to `true` after the Channel has been configured to send all future | ||
events to the Subscription's `spec.subscriber`. The Channel MAY send some events | ||
to the Subscription before prior to the Subscription's `Ready` condition being |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to the Subscription before prior to the Subscription's
Ready
condition being
Typo, delete prior or before.
No problem, I'm happy to make fix-up PRs (or you can). This started as a clearnup, but I discovered that both the content (all SHOULD requirements) and the structure (mixed control and data plane requirements, schemas by reference). I'm hopeful that all the PRs going forward can be smaller or more focused. 😁 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@evankanderson fwiw, I realized that I had these two questions pending and were not submitted.
Broker can retry event delivery beyond the duration of receiving the event). | ||
|
||
For each event received by the Broker, the Broker MUST evaluate each associated | ||
Trigger **exactly once** (where "associated" means a Trigger with a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason behind this exactly once ? What about cases where the broker introduces some trigger filters optimization and/or caches the filters state? I can imagine for some cases the Broker would choose to not even evaluate any associated Trigger. Am I missing something?
|
||
### Event Delivery | ||
|
||
Once a Trigger or Subscription has decided to deliver an event, it MUST do the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason behind being explicit that:
- The trigger is the deciding component? Can't it be the broker itself in some designs based on the filters?
- That step 1. needs to take place each time a delivery decision is taken? For instance what if object's status are cached and not read for every event delivery?
Signed-off-by: Alfusainey Jallow <alf.jallow@gmail.com>
This builds on #24
Changes
helper.md
andsources.md
, as it's not clear how much here needs to be standardized.broker.md
,channel.md
, andinterfaces.md
) into a singlecontrol-plane.md
file, similar to serving.This should probably be considered a rewrite; there are a number of places where I either clarified or rewrote APIs (in particular,
status
anddeadLetterSink
, which were not handled consistently)./kind cleanup api-change enhancement
Fixes knative/eventing#4595
Release Note
Docs
This may need to search & replace a few links in knative/docs. Assuming that the update looks reasonable, I'll add a PR here to do that in the next day or two.