一文搞懂关于 Kubernetes 的 CrashLoopBackOff的问题解决方案

CrashLoopBackOff 概述:

首先关于CrashLoopBackOff并不是代表一种错误, "CrashLoopBackOff 是 Kubernetes 中的一个状态,表示在一个 Pod 中发生的重启循环:Pod 中的一个容器启动,但崩溃,然后反复重启。

Kubernetes 会在重启之间等待逐渐增加的退避时间,我们在发现CrashLoopBackOff可以对集群进行及时的修复。因此,CrashLoopBackOff 本身并不是一个问题,而是表明有一个错误发生,阻止了 Pod 正确启动。"

CrashLoopBackOff之所以会导致Pod重新启动,是因为在Pod的配置策略中 restartPolicy 设置为 Always(默认)或 OnFailure。kubelet 读取此配置并重新启动 Pod 中的容器,导致循环。实际上,这种行为非常有用,因为它为缺少的资源完成加载提供了一些时间,同时也为我们检测问题和调试提供了时间

  • 这方面稍后会详细介绍。

这解释了 "CrashLoop" 的部分,但 "BackOff" 时间是什么呢?基本上,它是重启之间的指数延迟(10秒,20秒,40秒,...),最多延迟五分钟。当一个 Pod 的状态显示为 CrashLoopBackOff 时,这意味着它当前正在等待指定的时间,然后再次重新启动 Pod。而且,除非问题被修复,否则它很可能会再次失败。

在本文中,您将会看到:

  1. 什么是 CrashLoopBackOff?
  2. 如何检测 CrashLoopBackOff 问题
  3. CrashLoopBackOff 的常见原因
  4. Kubernetes 调试 CrashLoopBackOff 的工具
  5. 如何使用 Prometheus 检测 CrashLoopBackOff

如何在您的集群中检测 CrashLoopBackOff?

很可能,您通过使用 kubectl get pods 命令列出 Pods 时,发现了一个或多个处于这种状态的 Pods:

sql 复制代码
$ kubectl get pods
NAME                     READY     STATUS             RESTARTS   AGE
flask-7996469c47-d7zl2   1/1       Running            1          77d
flask-7996469c47-tdr2n   1/1       Running            0          77d
nginx-5796d5bc7c-2jdr5   0/1       CrashLoopBackOff   2          1m
nginx-5796d5bc7c-xsl6p   0/1       CrashLoopBackOff   2          1m

从输出中,您可以看到最后两个 Pods:

  1. 处于未就绪状态(0/1)。
  2. 它们的状态显示为 CrashLoopBackOff。
  3. 列 RESTARTS 显示一个或多个重新启动。

这三个信号指向了我们之前解释的情况:Pods 失败,然后被重新启动。在重新启动之间,存在一个优雅的等待期,这被表示为 CrashLoopBackOff。

您也可能"幸运"地在 Pods 处于短暂的 Running 或 Failed 状态时找到它们。

CrashLoopBackOff 的常见原因

CrashLoopBackOff 的常见原因

需要注意的是,CrashLoopBackOff 不是导致 Pod 崩溃的实际错误。请记住,它只是在状态列中显示正在发生的循环。您需要找到影响容器的根本错误。

与实际应用程序相关的一些错误包括:

  1. 配置错误:比如配置文件中的拼写错误。
  2. 资源不可用:比如未挂载的持久卷(PersistentVolume)。
  3. 命令行参数错误:要么缺失,要么不正确。
  4. 错误和异常:可以是任何与您的应用程序非常具体的错误。

最后,与网络和权限相关的错误包括:

  1. 尝试绑定已存在的端口。
  2. 内存限制过低,因此容器会因内存不足而被终止。
  3. 存活探测错误未将 Pod 报告为就绪。
  4. 只读文件系统,或者一般权限不足。

类似的等待状态还有 ImagePullBackOff,这是在无法拉取容器镜像时出现的状态。

再次强调,这只是可能导致问题的一些原因列表,还可能有其他原因。现在让我们看看如何深入挖掘并找到实际的原因。

vbnet 复制代码
$ kubectl describe pod the-pod-name
Name:         the-pod-name
Namespace:    default
Priority:     0
...
State:          Waiting
Reason:       CrashLoopBackOff
Last State:     Terminated
Reason:       Error
...
Warning  BackOff                1m (x5 over 1m)   kubelet, ip-10-0-9-132.us-east-2.compute.internal  Back-off restarting failed container
...

从描述输出中,您可以提取以下信息:

  1. 当前 Pod 的状态为 "等待"。
  2. 等待状态的原因是 "CrashLoopBackOff"。
  3. 最后(或以前)的状态是 "终止"。
  4. 最后一次终止的原因是 "错误"。

