Lembre-se dos problemas causados por uma verificação de integridade do k8s

fundo do problema

O celular recebeu uma mensagem de texto de aviso e a interface do ambiente online está anormal! ! ! O conteúdo do alarme é que um determinado código de status da API de serviço externo é anormal e o código de status é 500. O mocinho foi até a plataforma PaaS (KuberSphere) verificar na primeira reação, e constatou que um pod do serviço estava reiniciando, e continuou reiniciando após o reinício. Neste momento, outra mensagem de recuperação de alarme foi recebida (cerca de um minuto após a mensagem de alarme) e o código de status era 200. . . Este artigo discute esta questão.

exame de saúde k8s

sonda k8s

As sondagens k8s são diagnósticos periódicos executados pelo kubelet em contêineres. Para realizar diagnósticos, o kubelet chama o Handler implementado pelo container . Existem três tipos de manipuladores:

  • ExecAction : Executa o comando especificado dentro do contêiner. O diagnóstico é considerado bem-sucedido se o comando sair com um código de retorno 0.
  • CPSocketAction : executa uma verificação de TCP no endereço IP do contêiner na porta especificada. O diagnóstico é considerado bem-sucedido se a porta estiver aberta.
  • HTTPGetAction : executa uma solicitação HTTP Get para o endereço IP do contêiner na porta e no caminho especificados. Um diagnóstico é considerado bem-sucedido se a resposta tiver um código de status maior ou igual a 200 e menor que 400.

sonda de verificação de integridade do k8s

  • livenessProbe (sonda de sobrevivência) : é usado para determinar se o contêiner está ativo (estado de execução). Se a sonda livenessProbe detectar que o contêiner não está íntegro, o kubelet "matará" o contêiner e fará o processamento correspondente de acordo com a estratégia de reinicialização do contêiner . Se um contêiner não contiver um teste livenessProbe, o kubelet pensará que o valor retornado pelo teste livenessProbe do contêiner sempre será Success.
  • readinessProbe (sonda de prontidão) : Usado para determinar se o serviço de contêiner está disponível (estado Pronto) e o Pod que atinge o estado Pronto pode receber solicitações. Para o pod gerenciado pelo serviço, o relacionamento entre o serviço e o PodEndpoint também será definido com base no fato de o pod estar pronto. Se o status Pronto se tornar falso durante o processo em execução, o sistema irá isolá-lo automaticamente da lista de Endpoints de back-end do serviço e, em seguida, adicionar o Pod restaurado ao estado Pronto de volta à lista de Endpoints de back-end.
  • startupProbe (sonda de inicialização) : Se startupProbe estiver configurado, outras sondagens serão proibidas até que seja bem-sucedida e nenhuma outra sondagem será executada após o sucesso. É mais adequado para cenários em que o tempo de inicialização do contêiner é longo. Requer kubernetes versão v1.18 ou superior.

identifique o problema

As verificações de integridade que configuramos são as seguintes:

livenessProbe:
  httpGet:
    path: /actuator/health
    port: 8080
    scheme: HTTP
  initialDelaySeconds: 90
  timeoutSeconds: 3
  periodSeconds: 10
  successThreshold: 1
  failureThreshold: 3
readinessProbe:
  httpGet:
    path: /actuator/health
    port: 8080
    scheme: HTTP
  initialDelaySeconds: 90
  timeoutSeconds: 3
  periodSeconds: 10
  successThreshold: 1
  failureThreshold: 3
复制代码

Aqui estão alguns significados de configuração da seguinte forma:

configuração significado
httpGet.path obter caminho de solicitação
httpGet.port obter porta de solicitação
httpGet.scheme obter protocolo de solicitação
initialDelaySeconds Atraso inicial, em segundos, quanto tempo um contêiner deve esperar após iniciar antes de verificar sua integridade.
timeoutSeconds Tempo limite (em segundos), quanto tempo esperar para que o probe seja concluído. Se o tempo for excedido, considera-se que a sonda falhou. O padrão é 1 segundo. O valor mínimo é 1.
periodSegundos Frequência de execução da sondagem (segundos), com que frequência realizar a sondagem, em segundos. O padrão é 10 segundos. O valor mínimo é 1.
limiar de sucesso Limite de integridade, após a detecção falhar, a detecção bem-sucedida mínima consecutiva é bem-sucedida. O valor padrão é 1. O valor mínimo é 1. Deve ser 1 na sonda de vivacidade e iniciar a sondagem.
limite de falha Limite não íntegro, o número mínimo de falhas de investigação consecutivas necessárias para que a investigação entre no estado de falha.

