本文深入了解CrashLoopBackOff错误的含义,为什么会发生,以及如何排除故障,让你的Kubernetes Pods快速恢复并在它们发生时快速运行。
CrashLoopBackOff听起来可能像90年代摇滚乐队的名字,也可能是70年代林戈·斯塔尔(Ringo Starr)的一首晦涩的歌曲。但实际上,crashloopbackoff与音乐产业没有任何关系,一切都与Kubernetes的性能和可靠性有关。由于各种原因,Kubernetes Pods可能会以一种称为CrashLoopBackOff的状态结束,除非你修复它,否则依赖于这些Pods的任何应用程序都不能正确运行。
什么是CrashLoopBackOff错误?
CrashLoopBackOff错误是Kubernetes Pod内的容器重新启动并随后崩溃的一种情况。当这种情况发生时,Kubernetes将开始在重新启动之间引入延迟-称为回退期,以便给管理员时间来纠正触发反复崩溃的任何问题。
因此,尽管CrashLoopBackOff听起来像是一个毫无意义的术语,但仔细想想它实际上是有意义的:它指的是容器处于重复崩溃循环中的一种状态,在崩溃之间引入了回退期。
CrashLoopBackOff的原因
虽然所有的CrashLoopBackOff状态都会导致相同类型的问题——一个永不结束的崩溃循环——但有许多潜在的原因:
- ImagePullBackOff:你的容器可能不能正常启动,因为一个镜像不能正常获取。
- OutOfMemory (OOM):容器可能超出其允许的内存限制。
- 配置错误:不恰当的环境变量或命令参数等配置问题可能会触发崩溃循环。
- 应用程序bug:应用程序代码中的错误可能会导致容器在启动后不久就崩溃。
- 资源冲突:多个容器可能会竞争相同的资源,导致它们崩溃。
- 持久存储问题:如果访问持久存储卷出现问题,容器可能无法正常启动。
- 网络连接问题:可能是由网络配置问题或网络故障引起的,会触发崩溃。
简而言之,基本上任何可能导致容器在启动后立即崩溃的情况都有可能导致CrashLoopBackOff状态。如果容器反复尝试重新启动并且反复失败,则会得到此错误。
在Kubernetes中,CrashLoopBackOff错误看起来像什么?
当CrashLoopBackOff事件发生时,Kubernetes控制台上没有红灯开始闪烁。Kubernetes并没有明确地警告你这个问题。但是你可以通过以下命令检查Pods的状态来弄清楚:
kubectl get pods -n demo-ng
(demo-ng是pod所在的命名空间,顾名思义,它是一个演示名称)。
如果你看到如下结果,你就知道你有一个CrashLoopBackOff问题:
NAME READY STATUS RESTARTS AGE
adservice-79f74f8b7-92lqr 1/1 Running 14 (5m25s ago) 42m
cartservice-74d857d84-ddhsv 1/1 Running 15 (95s ago) 42m
checkoutservice-7db49c4d49-7cv5d 0/1 CrashLoopBackOff 16 (106s ago) 42m
currency-service-7b4d8694d4-tttrz 1/1 Running 0 42m
currencyservice-75df859666-5858z 0/1 CrashLoopBackOff 16 (100s ago) 42m
email-service-7995bddbb9-774fv 1/1 Running 0 42m
emailservice-865447b4d8-xs48l 1/1 Running 3 (31m ago) 42m
eventfetcherservice-575cb8f9fc-g5spx 1/1 Running 0 42m
favorites-service-7b9dcfb85d-z9gzk 1/1 Running 0 42m
具体来说,在上面的例子中,有两个pod遇到了这个问题——currencyservice和checkoutservice Pods。
如果你看到pod不是处于Ready状态,或者已经重新启动了多次(可以通过查看kubectl输出的重启列中的重新启动计数来检查),也可能会出现CrashLoopBackOff错误。尽管这些条件并不一定意味着CrashLoopBackOff错误,但它们可能发生其他错误,即使Kubernetes没有显式地将Pod状态描述为CrashLoopBackOff。
故障排除和修复CrashLoopBackOff错误
当然,知道存在CrashLoopBackOff问题只是解决问题的第一步。你需要深入研究CrashLoopBackOff错误的原因,并找出解决它们的方法。
检查Pod描述
这个过程的第一步是使用kubectl describe Pod命令获取尽可能多的Pod信息。例如,如果你正在排除上面看到的checkoutservice-7db49c4d49-7cv5d Pod中的CrashLoopBackOff错误,您可以运行:
kubectl describe pod -n demo-ng checkoutservice-7db49c4d49-7cv5d
将看到如下输出:
Name: checkoutservice-7db49c4d49-7cv5d
Namespace: demo-ng
Priority: 0
Node: ip-172-31-21-64.eu-west-3.compute.internal/172.31.21.64
Start Time: Mon, 06 Feb 2023 13:24:51 +0200
Labels: app=checkoutservice
app.kubernetes.io/version=9ed644f
pod-template-hash=7db49c4d49
skaffold.dev/run-id=4cf3c87d-76f0-498a-8616-80276ea71596
Annotations: app.kubernetes.io/repo: https://github.com/groundcover-com/demo-app
kubernetes.io/psp: eks.privileged
Status: Running
IP: 172.31.28.25
IPs:
IP: 172.31.28.25
Controlled By: ReplicaSet/checkoutservice-7db49c4d49
Containers:
checkoutservice:
Container ID: docker://1f34cd7a1a44473c0521d53fc082eb7171edf666925048e0051ac5654d7a2fd1
Image: 125608480246.dkr.ecr.eu-west-3.amazonaws.com/checkoutservice:9ed644f@sha256:a9d3f3bf80b3c31291595733025b8a6e0a87796b410d7baacc5bd9eee95dd180
Image ID: docker-pullable://125608480246.dkr.ecr.eu-west-3.amazonaws.com/checkoutservice@sha256:a9d3f3bf80b3c31291595733025b8a6e0a87796b410d7baacc5bd9eee95dd180
Port: 5050/TCP
Host Port: 0/TCP
State: Waiting
Reason: CrashLoopBackOff
Last State: Terminated
Reason: Error
Exit Code: 2
Started: Mon, 06 Feb 2023 14:05:35 +0200
Finished: Mon, 06 Feb 2023 14:06:03 +0200
Ready: False
Restart Count: 16
Limits:
cpu: 200m
memory: 128Mi
Requests:
cpu: 100m
memory: 64Mi
Liveness: exec [/bin/grpc_health_probe -addr=:5050] delay=0s timeout=1s period=10s #success=1 #failure=3
Readiness: exec [/bin/grpc_health_probe -addr=:5050] delay=0s timeout=1s period=10s #success=1 #failure=3
Environment:
PORT: 5050
PRODUCT_CATALOG_SERVICE_ADDR: productcatalogservice:3550
SHIPPING_SERVICE_ADDR: shippingservice:50051
PAYMENT_SERVICE_ADDR: paymentservice:50051
EMAIL_SERVICE_ADDR: emailservice:5000
CURRENCY_SERVICE_ADDR: currencyservice:7000
CART_SERVICE_ADDR:
在查看输出时,应特别注意以下事项:
- pod定义
- 容器
- 容器镜像获取
- 容器资源的分配
- 参数错误/或缺失
在上面的示例中,你可以看到准备就绪探测失败了。还要注意Warning BackOff…restarting failed容器消息。这是关联重启循环的事件。即使多次重新启动,也应该只有一行。
检查Pod事件
也可以使用kubectl get events命令来获取这些信息:
kubectl get events -n demo-ng --field-selector
involvedObject.name=checkoutservice-7db49c4d49-7cv5d
输出如下:
请注意,这些是我们通过描述Pod得到的相同信息。
查看容器日志
在这一点上,我们已经知道了为什么容器会重启——准备就绪探针失败和反复失败的重启有关——但我们仍然不知道这些事情发生的确切原因。
我们查一下容器日志看看能不能找到线索。我们运行:
kubectl logs -n demo-ng checkoutservice-7db49c4d49-7cv5d --all-containers
输出如下:
{"message":"starting to load data…","severity":"info","timestamp":"2023-02-06T12:11:49.985473135Z"}
{"message":"[PlaceOrder] user_id=\"d7f14948-0863-4ae9-a26e-92eeb1fbb7ae\" user_currency=\"USD\"","severity":"info","timestamp":"2023-02-06T12:13:36.450163905Z"}
{"message":"executing data currency conversion script"","severity":"info","timestamp":"2023-02-06T12:11:49.986148642Z"}
{"message":"no such file or directory: /Users/my_user/bin/currency_script.sh","severity":"error","timestamp":"2023-02-06T12:13:07.597217324Z"}
遗憾的是,这在很多情况下可能没有帮助。但是在我们的例子中——应用程序错误指出了CrashLoopBackOff的根本原因——应用程序试图运行一个找不到的脚本。在这种情况下,应用程序的错误可以帮助我们解决问题,并消除CrashLoopBackoff..
查看ReplicaSet
在其他情况下,容器日志没有提供线索的话,我们需要继续挖掘。可以通过检查控制Pod的工作负载来寻找更多线索。
控制Pod的ReplicaSet可能包含导致CrashLoopBackOff的错误配置。
当我们描述Pod时,我们看到了以下内容:
Controlled By: ReplicaSet/checkoutservice-7db49c4d49
这一行告诉我们Pod是ReplicaSet的一部分。因此,通过描述ReplicaSet来调查控制Pod的ReplicaSet,如下所示:
kubectl describe replicasets.apps -n demo-ng checkoutservice-7db49c4d49
结果可能会帮助我们发现工作负载中控制checkout服务的更深层次的配置,这可能是继续结局问题的好方法。
kubernetes中防止CrashLoopBackOff错误的最佳实践
当然,相比能够轻松地排除crashloopbackoff故障更好的方法是在一开始就防止问题的发生。虽然你不能预测pod可能发生CrashLoopBackOff的原因,但你可以遵循一些最佳实践来降低这类问题的风险:
- 正确配置资源限制:确保你为容器设置了合理的资源限制,这样资源的缺乏就不会导致容器无法启动。
- 在部署之前测试容器镜像:在部署Pod之前,测试是识别获取容器镜像及其依赖关系问题的好方法。
- 监控网络连接和持久存储:有很多原因需要监控网络和存储,但识别可能导致crashloopbackoff的问题是其中最主要的原因。
- 实现健壮的错误处理:错误处理得越好,应用程序遇到CrashLoopBackOff情况的几率就越低。
缓解CrashLoopBackOffs
在一个完美的世界里,你的容器和pod每次都能完美启动。
在现实世界中,Kubernetes管理员制定的最好的计划并不如您所期望的那样。有时,意想不到的错误会导致pod处于CrashLoopBackOff状态。
幸运的是,只需借助kubectl的一点帮助,就可以很容易地找到这些错误的根本原因——或者更好的是,可以使用一些检测工具,深入、持续地查看Kubernetes集群中的容器、pod和其他所有东西。