Solucionar problemas de servidor de API e etcd nos Serviços de Kubernetes do Azure
Este guia foi projetado para ajudá-lo a identificar e resolver quaisquer problemas improváveis que você possa encontrar no servidor de API em grandes implantações do AKS (Serviços de Kubernetes do Microsoft Azure).
A Microsoft testou a confiabilidade e o desempenho do servidor de API em uma escala de 5.000 nós e 200.000 pods. O cluster que contém o servidor de API tem a capacidade de escalar horizontalmente e fornecer automaticamente SLOs (Objetivos de Nível de Serviço) do Kubernetes. Se você tiver altas latências ou tempos limite, provavelmente é porque há um vazamento de recursos no diretório distribuído etc
(etcd) ou um cliente ofensivo tem chamadas de API excessivas.
Pré-requisitos
A ferramenta kubectl do Kubernetes. Para instalar o kubectl usando a CLI do Azure, execute o comando az aks install-cli .
Logs de diagnóstico do AKS (especificamente, eventos kube-audit) que são habilitados e enviados para um workspace do Log Analytics. Para determinar se os logs são coletados usando o modo de diagnóstico do Azure ou específico do recurso, verifique a folha Configurações de Diagnóstico no portal do Azure.
A camada Standard para clusters do AKS. Se você estiver usando a camada Gratuita, o servidor de API e o etcd conterão recursos limitados. Os clusters do AKS na camada Gratuita não fornecem alta disponibilidade. Geralmente, essa é a causa raiz dos problemas do servidor de API e do etcd.
O plug-in kubectl-aks para executar comandos diretamente nos nós do AKS sem usar o painel de controle do Kubernetes.
Verificações básicas de integridade
Eventos de integridade de recurso
O AKS fornece eventos de integridade de recursos para tempo de inatividade de componentes críticos. Antes de continuar, verifique se não há eventos críticos relatados no Resource Health.
Diagnosticar e resolver problemas
O AKS fornece uma categoria de solução de problemas dedicada para Disponibilidade e Desempenho do Cluster e do Painel de Controle.
Sintomas
A tabela a seguir descreve os sintomas comuns de falhas do servidor de API:
Sintoma | Descrição |
---|---|
Tempos limite do servidor de API | Tempos limite frequentes que estão além das garantias no SLA do servidor de API do AKS. Por exemplo, kubectl comandos time-out. |
Altas latências | Altas latências que fazem com que os SLOs do Kubernetes falhem. Por exemplo, o kubectl comando leva mais de 30 segundos para listar pods. |
Pod do servidor de API no CrashLoopbackOff status ou enfrentando falhas de chamada de webhook |
Verifique se você não tem nenhum webhook de admissão personalizado (como o mecanismo de política Kyverno ) que está bloqueando as chamadas para o servidor de API. |
Lista de verificação de solução de problemas
Se você estiver enfrentando tempos de alta latência, siga estas etapas para identificar o cliente ofensivo e os tipos de chamadas de API que falham.
Etapa 1: Identificar os principais agentes de usuário pelo número de solicitações
Para identificar quais clientes geram mais solicitações (e potencialmente a maior carga do servidor de API), execute uma consulta semelhante ao código a seguir. A consulta a seguir lista os 10 principais agentes de usuário pelo número de solicitações de servidor de API enviadas.
AKSAudit
| where TimeGenerated between(now(-1h)..now()) // When you experienced the problem
| summarize count() by UserAgent
| top 10 by count_
| project UserAgent, count_
Observação
Se sua consulta não retornar resultados, talvez você tenha selecionado a tabela errada para consultar os logs de diagnóstico. No modo específico do recurso, os dados são gravados em tabelas individuais, dependendo da categoria do recurso. Os logs de diagnóstico são gravados na AKSAudit
tabela. No modo de diagnóstico do Azure, todos os dados são gravados na AzureDiagnostics
tabela. Para obter mais informações, confira Logs de recursos do Azure.
Embora seja útil saber quais clientes geram o maior volume de solicitações, o alto volume de solicitações por si só pode não ser motivo de preocupação. Um indicador melhor da carga real que cada cliente gera no servidor de API é a latência de resposta que eles experimentam.
Etapa 2: Identificar e mapear a latência média das solicitações do servidor de API por agente de usuário
Para identificar a latência média das solicitações do servidor de API por agente de usuário, conforme plotado em um gráfico de tempo, execute a seguinte consulta:
AKSAudit
| where TimeGenerated between(now(-1h)..now()) // When you experienced the problem
| extend start_time = RequestReceivedTime
| extend end_time = StageReceivedTime
| extend latency = datetime_diff('millisecond', end_time, start_time)
| summarize avg(latency) by UserAgent, bin(start_time, 5m)
| render timechart
Essa consulta é uma continuação da consulta na seção "Identificar os principais agentes de usuário pelo número de solicitações". Isso pode fornecer mais informações sobre a carga real gerada por cada agente de usuário ao longo do tempo.
Dica
Ao analisar esses dados, você pode identificar padrões e anomalias que podem indicar problemas no cluster ou nos aplicativos do AKS. Por exemplo, você pode notar que um determinado usuário está enfrentando alta latência. Esse cenário pode indicar o tipo de chamadas de API que estão causando carga excessiva no servidor de API ou etcd.
Etapa 3: Identificar chamadas de API inválidas para um determinado agente de usuário
Execute a seguinte consulta para tabular a latência do 99º percentil (P99) de chamadas de API em diferentes tipos de recursos para um determinado cliente:
AKSAudit
| where TimeGenerated between(now(-1h)..now()) // When you experienced the problem
| extend HttpMethod = Verb
| extend Resource = tostring(ObjectRef.resource)
| where UserAgent == "DUMMYUSERAGENT" // Filter by name of the useragent you are interested in
| where Resource != ""
| extend start_time = RequestReceivedTime
| extend end_time = StageReceivedTime
| extend latency = datetime_diff('millisecond', end_time, start_time)
| summarize p99latency=percentile(latency, 99) by HttpMethod, Resource
| render table
Os resultados dessa consulta podem ser úteis para identificar os tipos de chamadas de API que falham nos SLOs upstream do Kubernetes. Na maioria dos casos, um cliente ofensivo pode estar fazendo muitas LIST
chamadas em um grande conjunto de objetos ou objetos muito grandes. Infelizmente, não há limites rígidos de escalabilidade disponíveis para orientar os usuários sobre a escalabilidade do servidor de API. Os limites de escalabilidade do servidor de API ou do etcd dependem de vários fatores explicados em Limites de escalabilidade do Kubernetes.
Causa 1: uma regra de rede bloqueia o tráfego dos nós do agente para o servidor de API
Uma regra de rede pode bloquear o tráfego entre os nós do agente e o servidor de API.
Para verificar se uma política de rede configurada incorretamente está bloqueando a comunicação entre o servidor de API e os nós do agente, execute os seguintes comandos kubectl-aks:
kubectl aks config import \
--subscription <mySubscriptionID> \
--resource-group <myResourceGroup> \
--cluster-name <myAKSCluster>
kubectl aks check-apiserver-connectivity --node <myNode>
O comando config import recupera as informações do Conjunto de Dimensionamento de Máquinas Virtuais para todos os nós no cluster. Em seguida, o comando check-apiserver-connectivity usa essas informações para verificar a conectividade de rede entre o servidor de API e um nó especificado, especificamente para sua instância de conjunto de dimensionamento subjacente.
Observação
Se a saída do comando contiver a Connectivity check: succeeded
mensagem, a conectividade de check-apiserver-connectivity
rede será desimpedida.
Solução 1: Corrija a política de rede para remover o bloqueio de tráfego
Se a saída do comando indicar que ocorreu uma falha de conexão, reconfigure a política de rede para que ela não bloqueie desnecessariamente o tráfego entre os nós do agente e o servidor de API.
Causa 2: Um cliente ofensivo vaza objetos etcd e resulta em uma lentidão do etcd
Um problema comum é criar continuamente objetos sem excluir os não utilizados no banco de dados etcd. Isso pode causar problemas de desempenho quando o etcd lida com muitos objetos (mais de 10.000) de qualquer tipo. Um rápido aumento de alterações em tais objetos também pode fazer com que o tamanho do banco de dados etcd (4 gigabytes por padrão) seja excedido.
Para verificar o uso do banco de dados etcd, navegue até Diagnosticar e Resolver problemas no portal do Azure. Execute a ferramenta de diagnóstico de Problemas de Disponibilidade do Etcd pesquisando por "etcd" na caixa de pesquisa. A ferramenta de diagnóstico mostra o detalhamento do uso e o tamanho total do banco de dados.
Se você quiser apenas uma maneira rápida de exibir o tamanho atual do banco de dados etcd em bytes, execute o seguinte comando:
kubectl get --raw /metrics | grep -E "etcd_db_total_size_in_bytes|apiserver_storage_size_bytes|apiserver_storage_db_total_size_in_bytes"
Observação
O nome da métrica no comando anterior é diferente para diferentes versões do Kubernetes. Para o Kubernetes 1.25 e versões anteriores, use etcd_db_total_size_in_bytes
. Para o Kubernetes 1.26 a 1.28, use apiserver_storage_db_total_size_in_bytes
.
Solução 2: Defina cotas para criação de objetos, exclua objetos ou limite o tempo de vida do objeto no etcd
Para evitar que o etcd atinja a capacidade e cause tempo de inatividade do cluster, você pode limitar o número máximo de recursos criados. Você também pode diminuir o número de revisões geradas para instâncias de recursos. Para limitar o número de objetos que podem ser criados, você pode definir cotas de objetos.
Se você identificou objetos que não estão mais em uso, mas estão consumindo recursos, considere excluí-los. Por exemplo, você pode excluir trabalhos concluídos para liberar espaço:
kubectl delete jobs --field-selector status.successful=1
Para objetos que dão suporte à limpeza automática, você pode definir valores de vida útil (TTL) para limitar o tempo de vida desses objetos. Você também pode rotular seus objetos para que possa excluir em massa todos os objetos de um tipo específico usando seletores de rótulo. Se você estabelecer referências de proprietário entre objetos, todos os objetos dependentes serão excluídos automaticamente depois que o objeto pai for excluído.
Causa 3: Um cliente ofensivo faz chamadas LIST ou PUT excessivas
Se você determinar que o etcd não está sobrecarregado com muitos objetos, um cliente ofensivo pode estar fazendo muitas LIST
PUT
chamadas para o servidor de API.
Solução 3a: Ajustar seu padrão de chamada de API
Considere ajustar o padrão de chamada de API do cliente para reduzir a pressão no plano de controle.
Solução 3b: Limitar um cliente que está sobrecarregando o plano de controle
Se você não puder ajustar o cliente, poderá usar o recurso Prioridade e Imparcialidade no Kubernetes para limitar o cliente. Esse recurso pode ajudar a preservar a integridade do plano de controle e evitar que outros aplicativos falhem.
O procedimento a seguir mostra como limitar a API LIST Pods de um cliente ofensivo definida como cinco chamadas simultâneas:
Crie um FlowSchema que corresponda ao padrão de chamada de API do cliente ofensivo:
apiVersion: flowcontrol.apiserver.k8s.io/v1beta2 kind: FlowSchema metadata: name: restrict-bad-client spec: priorityLevelConfiguration: name: very-low-priority distinguisherMethod: type: ByUser rules: - resourceRules: - apiGroups: [""] namespaces: ["default"] resources: ["pods"] verbs: ["list"] subjects: - kind: ServiceAccount serviceAccount: name: bad-client-account namespace: default
Crie uma configuração de prioridade mais baixa para limitar chamadas de API inválidas do cliente:
apiVersion: flowcontrol.apiserver.k8s.io/v1beta2 kind: PriorityLevelConfiguration metadata: name: very-low-priority spec: limited: assuredConcurrencyShares: 5 limitResponse: type: Reject type: Limited
Observe a chamada limitada nas métricas do servidor de API.
kubectl get --raw /metrics | grep "restrict-bad-client"
Causa 4: um webhook personalizado pode causar um deadlock nos pods do servidor de API
Um webhook personalizado, como Kyverno, pode estar causando um deadlock nos pods do servidor de API.
Verifique os eventos relacionados ao seu servidor de API. Você pode ver mensagens de evento semelhantes ao seguinte texto:
Ocorreu um erro interno: falha ao chamar o webhook "mutate.kyverno.svc-fail": falha ao chamar o webhook: Post "https://kyverno-system-kyverno-system-svc.kyverno-system.svc:443/mutate/fail?timeout=10s": write unix @ -> / tunnel-uds / proxysocket: write: tubo quebrado
Neste exemplo, o webhook de validação está bloqueando a criação de alguns objetos do servidor de API. Como esse cenário pode ocorrer durante o tempo de inicialização, o servidor de API e os pods do Konnectivity não podem ser criados. Portanto, o webhook não pode se conectar a esses pods. Essa sequência de eventos causa o deadlock e a mensagem de erro.
Solução 4: Excluir configurações de webhook
Para corrigir esse problema, exclua as configurações de webhook de validação e mutação. Para excluir essas configurações de webhook no Kyverno, consulte o artigo de solução de problemas do Kyverno.
Aviso de isenção de responsabilidade para contatos de terceiros
A Microsoft fornece informações de contato de terceiros para ajudá-lo a encontrar informações adicionais sobre esse tópico. Essas informações de contato podem ser alteradas sem aviso prévio. A Microsoft não garante a precisão das informações de contato de terceiros.
Aviso de isenção de responsabilidade para informações de terceiros
Os produtos de terceiros mencionados neste artigo são produzidos por empresas independentes da Microsoft. A Microsoft não oferece nenhuma garantia, implícita ou não, do desempenho ou da confiabilidade desses produtos.
Entre em contato conosco para obter ajuda
Se você tiver dúvidas ou precisar de ajuda, crie uma solicitação de suporte ou peça ajuda à comunidade de suporte do Azure. Você também pode enviar comentários sobre o produto para a comunidade de comentários do Azure.