Knative Eventing offers robust event-driven capabilities for serverless applications with its Broker-Trigger model. This component enables event forwarding and filtering, and can be used to orchestrate complex event flows. The Broker-Trigger model is ideal for applications that respond to external or internal triggers, such as automatically sending notifications based on user behaviors and processing data streams from various sources. This topic describes how to build a simple event-driven architecture using Knative Eventing, covering service deployment, message delivery mechanism, and feature verification.
How it works
Knative Eventing provides a comprehensive event model that interfaces with various external event systems. After events are ingested, they are forwarded internally using the Cloud Events standard and are processed using the Broker-Trigger event-driven model.
As shown in the following figure, in the Knative event-driven architecture, the Broker acts as an intermediary for message transmission, while the Trigger automatically initiates workflows under specific conditions. The principle of the Broker-Trigger event-driven model is to have the Trigger subscribe to and filter Broker events, then dispatch the events to the corresponding services for consumption.
Event Source: The origin of events, which can be internal systems such as database updates, or external services such as cloud messaging services.
Ingress: Receives external events into the Knative cluster.
Channel: In Knative Eventing, using the Broker-Trigger model requires selecting an appropriate channel, which forwards events. Supported event forwarding channels include ApsaraMQ for Kafka, NATS Streaming, and InMemoryChannel. The default channel is InMemoryChannel.
Broker: Acts as the event intermediary, routing events from different sources according to the configured Trigger. Brokers can implement complex event flows and processing logic, supporting multiple protocols and backend event services such as NATS and ApsaraMQ for Kafka, making event management and distribution more flexible and efficient.
Trigger: Defines how events are routed to specific Services. Each Trigger is associated with an event filter, usually based on event type or content, and a Service target. Only events that match the filter criteria are sent to the specified Service.
Service: The final processor of events. After receiving events routed by Triggers, it executes the corresponding business logic.
Prerequisites
Knative Serving and Knative Eventing are installed. For more information, see Deploy Knative and Deploy Knative Eventing.
The following sections describe the process of building a basic event-driven system using the Knative Eventing framework, including the creation, transmission, and consumption of events.
Step 1: Deploy a Knative Service
This section uses event-display
as an example of a Knative Service. The primary responsibility of event-display
is to receive events and print their contents.
Use the following YAML template to create a Knative Service:
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 Knative Service.
kubectl apply -f event-display.yaml
Verify whether the Knative Service is created.
kubectl get ksvc
Expected output:
NAME URL LATESTCREATED LATESTREADY READY REASON event-display http://event-display.default.example.com event-display-00001 event-display-00001 True
Step 2: Create a Broker and a Trigger
Create a Broker named default
and a Trigger named my-service-trigger
. The Trigger ensures that events not explicitly handled are routed to the event-display
Service deployed in Step 1.
Create a Broker.
Use the following YAML template to create a Broker:
apiVersion: eventing.knative.dev/v1 kind: Broker metadata: name: default namespace: default
Deploy the Broker.
kubectl apply -f broker.yaml
Verify whether the Broker is created.
kubectl get broker
Expected output:
NAME URL AGE READY REASON default http://broker-ingress.knative-eventing.svc.cluster.local/default/default 9s True
The output displays the information and URL of the Broker. The URL indicates where to send events.
Create a Trigger.
Create a Trigger with the sample code below.
Subscribe to the default Broker to route events to the
event-display
Service.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-display
The
my-service-trigger
created by the preceding YAML template is linked to thedefault Broker
and specifies theevent-display
Service as a subscriber. This means that any events sent to thedefault Broker
, provided that no other specific Triggers are specified to handle them, will be forwarded to theevent-display
Service.Deploy the Trigger.
kubectl apply -f trigger.yaml
Verify whether the Trigger is created.
kubectl get trigger
Expected output:
NAME BROKER SUBSCRIBER_URI AGE READY REASON my-service-trigger default http://event-display.default.svc.cluster.local 22s True
The output indicates that the Trigger is ready, which means that the Trigger is configured correctly and can receive and route events.
Step 3: Send events and verify if the Service can receive events
Simulate event triggering by sending an HTTP POST request directly to the Broker from an external source. Use the curl
command to send a request with specific CloudEvents headers to the Broker, and verify if the event-display
Service receives this message and prints it as expected.
Retrieve the event request address from the Broker using
broker-ingress.knative-eventing
. By sending event requests to the Broker, confirm that the Broker Service in the Knative Eventing system is correctly configured and can receive events.Use the
port-forward
function of kubectl to forward the internal Service port within the cluster to the local machine, allowing access to the Service.kubectl port-forward svc/broker-ingress -n knative-eventing 8080:80
Use the
curl
command to send a POST request to the local port 8080 to verify that the Service can correctly receive and process the request.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."}'
Expected output:
Note: Unnecessary use of -X or --request, POST is already inferred. * Trying 127.0.0.1:8080... * Connected to localhost (127.0.0.1) port 8080 (#0) > POST /default/default HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/8.1.2 > Accept: */* > Ce-Id: 53****3-88be-4077-9d7a-a3f162******9 > Ce-Specversion: 1.0 > Ce-Type: dev.knative.samples.helloworld > Ce-Source: dev.knative.samples/helloworldsource > Content-Type: application/json > Content-Length: 40 > < HTTP/1.1 202 Accepted < Allow: POST, OPTIONS < Date: Tue, 15 Oct 2024 09:36:42 GMT < Content-Length: 0 < * Connection #0 to host localhost left intact
The expected output confirms that the Service has correctly received the POST request sent to
http://localhost:8080/default/default
and has returned a202 Accepted
status code, indicating that the request has been accepted.
Inspect the logs of the
event-display
pod to confirm the event source.Retrieve details about the
event-display
pod and view its logs.kubectl get pods --namespace=default | grep event-display # The output is as follows: event-display-00001-deployment-766f7b9fd6-gfcz5 2/2 Running 0 3m43s
View the logs.
kubectl logs event-display-00001-deployment-766f7b9fd6-gfcz5 # The log output is as follows: 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 expected output indicates that an application running on Kubernetes is receiving CloudEvents events from the Knative Samples Hello World source, and that it is printing the contents of these events.