跳到內容

除錯 Knative 事件

這是一份關於如何除錯無法運作的 Knative 事件設定的演進文件。

對象

本文檔適用於熟悉 Knative 事件物件模型的人員。您不需要是專家,但確實需要大致了解事物如何組合在一起。

先決條件

  1. 設定 Knative 事件和 Eventing-contrib 資源

範例

本指南使用一個範例,其中包含一個將事件傳送到函式的事件來源。

src -> chan -> sub -> svc -> fn

請參閱 example.yaml 以取得完整的 YAML。若要讓本指南中的任何命令正常運作,您必須套用 example.yaml

kubectl apply --filename example.yaml

觸發事件

每當 Kubernetes Eventknative-debug 命名空間中發生時,就會發生 Knative 事件。我們可以透過以下命令來使其發生

kubectl --namespace knative-debug run to-be-deleted --image=image-that-doesnt-exist --restart=Never
# 5 seconds is arbitrary. We want K8s to notice that the Pod needs to be scheduled and generate at least one event.
sleep 5
kubectl --namespace knative-debug delete pod to-be-deleted

然後我們可以查看 Kubernetes Event(請注意,這些不是 Knative 事件!)

kubectl --namespace knative-debug get events

這應產生類似以下的輸出

LAST SEEN   FIRST SEEN   COUNT     NAME                             KIND      SUBOBJECT                        TYPE      REASON                   SOURCE                                         MESSAGE
20s         20s          1         to-be-deleted.157aadb9f376fc4e   Pod                                        Normal    Scheduled                default-scheduler                              Successfully assigned knative-debug/to-be-deleted to gke-kn24-default-pool-c12ac83b-pjf2

我的事件在哪裡?

您已套用 example.yaml,並且正在檢查 fn 的記錄

kubectl --namespace knative-debug logs -l app=fn -c user-container

但是您看不到任何事件到達。問題在哪裡?

檢查已建立的資源

首先要檢查的是所有已建立的資源,它們的狀態是否包含 ready true?

我們將嘗試從最基本的部件開始確定原因

  1. fn - Deployment 在 Knative 內部沒有任何依賴項。
  2. svc - Service 在 Knative 內部沒有任何依賴項。
  3. chan - Channel 依賴其後端的 頻道實作,並且在某種程度上依賴 sub
  4. src - Source 依賴 chan
  5. sub - Subscription 依賴 chansvc

fn

kubectl --namespace knative-debug get deployment fn -o jsonpath='{.status.availableReplicas}'

我們要看到 1。如果沒有,則需要除錯 Deployment。在 status 中是否有任何明顯錯誤?

kubectl --namespace knative-debug get deployment fn --output yaml

如果不明顯錯誤是什麼,則需要除錯 Deployment,這超出本文檔的範圍。

驗證 Pod 是否為 Ready

kubectl --namespace knative-debug get pod -l app=fn -o jsonpath='{.items[*].status.conditions[?(@.type == "Ready")].status}'

這應該傳回 True。如果沒有,則嘗試使用 Kubernetes 應用程式除錯指南除錯 Deployment

svc

kubectl --namespace knative-debug get service svc

我們只想確保它存在並且具有正確的名稱。如果它不存在,則您可能需要重新套用 example.yaml

驗證它是否指向預期的 Pod。

svcLabels=$(kubectl --namespace knative-debug get service svc -o go-template='{{range $k, $v := .spec.selector}}{{ $k }}={{ $v }},{{ end }}' | sed 's/.$//' )
kubectl --namespace knative-debug get pods -l $svcLabels

這應該會傳回一個 Pod,如果您檢查,它就是由 fn 產生的 Pod。

chan

chan 使用 in-memory-channel。這是一個非常基本的頻道,在 chanstatus 中會展現出一些錯誤模式。

kubectl --namespace knative-debug get channel.messaging.knative.dev chan -o jsonpath='{.status.conditions[?(@.type == "Ready")].status}'

這應該傳回 True。如果沒有,請取得完整資源

kubectl --namespace knative-debug get channel.messaging.knative.dev chan --output yaml

如果完全缺少 status,則表示 in-memory-channel 控制器有問題。請參閱 頻道控制器

接下來,驗證 chan 是否可定址

kubectl --namespace knative-debug get channel.messaging.knative.dev chan -o jsonpath='{.status.address.hostname}'

