Knative 事件驱动分步指南

Knative 事件驱动是一种在云原生环境中创建、发送和验证事件的方法。
75 位读者喜欢这篇文章。
Computer laptop in space

Opensource.com

在之前的文章中,我介绍了如何使用 Knative 创建小型应用程序,Knative 是一个开源项目,它向 Kubernetes 添加组件,用于部署、运行和管理无服务器、云原生应用程序。在本文中,我将解释 Knative 事件驱动,这是一种在云原生环境中创建、发送和验证事件的方法。

事件可以从您环境中的许多来源生成,并且可能难以管理或定义。由于 Knative 遵循 CloudEvents 规范,因此它允许您为您的环境设置一个通用的抽象点,在该点中,事件被定义为一个规范。

本文介绍了如何安装 Knative 事件驱动 0.20.0 版本,以及如何创建、触发和验证事件。由于涉及许多步骤,我建议您查看我的 GitHub 仓库,以便对照文件阅读本文。

设置您的配置

本演练使用带有 Kubernetes 1.19.0 的 Minikube。它还对 Minikube 环境进行了一些配置更改。

Minikube 预配置命令

$ minikube config set kubernetes-version v1.19.0
$ minikube config set memory 4000
$ minikube config set cpus 4

在启动 Minikube 之前,运行以下命令以确保您的配置保持不变并启动 Minikube

$ minikube delete
$ minikube start

安装 Knative 事件驱动

使用 kubectl 安装 Knative 事件驱动自定义资源定义 (CRD)。以下显示了命令和输出片段

$ kubectl apply --filename https://github.com/knative/eventing/releases/download/v0.20.0/eventing-crds.yaml

customresourcedefinition.apiextensions.k8s.io/apiserversources.sources.knative.dev created
customresourcedefinition.apiextensions.k8s.io/brokers.eventing.knative.dev created
customresourcedefinition.apiextensions.k8s.io/channels.messaging.knative.dev created
customresourcedefinition.apiextensions.k8s.io/triggers.eventing.knative.dev created

接下来,使用 kubectl 安装核心组件

$ kubectl apply --filename https://github.com/knative/eventing/releases/download/v0.20.0/eventing-core.yaml
namespace/knative-eventing created
serviceaccount/eventing-controller created
clusterrolebinding.rbac.authorization.k8s.io/eventing-controller created

由于您正在运行 Knative 事件驱动服务的独立版本,因此您必须安装内存通道以传递事件。使用 kubectl,运行

$ kubectl apply --filename https://github.com/knative/eventing/releases/download/v0.20.0/in-memory-channel.yaml

安装 broker,它利用通道并运行事件路由

$ kubectl apply --filename https://github.com/knative/eventing/releases/download/v0.20.0/mt-channel-broker.yaml
clusterrole.rbac.authorization.k8s.io/knative-eventing-mt-channel-broker-controller created
clusterrole.rbac.authorization.k8s.io/knative-eventing-mt-broker-filter created

接下来,创建一个命名空间并向其中添加一个小型 broker;此 broker 将事件路由到触发器。使用 kubectl 创建您的命名空间

$ kubectl create namespace eventing-test
namespace/eventing-test created

现在在您的命名空间中创建一个名为 default 的小型 broker。以下是我的 broker.yaml 文件(可以在我的 GitHub 仓库中找到)中的 YAML

apiVersion: eventing.knative.dev/v1
kind: broker
metadata:
  name: default
  namespace: eventing-test

然后使用 kubectl 应用您的 broker 文件

$ kubectl create -f broker.yaml
   broker.eventing.knative.dev/default created

验证一切都已启动并正在运行(在您运行命令后,您应该看到确认输出)

$ kubectl -n eventing-test get broker default                                                              
NAME      URL                                                                              AGE    READY   REASON
default   http://broker-ingress.knative-eventing.svc.cluster.local/eventing-test/default   3m6s   True

稍后发送事件时,您将需要 broker 输出中的此 URL,因此请保存它。

创建事件消费者

现在一切都已安装,您可以开始配置组件以处理事件。

首先,您需要创建事件消费者。在本演练中,您将创建两个消费者:hello-displaygoodbye-display。拥有两个消费者允许您了解如何针对每个事件消息定位消费者。

hello-display YAML 代码

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-display
spec:
  replicas: 1
  selector:
    matchLabels: &labels
      app: hello-display
  template:
    metadata:
      labels: *labels
    spec:
      containers:
        - name: event-display
          image: gcr.io/knative-releases/knative.dev/eventing-contrib/cmd/event_display

