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 :
- Um pod está reiniciando.
- Depois que a reinicialização do pod estiver concluída, ela continuará reiniciando.
- 告警短信大概一分钟后告警恢复。
到这里可以联想到,存活探针发送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端点如果异常,即可以通过详细信息定位到异常的组件!