故障排除

以下信息可以帮助您诊断和解决问题。

定位并调查 Neo4j Helm 图表的问题

Kubernetes 中 Neo4j Helm 图表的推出可以认为是以下大致步骤

  1. 创建 Neo4j Pod

  2. Neo4j Pod 被安排在特定的 Kubernetes 节点上运行。

  3. 创建 Neo4j Pod 中的所有 容器

  4. InitContainers 在 Neo4j Pod 中运行。

  5. Containers 在 Neo4j Pod 中运行。

  6. StartupReadiness 探测器将被检查。

在所有这些步骤成功完成之后,Neo4j StatefulSet、Pod 和服务必须处于 ready 状态。您应该能够连接到您的 Neo4j 数据库并使用它。

如果 Neo4j Helm 图表安装成功,但 Neo4j 无法启动并在 Kubernetes 中达到 ready 状态,那么故障排除将包含两个步骤。

  1. 使用 kubectl get 命令检查 Kubernetes 中资源的状态。这将识别出哪个步骤失败了。

  2. 收集与该步骤相关的的信息。

根据失败的步骤,您可以从 Kubernetes(例如,使用 kubectl describe)和 Neo4j 进程(例如,检查 Neo4j 调试日志)收集信息。

下表提供了开始调查 Neo4j Helm 图表部署问题的简单步骤。有关如何在 Kubernetes 中调试应用程序的更多信息,请参见 Kubernetes 文档

表 1. 调查 Neo4j Helm 图表部署问题

步骤

诊断

进一步调查

Neo4j Pod 已创建

如果 kubectl get pod <release-name>-0 没有返回单个 Pod 结果,则 Pod 创建存在问题。

描述 Neo4j StatefulSet - 检查 kubectl describe statefulset <release-name> 的输出。

Neo4j Pod 已调度

如果 kubectl get pod <release-name>-0 中显示的状态卡在 Pending 上,则 Pod 调度存在问题。

描述 Neo4j Pod kubectl describe pod <release-name>-0 并检查输出。

Neo4j Pod 中的容器已创建

如果 kubectl get pod <release-name>-0 中显示的状态卡在 Waiting 上,则创建或启动容器存在问题。

描述 Neo4j Pod - 检查 kubectl describe pod <release-name>-0 的输出,特别注意 Events

Neo4j Pod 中的 InitContainers

如果 kubectl get pod <release-name>-0 中显示的状态卡在 Init: 上(例如,Init:CrashLoopBackOffInit:Error 等),则 InitContainers 存在问题。
请注意,如果 Pod 的 StatusPodInitializingRunning,则 InitContainers 已经成功完成。

描述 Neo4j Pod - 检查 kubectl describe pod <release-name>-0 的输出,特别注意 InitContainer(注意 InitContainer 名称)和 Events。 使用 kubectl logs <pod-name> -c <init-container-name> 获取 InitContainer 日志。

Neo4j Pod 中的容器正在运行

如果 kubectl get pod <release-name>-0 中显示的状态与上面列出的状态不匹配,但 Pod 仍然没有达到 Running 状态,则在 Neo4j Pod 中运行容器存在问题。

描述 Neo4j Pod - 检查 kubectl describe pod <release-name>-0 的输出,特别注意 Container 状态(注意 Container 名称)和 Events。 使用 kubectl logs <pod-name> -c <init-container-name> 获取 Container 日志。 如果 Neo4j Container 正在启动,但意外退出(例如,状态为 CrashLoopBackOff),请按照 Neo4j 意外崩溃或重启 的说明操作。

启动和就绪探测器

如果 kubectl get pod <release-name>-0 中显示的状态为 Running,但 Pod 并未变为 ready 状态,则 StartupReadiness 探测器存在问题。

描述 Neo4j Pod - 检查 kubectl describe pod <release-name>-0 的输出,特别注意 Events 和探测器。 检查 Pod 日志 kubectl logs <release-name>-0、Neo4j 日志 kubectl exec <release-name>-0 -- tail -n 100 /logs/neo4j.log 和 Neo4j 调试日志 kubectl exec <release-name>-0 -- tail -n 500 /logs/debug.log

Neo4j 意外崩溃或重启

