The Broker and Trigger CRDs, both in eventing.knative.dev/v1alpha1
, are
interdependent.
Broker represents an 'event mesh'. Events are sent to the Broker's ingress and are then sent to any subscribers that are interested in that event. Once inside a Broker, all metadata other than the CloudEvent is stripped away (e.g. unless set as a CloudEvent attribute, there is no concept of how this event entered the Broker).
Example:
apiVersion: eventing.knative.dev/v1alpha1
kind: Broker
metadata:
name: default
spec:
channelTemplate:
provisioner:
apiVersion: eventing.knative.dev/v1alpha1
kind: ClusterChannelProvisioner
name: gcp-pubsub
Trigger represents a desire to subscribe to events from a specific Broker. Basic filtering on the types of events is provided.
Example:
apiVersion: eventing.knative.dev/v1alpha1
kind: Trigger
metadata:
name: my-service-trigger
spec:
filter:
sourceAndType:
type: dev.knative.foo.bar
subscriber:
ref:
apiVersion: serving.knative.dev/v1alpha1
kind: Service
name: my-service
There are two ways to create a Broker, via namespace annotation or manual setup.
Normally the namespace annotation is used to do this setup.
The easiest way to get started, is to annotate your namespace (replace default
with the desired namespace):
kubectl label namespace default knative-eventing-injection=enabled
This should automatically create the default
Broker
in that namespace.
kubectl -n default get broker default
In order to setup a Broker
manually, we must first create the required
ServiceAccount
and give it the proper RBAC permissions. This setup is required
once per namespace. These instructions will use the default
namespace, but you
can replace it with any namespace you want to install a Broker
into.
Create the ServiceAccount
.
kubectl -n default create serviceaccount eventing-broker-filter
Then give it the needed RBAC permissions:
kubectl -n default create rolebinding eventing-broker-filter \
--clusterrole=eventing-broker-filter \
--user=eventing-broker-filter
Note that the previous commands uses three different objects, all named
eventing-broker-filter
. The ClusterRole
is installed with Knative Eventing
here. The ServiceAccount
was
created two commands prior. The RoleBinding
is created with this command.
Now we can create the Broker
. Note that this example uses the name default
,
but could be replaced by any other valid name.
cat << EOF | kubectl apply -f -
apiVersion: eventing.knative.dev/v1alpha1
kind: Broker
metadata:
namespace: default
name: default
EOF
Now create some function that wants to receive those events. This document will
assume the following, but it could be anything that is Addressable
.
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: my-service
namespace: default
spec:
runLatest:
configuration:
revisionTemplate:
spec:
container:
# This corresponds to
# https://github.com/knative/eventing-sources/blob/v0.2.1/cmd/message_dumper/dumper.go.
image: gcr.io/knative-releases/github.com/knative/eventing-sources/cmd/message_dumper@sha256:ab5391755f11a5821e7263686564b3c3cd5348522f5b31509963afb269ddcd63
Create a Trigger
that sends only events of a particular type to my-service
:
apiVersion: eventing.knative.dev/v1alpha1
kind: Trigger
metadata:
name: my-service-trigger
namespace: default
spec:
filter:
sourceAndType:
type: dev.knative.foo.bar
subscriber:
ref:
apiVersion: serving.knative.dev/v1alpha1
kind: Service
name: my-service
The Webhook will default certain unspecified fields. For example if
spec.broker
is unspecified, it will default to default
. If
spec.filter.sourceAndType.type
or spec.filter.sourceAndType.Source
are
unspecified, then they will default to the special value Any
, which matches
everything.
The Webhook will default the YAML above to:
apiVersion: eventing.knative.dev/v1alpha1
kind: Trigger
metadata:
name: my-service-trigger
namespace: default
spec:
broker: default # Defaulted by the Webhook.
filter:
sourceAndType:
type: dev.knative.foo.bar
source: Any # Defaulted by the Webhook.
subscriber:
ref:
apiVersion: serving.knative.dev/v1alpha1
kind: Service
name: my-service
You can make multiple Trigger
s on the same Broker
corresponding to different
types, sources, and subscribers.
Now have something emit an event of the correct type (dev.knative.foo.bar
)
into the Broker
. We can either do this manually or with a normal Knative
Source.
The Broker
's address is well known, it will always be
<name>-broker.<namespace>.svc.<ending>
. In our case, it is
default-broker.default.svc.cluster.local
.
While SSHed into a Pod
with the Istio sidecar, run:
curl -v "http://default-broker.default.svc.cluster.local/" \
-X POST \
-H "X-B3-Flags: 1" \
-H "CE-CloudEventsVersion: 0.1" \
-H "CE-EventType: dev.knative.foo.bar" \
-H "CE-EventTime: 2018-04-05T03:56:24Z" \
-H "CE-EventID: 45a8b444-3213-4758-be3f-540bf93f85ff" \
-H "CE-Source: dev.knative.example" \
-H 'Content-Type: application/json' \
-d '{ "much": "wow" }'
Provide the Knative Source the default
Broker
as its sink:
apiVersion: sources.eventing.knative.dev/v1alpha1
kind: ContainerSource
metadata:
name: heartbeats-sender
spec:
image: github.com/knative/eventing-sources/cmd/heartbeats/
sink:
apiVersion: eventing.knative.dev/v1alpha1
kind: Broker
name: default
Broker and Trigger are intended to be black boxes. How they are implemented should not matter to the end user. This section describes the specific implementation that is currently in the repository. However, the implmentation may change at any time, absolutely no guarantees are made about the implmentation.
Namespaces are reconciled by the
Namespace Reconciler. The Namespace Reconciler
looks for all namespace
s that have the label
knative-eventing-injection: enabled
. If that label is present, then the
Namespace Reconciler
reconciles:
- Creates the Broker Filter's
ServiceAccount
,eventing-broker-filter
. - Ensures that
ServiceAccount
has the requisite RBAC permissions by giving it theeventing-broker-filter
Role
. - Creates a
Broker
nameddefault
.
Broker
s are reconciled by the
Broker Reconciler. For each Broker
, it
reconciles:
- The 'everything'
Channel
. This is aChannel
that all events in theBroker
are sent to. Anything that passes theBroker
's Ingress is sent to thisChannel
. AllTrigger
s subscribe to thisChannel
. - The 'filter'
Deployment
. TheDeployment
runs cmd/broker/filter. Its purpose is the data plane for allTrigger
s related to thisBroker
.- This piece is very similar to the existing Channel dispatchers, in that
all
Trigger
s for a givenBroker
route to this singleDeployment
. The code inspects the Host header to determine whichTrigger
the request is related to and then carries it out. - Internally this binary uses the pkg/broker library.
- This piece is very similar to the existing Channel dispatchers, in that
all
- The 'filter' Kubernetes
Service
. ThisService
points to the 'filter'Deployment
. - The 'ingress'
Deployment
. TheDeployment
runs cmd/broker/ingress. Its purpose is to inspect all events that are entering theBroker
. - The 'ingress' Kubernetes
Service
. ThisService
points to the 'ingress'Deployment
. ThisService
's address is the address given for theBroker
.
Trigger
s are reconciled by the
Trigger Reconciler. For each Trigger
,
it reconciles:
- Determines the subscriber's URI.
- Currently uses the same logic as the
Subscription
Reconciler, so supports Addressables and KubernetesService
s.
- Currently uses the same logic as the
- Creates a Kubernetes
Service
and IstioVirtualService
pair. This allows all Istio enabledPod
s to send to theTrigger
's address.- This is the same as the current
Channel
implementation. TheService
points nowhere. TheVirtualService
reroutes requests that originally went to theService
, to instead go to theBroker
's 'filter'Service
.
- This is the same as the current
- Creates
Subscription
from theBroker
's 'everything'Channel
to theTrigger
's KubernetesService
.