Kubernetes event using the API Server Source

This example shows how to wire Kubernetes cluster events, using the API Server Source, for consumption by a function that has been implemented as a Knative Service.

Before you begin

  1. You must have a Knative cluster running both the Serving and Eventing components. To learn how to install the required components, see Installing Knative.

  2. You can follow the steps below to create new files, or you clone a copy from the repo by running:

    1. git clone -b "release-0.13" https://github.com/knative/docs knative-docs
    2. cd knative-docs/docs/eventing/samples/kubernetes-event-source

Deployment Steps

Broker

These instructions assume the namespace default, which you can change to your preferred namespace. If you use a different namespace, you will need to modify all the YAML files deployed in this sample to point at that namespace.

  1. Create the default Broker in your namespace:

    1. kubectl create -f - <<EOF
    2. apiVersion: eventing.knative.dev/v1
    3. kind: Broker
    4. metadata:
    5. name: default
    6. EOF

Service Account

  1. Create a Service Account that the ApiServerSource runs as. The ApiServerSource watches for Kubernetes events and forwards them to the Knative Eventing Broker. Create a file named serviceaccount.yaml and copy the code block below into it.

    1. apiVersion: v1
    2. kind: ServiceAccount
    3. metadata:
    4. name: events-sa
    5. namespace: default
    6. ---
    7. apiVersion: rbac.authorization.k8s.io/v1
    8. kind: ClusterRole
    9. metadata:
    10. name: event-watcher
    11. rules:
    12. - apiGroups:
    13. - ""
    14. resources:
    15. - events
    16. verbs:
    17. - get
    18. - list
    19. - watch
    20. ---
    21. apiVersion: rbac.authorization.k8s.io/v1
    22. kind: ClusterRoleBinding
    23. metadata:
    24. name: k8s-ra-event-watcher
    25. roleRef:
    26. apiGroup: rbac.authorization.k8s.io
    27. kind: ClusterRole
    28. name: event-watcher
    29. subjects:
    30. - kind: ServiceAccount
    31. name: events-sa
    32. namespace: default

    If you want to re-use an existing Service Account with the appropriate permissions, you need to modify the serviceaccount.yaml.

  2. Enter the following command to create the service account from serviceaccount.yaml:

    1. kubectl apply --filename serviceaccount.yaml

Create Event Source for Kubernetes Events

  1. In order to receive events, you have to create a concrete Event Source for a specific namespace. Create a file named k8s-events.yaml and copy the code block below into it.

    1. apiVersion: sources.knative.dev/v1
    2. kind: ApiServerSource
    3. metadata:
    4. name: testevents
    5. namespace: default
    6. spec:
    7. serviceAccountName: events-sa
    8. mode: Resource
    9. resources:
    10. - apiVersion: v1
    11. kind: Event
    12. sink:
    13. ref:
    14. apiVersion: eventing.knative.dev/v1
    15. kind: Broker
    16. name: default

    If you want to consume events from a different namespace or use a different Service Account, you need to modify k8s-events.yaml accordingly.

  2. Enter the following command to create the event source:

    1. kubectl apply --filename k8s-events.yaml

Trigger

In order to check the ApiServerSource is fully working, we will create a simple Knative Service that dumps incoming messages to its log and creates a Trigger from the Broker to that Knative Service.

  1. Create a file named trigger.yaml and copy the code block below into it.

    1. apiVersion: eventing.knative.dev/v1
    2. kind: Trigger
    3. metadata:
    4. name: testevents-trigger
    5. namespace: default
    6. spec:
    7. broker: default
    8. subscriber:
    9. ref:
    10. apiVersion: serving.knative.dev/v1
    11. kind: Service
    12. name: event-display
    13. ---
    14. # This is a very simple Knative Service that writes the input request to its log.
    15. apiVersion: serving.knative.dev/v1
    16. kind: Service
    17. metadata:
    18. name: event-display
    19. namespace: default
    20. spec:
    21. template:
    22. spec:
    23. containers:
    24. - # This corresponds to
    25. # https://github.com/knative/eventing-contrib/tree/main/cmd/event_display/main.go
    26. image: gcr.io/knative-releases/knative.dev/eventing-contrib/cmd/event_display
  2. If the deployed ApiServerSource is pointing at a Broker other than default, modify trigger.yaml by adding spec.broker with the Broker’s name.

  3. Deploy trigger.yaml:

    1. kubectl apply --filename trigger.yaml

Create Events

Create events by launching a pod in the default namespace. Create a busybox container and immediately delete it:

  1. kubectl run busybox --image=busybox --restart=Never -- ls
  2. kubectl delete pod busybox

Verify

We will verify that the Kubernetes events were sent into the Knative eventing system by looking at our message dumper function logs. If you deployed the Trigger, continue using this section. If not, you will need to look downstream yourself:

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

You should see log lines similar to:

  1. ☁️ cloudevents.Event
  2. Validation: valid
  3. Context Attributes,
  4. specversion: 1.0
  5. type: dev.knative.apiserver.resource.update
  6. source: https://10.96.0.1:443
  7. subject: /apis/v1/namespaces/default/events/testevents.15dd3050eb1e6f50
  8. id: e0447eb7-36b5-443b-9d37-faf4fe5c62f0
  9. time: 2020-07-28T16:35:14.172979816Z
  10. datacontenttype: application/json
  11. Extensions,
  12. kind: Event
  13. knativearrivaltime: 2020-07-28T16:35:14.173381505Z
  14. knativehistory: default-kne-trigger-kn-channel.default.svc.cluster.local
  15. name: busybox.1625f7cfa4cd12f8
  16. namespace: default
  17. Data,
  18. {
  19. "apiVersion": "v1",
  20. "count": 1,
  21. "eventTime": null,
  22. "firstTimestamp": "2020-07-28T16:35:14Z",
  23. "involvedObject": {
  24. "apiVersion": "v1",
  25. "fieldPath": "spec.containers{busybox}",
  26. "kind": "Pod",
  27. "name": "busybox",
  28. "namespace": "default",
  29. "resourceVersion": "28987493",
  30. "uid": "1efb342a-737b-11e9-a6c5-42010a8a00ed"
  31. },
  32. "kind": "Event",
  33. "lastTimestamp": "2020-07-28T16:35:14Z",
  34. "message": "Started container",
  35. "metadata": {
  36. "creationTimestamp": "2020-07-28T16:35:14Z",
  37. "name": "busybox.1625f7cfa4cd12f8",
  38. "namespace": "default",
  39. "resourceVersion": "506088",
  40. "selfLink": "/api/v1/namespaces/default/events/busybox.1625f7cfa4cd12f8",
  41. "uid": "7f841049-7979-48db-9cbc-93ed2346a1b5",
  42. },
  43. "reason": "Started",
  44. "reportingComponent": "",
  45. "reportingInstance": "",
  46. "source": {
  47. "component": "kubelet",
  48. "host": "gke-knative-auto-cluster-default-pool-23c23c4f-xdj0"
  49. },
  50. "type": "Normal"
  51. }

Cleanup

You can remove the ServiceAccount, ClusterRoles, ClusterRoleBinding, ApiServerSource, Service and Trigger using:

  1. kubectl --namespace default delete --filename serviceaccount.yaml
  2. kubectl --namespace default delete --filename k8s-events.yaml
  3. kubectl --namespace default delete --filename trigger.yaml