Knative 初體驗:Eventing Hello World

基於事件驅動是 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 如下:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: events-sa
  namespace: default

---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: event-watcher
rules:
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - get
  - list
  - watch

---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: k8s-ra-event-watcher
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: event-watcher
subjects:
- kind: ServiceAccount
  name: events-sa
  namespace: default

執行如下操作:

kubectl apply --filename serviceaccount.yaml

創建 Event Source

Knative Eventing 中 通過 Event Source 對接第三方系統產生統一的事件類型。當前支持 ApiServerSource,GitHub 等多種數據源。這裏我們創建一個 ApiServerSource 事件源用於接收 Kubernetes Events 事件並進行轉發。k8s-events.yaml 如下:

apiVersion: sources.eventing.knative.dev/v1alpha1
kind: ApiServerSource
metadata:
  name: testevents
  namespace: default
spec:
  serviceAccountName: events-sa
  mode: Resource
  resources:
  - apiVersion: v1
    kind: Event
  sink:
    apiVersion: eventing.knative.dev/v1alpha1
    kind: Broker
    name: default

這裏通過 sink 參數指定事件接收方,支持 Broker 和 k8s service。

執行命令:

kubectl apply --filename k8s-events.yaml

創建 Knative Service

首先構建你的事件處理服務,可以參考 knative-sample/event-display開源項目。

這裏的 Service 服務僅把接收到的事件打印出來,處理邏輯如下:

package main
import (
    "context"
    "fmt"
    "log"
    cloudevents "github.com/cloudevents/sdk-go"
    "github.com/knative-sample/event-display/pkg/kncloudevents"
)
/*
Example Output:

☁  cloudevents.Event:
Validation: valid
Context Attributes,
  SpecVersion: 0.2
  Type: dev.knative.eventing.samples.heartbeat
  Source: https://github.com/knative/eventing-sources/cmd/heartbeats/#local/demo
  ID: 3d2b5a1f-10ca-437b-a374-9c49e43c02fb
  Time: 2019-03-14T21:21:29.366002Z
  ContentType: application/json
  Extensions:
    the: 42
    beats: true
    heart: yes
Transport Context,
  URI: /
  Host: localhost:8080
  Method: POST
Data
  {
    "id":162,
    "label":""
  }
*/

func display(event cloudevents.Event) {
    fmt.Printf("Hello World: \n")
    fmt.Printf("cloudevents.Event\n%s", event.String())
}

func main() {
    c, err := kncloudevents.NewDefaultClient()
    if err != nil {
        log.Fatal("Failed to create client, ", err)
    }
    log.Fatal(c.StartReceiver(context.Background(), display))
}

通過上面的代碼,可以輕鬆構建你自己的鏡像。鏡像構建完成之後,接下來可以創建一個簡單的 Knative Service, 用於消費 ApiServerSource 產生的事件。

service.yaml 示例如下:

apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
  name: event-display
  namespace: default
spec:
  template:
    spec:
      containers:
      -  image: {yourrepo}/{yournamespace}/event-display:latest

執行命令:

kubectl apply --filename service.yaml

創建 Broker

在所選命名空間下,創建 default Broker。假如選擇 default 命名空間, 執行操作如下。

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 示例如下:

apiVersion: eventing.knative.dev/v1alpha1
kind: Trigger
metadata:
  name: testevents-trigger
  namespace: default
spec:
  subscriber:
    ref:
      apiVersion: serving.knative.dev/v1alpha1
      kind: Service
      name: event-display

執行命令:

kubectl apply --filename trigger.yaml

注意:如果沒有使用默認的 Broker, 在 Trigger 中可以通過 spec.broker 指定 Broker 名稱。

驗證

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

kubectl run busybox --image=busybox --restart=Never -- ls
kubectl delete pod busybox

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

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

日誌輸出類似下面,說明已經成功接收事件。

Hello World:  
☁️  CloudEvent: valid ✅
Context Attributes,
  SpecVersion: 0.2
  Type: dev.knative.apiserver.resource.add
  Source: https://10.39.240.1:443
  ID: 716d4536-3b92-4fbb-98d9-14bfcf94683f
  Time: 2019-05-10T23:27:06.695575294Z
  ContentType: application/json
  Extensions:
    knativehistory: default-broker-b7k2p-channel-z7mqq.default.svc.cluster.local
    subject: /apis/v1/namespaces/default/events/busybox.159d7608e3a3572c
Transport Context,
  URI: /
  Host: auto-event-display.default.svc.cluster.local
  Method: POST
Data,
  {
    "apiVersion": "v1",
    "count": 1,
    "eventTime": null,
    "firstTimestamp": "2019-05-10T23:27:06Z",
    "involvedObject": {
      "apiVersion": "v1",
      "fieldPath": "spec.containers{busybox}",
      "kind": "Pod",
      "name": "busybox",
      "namespace": "default",
      "resourceVersion": "28987493",
      "uid": "1efb342a-737b-11e9-a6c5-42010a8a00ed"
    },
    "kind": "Event",
    "lastTimestamp": "2019-05-10T23:27:06Z",
    "message": "Started container",
    "metadata": {
      "creationTimestamp": "2019-05-10T23:27:06Z",
      "name": "busybox.159d7608e3a3572c",
      "namespace": "default",
      "resourceVersion": "506088",
      "selfLink": "/api/v1/namespaces/default/events/busybox.159d7608e3a3572c",
      "uid": "2005af47-737b-11e9-a6c5-42010a8a00ed"
    },
    "reason": "Started",
    "reportingComponent": "",
    "reportingInstance": "",
    "source": {
      "component": "kubelet",
      "host": "gke-knative-auto-cluster-default-pool-23c23c4f-xdj0"
    },
    "type": "Normal"
  }

總結

相信通過上面的例子你已經瞭解了 Knative Eventing 如何產生事件、處理事件以及消費事件。對 Eventing 中的事件處理模型也有了初步的瞭解。當然你可以自己定義一個事件消費服務,來處理事件。

Next

你是否已對 Knative Eventing 產生了興趣,是否有點意猶未盡的樣子? 別急,接下來我們會繼續深入分析 Knative Eventing。包括:

  • 如何自定義數據源 Event Source?
  • 如何使用第三方消息服務?
  • 在遇到系統告警時,是否可以通過郵件、釘釘等發送消息?

讓我們後續一起探索 Knative Eventing,歡迎持續關注。

作者介紹

元毅,阿里雲智能事業羣高級開發工程師

本文轉載自公衆號阿里巴巴雲原生(ID:Alicloudnative)

原文鏈接

https://mp.weixin.qq.com/s?__biz=MzUzNzYxNjAzMg==&mid=2247485306&idx=1&sn=db92ddb8d367d63e3e93bc85aecc2d87&chksm=fae50cb5cd9285a3480bccbb904b62a52ee893b9c36a9b4c406101c6540eef8ee7a0cf21f506&token=776355447&lang=zh_CN#rd

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章