---

kind: Service
apiVersion: v1
metadata:
  name: hello-display
spec:
  selector:
    app: hello-display
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

goodbye-display YAML 代码

apiVersion: apps/v1
kind: Deployment
metadata:
  name: goodbye-display
spec:
  replicas: 1
  selector:
    matchLabels: &labels
      app: goodbye-display
  template:
    metadata:
      labels: *labels
    spec:
      containers:
        - name: event-display
          # Source code: https://github.com/knative/eventing-contrib/tree/master/cmd/event_display
          image: gcr.io/knative-releases/knative.dev/eventing-contrib/cmd/event_display

---

kind: Service
apiVersion: v1
metadata:
  name: goodbye-display
spec:
  selector:
    app: goodbye-display
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

两个消费者之间 YAML 的差异在于 appmetadata name 部分。虽然两个消费者都在相同的端口上,但您可以在生成事件时定位其中一个。使用 kubectl 创建消费者

$ kubectl -n eventing-test apply -f hello-display.yaml
deployment.apps/hello-display created
service/hello-display created

$ kubectl -n eventing-test apply -f goodbye-display.yaml
deployment.apps/goodbye-display created
service/goodbye-display created

在应用 YAML 文件后,检查以确保部署正在运行

$ kubectl -n eventing-test get deployments hello-display goodbye-display
NAME              READY   UP-TO-DATE   AVAILABLE   AGE
hello-display     1/1     1            1           2m4s
goodbye-display   1/1     1            1           34s

创建触发器

现在,您需要创建触发器,它们定义消费者接收的事件。您可以定义触发器以使用来自您的云事件的任何过滤器。broker 从触发器接收事件并将事件发送到正确的消费者。这组示例创建了两个具有不同定义的触发器。例如,您可以将属性类型为 greeting 的事件发送到 hello-display 消费者。

greeting-trigger.yaml 代码

apiVersion: eventing.knative.dev/v1
kind: Trigger
metadata:
  name: hello-display
spec:
  broker: default
  filter:
    attributes:
      type: greeting
  subscriber:
    ref:
     apiVersion: v1
     kind: Service
     name: hello-display

要创建第一个触发器,请应用您的 YAML 文件

$ kubectl -n eventing-test apply -f greeting-trigger.yaml
trigger.eventing.knative.dev/hello-display created

接下来,使用 sendoff-trigger.yaml 创建第二个触发器。这将把任何属性为 source sendoff 的内容发送到您的 goodbye-display 消费者。

sendoff-trigger.yaml 代码

apiVersion: eventing.knative.dev/v1
kind: Trigger
metadata:
  name: goodbye-display
spec:
  broker: default
  filter:
    attributes:
      source: sendoff
  subscriber:
    ref:
      apiVersion: v1
      kind: Service
      name: goodbye-display

接下来,将您的第二个触发器定义应用于集群

$ kubectl -n eventing-test apply -f sendoff-trigger.yaml
trigger.eventing.knative.dev/goodbye-display created

通过使用 kubectl 从集群获取您的触发器来确认一切都已正确就位

$ kubectl -n eventing-test get triggers
NAME              BROKER    SUBSCRIBER_URI                                            AGE   READY   
goodbye-display   default   http://goodbye-display.eventing-test.svc.cluster.local/   24s   True    
hello-display     default   http://hello-display.eventing-test.svc.cluster.local/     46s   True

创建事件生产者

创建一个 pod,您可以使用它来发送事件。这是一个简单的 pod 部署,带有 curl 和 SSH 访问权限,供您使用 curl 发送事件。由于 broker 只能从安装了 Knative 事件驱动的集群内部访问,因此 pod 需要位于集群中;这是将事件发送到集群中的唯一方法。使用带有此代码的 event-producer.yaml 文件

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: curl
  name: curl
spec:
  containers:
    - image: radial/busyboxplus:curl
      imagePullPolicy: IfNotPresent
      name: curl
      resources: {}
      stdin: true
      terminationMessagePath: /dev/termination-log
      terminationMessagePolicy: File
      tty: true

接下来,使用 kubectl 部署 pod

$ kubectl -n eventing-test apply -f event-producer.yaml
pod/curl created

要验证,请获取部署并确保 pod 已启动并正在运行

