一文搞懂关于 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命令来跟踪它,我们还看到了可能导致这种状态的常见配置错误,以及可以用来调试的工具。

相关推荐
sin22018 分钟前
springboot测试类里注入不成功且运行报错
spring boot·后端·sqlserver
kirito学长-Java1 小时前
springboot/ssm网上宠物店系统Java代码编写web宠物用品商城项目
java·spring boot·后端
海绵波波1071 小时前
flask后端开发(9):ORM模型外键+迁移ORM模型
后端·python·flask
余生H1 小时前
前端Python应用指南(二)深入Flask:理解Flask的应用结构与模块化设计
前端·后端·python·flask·全栈
绝无仅有2 小时前
PHP语言laravel框架中基于Redis的异步队列使用实践与原理
后端·面试·架构
AI人H哥会Java2 小时前
【Spring】基于XML的Spring容器配置——<bean>标签与属性解析
java·开发语言·spring boot·后端·架构
计算机学长felix2 小时前
基于SpringBoot的“大学生社团活动平台”的设计与实现(源码+数据库+文档+PPT)
数据库·spring boot·后端
sin22012 小时前
springboot数据校验报错
spring boot·后端·python
去哪儿技术沙龙2 小时前
去哪儿机票智能预警系统-雷达系统落地实践
后端