All Products
Search
Document Center

Container Service for Kubernetes:Send your first event with Knative Eventing

Last Updated:Mar 26, 2026

This tutorial walks you through building a minimal event-driven system on ACK using Knative Eventing's Broker-Trigger model. By the end, you'll have a running event pipeline: a Broker accepts events, a Trigger routes them, and a Knative Service receives and logs them.

How it works

Knative Eventing uses the CloudEvents standard to pass events between components. In the Broker-Trigger model, events flow through three stages:

  1. An event source sends a CloudEvent to a Broker.

  2. The Broker evaluates each event against registered Triggers.

  3. Each Trigger forwards matching events to its subscriber Service.

image

The components in the diagram are:

  • Event Source: The origin of events—an internal system such as a database, or an external service such as a cloud messaging service.

  • Ingress: The entry point that receives external events into the Knative cluster.

  • Channel: The backend transport layer that forwards events within the Broker. Supported options include ApsaraMQ for Kafka, NATS Streaming, and InMemoryChannel. The default is InMemoryChannel.

  • Broker: The event hub. It accepts events from sources and routes them to Triggers based on their configuration. Brokers support multiple backend options such as NATS and ApsaraMQ for Kafka, making event management flexible at scale.

  • Trigger: The routing rule. Each Trigger subscribes to a Broker, applies an optional event filter (by type, source, or other CloudEvent attributes), and forwards matching events to a subscriber Service.

  • Service: The event consumer. It receives routed events from Triggers and executes business logic.

Prerequisites

Before you begin, ensure that you have:

Step 1: Deploy a Knative Service

Deploy event-display, a sample Knative Service that receives events and prints their contents to the log.

  1. Create a file named event-display.yaml with 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
  2. Deploy the Knative Service:

    kubectl apply -f event-display.yaml
  3. Verify the Service is ready:

    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

The event-display Service is now running and ready to receive events. Next, create a Broker to accept events and a Trigger to route them to this Service.

Step 2: Create a Broker and a Trigger

Warning

The default InMemoryChannel-backed Broker is for development and testing only. Do not use it in production. For production workloads, configure a Broker backed by ApsaraMQ for Kafka or another durable channel.

Create a Broker

Create a Broker named default. Events sent to this Broker's endpoint are evaluated against all Triggers subscribed to it.

  1. Create a file named broker.yaml with the following content:

    apiVersion: eventing.knative.dev/v1
    kind: Broker
    metadata:
      name: default
      namespace: default
  2. Deploy the Broker:

    kubectl apply -f broker.yaml
  3. Verify the Broker is ready:

    kubectl get broker

    Expected output:

    NAME      URL                                                                        AGE   READY   REASON
    default   http://broker-ingress.knative-eventing.svc.cluster.local/default/default   9s    True

    The URL in the output is the endpoint for sending events to this Broker.

The Broker is ready, but events sent to it have nowhere to go yet. A Broker is a receptacle for events—without a Trigger, no event gets forwarded anywhere. Create a Trigger to subscribe to the Broker and route events to event-display.

Create a Trigger

  1. Create a file named trigger.yaml with 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-display

    This Trigger subscribes to the default Broker without a filter, so it forwards all events to event-display. To route only specific events, add a filter field with CloudEvent attribute conditions—for example, type: dev.knative.samples.helloworld to match only events of that type.

  2. Deploy the Trigger:

    kubectl apply -f trigger.yaml
  3. Verify the Trigger is ready:

    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 pipeline is in place. The next step sends a test event through it.

Step 3: Send an event and verify delivery

Use kubectl port-forward to expose the Broker's ingress locally, then send a CloudEvent with curl and confirm that event-display received it.

  1. Forward the Broker ingress port to your local machine:

    kubectl port-forward svc/broker-ingress -n knative-eventing 8080:80
  2. In a separate terminal, send a CloudEvent 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."}'

    A 202 Accepted response confirms the Broker received the event:

    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
  3. Get the name of the event-display Pod:

    kubectl get pods --namespace=default | grep event-display

    Output:

    event-display-00001-deployment-766f7b9fd6-gfcz5   2/2     Running   0          3m43s
  4. Check the Pod logs to confirm the event was received:

    kubectl logs event-display-00001-deployment-766f7b9fd6-gfcz5

    Expected output:

    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 shows the full CloudEvent, confirming that the Broker routed the event and event-display received it successfully.