Knative 初体验:Eventing Hello World

野性酷女 2022-01-11 23:59 291阅读 0赞

作者 | 阿里云智能事业群高级开发工程师 元毅

基于事件驱动是Serveless的核心功能之一,通过事件驱动服务,满足了用户按需付费(Pay-as-you-go)的需求。在之前的文章中我们介绍过 Knative Eventing 由事件源、事件处理模型和事件消费 3 个主要部分构成,那么事件如何通过这 3 个组件产生、处理以及消费呢? 本文通过 Kubernetes Event Source 示例介绍一下 Knative Eventing 中如何获取事件,并且将事件传递给 Serving 进行消费。其中事件处理基于 Broker/Trigger 模型。

背景知识

先了解一下Broker/Trigger 事件处理模型。从 v0.5 开始,Knative Eventing 定义 Broker 和 Trigger 对象,从而能方便的对事件进行过滤。

  • Broker 提供一个事件集,可以通过属性选择该事件集。它负责接收事件并将其转发给由一个或多个匹配 Trigger 定义的订阅者。
  • Trigger 描述基于事件属性的过滤器。同时可以根据需要创建多个 Trigger。

Broker/Tiggger 模型流程处理如图所示:

前置准备

  • Knative 版本 >= 0.5
  • 安装完成 Knative Serving
  • 安装完成 Knative Eventing

操作步骤

先看一下 Kubernetes Event Source 示例处理流程,如图所示:

​​​​​​​

接下来介绍一下各个阶段如何进行操作处理。

创建 Service Account

ApiServerSource 创建 Service Account, 用于授权 ApiServerSource 获取 Kubernetes Events 。

serviceaccount.yaml 如下:

  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复制代码

执行如下操作:

  1. kubectl apply --filename serviceaccount.yaml复制代码

创建 Event Source

Knative Eventing 中 通过 Event Source 对接第三方系统产生统一的事件类型。当前支持 ApiServerSource,GitHub 等多种数据源。这里我们创建一个 ApiServerSource 事件源用于接收 Kubernetes Events 事件并进行转发。k8s-events.yaml 如下:

  1. apiVersion: sources.eventing.knative.dev/v1alpha1
  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. apiVersion: eventing.knative.dev/v1alpha1
  14. kind: Broker
  15. name: default复制代码

这里通过 sink 参数指定事件接收方,支持 Broker 和 k8s service。

执行命令:

  1. kubectl apply --filename k8s-events.yaml复制代码

创建 Knative Service

首先构建你的事件处理服务,可以参考 knative-sample/event-display开源项目。

这里的 Service 服务仅把接收到的事件打印出来,处理逻辑如下:

  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "log"
  6. cloudevents "github.com/cloudevents/sdk-go"
  7. "github.com/knative-sample/event-display/pkg/kncloudevents"
  8. )
  9. /*
  10. Example Output:
  11. cloudevents.Event:
  12. Validation: valid
  13. Context Attributes,
  14. SpecVersion: 0.2
  15. Type: dev.knative.eventing.samples.heartbeat
  16. Source: https://github.com/knative/eventing-sources/cmd/heartbeats/#local/demo
  17. ID: 3d2b5a1f-10ca-437b-a374-9c49e43c02fb
  18. Time: 2019-03-14T21:21:29.366002Z
  19. ContentType: application/json
  20. Extensions:
  21. the: 42
  22. beats: true
  23. heart: yes
  24. Transport Context,
  25. URI: /
  26. Host: localhost:8080
  27. Method: POST
  28. Data
  29. {
  30. "id":162,
  31. "label":""
  32. }
  33. */
  34. func display(event cloudevents.Event) {
  35. fmt.Printf("Hello World: \n")
  36. fmt.Printf("cloudevents.Event\n%s", event.String())
  37. }
  38. func main() {
  39. c, err := kncloudevents.NewDefaultClient()
  40. if err != nil {
  41. log.Fatal("Failed to create client, ", err)
  42. }
  43. log.Fatal(c.StartReceiver(context.Background(), display))
  44. }复制代码

通过上面的代码,可以轻松构建你自己的镜像。镜像构建完成之后,接下来可以创建一个简单的 Knative Service, 用于消费 ApiServerSource 产生的事件。

service.yaml 示例如下:

  1. apiVersion: serving.knative.dev/v1alpha1
  2. kind: Service
  3. metadata:
  4. name: event-display
  5. namespace: default
  6. spec:
  7. template:
  8. spec:
  9. containers:
  10. - image: {yourrepo}/{yournamespace}/event-display:latest复制代码