$ kubectl get pods -n eventing-test
NAME                               READY   STATUS    RESTARTS   AGE
curl                               1/1     Running   0          8m13s

发送一些事件

由于本文的配置量很大,我想象您会很高兴终于能够发送一些事件并测试您的服务。事件必须在集群内部传递。通常,事件将围绕集群内部的应用程序定义,并来自这些应用程序。但此示例将从您名为 curl 的 pod 手动发送事件。

首先登录到 pod

$ kubectl -n eventing-test attach curl -it

登录后,您将看到类似于以下的输出

Defaulting container name to curl.
Use 'kubectl describe pod/curl -n eventing-test' to see all of the containers in this pod.
If you don't see a command prompt, try pressing enter.
[ root@curl:/ ]$

现在,使用 curl 生成一个事件。这需要一些额外的定义,并且需要安装期间生成的 broker URL。此示例向 broker 发送问候语

curl -v "http://broker-ingress.knative-eventing.svc.cluster.local/eventing-test/default" \
  -X POST \
  -H "Ce-Id: say-hello" \
  -H "Ce-Specversion: 1.0" \
  -H "Ce-Type: greeting" \
  -H "Ce-Source: not-sendoff" \
  -H "Content-Type: application/json" \
  -d '{"msg":"Hello Knative!"}'

Ce 是 CloudEvent 的缩写,它是 Knative 遵循的 标准化的 CloudEvents 规范。您还需要知道事件 ID(这对于验证它是否已传递很有用)、类型、源(必须指定它不是 sendoff,这样它就不会发送到 sendoff 触发器中定义的源)和消息。

当您运行命令时,这应该是输出(并且您应该收到 202 Accepted 响应)

> POST /eventing-test/default HTTP/1.1
> User-Agent: curl/7.35.0
> Host: broker-ingress.knative-eventing.svc.cluster.local
> Accept: */*
> Ce-Id: say-hello
> Ce-Specversion: 1.0
> Ce-Type: greeting
> Ce-Source: not-sendoff
> Content-Type: application/json
> Content-Length: 24
>
< HTTP/1.1 202 Accepted
< Date: Sun, 24 Jan 2021 22:25:25 GMT
< Content-Length: 0

202 表示触发器将其发送到 hello-display 消费者(由于定义)。

接下来,使用此新 curl 命令向 goodbye-display 消费者发送第二个定义

curl -v "http://broker-ingress.knative-eventing.svc.cluster.local/eventing-test/default" \
  -X POST \
  -H "Ce-Id: say-goodbye" \
  -H "Ce-Specversion: 1.0" \
  -H "Ce-Type: not-greeting" \
  -H "Ce-Source: sendoff" \
  -H "Content-Type: application/json" \
  -d '{"msg":"Goodbye Knative!"}'

这一次,它是 sendoff 而不是问候语,这基于前面设置部分中的触发器定义。它被定向到 goodbye-display 消费者。

您的输出应如下所示,并返回另一个 202

> POST /eventing-test/default HTTP/1.1
> User-Agent: curl/7.35.0
> Host: broker-ingress.knative-eventing.svc.cluster.local
> Accept: */*
> Ce-Id: say-goodbye
> Ce-Specversion: 1.0
> Ce-Type: not-greeting
> Ce-Source: sendoff
> Content-Type: application/json
> Content-Length: 26
>
< HTTP/1.1 202 Accepted
< Date: Sun, 24 Jan 2021 22:33:00 GMT
< Content-Length: 0

恭喜,您发送了两个事件!

在继续下一节之前,键入 exit 退出 pod。

验证事件

现在事件已发送,您如何知道正确的消费者收到了它们?通过转到每个消费者并在日志中验证它。

hello-display 消费者开始:

$ kubectl -n eventing-test logs -l app=hello-display --tail=100

此示例集群中没有太多运行的东西,因此您应该只看到一个事件

☁️  cloudevents.Event
Validation: valid
Context Attributes,
  specversion: 1.0
  type: greeting
  source: not-sendoff
  id: say-hello
  datacontenttype: application/json
Extensions,
  knativearrivaltime: 2021-01-24T22:25:25.760867793Z
Data,
  {
    "msg": "Hello Knative!"
  }

您已确认 hello-display 消费者收到了事件!现在检查 goodbye-display 消费者并确保另一条消息已到达。

首先运行相同的命令,但使用 goodbye-display

