本文選自 《Knative 雲原生應用開發指南》 。
前置準備
- Knative 版本 >= 0.5
- 已安裝 Serving 元件
- 已安裝 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 如何産生事件、處理事件以及消費事件。當然你可以自己定義一個事件消費服務,來處理事件。
“ 阿裡巴巴雲原生 關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的技術圈。”