這應該會傳回一個 URI,可能以 '.cluster.local' 結尾。如果沒有,則表示在協調期間發生錯誤。請參閱 頻道控制器

我們將驗證 chan 建立的兩個資源是否存在且為 Ready

Service

chan 建立一個 K8s Service

kubectl --namespace knative-debug get service -l messaging.knative.dev/role=in-memory-channel

它的規格完全不重要,因為 Istio 會忽略它。它只需要存在,以便 src 可以向其傳送事件。如果它不存在,則表示在 chan 協調期間發生錯誤。請參閱 頻道控制器

src

src 是一個 ApiServerSource

首先,我們將驗證 src 是否正在寫入 chan

kubectl --namespace knative-debug get apiserversource src -o jsonpath='{.spec.sink}'

這應該傳回 map[apiVersion:messaging.knative.dev/v1 kind:Channel name:chan]。如果沒有,則表示 src 的設定不正確,並且需要修正其 spec。修正應該就像將其 spec 更新為具有正確的 sink 一樣簡單(請參閱 example.yaml)。

現在我們知道 src 正在傳送至 chan,讓我們驗證它是否為 Ready

kubectl --namespace knative-debug get apiserversource src -o jsonpath='{.status.conditions[?(.type == "Ready")].status}'

sub

sub 是從 chanfnSubscription

驗證 sub 是否為 Ready

kubectl --namespace knative-debug get subscription sub -o jsonpath='{.status.conditions[?(.type == "Ready")].status}'

這應該傳回 True。如果沒有,請查看所有狀態項目。

kubectl --namespace knative-debug get subscription sub --output yaml

控制器

每個資源都有一個正在監看它的控制器。到目前為止,它們往往在寫入失敗狀態訊息和事件方面做得不好,因此我們需要查看控制器的記錄。

注意

控制 fn 的 Kubernetes Deployment 控制器超出本文檔的範圍。

服務控制器

Kubernetes Service 控制器,負責控制 svc,不在本文檔的討論範圍內。

通道控制器 (Channel Controller)

並沒有單一的 Channel 控制器。而是每個 Channel CRD 都會有一個控制器。 chan 使用 InMemoryChannel Channel CRD,其控制器為

kubectl --namespace knative-eventing get pod -l messaging.knative.dev/channel=in-memory-channel,messaging.knative.dev/role=controller --output yaml

使用以下指令查看其日誌

kubectl --namespace knative-eventing logs -l messaging.knative.dev/channel=in-memory-channel,messaging.knative.dev/role=controller

請特別留意任何日誌級別為 warningerror 的行。

來源控制器 (Source Controller)

每個來源 (Source) 都會有自己的控制器。 src 是一個 ApiServerSource,因此其控制器為

kubectl --namespace knative-eventing get pod -l app=sources-controller

這實際上是一個單一的二進制檔,運行多個來源控制器,其中重要的是 ApiServerSource 控制器

ApiServerSource 控制器

ApiServerSource 控制器與 Eventing 的其他一些來源控制器在同一個二進制檔中運行。它是

kubectl --namespace knative-debug get pod -l eventing.knative.dev/sourceName=src,eventing.knative.dev/source=apiserver-source-controller

使用以下指令查看其日誌

kubectl --namespace knative-debug logs -l eventing.knative.dev/sourceName=src,eventing.knative.dev/source=apiserver-source-controller

請特別留意任何日誌級別為 warningerror 的行。

訂閱控制器 (Subscription Controller)

Subscription 控制器控制 sub。它嘗試解析 Channel 應該將事件發送到哪些位址,一旦解析完成,就將這些位址注入到 Channelspec.subscribable 中。

kubectl --namespace knative-eventing get pod -l app=eventing-controller

使用以下指令查看其日誌

kubectl --namespace knative-eventing logs -l app=eventing-controller

請特別留意任何日誌級別為 warningerror 的行。

資料平面 (Data Plane)

整個 控制平面 看起來都很正常,但我們仍然沒有收到任何事件。現在我們需要調查資料平面。

Knative 事件的傳輸路徑如下

  1. 事件由 src 產生。

  2. 在這個案例中,它是由於 Kubernetes Event 觸發的,但就 Knative 而言,Source 是從頭 (denovo,無中生有) 產生事件。

  3. src 將事件 POST 到 chan 的位址,http://chan-kn-channel.knative-debug.svc.cluster.local

  4. 通道分發器 (Channel Dispatcher) 接收請求並檢查 Host 標頭,以確定它對應哪個 Channel。它看到它對應於 knative-debug/chan,因此將請求轉發到 sub 中定義的訂閱者,特別是 svc,它由 fn 提供支援。

  5. fn 接收請求並記錄它。

