初探 Knative 基本功能與概念(下)

初探 Knative 基本功能與概念(下)

Eventing

Eventing 提供用於 Consuming 以及 Producing 的事件建構區塊,並遵守著 CloudEvents 規範來實現,而該元件目標是對事件進行抽象處理,以讓開發者不需要關注後端相關具體細節,這樣開發者就不需要思考使用哪一套訊息佇列系統。

而 Knative Eventing 也透過 Kubernetes CRD 定義了一組新資源,這些資源被用在事件的 Producing 與 Consuming 上,而這類資源主要分成以下:

Channels

  • 這些是發布者(Publishers)向其發送訊息的 Pub/Sub Topics,因此 Channel 可視為獲取或放置事件的位置目錄。
  • Bus。Channels 的後端供應者,即支援事件的訊息服務平台,如 Google Cloud PubSub、Apache Kafka 與 NATS 等等。
apiVersion: channels.knative.dev/v1alpha1 kind: Bus metadata: name: kafka spec: dispatcher: args: - -logtostderr - -stderrthreshold - INFO env: - name: KAFKA_BROKERS valueFrom: configMapKeyRef: key: KAFKA_BROKERS name: kafka-bus-config image: gcr.io/knative-releases/github.com/knative/eventing/pkg/buses/kafka/dispatcher@sha256:d925663bb965001287b042c8d3ebdf8b4d3f0e7aa2a9e1528ed39dc78978bcdb name: dispatcher
  • 為應用程式與函式指定 Knative Service,並指明 Channel 所要傳遞的具體訊息。為程式與函式的進入位址。

Feeds: 提供一個抽象層來讓外部可以提供資料來源,並將之路由到叢集中。會將事件來源中的單個事件類型附加到某一個行為。

  • EventSource 與 ClusterEventSource 是一個 Kubernetes 資源,被用來描述可能產生的 EventTypes 外部系統。
apiVersion: feeds.knative.dev/v1alpha1 kind: EventSource metadata: name: github namespace: default spec: image: gcr.io/knative-releases/github.com/knative/eventing/pkg/sources/github@sha256:a5f6733797d934cd4ba83cf529f02ee83e42fa06fd0e7a9d868dd684056f5db0 source: github type: github
  • EventType 與 ClusterEventType 同樣是 Kubernetes 資源,被用來表示不同 EventSource 支援的事件類型。
apiVersion: feeds.knative.dev/v1alpha1 kind: EventType metadata: name: pullrequest namespace: default spec: description: notifications on pullrequests eventSource: github
  • Flows: 該資源會將事件綁定到 Route(應用程式與函式端點)上,並選擇使用哪種事件路由的 Channel 與 Bus。
apiVersion: flows.knative.dev/v1alpha1 kind: Flow metadata: name: k8s-event-flow namespace: default spec: serviceAccountName: feed-sa trigger: eventType: dev.knative.k8s.event resource: k8sevents/dev.knative.k8s.event service: k8sevents parameters: namespace: default action: target: kind: Route apiVersion: serving.knative.dev/v1alpha1 name: read-k8s-events

以上是簡單介紹,接下來我們將透過 Minikube 來初步玩玩 Knative 功能。

透過 Minikube 初步入門

本節將安裝 Minikube 來建立 Knative 環境,透過完成簡單範例來體驗。

事前準備

  • 在測試機器安裝 Minikube 二進制執行檔,請至 Minikube Releases 下載
  • 在測試機器下載 Virtual Box 來提供給 Minikube 建立虛擬機
  • IMPORTANT: 測試機器記得開啟 VT-x or AMD-v virtualization
  • 雖然建議用 vbox,但是討厭 Oracle 的人可以改用其他虛擬化工具(ex: kvm, xhyve),理論上可以動
  • 下載 Kubernetes CLI 工具 kubeclt

啟動 Minukube

首天透過 Minikube 來啟動一台 VM 部署單節點 Kubernetes,由於這邊會用到很多系統服務,因此需要開多一點系統資源:

$ minikube start --memory=8192 --cpus=4 \ --kubernetes-version=v1.10.5 \ --extra-config=apiserver.admission-control="LimitRanger,NamespaceExists,NamespaceLifecycle,ResourceQuota,ServiceAccount,DefaultStorageClass,MutatingAdmissionWebhook"

