一个supervisor和k8s健康检查的问题

1,054 阅读10分钟

情景描述

本周三晚上,QA进行攻防演练,将k8s中部署的服务给搞挂了,直接“午夜凶铃”就在我的手机上响起来了。半梦半醒之间,我赶忙爬起来,排查问题。 image.png


问题提出

服务进程已经托管给supervisor了,supervisor管理进程后,进程挂了,为什么没自动拉起来

不知道supervisor是什么的小伙伴可以参考这篇文章 一个让女朋友开心的工具


问题溯源

我们先来看一下在哪些情况下,supervisor不会自动拉起挂掉的进程

当一个进程被Supervisor管理时,Supervisor会监控该进程的状态并尝试重新启动它,以确保进程持续运行。然而,如果进程在挂掉后没有自动重新拉起来,可能有以下几个原因:

  1. 配置问题:可能是Supervisor的配置文件中存在错误,导致无法正确地启动进程或重新拉起进程。检查Supervisor配置文件,确保进程的相关配置正确无误。

  2. 重试次数限制:Supervisor通常会在进程失败后尝试重新启动它,但可能限制了重试的次数。这可以通过Supervisor的配置参数进行设置。检查Supervisor的配置文件,查看重试次数的设置。

  3. 进程无法正常退出:如果进程没有正常退出(例如出现了无限循环或其他错误),Supervisor可能无法检测到进程已经挂掉,因此无法重新拉起它。确保进程能够正常退出,并检查进程的日志文件以查找可能的错误信息。

  4. 依赖问题:如果进程依赖于其他组件或服务,并且这些依赖项没有正确地配置或启动,那么Supervisor可能无法自动拉起进程。确保所有必要的依赖项都已正确配置和启动。

  5. Supervisor自身故障:极少数情况下,Supervisor本身可能出现问题,导致无法正确管理进程。在这种情况下,您可以尝试重启Supervisor服务或查看Supervisor的日志文件以获取更多信息。

总之,当Supervisor无法自动拉起进程时,需要检查Supervisor的配置、进程的状态以及可能的依赖关系,以确定问题的根本原因。

上述的原因在经过检查后,发现只有2,可能存在问题


排查重试次数限制

首先看一下配置次数的示例:

[supervisord]
logfile=/var/log/supervisor/supervisord.log  ; Supervisor日志文件的路径
logfile_maxbytes=50MB                         ; 日志文件的最大大小
logfile_backups=10                            ; 日志文件的备份数量
loglevel=info                                 ; 日志级别(可选值:debug、info、warning、error、critical)

[program:myapp]
command=/path/to/myapp                      ; 要执行的命令或脚本
directory=/path/to/app/directory            ; 进程工作目录
user=myuser                                 ; 执行进程的用户
autostart=true                              ; 是否自动启动进程
autorestart=true                            ; 是否在进程退出后自动重启
startsecs=3                                 ; 启动进程后等待多少秒进行健康检查
startretries=5                              ; 重试次数
redirect_stderr=true                        ; 是否将标准错误输出重定向到日志文件
stdout_logfile=/var/log/myapp.log           ; 进程标准输出的日志文件路径

[group:myappgroup]
programs=myapp

[eventlistener:myapprestart]
command=/path/to/restart_script.py
events=PROCESS_STATE_EXITED
process_name=%(program_name)s_%(process_num)s
numprocs=2                              ; 启动两个进程
numprocs_start=1                        ; 起始索引为1


; [program:anotherapp]
; command=/path/to/anotherapp
; ...

; 可以在同一个配置文件中定义多个进程,每个进程使用一个[program:<name>]部分

在示例配置文件中,[supervisord]部分定义了Supervisor的全局配置,包括日志文件的路径和相关设置。

[program:myapp]部分定义了一个名为"myapp"的进程,其中指定了要执行的命令、工作目录、用户、自动启动和自动重启等参数。根据实际情况添加多个类似的[program:<name>]部分,以定义更多的进程。然后,我们定义了一个名为"myapprestart"的事件监听器。该事件监听器的command参数指定了一个重启脚本的路径。

在事件监听器部分,我们使用了numprocs参数设置为2,表示要启动两个进程。numprocs_start参数设置为1,表示起始索引为1。这意味着第一个进程将具有索引1,第二个进程将具有索引2。通过这种设置,Supervisor将自动重启挂掉的进程,并在重启时使用递增的索引。

检查服务的配置文件发现,并没有限制supervisor的重试次数,所以与此无关

image.png


经过上述这一点的排查,我突然想到,k8s的健康检查是怎么做的呢,会不会跟这个有关系

k8s的健康检查是怎么做的

查找资料