如果 Neo4j Pod 启动,但随后意外崩溃或重启,则可能有多种原因。已知原因包括:

  • Neo4j 的配置无效或不正确,导致它在容器启动后不久就关闭。

  • Neo4j Java 进程耗尽内存并退出,出现 OutOfMemoryException

  • 某些中断影响了 Neo4j Pod 调度的 Kubernetes 节点,例如,它正在被关闭或已关闭。

  • Neo4j Pod 中的容器由于使用超出为容器配置的资源限制(OOMKilled)的内存而被操作系统关闭。

  • 非常长的垃圾收集暂停会导致 Neo4j Pod 的 LivenessProbe 失败,从而导致 Kubernetes 重启 Neo4j。

OOMKILLEDOutOfMemoryException 看起来非常相似,但它们出现在不同的地方,并且修复方法也不同。了解这一点并确保您知道自己正在处理什么非常重要。

以下是一些检查,可以帮助您排查崩溃和意外重启问题。

描述 Neo4j Pod

使用 kubectl 描述 Neo4j Pod。

kubectl describe pod <release-name>-0

检查 Neo4j 容器状态

检查容器的 StateLast State。这显示了在 OOMKilled 后重新启动的容器的 Last State 的外观。

$ kubectl describe pod neo4j-0
State:          Running
  Started:      Mon, 1 Jan 2021 00:02:00 +0000
Last State:     Terminated
  Reason:       OOMKilled
  Exit Code:    137
  Started:      Mon, 1 Jan 2021 00:00:00 +0000
  Finished:     Mon, 1 Jan 2021 00:01:00 +0000

如果 Exit Code: 137 出现在此处或其他日志中,即使没有出现 "OOMKilled" 字符串,也表明 OOMKilled 发生了。

检查最近的 Events

kubectl describe 输出在顶部显示较旧的事件,在底部显示较新的事件。通常,您可以忽略较旧的事件。

一个 Killing 事件表明 Neo4j 容器被 Kubernetes kubelet 杀死了。
$ kubectl describe pod neo4j-0
Events:
Type    Reason       Age      From                  Message
----    ------       ----     ----                  -------
Normal  Scheduled    6m30s    default-scheduler     Successfully assigned default/neo4j-0 to k8s-node-a
...
Normal  Killing        56s    kubelet, k8s-node-a   Killing container with id docker://neo4j-0-neo4j:Need to kill Pod

从这个事件日志本身无法明确了解 Kubernetes 为什么要决定杀死 Neo4j 容器。

此示例中的下一步可能是检查:

  • 容器是否被 OOMKilled

  • 容器是否失败了 LivenessStartup 探测器。

  • 调查该节点,看看是否有任何原因可能导致它杀死容器,例如,kubectl describe node <k8s node>

检查 Neo4j 日志和指标

Neo4j Helm 图表将 Neo4j 配置为将日志和指标持久化到提供的卷中。如果没有为日志或指标明确配置卷,则它们将持久化存储在 Neo4j 的 data 卷中。这确保了意外崩溃或关闭的 Neo4j 实例的日志和指标输出将被保留。

从正在运行的 Neo4j Pod 收集数据

  • 使用 kubectl cp 命令从 Pod 下载所有 Neo4j 日志。

    kubectl cp <neo4j-pod-name>:/logs neo4j-logs/
  • 如果为 Neo4j 启用了 CSV 指标收集(默认情况下),请使用以下命令从 Pod 下载所有 Neo4j 指标:

    kubectl cp <neo4j-pod-name>:/metrics neo4j-metrics/

从未运行的 Neo4j Pod 收集数据

如果 Neo4j Pod 无法运行,或者崩溃过于频繁以至于无法使用 kubectl cp,则应将 Neo4j 部署置于 离线维护模式 下以收集日志和指标。

检查容器日志

主要 Neo4j DBMS 进程的日志被持久化到磁盘上,可以按照 检查 Neo4j 日志和指标 中的描述访问。但是,Neo4j 启动日志以及 Neo4j Pod 中其他容器的日志会被发送到容器的 stdoutstderr 流。可以使用 kubectl logs <pod name> -c <container name> 查看这些容器日志。

不幸的是,如果容器在崩溃或意外关闭后重新启动,通常 kubectl logs 会显示新容器实例的日志(在重新启动之后),而先前容器实例的日志(意外关闭的实例)则无法通过 kubectl logs 获取。

要捕获崩溃容器的日志,您可以尝试:

  • 在连接到 Kubernetes 集群的日志收集器/聚合器(例如 Stackdriver、Cloudwatch Logs、Logstash 等)中查看容器日志。如果您使用的是托管 Kubernetes 平台,则通常默认情况下会启用此功能。

  • 使用 kubectl logs --follow 流式传输正在运行的容器的日志,直到它再次崩溃。