执行命令:

  1. kubectl apply --filename service.yaml复制代码

创建 Broker

在所选命名空间下,创建 default Broker。假如选择 default 命名空间, 执行操作如下。

  1. kubectl label namespace default knative-eventing-injection=enabled复制代码

这里 Eventing Controller 会根据设置knative-eventing-injection=enabled 标签的 namepace, 自动创建 Broker。并且使用在webhook中默认配置的 ClusterChannelProvisioner(in-memory)。

创建 Trigger

Trigger 可以理解为 Broker 和Service 之间的过滤器,可以设置一些事件的过滤规则。这里为默认的 Broker 创建一个最简单的 Trigger,并且使用 Service 进行订阅。trigger.yaml 示例如下:

  1. apiVersion: eventing.knative.dev/v1alpha1
  2. kind: Trigger
  3. metadata:
  4. name: testevents-trigger
  5. namespace: default
  6. spec:
  7. subscriber:
  8. ref:
  9. apiVersion: serving.knative.dev/v1alpha1
  10. kind: Service
  11. name: event-display复制代码

执行命令:

  1. kubectl apply --filename trigger.yaml复制代码

注意:如果没有使用默认的 Broker, 在 Trigger 中可以通过 spec.broker 指定 Broker 名称。

验证

执行如下命令,生成 k8s events。

  1. kubectl run busybox --image=busybox --restart=Never -- ls
  2. kubectl delete pod busybox复制代码

可以通过下述方式查看 Knative Service 是否接收到事件。

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

日志输出类似下面,说明已经成功接收事件。

  1. Hello World:
  2. CloudEvent: valid
  3. Context Attributes,
  4. SpecVersion: 0.2
  5. Type: dev.knative.apiserver.resource.add
  6. Source: https://10.39.240.1:443
  7. ID: 716d4536-3b92-4fbb-98d9-14bfcf94683f
  8. Time: 2019-05-10T23:27:06.695575294Z
  9. ContentType: application/json
  10. Extensions:
  11. knativehistory: default-broker-b7k2p-channel-z7mqq.default.svc.cluster.local
  12. subject: /apis/v1/namespaces/default/events/busybox.159d7608e3a3572c
  13. Transport Context,
  14. URI: /
  15. Host: auto-event-display.default.svc.cluster.local
  16. Method: POST
  17. Data,
  18. {
  19. "apiVersion": "v1",
  20. "count": 1,
  21. "eventTime": null,
  22. "firstTimestamp": "2019-05-10T23:27:06Z",
  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": "2019-05-10T23:27:06Z",
  34. "message": "Started container",
  35. "metadata": {
  36. "creationTimestamp": "2019-05-10T23:27:06Z",
  37. "name": "busybox.159d7608e3a3572c",
  38. "namespace": "default",
  39. "resourceVersion": "506088",
  40. "selfLink": "/api/v1/namespaces/default/events/busybox.159d7608e3a3572c",
  41. "uid": "2005af47-737b-11e9-a6c5-42010a8a00ed"
  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. }复制代码

总结

相信通过上面的例子你已经了解了 Knative Eventing 如何产生事件、处理事件以及消费事件。对 Eventing 中的事件处理模型也有了初步的了解。当然你可以自己定义一个事件消费服务,来处理事件。

Next

你是否已对 Knative Eventing 产生了兴趣,是否有点意犹未尽的样子? 别急,接下来我们会继续深入分析 Knative Eventing。包括:

  • 如何自定义数据源 Event Source?
  • 如何使用第三方消息服务?
  • 在遇到系统告警时,是否可以通过邮件、钉钉等发送消息?

让我们后续一起探索 Knative Eventing,欢迎持续关注。

本文作者:jessie筱姜

原文链接

本文为云栖社区原创内容,未经允许不得转载。

转载于:https://juejin.im/post/5d089a7e6fb9a07edc0b5898

发表评论

表情:
评论列表 (有 0 条评论,291人围观)

还没有评论,来说两句吧...

相关阅读

    相关 TestNG-Hello World

    最近因为工作需要,要了解TestNG并应用到项目的单元测试和集成测试中。准备写点文章,记录一下对TestNG的使用和了解。这篇文章是这个系列的第一篇,简要介绍TestNG是什么