Kubernetes(K8s)提供了多种方式进行健康检查,以确保容器或应用程序在集群中的运行状态。以下是Kubernetes中常用的健康检查方式:

  1. 就绪探针(Readiness Probe):就绪探针用于确定应用程序是否已经准备好接收流量。Kubernetes将定期向容器发送HTTP请求、TCP连接或执行命令,并根据返回的状态码或响应结果来判断容器是否已经就绪。如果就绪探针失败,Kubernetes会将容器从服务负载均衡器中暂时剔除,直到容器重新就绪。

  2. 存活探针(Liveness Probe):存活探针用于确定容器是否仍然在运行,并且能够正常处理请求。类似于就绪探针,Kubernetes定期向容器发送HTTP请求、TCP连接或执行命令,并根据返回的状态码或响应结果来判断容器的存活状态。如果存活探针失败,Kubernetes会重新启动容器或标记容器为失败状态,并触发重启策略。

  3. 启动探针(Startup Probe):启动探针用于确定容器是否已经成功启动。它在容器启动后的初始阶段进行检查,与就绪探针和存活探针不同,它不会影响容器的就绪状态或存活状态。启动探针可以帮助Kubernetes等待应用程序的启动过程完成,然后再将其纳入服务负载均衡器。

这些健康检查方式可以通过在Kubernetes配置文件(如Deployment或Pod描述文件)中定义来启用。您可以指定探针的类型(HTTP、TCP或命令执行)、路径、端口、超时时间以及成功或失败的阈值等参数。Kubernetes会定期执行这些探针,并根据结果来决定容器的状态和行为。

通过使用这些健康检查方式,Kubernetes可以自动监测和管理容器的健康状态,确保应用程序在集群中的可用性和稳定性。

请教运维老师 问题.png

k8s的健康检查原理得到证实

查看配置文件

image.png

发现容器的健康检查被关闭了,且修改了检测的服务端口号


问题继续探索

如果把健康检查关闭,supervisor还会重新拉起挂掉的pod吗?


如果将Kubernetes中的健康检查功能关闭,Supervisor将无法直接重新拉起挂掉的Pod。这是因为Supervisor通常依赖于健康检查来确定进程的状态,并在进程失败时触发重新启动。健康检查是Kubernetes的一项关键功能,用于监控容器的健康状态,并根据需要自动重启或替换不健康的容器。

当健康检查被关闭时,Kubernetes将无法及时检测到容器的故障或不健康状态,因此无法主动触发重新拉起。这可能会导致挂掉的Pod长时间处于不可用状态,而无法得到自动修复。

关闭健康检查功能可能会导致以下问题:

  1. 不可用性:如果一个Pod挂掉,但没有健康检查来监测并触发重新拉起,该Pod将继续处于故障状态,无法提供正常的服务,导致应用程序的不可用性。

  2. 资源浪费:没有健康检查来检测不健康的Pod,Kubernetes将无法自动替换故障的Pod。这可能导致资源浪费,因为不健康的Pod可能继续占用节点资源,而无法被自动替换。

因此,建议在Kubernetes中保持健康检查功能的启用,以便及时检测和处理不健康的Pod。健康检查有助于确保应用程序的高可用性和稳定性,并使Supervisor能够有效地重新拉起挂掉的Pod。


结论得出

服务不可用的原因是QA手动kill掉了运行中的pod,并且关闭了健康检查且修改了健康检查所监听的服务端口号,导致即使服务挂掉,supervisor也无法自动拉起服务。


补充知识

k8s的健康检查是什么?

Kubernetes(K8s)的健康检查是一种机制,用于监测和管理容器或应用程序的健康状态。它通过定期检查容器或应用程序的可用性和正确性,以确保它们能够正常运行并提供服务。

健康检查通常包括以下几个方面:

  1. 就绪性检查(Readiness Check):用于确定容器是否已准备好接收流量。就绪性检查确保容器已完成启动过程、初始化必要的资源并已连接到所需的依赖项。只有通过了就绪性检查的容器才会被认为是可用的,并将接收流量。

  2. 存活性检查(Liveness Check):用于确定容器是否仍然存活和正常工作。存活性检查定期检测容器的状态,例如发送HTTP请求、检查TCP连接或执行自定义命令。如果容器未通过存活性检查,则Kubernetes会认为容器已故障,并根据定义的重启策略(如重启策略为"Always")来重新启动容器。

为什么需要健康检查呢?

  1. 故障恢复:健康检查能够自动检测容器或应用程序的故障,并触发相应的故障恢复机制。如果容器发生故障或无法正常提供服务,Kubernetes可以自动将其重新启动或替换为新的容器,从而提高应用程序的可用性。

  2. 负载均衡:健康检查对于负载均衡非常重要。通过将健康检查与负载均衡器结合使用,Kubernetes可以根据容器的健康状态来决定是否将流量转发给它们。只有通过健康检查的容器才会被纳入负载均衡器,以确保将流量分配给可用和健康的容器。

  3. 避免服务瘫痪:通过定期检查容器或应用程序的健康状态,Kubernetes能够避免将流量发送到不可用或不正常的容器。这有助于防止由于故障容器的存在而导致整个服务瘫痪的情况发生。

总而言之,健康检查是Kubernetes中重要的功能之一,它通过定期检测容器的状态来提高应用程序的可用性、故障恢复能力和负载均衡效果,确保容器能够持续地提供稳定和可靠的服务。

写在最后

感谢大家的阅读,晴天将继续努力,分享更多有趣且实用的主题,如有错误和纰漏,欢迎给予指正。 更多文章敬请关注作者个人公众号 晴天码字