跳过内容

调试 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 依赖于其支持的 channel 实现,并且在一定程度上依赖于 sub
  4. src - Source 依赖于 chan
  5. sub - Subscription 同时依赖于 chansvc

fn

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

我们希望看到 1。如果您没有看到,那么您需要调试 Deploymentstatus 中是否提到了明显错误?

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。如果返回 False,那么尝试使用 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,如果您检查该 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。如果返回 False,则获取完整的资源

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' 结尾。如果返回 False,则意味着在协调过程中出现了问题。请参阅 通道控制器

我们将验证 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]。如果返回 False,则 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。如果返回 False,则查看所有状态条目。

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

控制器

每个资源都有一个在监视它的控制器。截至目前,这些控制器在写入故障状态消息和事件方面做得不好,因此我们需要查看控制器的日志。

注意

控制 fn 的 Kubernetes Deployment 控制器超出了本文档的范围。

服务控制器

控制 svc 的 Kubernetes Service 控制器超出了本文档的范围。

通道控制器

没有一个单一的 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 的行。

源控制器

每个源都有自己的控制器。src 是一个 ApiServerSource,因此它的控制器是

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

这实际上是一个运行多个源控制器的单一二进制文件,其中包括 ApiServerSource 控制器

ApiServerSource 控制器

ApiServerSource 控制器与事件中其他一些源控制器在同一二进制文件中运行。它是

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 控制器控制 sub。它尝试解析 Channel 应该发送事件的地址,解析完成后,将这些地址注入 Channelspec.subscribable 中。

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

使用以下命令查看其日志

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

特别注意任何日志级别为 warningerror 的行。

数据平面

整个 控制平面 看起来很健康,但是我们仍然没有收到任何事件。现在我们需要调查数据平面。

Knative 事件遵循以下路径

  1. 事件由 src 生成。

  2. 在本例中,它是由于 Kubernetes Event 触发它而产生的,但就 Knative 而言,Source 正在从无到有地生成事件。

  3. src 正在将事件 POST 到 chan 的地址 http://chan-kn-channel.knative-debug.svc.cluster.local

  4. 通道调度器接收请求,并内省 Host 标头以确定它对应于哪个 Channel。它看到它对应于 knative-debug/chan,因此将请求转发到 sub 中定义的订阅者,特别是 svc,它由 fn 支持。

  5. fn 接收请求并记录它。

我们将按照事件应该传播的顺序调查组件。

通道调度器

通道调度器是接收将事件推送到通道的 POST 请求,并在收到事件时向这些通道的订阅者发送 POST 请求的组件。对于此示例中使用的内存通道,只有一个二进制文件同时处理所有内存通道通道的接收和调度方面。

首先,我们将检查调度器的日志,看看是否有任何明显的问题。

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,并且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/发送请求时遇到了问题。

我们使用分析和 Cookie 来了解网站流量。有关您使用我们网站的信息将与 Google 共享,以用于该目的。 了解更多。