做者 | 阿里雲智能事業羣高級開發工程師 元毅git
基於事件驅動是Serveless的核心功能之一,經過事件驅動服務,知足了用戶按需付費(Pay-as-you-go)的需求。在以前的文章中咱們介紹過 Knative Eventing 由事件源、事件處理模型和事件消費 3 個主要部分構成,那麼事件如何經過這 3 個組件產生、處理以及消費呢? 本文經過 Kubernetes Event Source 示例介紹一下 Knative Eventing 中如何獲取事件,而且將事件傳遞給 Serving 進行消費。其中事件處理基於 Broker/Trigger 模型。github
[]()web
背景知識json
先了解一下Broker/Trigger 事件處理模型。從 v0.5 開始,Knative Eventing 定義 Broker 和 Trigger 對象,從而能方便的對事件進行過濾。api
Broker 提供一個事件集,能夠經過屬性選擇該事件集。它負責接收事件並將其轉發給由一個或多個匹配 Trigger 定義的訂閱者。
Trigger 描述基於事件屬性的過濾器。同時能夠根據須要建立多個 Trigger。
Broker/Tiggger 模型流程處理如圖所示:app
[]()less
前置準備ui
Knative 版本 >= 0.5
安裝完成 Knative Serving
安裝完成 Knative Eventing
[]()阿里雲
操做步驟
先看一下 Kubernetes Event Source 示例處理流程,如圖所示:
spa
接下來介紹一下各個階段如何進行操做處理。
[]()
建立 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:
verbs:
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:
執行以下操做:
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:
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/ev...
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,歡迎持續關注。