在之前的文章中,我介绍了如何使用 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-display 和 goodbye-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 的差异在于 app
和 metadata 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 定义发送到了两个消费者。如果需要将事件发送到多个位置,您可以编写定义以将其发送到多个消费者。
试一试!
如果内部事件驱动要发送到您选择的预定义位置,则很容易跟踪。尽情享受在您的集群中使用事件驱动的乐趣吧!
评论已关闭。