O documento de configuração fornecido pela empresa não inclui a configuração do probe de inicialização. Supõe-se que a versão do k8s implantada não suporte o probe de inicialização.

Do pano de fundo do problema, extraímos alguns pontos- chave :

  1. Um pod está reiniciando.
  2. Depois que a reinicialização do pod estiver concluída, ela continuará reiniciando.
  3. 告警短信大概一分钟后告警恢复。

到这里可以联想到,存活探针发送get请求获取到的响应的状态码不在 200 和 400之间或者直接超时,所以容器重启直接影响服务,告警通知;但是配置的初始延迟为90秒太短导致一直重启;就在这时就绪探针判断 Ready 状态变为False,则系统自动将其从 Service 的后端 Endpoint 列表中隔离出去,故障 pod 排除掉之后,告警恢复。

是什么原因导致正在运行的容器,PaaS平台是有事件日志的,当时忘记截图了(盘的时候查不到了)... 记得当时有http超时事件,也有状态码为503的事件。超时可能是网络波动或者大概率是初始延迟设置过短。那么这个503状态码到底是为什么呢?

Actuator

Actuator是Springboot的一个模块,模块提供了Spring Boot的所有生产就绪功能。

Endpoints

Actuator 端点允许您监视应用程序并与之交互。 Spring Boot 包括许多内置端点,并允许您添加自己的端点。 例如,提供基本的应用程序运行状况信息的 health 端点。

Actuator的health端点

我们配置健康检查用的接口就是Actuator提供的 health 端点接口。像我们引入DB依赖,Nacos依赖啥的,这些依赖实现了Actuator的health策略接口HealthIndicator,请求health端点的时候就会调用策略实现类检查健康状况。

health端点的返回会返回一个status,可以通过配置management.endpoint.health.show-details=always设置返回详细信息。

下边是一个详细信息的返回值。

{
    "components":{
        "db":{
            "components":{
                "dataSource":{
                    "details":{
                        "database":"MySQL",
                        "result":1,
                        "validationQuery":"/* ping */ SELECT 1"
                    },
                    "status":{
                        "code":"UP",
                        "description":""
                    }
                },
                "dataSource2":{
                    "details":{
                        "database":"MySQL",
                        "result":1,
                        "validationQuery":"/* ping */ SELECT 1"
                    },
                    "status":{
                        "code":"UP",
                        "description":""
                    }
                }
            },
            "status":{
                "code":"UP",
                "description":""
            }
        },
        "discoveryComposite":{
            "components":{
                "discoveryClient":{
                    "details":{
                        "services":[
                            "***",
                            "***",
                            "***-gateway"
                        ]
                    },
                    "status":{
                        "code":"UP",
                        "description":""
                    }
                }
            },
            "status":{
                "code":"UP",
                "description":""
            }
        },
        "diskSpace":{
            "details":{
                "total":"528309530624",
                "free":"463192977408",
                "threshold":10485760
            },
            "status":{
                "code":"UP",
                "description":""
            }
        },
        "mail":{
            "details":{
                "location":"10.************:25"
            },
            "status":{
                "code":"UP",
                "description":""
            }
        },
        "ping":{
            "details":{

            },
            "status":{
                "code":"UP",
                "description":""
            }
        },
        "refreshScope":{
            "details":{

            },
            "status":{
                "code":"UP",
                "description":""
            }
        }
    },
    "groups":[

    ],
    "status":{
        "code":"UP",
        "description":""
    }
}
复制代码

返回的Status的code编码有四种。

/**
 * 指示组件或子系统处于未知状态。
 */
public static final Status UNKNOWN = new Status("UNKNOWN");

/**
 * 指示组件或子系统按预期运行。
 */
public static final Status UP = new Status("UP");

/**
 * 指示组件或子系统发生了意外故障。
 */
public static final Status DOWN = new Status("DOWN");

/**
 * 指示组件或子系统已从服务中取出,不应再使用。
 */
public static final Status OUT_OF_SERVICE = new Status("OUT_OF_SERVICE");
复制代码

翻看源码看到了这四个编码与http状态码的关系,即 DOWN 和 OUT_OF_SERVICE 会返回http状态码 503,其他返回200状态码。

health端点如果异常,即可以通过详细信息定位到异常的组件!

Acho que você gosta

Origin juejin.im/post/7215253602204418104
Recomendado
Clasificación