×
Community Blog Knative Eventing Hello World: An Introduction to Knative

Knative Eventing Hello World: An Introduction to Knative

This article illustrates how to obtain events in Knative Eventing and pass them to Knative Serving for consumption using the Kubernetes Event Source example.

By Yuan Yi, Senior Development Engineer at Alibaba Cloud

Event-based driving is one of the core functions of Serverless computing. The event-driven service is ideal to meet the Pay-As-You-Go demand of users. The previous article in this series introduced three essential parts of Knative Eventing - Event Source, Event Processing Model, and Event Consumption.

Moving ahead, it is imperative to understand how events are generated, processed, and consumed through these three components. Using the Kubernetes Event Source example, this article demonstrates how to obtain events in Knative Eventing and pass them to Knative Serving for consumption. It employs the Broker/Trigger model for event processing.

Background

First, let's take a look at the Broker/Trigger event processing model. Starting with v0.5, Knative Eventing defines the Broker and Trigger objects to facilitate easy event filtering.

  • The Broker provides an event set, which is selected through properties. It is responsible for receiving events and forwarding them to subscribers defined by one or more matching Triggers.
  • The Trigger describes filters based on event properties. And, multiple Triggers are created as per the requirements.

The process of Broker/Trigger model is as shown in the following figure.

1

Preparations

Following is the list of requirements to implement the model:

  • Knative Version >= 0.5
  • Knative Serving installed
  • Knative Eventing installed

Procedures

To begin with, let's look at the process of the Kubernetes Event Source sample, as shown in the following figure.

2

Next, let's see how to process operations at various stages.

Create a Service Account

Create a service account for ApiServerSource. This account authorizes ApiServerSource to obtain Kubernetes events.

The serviceaccount.yaml is as follows.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: events-sa
  namespace: default

---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: event-watcher
rules:
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - get
  - list
  - watch

---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: k8s-ra-event-watcher
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: event-watcher
subjects:
- kind: ServiceAccount
  name: events-sa
  namespace: default

Perform the following operations.

kubectl apply --filename serviceaccount.yaml

Create an Event Source

In Knative Eventing, a unified event type is generated by connecting the event source to a third-party system. Currently, multiple data sources, such as ApiServerSource and GitHub, are supported. Here, let's create an ApiServerSource event source to receive and forward Kubernetes events. The k8s-events.yaml is as follows.

apiVersion: sources.eventing.knative.dev/v1alpha1
kind: ApiServerSource
metadata:
  name: testevents
  namespace: default
spec:
  serviceAccountName: events-sa
  mode: Resource
  resources:
  - apiVersion: v1
    kind: Event
  sink:
    apiVersion: eventing.knative.dev/v1alpha1
    kind: Broker
    name: default

The "sink" parameter is used here to specify the event receiver. The Broker and K8S services are supported.

Run the following command.

kubectl apply --filename k8s-events.yaml

Create a Knative Service

First, create an event processing service.

Here, the service only prints the received events. The following snippet shows the processing logic.

package main
import (
    "context"
    "fmt"
    "log"
    cloudevents "github.com/cloudevents/sdk-go"
    "github.com/knative-sample/event-display/pkg/kncloudevents"
)
/*
Example Output:

  cloudevents.Event:
Validation: valid
Context Attributes,
  SpecVersion: 0.2
  Type: dev.knative.eventing.samples.heartbeat
  Source: https://github.com/knative/eventing-sources/cmd/heartbeats/#local/demo
  ID: 3d2b5a1f-10ca-437b-a374-9c49e43c02fb
  Time: 2019-03-14T21:21:29.366002Z
  ContentType: application/json
  Extensions:
    the: 42
    beats: true
    heart: yes
Transport Context,
  URI: /
  Host: localhost:8080
  Method: POST
Data
  {
    "id":162,
    "label":""
  }
*/

func display(event cloudevents.Event) {
    fmt.Printf("Hello World: \n")
    fmt.Printf("cloudevents.Event\n%s", event.String())
}

func main() {
    c, err := kncloudevents.NewDefaultClient()
    if err != nil {
        log.Fatal("Failed to create client, ", err)
    }
    log.Fatal(c.StartReceiver(context.Background(), display))
}

