Knative Eventing uses the Broker-Trigger model to route and filter events between services. This tutorial deploys a complete event-driven system on ACK: a Knative Service that receives events, a Broker that routes them, a Trigger that connects the two, and a curl command that sends the first event end-to-end.
How it works
Knative Eventing ingests events from external systems and forwards them internally using the CloudEvents standard. The Broker-Trigger model sits at the center: the Broker receives events from any source, and each Trigger subscribes to that Broker, applies an optional filter, and dispatches matching events to a downstream Service.
The architecture consists of six components:
-
Event source — the origin of events, such as a database update or a cloud messaging service.
-
Ingress — receives external events into the Knative cluster.
-
Channel — forwards events within the Broker-Trigger model. Supported channels include ApsaraMQ for Kafka, NATS Streaming, and InMemoryChannel. The default is InMemoryChannel.
-
Broker — routes events from different sources according to the configured Triggers. Supports backends such as NATS and ApsaraMQ for Kafka.
-
Trigger — defines how events are routed to a specific Service. Each Trigger has an event filter and a Service target; only matching events are forwarded.
-
Service — the final processor that executes business logic after receiving events from a Trigger.
Prerequisites
Before you begin, ensure that you have:
-
Knative Serving installed. See Deploy Knative.
-
Knative Eventing installed. See Deploy Knative Eventing.
Step 1: Deploy a Knative Service
Deploy event-display, a Knative Service that receives events and prints their contents to logs. After this step, you will have a running Service ready to consume events.
-
Create a file named
event-display.yamlwith the following content:apiVersion: serving.knative.dev/v1 kind: Service metadata: name: event-display namespace: default spec: template: spec: containers: - image: registry.cn-hangzhou.aliyuncs.com/knative-sample/event-display:v1028 -
Deploy the Service:
kubectl apply -f event-display.yaml -
Verify the Service is ready:
kubectl get ksvcThe expected output is similar to:
NAME URL LATESTCREATED LATESTREADY READY REASON event-display http://event-display.default.example.com event-display-00001 event-display-00001 TrueA
READYvalue ofTrueconfirms the Service is running and ready to receive events. If the Service does not reachReadystate, run the following command to diagnose:kubectl describe ksvc event-display
Step 2: Create a Broker and a Trigger
Create a Broker named default and a Trigger named my-service-trigger. After this step, any event sent to the Broker will be automatically routed to the event-display Service.
Create a Broker
-
Create a file named
broker.yamlwith the following content:apiVersion: eventing.knative.dev/v1 kind: Broker metadata: name: default namespace: default -
Deploy the Broker:
kubectl apply -f broker.yaml -
Verify the Broker is ready:
kubectl get brokerThe expected output is similar to:
NAME URL AGE READY REASON default http://broker-ingress.knative-eventing.svc.cluster.local/default/default 9s TrueThe
URLfield shows where to send events to this Broker. AREADYvalue ofTrueconfirms the Broker is configured correctly. If the Broker does not reachReadystate, run the following command to diagnose:kubectl describe broker default
Create a Trigger
-
Create a file named
trigger.yamlwith the following content:apiVersion: eventing.knative.dev/v1 kind: Trigger metadata: name: my-service-trigger spec: broker: default subscriber: ref: apiVersion: serving.knative.dev/v1 kind: Service name: event-displayThis Trigger has no
filterfield, so it forwards all events sent to thedefaultBroker toevent-display. Omitting the filter is useful for testing and debugging. In production, add a filter to route only specific event types. -
Deploy the Trigger:
kubectl apply -f trigger.yaml -
Verify the Trigger is ready:
kubectl get triggerThe expected output is similar to:
NAME BROKER SUBSCRIBER_URI AGE READY REASON my-service-trigger default http://event-display.default.svc.cluster.local 22s TrueA
READYvalue ofTrueconfirms the Trigger is correctly subscribed to the Broker and will forward events toevent-display. If the Trigger does not reachReadystate, run the following command to diagnose:kubectl describe trigger my-service-trigger
Step 3: Send an event and verify delivery
Send a test event to the Broker and confirm that event-display receives and logs it. This step uses kubectl port-forward to expose the Broker's internal endpoint locally, then sends a CloudEvents-formatted HTTP POST request.
-
Forward the Broker ingress port to your local machine:
kubectl port-forward svc/broker-ingress -n knative-eventing 8080:80 -
In a separate terminal, send a POST request to the Broker:
curl -v "http://localhost:8080/default/default" \ -X POST \ -H "Ce-Id: 536808d3-88be-4077-9d7a-a3f162705f79" \ -H "Ce-Specversion: 1.0" \ -H "Ce-Type: dev.knative.samples.helloworld" \ -H "Ce-Source: dev.knative.samples/helloworldsource" \ -H "Content-Type: application/json" \ -d '{"msg":"Hello World from the curl pod."}'The expected response ends with:
< HTTP/1.1 202 AcceptedA
202 Acceptedresponse confirms the Broker received the request and accepted the event for processing. -
Get the name of the
event-displaypod:kubectl get pods --namespace=default | grep event-displayThe expected output is similar to:
event-display-00001-deployment-766f7b9fd6-gfcz5 2/2 Running 0 3m43s -
View the pod logs to confirm the event was delivered:
kubectl logs event-display-00001-deployment-766f7b9fd6-gfcz5The expected output is similar to:
Defaulted container "user-container" out of: user-container, queue-proxy ☁️ cloudevents.Event Context Attributes, specversion: 1.0 type: dev.knative.samples.helloworld source: dev.knative.samples/helloworldsource id: 536808d3-88be-4077-9d7a-a3f162705f79 datacontenttype: application/json Extensions, knativearrivaltime: 2024-10-28T11:48:56.929517041Z Data, { "msg": "Hello World from the curl pod1." }The log confirms that
event-displayreceived the CloudEvent from the Broker and printed its full contents, including the CloudEvents headers and the JSON payload.
What's next
-
Add a filter to your Trigger to route only specific event types. See Trigger filtering.
-
Replace InMemoryChannel with ApsaraMQ for Kafka or NATS Streaming for production-grade event persistence.
-
Deploy additional Triggers to fan out events to multiple Services.