Solução de problemas de contenção de recursos

Nesta página, descrevemos como identificar e solucionar problemas de contenção de recursos no seu ambiente do Google Distributed Cloud.

Se precisar de mais ajuda, entre em contato com o Cloud Customer Care.

Visão geral

Às vezes, o Google Distributed Cloud pode enfrentar contenção de recursos, fazendo com que seus contêineres fiquem lentos, tenham um desempenho inferior ou sejam encerrados. Isso pode acontecer devido ao alto consumo de CPU ou memória pelos contêineres.

Como funciona o gerenciamento de CPU e memória

  • CPU:

    • Um pod é programado para um nó com base nas solicitações de CPU especificadas pelos contêineres no pod.
    • Um contêiner em um pod não pode usar mais CPUs do que o limite especificado pelo contêiner
    • O uso da CPU do contêiner é limitado no limite da CPU.
    • Se o uso da CPU estiver limitado no nível do nó, os contêineres serão automaticamente atribuídos aos ciclos da CPU de modo proporcional às solicitações.

    Saiba mais sobre como os pods com solicitações de recursos são programados.

  • Memória:

    • Um pod é programado para um nó com base nas solicitações de memória especificadas pelos contêineres no pod.
    • Um contêiner não pode usar mais memória do que o limite especificado pelo contêiner.
    • Se não houver um limite de memória especificado, um contêiner poderá consumir toda a memória disponível em um nó. Em seguida, o sistema pode acionar o OOM-Killer (Out Of Memory Killer) e remover os pods de baixa prioridade.

Para saber mais, consulte Atribuir recursos de CPU, Atribuir recursos de memória no Kubernetes e Métricas do GKE Enterprise.

Problemas

O contêiner fica lento

Problemas de contenção da CPU podem tornar os contêineres lentos. Confira a seguir alguns dos possíveis motivos:

Alta utilização da CPU no contêiner:

Um contêiner pode ficar lento se não receber ciclos de CPU proporcionais às solicitações da CPU ou se as solicitações da CPU tiverem sido definidas para um valor muito baixo do que o contêiner precisa. Portanto, verifique a proporção entre o limite da CPU e a utilização da CPU no contêiner.

No console do Google Cloud > Monitoring > Metrics Explorer, no editor MQL, execute a seguinte consulta:

  fetch k8s_container
  | metric 'kubernetes.io/anthos/container/cpu/limit_utilization'
  | group_by 1m, [value_limit_utilization_mean: mean(value.limit_utilization)]
  | filter resource.cluster_name == 'CLUSTER_NAME'
  | filter resource.container_name == 'CONTAINER_NAME'
  | filter resource.pod_name == 'POD_NAME'
  | filter resource.namespace_name == 'NAMESPACE_NAME'
  | every 1m

Em seguida, execute um destes procedimentos:

Alta utilização da CPU no nó

Se a proporção entre o limite de CPU e a utilização não for alta para nenhum contêiner individual do pod, é possível que o nó não tenha ciclos de CPU suficientes para alocar ao conjunto de contêineres em execução no nó. Portanto, siga estas etapas para verificar a proporção entre o uso real da CPU e as CPUs alocáveis no nó:

  1. Consiga o nó do pod que está funcionando lentamente:

    kubectl get pod –kubeconfig CLUSTER_KUBECONFIG --namespace NAMESPACE POD --output wide
    
  2. No console do Google Cloud > Monitoring > Metrics Explorer, no editor MQL, execute a seguinte consulta:

    fetch k8s_node
    | metric 'kubernetes.io/anthos/node/cpu/allocatable_utilization'
    | group_by 1m,
        [value_allocatable_utilization_mean: mean(value.allocatable_utilization)]
    | filter resource.cluster_name == 'CLUSTER_NAME'
    | filter resource.node_name == 'NODE_NAME'
    | every 1m
    

    Se essa proporção é alta (>=0,8), isso significa que o nó não tem ciclos de CPU suficientes e está com assinaturas em excesso. Então, siga estas etapas para verificar o uso da CPU para todos os outros pods nesse nó e investigar se há outro contêiner usando mais CPUs.

    1. Consiga todos os pods no nó:
    kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=NODE_NAME
    
    1. Verifique a utilização da CPU em cada contêiner:
    fetch k8s_container
    | metric 'kubernetes.io/anthos/container/cpu/limit_utilization'
    | group_by 1m, [value_limit_utilization_mean: mean(value.limit_utilization)]
    | filter resource.cluster_name == 'CLUSTER_NAME'
    | filter resource.container_name == 'CONTAINER_NAME'
    | filter resource.pod_name == 'POD_NAME'
    | filter resource.namespace_name == 'NAMESPACE_NAME'
    | every 1m
    

    Se houver outro contêiner com uma CPU alta no nó, aumente as solicitações e os limites de CPU no contêiner que esteja funcionando lentamente. Isso vai recriar o pod em outro nó para receber os ciclos de CPU necessários.

