Knative Eventing Delivery Methods


Knative Eventing docs are a little confusing when it comes to different event delivery methods it supports. It talks about event brokers and triggers and it also talks about sources, services, channels, and subscriptions. What to use and when? It’s not clear. Let’s break it down.

Delivery methods

There are 3 distinct methods in Knative:

  1. Simple delivery
  2. Complex delivery with optional reply
  3. Broker and Trigger delivery

Broker and Trigger delivery is what you should care about most of the time. However, the simple and complex delivery have been in Knative for a while and still good to know for what’s happening under the covers.

Simple delivery

In simple delivery, an event source sends messages directly to a service. It’s 1:1 with no delivery guarantees at all:

Simple delivery where a Source directly sends an event to a Service Simple delivery where a Source directly sends an event to a Service

For example, here is a CronJobSource that fires events on a given cron schedule, sending messages directly to a Knative Service:

apiVersion: sources.eventing.knative.dev/v1alpha1
kind: CronJobSource
metadata:
  name: source
spec:
  schedule: "* * * * *"
  data: '{"message": "Hello world from cron!"}'
  sink:
    apiVersion: serving.knative.dev/v1
    kind: Service
    name: service

You can see a full simple delivery example in my Knative Tutorial.

Complex delivery

Complex delivery allows delivery guarantees with channels and 1:n fanout with subscriptions.

Complex delivery with 1:n fanout Complex delivery with 1:n fanout

Source sends a message to a channel. It can be an in-memory channel or a more persistent channel like Kafka channel:

apiVersion: sources.eventing.knative.dev/v1alpha1
kind: CronJobSource
metadata:
  name: source
spec:
  schedule: "\* \* \* \* \*"
  data: '{"message": "Hello world from cron!"}'
  sink:
    apiVersion: messaging.knative.dev/v1alpha1
    kind: InMemoryChannel
    name: channel

Then, services connect to the channel via subscriptions:

apiVersion: messaging.knative.dev/v1alpha1
kind: Subscription
metadata:
  name: subscription1
spec:
  channel:
    apiVersion: messaging.knative.dev/v1alpha1
    kind: InMemoryChannel
    name: channel
  subscriber:
    ref:
      apiVersion: serving.knative.dev/v1
      kind: Service
      name: service1

Complex delivery also allows a service to reply to events with other events:

Complex delivery where Service2 replies an event with another event Complex delivery where Service2 replies an event with another event

In this case, Service2 replies back to incoming event with another event and this gets routed to Service3 via another channel and subscription. Replies are defined as part of the subscription:

apiVersion: messaging.knative.dev/v1alpha1  
kind: Subscription  
metadata:  
  name: subscription2  
spec:  
  channel:  
    apiVersion: messaging.knative.dev/v1alpha1  
    kind: InMemoryChannel  
    name: channel1  
  subscriber:  
    ref:  
      apiVersion: serving.knative.dev/v1  
      kind: Service  
      name: service2  
  reply:  
    ref:  
      apiVersion: messaging.knative.dev/v1alpha1  
      kind: InMemoryChannel  
      name: channel2

You can see a full complex delivery example and complex delivery with reply example in my Knative Tutorial.

Broker and Trigger delivery

Complex Delivery model works but it’s hard to maintain multiple channels, subscriptions and replies. It also does not have the concept for filtering, so services have to filter all messages themselves.

A simpler model to work with is broker and trigger. Broker combines channel, reply, and filter functionality into a single resource. Trigger provides declarative filtering of all events.

In this method, the previous example turns into this:

A broker is injected into the namespace of services and sources. Source sends events to the broker:

apiVersion: sources.eventing.knative.dev/v1alpha1  
kind: CronJobSource  
metadata:  
  name: source  
spec:  
  schedule: "\* \* \* \* \*"  
  data: '{"message": "Hello world from cron!"}'  
  sink:  
    apiVersion: eventing.knative.dev/v1alpha1  
    kind: Broker  
    name: default

Broker is backed by a channel. Services register interest to a certain event type with a trigger:

apiVersion: eventing.knative.dev/v1alpha1  
kind: Trigger  
metadata:  
  name: trigger1  
spec:  
  filter:  
    attributes:  
      type: dev.knative.cronjob.event  
  subscriber:  
    ref:  
      apiVersion: serving.knative.dev/v1  
      kind: Service  
      name: service1

Under the covers, trigger creates subscriptions. Any service can reply back to an incoming event. A reply event routed back through broker and services interested in that type event gets the event:

apiVersion: eventing.knative.dev/v1alpha1  
kind: Trigger  
metadata:  
  name: trigger3  
spec:  
  filter:  
    attributes:  
      type: dev.knative.samples.hifromknative  
  subscriber:  
    ref:  
      apiVersion: serving.knative.dev/v1  
      kind: Service  
      name: service3

You can see a full broker and trigger delivery example in my Knative Tutorial.

As I mentioned before, you’d generally only care about Broker and Trigger in Knative Eventing but I hope this post clarifies different delivery methods and what happens under the covers.

As always, feel free to reach out to me on Twitter, if you have any questions!


See also