我們將按照事件應該傳輸的順序來調查組件。

通道分發器 (Channel Dispatcher)

通道分發器是接收 POST 將事件推送到 Channel,然後在接收到事件時 POST 到這些 Channel 的訂閱者的組件。對於本範例中使用的 in-memory-channel,有一個單一的二進制檔處理所有 in-memory-channel Channel 的接收和分發端。

首先,我們將檢查分發器的日誌,看看是否有任何明顯的問題

kubectl --namespace knative-eventing logs -l messaging.knative.dev/channel=in-memory-channel,messaging.knative.dev/role=dispatcher -c dispatcher

理想情況下,我們會看到類似以下的行

{"level":"info","ts":"2019-08-16T13:50:55.424Z","logger":"inmemorychannel-dispatcher.in-memory-channel-dispatcher","caller":"provisioners/message_receiver.go:147","msg":"Request mapped to channel: knative-debug/chan-kn-channel","knative.dev/controller":"in-memory-channel-dispatcher"}
{"level":"info","ts":"2019-08-16T13:50:55.425Z","logger":"inmemorychannel-dispatcher.in-memory-channel-dispatcher","caller":"provisioners/message_dispatcher.go:112","msg":"Dispatching message to http://svc.knative-debug.svc.cluster.local/","knative.dev/controller":"in-memory-channel-dispatcher"}
{"level":"info","ts":"2019-08-16T13:50:55.981Z","logger":"inmemorychannel-dispatcher.in-memory-channel-dispatcher","caller":"provisioners/message_receiver.go:140","msg":"Received request for chan-kn-channel.knative-debug.svc.cluster.local","knative.dev/controller":"in-memory-channel-dispatcher"}

這表示請求正在被接收,然後發送到 svc,它正在返回 2XX 響應代碼(可能是 200、202 或 204)。

但是,如果我們看到類似以下的情況

{"level":"info","ts":"2019-08-16T16:10:16.859Z","logger":"inmemorychannel-dispatcher.in-memory-channel-dispatcher","caller":"provisioners/message_receiver.go:140","msg":"Received request for chan-kn-channel.knative-debug.svc.cluster.local","knative.dev/controller":"in-memory-channel-dispatcher"}
{"level":"info","ts":"2019-08-16T16:10:16.859Z","logger":"inmemorychannel-dispatcher.in-memory-channel-dispatcher","caller":"provisioners/message_receiver.go:147","msg":"Request mapped to channel: knative-debug/chan-kn-channel","knative.dev/controller":"in-memory-channel-dispatcher"}
{"level":"info","ts":"2019-08-16T16:10:16.859Z","logger":"inmemorychannel-dispatcher.in-memory-channel-dispatcher","caller":"provisioners/message_dispatcher.go:112","msg":"Dispatching message to http://svc.knative-debug.svc.cluster.local/","knative.dev/controller":"in-memory-channel-dispatcher"}
{"level":"error","ts":"2019-08-16T16:10:38.169Z","logger":"inmemorychannel-dispatcher.in-memory-channel-dispatcher","caller":"fanout/fanout_handler.go:121","msg":"Fanout had an error","knative.dev/controller":"in-memory-channel-dispatcher","error":"Unable to complete request Post http://svc.knative-debug.svc.cluster.local/: dial tcp 10.4.44.156:80: i/o timeout","stacktrace":"knative.dev/eventing/pkg/provisioners/fanout.(*Handler).dispatch\n\t/Users/xxxxxx/go/src/knative.dev/eventing/pkg/provisioners/fanout/fanout_handler.go:121\nknative.dev/eventing/pkg/provisioners/fanout.createReceiverFunction.func1.1\n\t/Users/i512777/go/src/knative.dev/eventing/pkg/provisioners/fanout/fanout_handler.go:95"}

那麼我們就知道發佈到 http://svc.knative-debug.svc.cluster.local/ 時出現了問題。

我們使用分析和 cookies 來了解網站流量。關於您使用我們網站的資訊將與 Google 分享用於該目的。 了解更多。