Caso seja um pod do sistema que esteja funcionando lentamente, entre em contato com o Suporte do Google.

Excesso de assinaturas da CPU no nível do vSphere

Se o consumo de CPU não estiver alto no nó ou no pod e o contêiner ainda estiver lento, a VM pode estar com excesso de assinaturas no nível do vSphere. Portanto, o nó não consegue receber os ciclos de CPU esperados da virtualização subjacente.

Siga estas etapas para verificar se a VM tem assinaturas em excesso. Se o excesso de assinaturas for detectado, tente o seguinte:

O pod é OOMkilled (Out of Memory-Killed)

Os pods podem ser OOMKilled devido a vazamentos de memória ou configuração incorreta de solicitações e limites de memória nos contêineres. Confira a seguir alguns dos possíveis motivos:

Uso elevado da memória no contêiner

Um pod poderá ser OOMkilled se algum contêiner em um pod consumir demais a memória alocada total. Portanto, verifique a proporção de solicitações de memória para os limites de memória no contêiner.

No console do Google Cloud > Monitoring > Metrics Explorer, no editor MQL, execute a seguinte consulta:

fetch k8s_container
| metric 'kubernetes.io/anthos/container/memory/limit_utilization'
| filter (metric.memory_type == 'non-evictable')
| group_by 1m, [value_limit_utilization_mean: mean(value.limit_utilization)]
| filter resource.cluster_name == 'CLUSTER_NAME'
| filter resource.container_name == 'CONTAINER_NAME'
| filter resource.pod_name == 'POD_NAME'
| filter resource.namespace_name == 'NAMESPACE_NAME'
| every 1m

Em seguida, execute um destes procedimentos:

Alto uso de memória no nó

Um pod poderá ser OOMkilled se o uso da memória de todos os pods em execução no nó exceder a memória disponível. Portanto, verifique se a condição MemoryPressure no nó é True.

  1. Execute o seguinte comando e inspecione a seção Conditions:

    kubectl describe nodes --kubeconfig CLUSTER_KUBECONFIG NODE-NAME
    
  2. Se a condição MemoryPressure for True, verifique a utilização da memória no nó:

    fetch k8s_node
    | metric 'kubernetes.io/anthos/node/memory/allocatable_utilization'
    | filter (metric.memory_type == 'non-evictable')
    | group_by 1m,
        [value_allocatable_utilization_mean: mean(value.allocatable_utilization)]
    | filter resource.cluster_name == 'CLUSTER_NAME'
    | filter resource.node_name = 'NODE_NAME'
    | every 1m
    

    Se essa proporção for alta (>= 0,8), significa que o nó não tem memória suficiente para alocar ao pod, possivelmente devido a alguns processos ou outros pods que consomem muita memória.

  3. Em console do Google Cloud > Monitoring > Metrics Explorer, no editor MQL, execute a consulta a seguir para verificar o uso da memória dos contêineres no nó:

    fetch k8s_node
    | metric 'kubernetes.io/anthos/container_memory_usage_bytes'
    | filter resource.cluster_name == 'CLUSTER_NAME'
    | filter resource.node_name == 'NODE_NAME'
    | group_by 1m,
        [value_container_memory_usage_bytes_mean:
          mean(value.container_memory_usage_bytes)]
    | every 1m
    

    Se houver um contêiner usando muita memória, investigue o funcionamento dele ou aumente a solicitação de memória do contêiner, se necessário.

Caso seja um pod do sistema que esteja consumindo muita memória, entre em contato com o Suporte do Google.

Além disso, é possível ativar o recurso de escalonamento automático no Google Distributed Cloud para aumentar e diminuir automaticamente os pools de nós com base nas demandas das cargas de trabalho.

Saiba como ativar o escalonador automático.

Problemas de etcd

Às vezes, seus clusters do Anthos no VMware podem apresentar falhas de contêiner devido a problemas de servidor do etcd, e você pode observar o seguinte:

  • Registros repetidos do servidor da API no formato:

    etcdserver: request timed out e etcdserver: leader changed

  • Registros repetidos do etcd no formato:

    W | wal: sync duration of 2.466870869s, expected less than 1s e W | etcdserver: read-only range request * took too long