$ kubectl -n eventing-test logs -l app=goodbye-display --tail=100
☁️  cloudevents.Event
Validation: valid
Context Attributes,
  specversion: 1.0
  type: not-greeting
  source: sendoff
  id: say-goodbye
  datacontenttype: application/json
Extensions,
  knativearrivaltime: 2021-01-24T22:33:00.515716701Z
Data,
  {
    "msg": "Goodbye Knative!"
  }

看起来两个事件都到达了它们各自的位置。恭喜您——您已正式使用 Knative 事件驱动!

奖励环节:向多个消费者发送事件

因此,您使用 curl 向每个消费者发送了事件,但是如果您想向两个消费者都发送事件怎么办?这使用了类似的 curl 命令,但有一些有趣的更改。在之前的触发器中,每个触发器都用不同的属性定义。greeting 触发器具有属性 type,sendoff 触发器具有属性 source。这意味着您可以进行 curl 调用并将其发送给两个消费者。

这是一个 curl 示例,演示了如何定义将事件发送到两个消费者

curl -v "http://broker-ingress.knative-eventing.svc.cluster.local/eventing-test/default" \
  -X POST \
  -H "Ce-Id: say-hello-goodbye" \
  -H "Ce-Specversion: 1.0" \
  -H "Ce-Type: greeting" \
  -H "Ce-Source: sendoff" \
  -H "Content-Type: application/json" \
  -d '{"msg":"Hello Knative! Goodbye Knative!"}'

如您所见,此 curl 命令的定义已更改为将 source 设置为 goodbye-display,并将 type 设置为 hello-display

以下是事件发送后的外观示例输出。

正在发送的事件的输出

> POST /eventing-test/default HTTP/1.1
> User-Agent: curl/7.35.0
> Host: broker-ingress.knative-eventing.svc.cluster.local
> Accept: */*
> Ce-Id: say-hello-goodbye
> Ce-Specversion: 1.0
> Ce-Type: greeting
> Ce-Source: sendoff
> Content-Type: application/json
> Content-Length: 41
>
< HTTP/1.1 202 Accepted
< Date: Sun, 24 Jan 2021 23:04:15 GMT
< Content-Length: 0

hello-display 的输出(显示两个事件)

$ kubectl -n eventing-test logs -l app=hello-display --tail=100
☁️  cloudevents.Event
Validation: valid
Context Attributes,
  specversion: 1.0
  type: greeting
  source: not-sendoff
  id: say-hello
  datacontenttype: application/json
Extensions,
  knativearrivaltime: 2021-01-24T22:25:25.760867793Z
Data,
  {
    "msg": "Hello Knative!"
  }
☁️  cloudevents.Event
Validation: valid
Context Attributes,
  specversion: 1.0
  type: greeting
  source: sendoff
  id: say-hello-goodbye
  datacontenttype: application/json
Extensions,
  knativearrivaltime: 2021-01-24T23:04:15.036352685Z
Data,
  {
    "msg": "Hello Knative! Goodbye Knative!"
  }

goodbye-display 的输出(也包含两个事件)

$ kubectl -n eventing-test logs -l app=goodbye-display --tail=100
☁️  cloudevents.Event
Validation: valid
Context Attributes,
  specversion: 1.0
  type: not-greeting
  source: sendoff
  id: say-goodbye
  datacontenttype: application/json
Extensions,
  knativearrivaltime: 2021-01-24T22:33:00.515716701Z
Data,
  {
    "msg": "Goodbye Knative!"
  }
☁️  cloudevents.Event
Validation: valid
Context Attributes,
  specversion: 1.0
  type: greeting
  source: sendoff
  id: say-hello-goodbye
  datacontenttype: application/json
Extensions,
  knativearrivaltime: 2021-01-24T23:04:15.036352685Z
Data,
  {
    "msg": "Hello Knative! Goodbye Knative!"
  }

如您所见,事件根据您的 curl 定义发送到了两个消费者。如果需要将事件发送到多个位置,您可以编写定义以将其发送到多个消费者。

试一试!

如果内部事件驱动要发送到您选择的预定义位置,则很容易跟踪。尽情享受在您的集群中使用事件驱动的乐趣吧!

接下来阅读什么
User profile image.
科技游民,从事我能找到的任何工作。IT 领域孤岛预防的倡导者,与所有团队共享信息的重要性。相信教育所有人并开源开发。热爱所有科技事物。关于 K8s、混沌以及我能找到的任何新的和闪亮的东西!Mastodon ID

评论已关闭。

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 获得许可。
© . All rights reserved.