With the above code, easily build your own image. After the image is built, create a simple Knative service to consume events generated by ApiServerSource.

The service.yaml example is shown below.

apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
  name: event-display
  namespace: default
spec:
  template:
    spec:
      containers:
      -  image: {yourrepo}/{yournamespace}/event-display:latest

Run the following command.

kubectl apply --filename service.yaml

Create a Broker

Under the selected namespace, create the default Broker. If you select the default namespace, perform the following operations.

kubectl label namespace default knative-eventing-injection=enabled

Here, the Eventing Controller automatically creates a Broker based on the namespace that sets the knative-eventing-injection=enabled tag. In addition, the default ClusterChannelProvisioner (in-memory) configured by default in the Web hook is used.

Create a Trigger

A Trigger works as a filter between the Broker and the Service. Set some filtering rules for events.

Now, let's create a simple Trigger for the default Broker, and use the Service for the subscription. The trigger.yaml example is given below.

apiVersion: eventing.knative.dev/v1alpha1
kind: Trigger
metadata:
  name: testevents-trigger
  namespace: default
spec:
  subscriber:
    ref:
      apiVersion: serving.knative.dev/v1alpha1
      kind: Service
      name: event-display

Run the following command.

kubectl apply --filename trigger.yaml

Note: If the default Broker is not used, specify the Broker name in the Trigger through spec.broker.

Verify

Run the following command to generate a K8S event.

kubectl run busybox --image=busybox --restart=Never -- ls
kubectl delete pod busybox

Now, execute the following command to check whether the Knative service receives the event.

kubectl get pods
kubectl logs -l serving.knative.dev/service=event-display -c user-container

The log output is similar to the following and indicates that the event is successfully received.

Hello World:  
️  CloudEvent: valid 
Context Attributes,
  SpecVersion: 0.2
  Type: dev.knative.apiserver.resource.add
  Source: https://10.39.240.1:443
  ID: 716d4536-3b92-4fbb-98d9-14bfcf94683f
  Time: 2019-05-10T23:27:06.695575294Z
  ContentType: application/json
  Extensions:
    knativehistory: default-broker-b7k2p-channel-z7mqq.default.svc.cluster.local
    subject: /apis/v1/namespaces/default/events/busybox.159d7608e3a3572c
Transport Context,
  URI: /
  Host: auto-event-display.default.svc.cluster.local
  Method: POST
Data,
  {
    "apiVersion": "v1",
    "count": 1,
    "eventTime": null,
    "firstTimestamp": "2019-05-10T23:27:06Z",
    "involvedObject": {
      "apiVersion": "v1",
      "fieldPath": "spec.containers{busybox}",
      "kind": "Pod",
      "name": "busybox",
      "namespace": "default",
      "resourceVersion": "28987493",
      "uid": "1efb342a-737b-11e9-a6c5-42010a8a00ed"
    },
    "kind": "Event",
    "lastTimestamp": "2019-05-10T23:27:06Z",
    "message": "Started container",
    "metadata": {
      "creationTimestamp": "2019-05-10T23:27:06Z",
      "name": "busybox.159d7608e3a3572c",
      "namespace": "default",
      "resourceVersion": "506088",
      "selfLink": "/api/v1/namespaces/default/events/busybox.159d7608e3a3572c",
      "uid": "2005af47-737b-11e9-a6c5-42010a8a00ed"
    },
    "reason": "Started",
    "reportingComponent": "",
    "reportingInstance": "",
    "source": {
      "component": "kubelet",
      "host": "gke-knative-auto-cluster-default-pool-23c23c4f-xdj0"
    },
    "type": "Normal"
  }

Summary

The above examples show how Knative Eventing generates, handles and consumes events. These illustrations also provide a preliminary understanding of the event handling model in Eventing. This article serves as the reference to define an event consumer service for handling events.

If you are you interested in Knative Eventing and want to know more, then stay tuned to Alibaba Cloud's Blog Channel as we continue our in-depth analysis of Knative Eventing. Upcoming articles include:

  • How to customize the data source Event Source?
  • How to use the third-party message service?
  • How to send messages by mail or DingTalk when a system alarm occurs?

Stay tuned to explore Knative Eventing.

0 0 0
Share on

You may also like

Comments

Related Products