在之前的文章中,我介绍了如何使用 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: 8080goodbye-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: 0202 表示触发器将其发送到 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: 0hello-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 定义发送到了两个消费者。如果需要将事件发送到多个位置,您可以编写定义以将其发送到多个消费者。
试一试!
如果内部事件驱动要发送到您选择的预定义位置,则很容易跟踪。尽情享受在您的集群中使用事件驱动的乐趣吧!
 
 
 
 
 
 
 
 

评论已关闭。