调试 Knative 事件¶
这是一份关于如何调试无法正常工作的 Knative 事件设置的不断发展中的文档。
受众¶
本文档面向熟悉 Knative 事件 对象模型的人员。您无需成为专家,但需要大致了解事物是如何组合在一起的。
先决条件¶
示例¶
本指南使用一个示例,该示例包含一个向函数发送事件的事件源。
查看 example.yaml 获取完整的 YAML。要使本指南中的任何命令起作用,您必须应用 example.yaml
kubectl apply --filename example.yaml
触发事件¶
每当 Kubernetes Event
在 knative-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?
我们将尝试从最基本的组件开始确定原因
fn
-Deployment
在 Knative 内部没有依赖项。svc
-Service
在 Knative 内部没有依赖项。chan
-Channel
依赖于其支持的channel 实现
,并且在一定程度上依赖于sub
。src
-Source
依赖于chan
。sub
-Subscription
同时依赖于chan
和svc
。
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
。如果返回 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
。这是一个非常基本的通道,并且很少出现将在 chan
的 status
中显示的故障模式。
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
是从 chan
到 fn
的 Subscription
。
验证 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
特别注意任何日志级别为 warning
或 error
的行。
源控制器¶
每个源都有自己的控制器。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
特别注意任何日志级别为 warning
或 error
的行。
订阅控制器¶
Subscription
控制器控制 sub
。它尝试解析 Channel
应该发送事件的地址,解析完成后,将这些地址注入 Channel
的 spec.subscribable
中。
kubectl --namespace knative-eventing get pod -l app=eventing-controller
使用以下命令查看其日志
kubectl --namespace knative-eventing logs -l app=eventing-controller
特别注意任何日志级别为 warning
或 error
的行。
数据平面¶
整个 控制平面 看起来很健康,但是我们仍然没有收到任何事件。现在我们需要调查数据平面。
Knative 事件遵循以下路径
-
事件由
src
生成。 -
在本例中,它是由于 Kubernetes
Event
触发它而产生的,但就 Knative 而言,Source
正在从无到有地生成事件。 -
src
正在将事件 POST 到chan
的地址http://chan-kn-channel.knative-debug.svc.cluster.local
。 -
通道调度器接收请求,并内省 Host 标头以确定它对应于哪个
Channel
。它看到它对应于knative-debug/chan
,因此将请求转发到sub
中定义的订阅者,特别是svc
,它由fn
支持。 -
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/
发送请求时遇到了问题。