Confira a seguir alguns dos possíveis motivos:

Limitação de CPU

O servidor do etcd pode estar lento devido à limitação de CPU no pod do servidor do etcd e/ou no nó em que o servidor do etcd está em execução. Consulte as etapas na seção O contêiner se torna lento para verificar se há problemas de contenção de CPU.

Se você detectar a contenção da CPU no pod do servidor do ectd ou no nó, adicione CPUs ao nó do plano de controle do cluster de usuário. Use gkectl update para editar o campo cpus no arquivo de configuração do cluster de usuário.

Pod do etcd OOMkilled

O pod do etcd pode ser OOMkilled devido a problemas de contenção de recursos. Consulte as etapas na seção O pod é OOMkilled (Out of Memory-Killed) para verificar se há problemas de contenção de memória com o pod do servidor do etcd e/ou com o nó em que o servidor do etcd está em execução.

Se você detectar OOMkills para o pod do etcd, aumente a memória disponível para o nó do plano de controle do cluster de usuário. Use gkectl update para editar o campo memoryMB no arquivo de configuração do cluster de usuário.

Lentidão do disco

Se não houver problemas com a CPU ou o consumo de memória no pod do servidor do etcd ou com o nó, o etcd pode estar lento se o repositório de dados estiver lento ou limitado.

Verifique os seguintes problemas:

  • Para verificar se o servidor do etcd está demorando muito para ler/gravar no disco:

    1. Busque os registros do etcd:

      kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG logs -n ETCD_POD_NAMESPACE ETCD_POD
      
    2. Procure as entradas do seguinte padrão para detectar se o etcd está demorando muito para ler o disco:

      W | etcdserver: read-only range request "key:\"/registry/configmaps/default/clusterapi-vsphere-controller-manager-leader-election\" " with result "range_response_count:1 size:685" took too long (6.893127339s) to execute

    3. Procure as entradas do seguinte padrão para detectar se o etcd está demorando muito para gravar no disco:

      W | wal: sync duration of 2.466870869s, expected less than 1s

    Se algum dos padrões de registro acima ou ambos forem exibidos com frequência nos registros do etcd, isso indica lentidão no disco. Em seguida, verifique o desempenho do repositório de dados e dos discos.

  • Para verificar as métricas do etcd:

    1. Busque as latências de sincronização do WAL do etcd:

      No console do Google Cloud > Monitoring > Metrics Explorer, no editor MQL, execute a seguinte consulta:

      fetch k8s_container::kubernetes.io/anthos/etcd_disk_wal_fsync_duration_seconds
      | every 1m
      | filter resource.cluster_name == 'CLUSTER_NAME'
      | filter resource.pod_name == 'POD_NAME'
      | filter resource.namespace_name == 'NAMESPACE_NAME'
      | percentile 99
      
    2. Busque as latências de gravação do etcd:

      No console do Google Cloud > Monitoring > Metrics Explorer, no editor MQL, execute a seguinte consulta:

      fetch k8s_container::kubernetes.io/anthos/etcd_disk_backend_commit_duration_seconds
      | every 1m
      | filter resource.cluster_name == 'CLUSTER_NAME'
      | filter resource.pod_name == 'POD_NAME'
      | filter resource.namespace_name == 'NAMESPACE_NAME'
      | percentile 99
      

    Se p99 para etcd_disk_wal_fsync_duration_seconds estiver continuamente acima de 10 ms e/ou p99 para etcd_disk_backend_commit_duration_seconds estiver continuamente acima de 25 ms, isso indica lentidão no disco. Em seguida, verifique o desempenho do repositório de dados e dos discos.

Latências de leitura/gravação no disco da VM

Siga estas etapas para verificar as latências de leitura/gravação no disco virtual da VM

  1. Identifique o nó do pod do etcd lento:

    kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG get pods -n ETCD_POD_NAMESPACE ETCD_POD -owide
    
  2. Faça login no vSphere e selecione a VM identificada na etapa acima: No vSphere, acesse Monitorar > Desempenho > Avançado e selecione Disco virtual, na seção Visualização, para identificar as latências de leitura e gravação dos discos virtuais.

    Se a latência de leitura/gravação do disco virtual for alta:

    • Examine outras VMs em execução no repositório de dados para verificar o alto uso de operações de entrada/saída por segundo (IOPS). Se alguma VM mostrar picos de IOPS, avalie o funcionamento dela.
    • Consulte sua equipe de laboratório/infraestrutura para garantir que a largura de banda de leitura e gravação não esteja limitada em nenhum momento.
    • Consulte sua equipe de laboratório/infraestrutura para identificar os problemas de desempenho do disco e de desempenho de armazenamento, se houver.