完成後,透過 kubectl 檢查:

$ kubectl get no NAME STATUS ROLES AGE VERSION minikube Ready master 1m v1.10.5

部署 Knative

由於 Knative 是基於 Istio 所開發,因此需要先部署相關服務,這邊透過 kubectl 來建立:

$ curl -L https://storage.googleapis.com/knative-releases/serving/latest/istio.yaml \ | sed 's/LoadBalancer/NodePort/' \ | kubectl apply -f - # 設定 inject namespace $ kubectl label namespace default istio-injection=enabled

這邊會需要一點時間下載映像檔,並啟動 Istio 服務,完成後會如下所示:

$ kubectl -n istio-system get po NAME READY STATUS RESTARTS AGE istio-citadel-7bdc7775c7-jn2bw 1/1 Running 0 5m istio-cleanup-old-ca-msvkn 0/1 Completed 0 5m istio-egressgateway-795fc9b47-4nz7j 1/1 Running 0 6m istio-ingress-84659cf44c-pvqd5 1/1 Running 0 6m istio-ingressgateway-7d89dbf85f-tgm24 1/1 Running 0 6m istio-mixer-post-install-lvrjv 0/1 Completed 0 6m istio-pilot-66f4dd866c-zmbv5 2/2 Running 0 6m istio-policy-76c8896799-cqmdn 2/2 Running 0 6m istio-sidecar-injector-645c89bc64-9mdwx 1/1 Running 0 5m istio-statsd-prom-bridge-949999c4c-qhdgf 1/1 Running 0 6m istio-telemetry-6554768879-b6vss 2/2 Running 0 6m

接著部署 Knative 元件至 Kubernetes 叢集,官方提供了一個release-lite.yaml檔案來協助建立輕量的測試環境,因此可以直接透過 kubectl 來建立:

$ curl -L https://storage.googleapis.com/knative-releases/serving/latest/release-lite.yaml \ | sed 's/LoadBalancer/NodePort/' \ | kubectl apply -f -
  • 這邊會部署以 Prometheus 組成的 Monitoring 系統,以及 Knative Serving 與 Build
  • 若是其他環境上的 Kubernetes 可以參考 Knative Install

這邊同樣需要一點時間來下載映像檔,並啟動相關服務,一但完成後會如下所示:

# Monitoring $ kubectl -n monitoring get po NAME READY STATUS RESTARTS AGE grafana-798cf569ff-m8w9c 1/1 Running 0 4m kube-state-metrics-77597b45f8-mxhxv 4/4 Running 0 1m node-exporter-8wbxd 2/2 Running 0 4m prometheus-system-0 1/1 Running 0 4m prometheus-system-1 1/1 Running 0 4m # Knative build $ kubectl -n knative-build get po NAME READY STATUS RESTARTS AGE build-controller-5cb4f5cb67-bs94k 1/1 Running 0 6m build-webhook-6b4c65546b-fzffg 1/1 Running 0 6m # Knative serving $ kubectl -n knative-serving get po NAME READY STATUS RESTARTS AGE activator-869d7d76c5-fngdm 2/2 Running 0 7m autoscaler-65855c89f6-pmzhr 2/2 Running 0 7m controller-5fbcf79dfb-q8cb8 1/1 Running 0 7m webhook-c98c7c654-lpnjj 1/1 Running 0 7m

到這邊已完成部署 Knative 元件,接下來將透過一些範例來了解 Knative 功能。

部署 Knative 應用程式

當上述元件部署完成後,就可以開始建立 Knative 應用程式與函式,這邊將利用簡單 HTTP Server + Slack 來實作一個簡單 Channel 訊息傳送,過程中將會使用到 Build、BuildTemplate 與 Knative Service 等資源。在開始前,先透過 Git 來取得範例專案,這邊主要是使用裡面的 Kubernetes 部署檔案:

$ git clone https://github.com/kairen/knative-slack-app $ cd knative-slack-app

由於本範例會利用 Kaniko 來建構應用程式的容器映像檔,並將自動將建構好的映像檔上傳至 DockeHub,因此這邊為了確保能夠上傳到自己的 DockerHub,需要建立 Secert 與 Service Account 來提供 Docker ID 與 Passwrod 給 Knative serving 使用:

$ export DOCKER_ID=$(echo -n "username" | base64) $ export DOCKER_PWD=$(echo -n "password" | base64) $ cat deploy/docker-secret.yml | \ sed "s/BASE64_ENCODED_USERNAME/${DOCKER_ID}/" | \ sed "s/BASE64_ENCODED_PASSWORD/${DOCKER_PWD}/" | \ kubectl apply -f - $ kubectl apply -f deploy/kaniko-sa.yml

接著建立一個 Secret 來保存 Slack 的資訊以提供給 Slack App 使用,如 Token:

$ export SLACK_TOKEN=$(echo -n "slack-token" | base64) $ export SLACK_CHANNEL_ID=$(echo -n "slack-channel-id" | base64) $ cat deploy/slack-secret.yml | \ sed "s/BASE64_ENCODED_SLACK_TOKEN/${SLACK_TOKEN}/" | \ sed "s/BASE64_ENCODED_SLACK_CHANNEL_ID/${SLACK_CHANNEL_ID}/" | \ kubectl apply -f -

接著建立 Kaniko Build template 來提供給 Knative Service 建構使用:

$ kubectl apply -f deploy/kaniko-buildtemplate.yml $ kubectl get buildtemplate NAME CREATED AT kaniko 7s

上面完成後,建立 Knative service 與 Istio HTTPS Service Entry 來提供應用程式,以及讓 Pod 能夠存取 Slack HTTPs API:

$ kubectl apply -f deploy/slack-https-sn.yml $ kubectl apply -f deploy/slack-app-service.yml $ kubectl get po -w NAME READY STATUS RESTARTS AGE slack-app-00001-9htqm 0/1 Init:2/3 0 8s slack-app-00001-9htqm 0/1 Init:2/3 0 8s slack-app-00001-9htqm 0/1 PodInitializing 0 3m slack-app-00001-9htqm 0/1 Completed 0 4m slack-app-00001-deployment-75f7f8dd8c-tskq8 0/3 Pending 0 0s slack-app-00001-deployment-75f7f8dd8c-tskq8 0/3 Pending 0 0s slack-app-00001-deployment-75f7f8dd8c-tskq8 0/3 Init:0/1 0 0s slack-app-00001-deployment-75f7f8dd8c-tskq8 0/3 PodInitializing 0 7s slack-app-00001-deployment-75f7f8dd8c-tskq8 2/3 Running 0 33s

這邊第一次執行會比較慢,因為需要下載 knative build 相關映像檔。

經過一段時間完成後,透過以下指令來確認服務是否正常:

$ export IP_ADDRESS=$(minikube ip):$(kubectl get svc knative-ingressgateway -n istio-system -o 'jsonpath={.spec.ports[?(@.port==80)].nodePort}') $ export DOMAIN=$(kubectl get services.serving.knative.dev slack-app -o=jsonpath='{.status.domain}') # 透過 cURL 工具以 Get method 存取 $ curl -X GET -H "Host: ${DOMAIN}" ${IP_ADDRESS} <h1>Hello slack app for Knative!!</h1> # 透過 cURL 工具以 Post method 傳送 msg $ curl -X POST \ -H 'Content-type: application/json' \ -H "Host: ${DOMAIN}" \ --data '{"msg":"Hello, World!"}' \ ${IP_ADDRESS} success

若成功的話,可以查看 Slack channel 是否有傳送訊息:

最後由於 Knative Serving 是 Request-driven,因此經過長時間沒有任何 request 時,將會自動縮減至 0 副本,直到再次收到 request 才會再次啟動一個實例,然而 Knative 也將大多資訊以 Prometheus 進行監控,因此我們能透過 Prometheus 來觀察狀態變化。

首先透過 kubectl 取得 Grafana NodePort 資訊:

$ kubectl -n monitoring get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ... grafana NodePort 10.96.197.116 <none> 30802:30326/TCP 1h prometheus-system-np NodePort 10.99.64.228 <none> 8080:32628/TCP 1h ...

透過瀏覽器開啟 http://minikube_ip:port 來查看。

另外也可以查看 HTTP request 狀態。

訂閱電子報

Select list(s)*

 

Loading