这与我们一直在解释的循环行为相吻合。

通过使用 kubectl describe pod,您可以检查以下是否存在配置错误:

  1. 检查Pod 的定义。
  2. 检查容器日志。
  3. 为容器拉取的镜像。
  4. 为容器分配的资源。
  5. 错误或丢失的参数。

这有助于找出问题并进行进一步的调试。

csharp 复制代码
...
Warning  BackOff                1m (x5 over 1m)   kubelet, ip-10-0-9-132.us-east-2.compute.internal  Back-off restarting failed container
...

在最后几行,您会看到与该 Pod 关联的最后事件的列表,其中之一是 "Back-off restarting failed container"。这是与重新启动循环相关的事件。即使发生多次重新启动,应该只有一行来表示这个事件。

2. 检查日志 - 使用 kubectl logs

您可以查看 Pod 中所有容器的日志:

css 复制代码
kubectl logs mypod --all-containers
Code language: JavaScript (javascript)

或者甚至是 Pod 中的一个容器的日志:

css 复制代码
kubectl logs mypod -c mycontainer
Code language: JavaScript (javascript)

In case there's a wrong value in the affected pod, logs may be displaying useful information.

3. Check the events -- kubectl get events

They can be listed with:

sql 复制代码
kubectl get events
Code language: JavaScript (javascript)

Alternatively, you can list all of the events of a single Pod by using:

sql 复制代码
kubectl get events --field-selector involvedObject.name=mypod
Code language: JavaScript (javascript)

Note that this information is also present at the bottom of the describe pod output.

4. Check the deployment -- kubectl describe deployment

You can get this information with:

sql 复制代码
kubectl describe deployment mydeployment
Code language: JavaScript (javascript)

If there's a Deployment defining the desired Pod state, it might contain a misconfiguration that is causing the CrashLoopBackOff.

Putting it all together

In the following example you can see how to dig into the logs, where an error in a command argument is found.

如何在 Prometheus 中检测 CrashLoopBackOff

如果您正在使用 Prometheus 进行云监控,以下是一些建议,可以帮助您在发生 CrashLoopBackOff 时触发警报。

您可以通过使用以下表达式(需要 Kube State Metrics)来快速扫描集群中处于 CrashLoopBackOff 状态的容器:

ini 复制代码
kube_pod_container_status_waiting_reason{reason="CrashLoopBackOff"} == 1

或者,您可以追踪发生在 Pod 中的重新启动次数,使用以下方式:

scss 复制代码
rate(kube_pod_container_status_restarts_total[5m]) > 0

警告:并非集群中的所有重新启动都与 CrashLoopBackOff 状态相关。

在每次 CrashLoopBackOff 期间之后应该会有一次重新启动(1),但也可能存在与 CrashLoopBackOff 无关的重新启动(2)。

之后,您可以创建一个像下面这样的Prometheus告警规则,以便在您的任何Pod处于这种状态时接收通知:

yaml 复制代码
- alert: RestartsAlert
  expr: rate(kube_pod_container_status_restarts_total[5m]) > 0
  for: 10m
  labels:
    severity: warning
  annotations:
    summary: Pod is being restarted
  description: Pod {{ $labels.pod }} in {{ $labels.namespace }} has a container {{ $labels.container }} which is being restarted

结论:

在本文中,我们了解到CrashLoopBackOff本身并不是一个错误,而只是表示Pod中正在发生重试循环的通知。

我们看到了它经历的各个状态的描述,以及如何使用kubectl命令来跟踪它,我们还看到了可能导致这种状态的常见配置错误,以及可以用来调试的工具。

相关推荐
短剑重铸之日7 分钟前
《SpringBoot4.0初识》第一篇:前瞻与思想
java·开发语言·后端·spring·springboot4.0
it_czz26 分钟前
LangSmith vs LangFlow vs LangGraph Studio 可视化配置方案对比
后端
蓝色王者28 分钟前
springboot 2.6.13 整合flowable6.8.1
java·spring boot·后端
花哥码天下1 小时前
apifox登录后设置token到环境变量
java·后端
hashiqimiya2 小时前
springboot事务触发滚动与不滚蛋
java·spring boot·后端
TeamDev3 小时前
基于 Angular UI 的 C# 桌面应用
前端·后端·angular.js
PPPHUANG3 小时前
一次 CompletableFuture 误用,如何耗尽 IO 线程池并拖垮整个系统
java·后端·代码规范
用户8356290780513 小时前
用Python轻松管理Word页脚:批量处理与多节文档技巧
后端·python
想用offer打牌3 小时前
一站式了解Spring AI Alibaba的流式输出
java·人工智能·后端
秋说3 小时前
华为 DevKit 25.2.rc1 源码迁移分析使用教程(openEuler + ARM64)
后端