Para mais informações, consulte as práticas recomendadas para escalonar recursos.

Problemas com o servidor da API

Se os contêineres no Google Distributed Cloud apresentarem latência durante a comunicação com o servidor da API ou os comandos do Kubectl falharem ou demorarem muito para responder, isso pode indicar problemas com o servidor da API.

Confira a seguir alguns dos possíveis motivos:

Alto volume de solicitações de API

O servidor da API pode estar lento para responder se a frequência e o volume das solicitações forem muito altos. O tempo de resposta lento pode persistir mesmo depois que o servidor de API começar a limitar as solicitações. Portanto, verifique a taxa de solicitações de API no servidor de API.

No console do Google Cloud > Monitoring > Metrics Explorer, no editor MQL, execute a seguinte consulta:

fetch k8s_container::kubernetes.io/anthos/apiserver_request_total
| filter resource.cluster_name == 'CLUSTER_NAME'
| filter resource.pod_name == 'APISERVER_POD_NAME'
| filter resource.namespace_name == 'NAMESPACE_NAME'
| align rate(1m)
| every 1m
| group_by [metric.verb]

Se houver um aumento inesperado nas solicitações da API, use o Cloud Audit Logging para identificar o pod que pode estar consultando o servidor de API com muita frequência.

  • Se for um pod do sistema, entre em contato com o Suporte do Google.
  • Se for um pod de usuário, investigue mais para determinar se as solicitações da API são esperadas.

Limitação de CPU

A alta taxa de solicitações no servidor da API pode levar à limitação da CPU. O servidor de API pode ficar lento devido à contenção de CPU no pod e/ou no nó do servidor.

Consulte a seção O contêiner fica lento para verificar se há problemas de contenção de CPU com o pod e/ou o nó.

Pod do servidor de API OOMkilled

O pod do servidor da API pode ser OOMkilled devido a problemas de contenção de recursos. Consulte as etapas na seção O pod é OOMkilled (Out of Memory-Killed) para verificar se há problemas de contenção de memória com o pod e/ou o nó.

Respostas lentas do etcd

O servidor de API depende da comunicação com o cluster do etcd para atender às solicitações de leitura/gravação dos clientes. Se o etcd estiver lento ou não responder, o servidor da API também ficará lento.

Busque os registros do servidor da API para verificar se ele está lento devido a problemas do etcd:

kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG logs -n APISERVER_NAMESPACE APISERVER_POD_NAME

Se você observar os registros recorrentes como etcdserver: request timedout ou etcdserver: leader changed, siga as etapas em Problemas do etcd para resolver problemas relacionados ao disco.

Se o cluster não exportar métricas

As técnicas mostradas anteriormente neste documento dependem da exportação de métricas do cluster para um projeto do Google Cloud.

Se o cluster não exportar métricas, use a linha de comando para investigar a contenção de recursos. Estes são alguns comandos que você pode executar na sua estação de trabalho do administrador para conferir as métricas.

Veja as métricas de um nó:

kubectl --kubeconfig CLUSTER_KUBECONFIG get --raw \
    /apis/metrics.k8s.io/v1beta1/nodes/NODE_NAME | jq

Substitua:

  • CLUSTER_KUBECONFIG: o caminho do arquivo kubeconfig do cluster
  • NODE_NAME: o nome do nó

Veja as métricas de um pod:

kubectl --kubeconfig CLUSTER_KUBECONFIG get --raw \
    /apis/metrics.k8s.io/v1beta1/namespaces/NAMESPACE/pods/POD_NAME | jq

Substitua:

  • NAMESPACE: o namespace do pod
  • POD_NAME: o nome do pod

Ver métricas de todos os nós:

kubectl --kubeconfig CLUSTER_KUBECONFIG top node

Veja as métricas de todos os pods em um namespace:

kubectl --kubeconfig CLUSTER_KUBECONFIG top pod --namespace NAMESPACE

Veja as métricas dos contêineres em todos os pods de um namespace:

kubectl --kubeconfig CLUSTER_KUBECONFIG top pod --containers --namespace NAMESPACE

Para mais informações, consulte kubectl top pod e kubectl top node

Também é possível executar o comando top de dentro de um contêiner em execução em um nó.

Confira duas maneiras de executar um comando dentro de um contêiner:

A seguir

Se precisar de mais ajuda, entre em contato com o Cloud Customer Care.