Resolução de problemas do tempo de execução do contentor

Este documento fornece passos de resolução de problemas para problemas comuns que pode encontrar com o tempo de execução do contentor nos seus nós do Google Kubernetes Engine (GKE).

Os caminhos de montagem com letras do disco simples falham em pools de nós do Windows com o containerd

Este problema foi resolvido na versão 1.6.6 e superior do containerd.

Os clusters do GKE que executam pools de nós do Windows Server que usam o tempo de execução do containerd antes da versão 1.6.6 podem ter erros ao iniciar contentores, como os seguintes:

failed to create containerd task : CreateComputeSystem : The parameter is incorrect : unknown

Para mais detalhes, consulte o problema do GitHub n.º 6589.

Solução

Para resolver este problema, atualize os seus conjuntos de nós para as versões mais recentes do GKE que usam a versão 1.6.6 ou superior do tempo de execução do containerd.

As imagens de contentores com linhas de comandos CMD ou ENTRYPOINT pré-escapadas que não são de matriz falham em pools de nós do Windows com o containerd

Este problema foi resolvido na versão 1.6 e superior do containerd.

Os clusters do GKE que executam pools de nós do Windows Server que usam o tempo de execução do containerd 1.5.X podem ter erros ao iniciar contentores, como os seguintes:

failed to start containerd task : hcs::System::CreateProcess : The system cannot find the file specified.: unknown

Para mais detalhes, consulte o problema do GitHub n.º 5067 e o problema do GitHub n.º 6300.

Solução

Para resolver este problema, atualize os seus conjuntos de nós para as versões mais recentes do GKE que usam a versão 1.6.6 ou superior do tempo de execução do containerd.

Os volumes de imagens de contentores com caminhos inexistentes ou caminhos semelhantes aos do Linux (barra invertida) falham em pools de nós do Windows com o containerd

Este problema foi resolvido na versão 1.6 e superior do containerd.

Os clusters do GKE que executam pools de nós do Windows Server que usam o tempo de execução do containerd 1.5.X podem ter erros ao iniciar contentores, como os seguintes:

failed to generate spec: failed to stat "<volume_path>": CreateFile : The system cannot find the path specified.

Para mais detalhes, consulte o problema n.º 5671 do GitHub.

Solução

Para resolver este problema, atualize os seus conjuntos de nós para as versões mais recentes do GKE que usam a versão 1.6.x ou superior do tempo de execução do containerd.

/etc/mtab: esse ficheiro ou diretório não existe

O tempo de execução do contentor Docker preenche este link simbólico no contentor por predefinição, mas o tempo de execução do containerd não o faz.

Para mais detalhes, consulte o problema do GitHub n.º 2419.

Solução

Para resolver este problema, crie manualmente o link simbólico /etc/mtab durante a criação da imagem.

ln -sf /proc/mounts /etc/mtab

Erro de obtenção de imagem: não é um diretório

Versões do GKE afetadas: todas

Quando cria uma imagem com kaniko, pode não ser possível extraí-la com o containerd e é apresentada a mensagem de erro "not a directory" (não é um diretório). Este erro ocorre se a imagem for criada de uma forma especial: quando um comando anterior remove um diretório e o comando seguinte recria os mesmos ficheiros nesse diretório.

O exemplo de Dockerfile seguinte com npm ilustra este problema.

RUN npm cache clean --force
RUN npm install

Para mais detalhes, consulte o problema n.º 4659 do GitHub.

Solução

Para resolver este problema, crie a imagem com docker build, que não é afetada por este problema.

Se docker build não for uma opção para si, combine os comandos num só. O exemplo de Dockerfile seguinte combina RUN npm cache clean --force e RUN npm install:

RUN npm cache clean --force && npm install

Faltam algumas métricas do sistema de ficheiros e o formato das métricas é diferente

Versões do GKE afetadas: todas

O ponto final do Kubelet /metrics/cadvisor fornece métricas do Prometheus, conforme documentado em Métricas para componentes do sistema Kubernetes. Se instalar um coletor de métricas que dependa desse ponto final, pode deparar-se com os seguintes problemas:

  • O formato das métricas no nó do Docker é k8s_<container-name>_<pod-name>_<namespace>_<pod-uid>_<restart-count>, mas o formato no nó do containerd é <container-id>.
  • Faltam algumas métricas do sistema de ficheiros no nó do containerd, da seguinte forma:

    container_fs_inodes_free
    container_fs_inodes_total
    container_fs_io_current
    container_fs_io_time_seconds_total
    container_fs_io_time_weighted_seconds_total
    container_fs_limit_bytes
    container_fs_read_seconds_total
    container_fs_reads_merged_total
    container_fs_sector_reads_total
    container_fs_sector_writes_total
    container_fs_usage_bytes
    container_fs_write_seconds_total
    container_fs_writes_merged_total
    

Solução

Pode mitigar este problema usando o cAdvisor como um conjunto de daemons autónomo.

  1. Encontre a versão do cAdvisor mais recente com o padrão de nome vX.Y.Z-containerd-cri (por exemplo, v0.42.0-containerd-cri).
  2. Siga os passos em cAdvisor Kubernetes Daemonset para criar o daemonset.
  3. Indique ao coletor de métricas instalado que use o ponto final /metrics do cAdvisor que fornece o conjunto completo de métricas de contentores do Prometheus.

Alternativas

  1. Migre a sua solução de monitorização para o Cloud Monitoring, que fornece o conjunto completo de métricas de contentores.
  2. Recolha métricas da API de resumo do Kubelet com um ponto final de /stats/summary.

As operações baseadas em anexos não funcionam corretamente após os reinícios do tempo de execução do contentor no GKE Windows

Versões do GKE afetadas: 1.21 a 1.21.5-gke.1802, 1.22 a 1.22.3-gke.700

Os clusters do GKE que executam pools de nós do Windows Server que usam o tempo de execução do containerd (versão 1.5.4 e 1.5.7-gke.0) podem ter problemas se o tempo de execução do contentor for reiniciado à força, com as operações de associação a contentores em execução existentes a não conseguirem associar novamente a E/S. O problema não causa falhas nas chamadas da API, mas os dados não são enviados nem recebidos. Isto inclui dados para APIs e CLIs de anexação e registos através do servidor de API do cluster.

Solução

Para resolver este problema, atualize para a versão corrigida do tempo de execução do contentor (1.5.7-gke.1) com versões mais recentes do GKE.

Os pods apresentam a mensagem de erro failed to allocate for range 0: no IP addresses available in range set

Versões do GKE afetadas: 1.24.6-gke.1500 ou anterior, 1.23.14-gke.1800 ou anterior e 1.22.16-gke.2000 ou anterior

Os clusters do GKE que executam pools de nós que usam o containerd podem ter problemas de fuga de IP e esgotar todos os IPs de pods num nó. Um pod agendado num nó afetado apresenta uma mensagem de erro semelhante à seguinte:

failed to allocate for range 0: no IP addresses available in range set: 10.48.131.1-10.48.131.62

Para mais informações sobre o problema, consulte o problema n.º 5438 do GitHub do containerd e o problema n.º 5768 do GitHub.

Existe um problema conhecido no GKE Dataplane V2 que pode acionar este problema. No entanto, este problema pode ser acionado por outras causas, incluindo runc bloqueado.

Solução

Para resolver este problema, siga as soluções alternativas mencionadas nas Soluções alternativas para clusters GKE padrão para o GKE Dataplane V2.

Diferença no comportamento da sondagem exec quando a sondagem excede o limite de tempo

Versões do GKE afetadas: todas

O comportamento da sondagem exec em imagens do containerd é diferente do comportamento em imagens do dockershim. Quando a análise de execução definida para o pod excede o limite declarado do Kubernetes timeoutSeconds nas imagens dockershim, é tratada como uma falha de análise. Nas imagens do containerd, os resultados da sondagem devolvidos após o limite declarado de timeoutSeconds são ignorados.

Solução

No GKE, o Feature Gate ExecProbeTimeout está definido como false e não pode ser alterado. Para resolver este problema, aumente o limite timeoutSeconds para todas as sondagens de execução afetadas ou implemente a funcionalidade de tempo limite como parte da lógica de sondagem.

Resolva problemas com registos privados

Esta secção fornece informações de resolução de problemas para configurações de registo privado no containerd.

A obtenção de imagens falha com o erro x509: certificate signed by unknown authority

Este problema ocorre se o GKE não conseguir encontrar um certificado para um domínio de registo privado específico. Pode verificar este erro no Cloud Logging com a seguinte consulta:

  1. Aceda à página Explorador de registos na Google Cloud consola:

    Aceda ao Explorador de registos

  2. Execute a seguinte consulta:

    ("Internal error pulling certificate" OR
    "Failed to get credentials from metadata server" OR
    "Failed to install certificate")
    

Para resolver este problema, experimente o seguinte:

  1. No GKE Standard, abra o ficheiro de configuração que existe no seguinte caminho:

    /etc/containerd/hosts.d/DOMAIN/config.toml
    

    Substitua DOMAIN pelo FQDN do registo.

  2. Verifique se o ficheiro de configuração contém o FQDN correto.

  3. Verifique se o caminho para o certificado no campo secretURI no ficheiro de configuração está correto.

  4. Confirme se o certificado existe no Secret Manager.

Certificado não presente

Este problema ocorre se o GKE não conseguir obter o certificado do Secret Manager para configurar o containerd nos seus nós.

Para resolver este problema, experimente o seguinte:

  1. Certifique-se de que o nó afetado executa o SO otimizado para contentores. Os nós do Ubuntu e do Windows não são suportados.
  2. No ficheiro de configuração, certifique-se de que o caminho para o segredo no campo secretURI está correto.
  3. Verifique se a conta de serviço do IAM do seu cluster tem as autorizações corretas para aceder ao segredo.
  4. Verifique se o cluster tem o âmbito de acesso cloud-platform. Para ver instruções, consulte o artigo Verifique os âmbitos de acesso.

A opção de registo não segura não está configurada para a rede local (10.0.0.0/8)

Versões do GKE afetadas: todas

Nas imagens do containerd, a opção de registo não seguro não está configurada para a rede local 10.0.0.0/8. Se usar registos privados não seguros, pode notar erros semelhantes aos seguintes:

pulling image: rpc error: code = Unknown desc = failed to pull and unpack image "IMAGE_NAME": failed to do request: Head "IMAGE_NAME": http: server gave HTTP response to HTTPS client

Para resolver este problema, experimente o seguinte:

  • Use o Artifact Registry
  • Configure o TLS nos seus registos privados se o seu exemplo de utilização suportar esta opção. Pode usar um ficheiro de configuração do containerd para indicar ao GKE que use certificados que armazena no Secret Manager para aceder ao seu registo privado. Para ver instruções, consulte o artigo Aceda a registos privados com certificados de AC privada.

Configure DaemonSets privilegiados para modificar a configuração do containerd

Para clusters Standard, experimente os seguintes passos. Esta solução alternativa não está disponível no Autopilot porque os contentores privilegiados representam um risco de segurança. Se o seu ambiente estiver exposto à Internet, considere a sua tolerância ao risco antes de implementar esta solução. Em todos os casos, recomendamos vivamente que configure o TLS para o seu registo privado e use a opção Secret Manager.

  1. Reveja o seguinte manifesto:

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: insecure-registries
      namespace: default
      labels:
        k8s-app: insecure-registries
    spec:
      selector:
        matchLabels:
          name: insecure-registries
      updateStrategy:
        type: RollingUpdate
      template:
        metadata:
          labels:
            name: insecure-registries
        spec:
          nodeSelector:
            cloud.google.com/gke-container-runtime: "containerd"
          hostPID: true
          containers:
            - name: startup-script
              image: registry.k8s.io/startup-script:v2
              imagePullPolicy: Always
              securityContext:
                privileged: true
              env:
              - name: ADDRESS
                value: "REGISTRY_ADDRESS"
              - name: STARTUP_SCRIPT
                value: |
                  set -o errexit
                  set -o pipefail
                  set -o nounset
    
                  if [[ -z "$ADDRESS" || "$ADDRESS" == "REGISTRY_ADDRESS" ]]; then
                    echo "Error: Environment variable ADDRESS is not set in containers.spec.env"
                    exit 1
                  fi
    
                  echo "Allowlisting insecure registries..."
                  containerd_config="/etc/containerd/config.toml"
                  hostpath=$(sed -nr 's;  config_path = "([-/a-z0-9_.]+)";\1;p' "$containerd_config")
                  if [[ -z "$hostpath" ]]; then
                    echo "Node uses CRI config model V1 (deprecated), adding mirror under $containerd_config..."
                    grep -qxF '[plugins."io.containerd.grpc.v1.cri".registry.mirrors."'$ADDRESS'"]' "$containerd_config" || \
                      echo -e '[plugins."io.containerd.grpc.v1.cri".registry.mirrors."'$ADDRESS'"]\n  endpoint = ["http://'$ADDRESS'"]' >> "$containerd_config"
                  else
                    host_config_dir="$hostpath/$ADDRESS"
                    host_config_file="$host_config_dir/hosts.toml"
                    echo "Node uses CRI config model V2, adding mirror under $host_config_file..."
                    if [[ ! -e "$host_config_file" ]]; then
                      mkdir -p "$host_config_dir"
                      echo -e "server = \"https://$ADDRESS\"\n" > "$host_config_file"
                    fi
                    echo -e "[host.\"http://$ADDRESS\"]\n  capabilities = [\"pull\", \"resolve\"]\n" >> "$host_config_file"
                  fi
                  echo "Reloading systemd management configuration"
                  systemctl daemon-reload
                  echo "Restarting containerd..."
                  systemctl restart containerd

    No campo .spec.containers.env, substitua o valor REGISTRY_ADDRESS da variável ADDRESS pelo endereço do seu registo HTTP local no formato DOMAIN_NAME:PORT. Por exemplo,

    containers:
    - name: startup-script
      ...
      env:
      - name: ADDRESS
        value: "example.com:5000"
    
  2. Implemente o DaemonSet:

    kubectl apply -f insecure-registry-ds.yaml
    

O DaemonSet adiciona o seu registo não seguro à configuração do containerd em todos os nós.

O containerd ignora todos os mapeamentos de dispositivos para pods privilegiados

Versões do GKE afetadas: todas

Para pods do Kubernetes privilegiados, o tempo de execução do contentor ignora quaisquer mapeamentos de dispositivos que volumeDevices.devicePath lhe sejam transmitidos e, em vez disso, disponibiliza todos os dispositivos no anfitrião ao contentor em /dev.

O containerD tem fugas de processos de shim quando os nós estão sob pressão de E/S

Versões do GKE afetadas: 1.25.0 a 1.25.15-gke.1040000, 1.26.0 a 1.26.10-gke.1030000, 1.27.0 a 1.27.6-gke.1513000 e 1.28.0 a 1.28.3-gke.1061000

Quando um nó do GKE está sob pressão de E/S, o containerd pode não conseguir eliminar os processos containerd-shim-runc-v2 quando um pod é eliminado, o que resulta em fugas de processos. Quando a fuga ocorre num nó, vê mais processos containerd-shim-runc-v2 no nó do que o número de pods nesse nó. Também pode verificar um aumento da utilização da memória e da CPU, juntamente com PIDs adicionais. Para ver detalhes, consulte o problema do GitHub Corrija o shim com fugas causado pela elevada pressão de E/S.

Para resolver este problema, atualize os seus nós para as seguintes versões ou posteriores:

  • 1.25.15-gke.1040000
  • 1.26.10-gke.1030000
  • 1.27.6-gke.1513000
  • 1.28.3-gke.1061000

A família de endereços IPv6 está ativada em pods que executam o containerd

Versões do GKE afetadas: 1.18, 1.19, 1.20.0 a 1.20.9

A família de imagens IPv6 está ativada para pods executados com o containerd. A imagem dockershim desativa o IPv6 em todos os pods, enquanto a imagem do containerd não o faz. Por exemplo, localhost é resolvido primeiro para o endereço IPv6 ::1. Normalmente, isto não é um problema, mas pode resultar num comportamento inesperado em determinados casos.

Solução

Para resolver este problema, use um endereço IPv4, como 127.0.0.1, explicitamente ou configure uma aplicação em execução no Pod para funcionar em ambas as famílias de endereços.

O aprovisionamento automático de nós apenas aprovisiona o SO otimizado para contentores com pools de nós do Docker

Versões do GKE afetadas: 1.18, 1.19, 1.20.0 a 1.20.6-gke.1800

O aprovisionamento automático de nós permite o dimensionamento automático de conjuntos de nós com qualquer tipo de imagem suportado, mas só pode criar conjuntos de nós novos com o tipo de imagem SO otimizado para contentores com Docker.

Solução

Para resolver este problema, atualize os seus clusters do GKE para a versão 1.20.6-gke.1800 ou posterior. Nestas versões do GKE, o tipo de imagem predefinido pode ser definido para o cluster.

Conflito com o 172.17/16intervalo de endereços IP

Versões do GKE afetadas: 1.18.0 a 1.18.14

O intervalo de endereços IP 172.17/16 está ocupado pela interface docker0 na VM do nó com o containerd ativado. O tráfego enviado ou originário desse intervalo pode não ser encaminhado corretamente (por exemplo, um Pod pode não conseguir estabelecer ligação a um anfitrião com ligação VPN com um endereço IP dentro de 172.17/16).

As métricas da GPU não são recolhidas

Versões do GKE afetadas: 1.18.0 a 1.18.18

As métricas de utilização da GPU não são recolhidas quando usa o containerd como um tempo de execução em versões do GKE anteriores à 1.18.18.

Solução

Para resolver este problema, atualize os seus clusters para as versões 1.18.18 ou posteriores do GKE.

Não é possível usar imagens com config.mediaType definido como application/octet-stream no containerd

Versões do GKE afetadas: todas

Não é possível usar imagens com config.mediaType definido como "application/octet-stream" no containerd. Para mais informações, consulte o problema do GitHub n.º 4756. Estas imagens não são compatíveis com a especificação da Open Container Initiative e são consideradas incorretas. Estas imagens funcionam com o Docker para oferecer compatibilidade com versões anteriores, enquanto no containerd estas imagens não são suportadas.

Sintoma e diagnóstico

Exemplo de erro nos registos de nós:

Error syncing pod <pod-uid> ("<pod-name>_<namespace>(<pod-uid>)"), skipping: failed to "StartContainer" for "<container-name>" with CreateContainerError: "failed to create containerd container: error unpacking image: failed to extract layer sha256:<some id>: failed to get reader from content store: content digest sha256:<some id>: not found"

Normalmente, o manifesto de imagens pode ser encontrado no registo onde está alojado. Depois de ter o manifesto, verifique config.mediaType para determinar se tem este problema:

"mediaType": "application/octet-stream",

Solução

Uma vez que a comunidade do containerd decidiu não suportar essas imagens, todas as versões do containerd são afetadas e não existe uma correção. A imagem do contentor tem de ser recompilada com a versão 1.11 ou posterior do Docker, e tem de se certificar de que o campo config.mediaType não está definido como "application/octet-stream".

CNI não inicializado

Versões do GKE afetadas: todas

Se vir um erro semelhante ao seguinte, a configuração da interface de rede do contentor (CNI) não está pronta:

Error: "network is not ready: container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:Network plugin returns error: cni plugin not initialized".

Existem dois motivos principais para a ocorrência deste erro:

  • O CNI não concluiu a instalação
  • O webhook tem uma configuração incorreta

Certifique-se de que a instalação da CNI foi concluída

Pode ver este erro nos ficheiros de registo durante o arranque do nó enquanto o GKE instala a configuração da CNI. Se vir este erro, mas o GKE estiver a criar todos os nós corretamente, pode ignorá-lo em segurança.

Esta situação pode ocorrer porque a CNI fornece aos pods a respetiva conetividade de rede, pelo que os pods precisam da CNI para funcionar. No entanto, o Kubernetes usa taints para marcar nós que não estão prontos, e os pods do sistema podem tolerar estes taints. Isto significa que os pods do sistema podem ser iniciados num novo nó antes de a rede estar pronta, o que resulta no erro.

Para resolver este problema, aguarde que o GKE termine a instalação da configuração do CNI. Depois de o CNI terminar a configuração da rede, os pods do sistema são iniciados com êxito sem necessidade de intervenção.

Corrija webhooks configurados incorretamente

Se o erro CNI not initialized persistir e notar que o GKE não está a criar nós durante uma atualização, uma alteração de tamanho ou outra ação, pode ter um webhook configurado incorretamente.

Se tiver um webhook personalizado que interceta o comando do controlador DaemonSet para criar um pod e esse webhook estiver configurado incorretamente, pode ver o erro como um estado de erro do nó na Google Cloud consola. Esta configuração incorreta impede o GKE de criar um pod netd ou calico-node. Se os pods netd ou calico-node forem iniciados com êxito enquanto o erro persistir, contacte o apoio ao cliente.

Para corrigir webhooks configurados incorretamente, conclua os seguintes passos:

  1. Identifique webhooks configurados incorretamente.

    Se estiver a usar um cluster com a aplicação da política de rede do Dataplane V1 ativada, também pode verificar o estado do pod para obter informações sobre que webhooks estão a causar este erro:calico-typha

    kubectl describe pod -n kube-system -l k8s-app=calico-typha
    

    Se o Pod tiver um erro, o resultado é semelhante ao seguinte:

    Events:
    Type     Reason        Age                     From                   Message
    ----     ------        ----                    ----                   -------
    Warning  FailedCreate  9m15s (x303 over 3d7h)  replicaset-controller  Error creating: admission webhook WEBHOOK_NAME denied the request [...]
    

    Neste resultado, WEBHOOK_NAME é o nome de um webhook com falhas. A sua saída pode incluir informações sobre um tipo diferente de erro.

  2. Se quiser manter os webhooks configurados incorretamente, resolva os problemas. Se não forem necessárias, elimine-as executando os seguintes comandos:

    kubectl delete mutatingwebhookconfigurations WEBHOOK_NAME
    kubectl delete validatingwebhookconfigurations WEBHOOK_NAME
    

    Substitua WEBHOOK_NAME pelo nome do webhook configurado incorretamente que quer remover.

  3. Configure os webhooks para ignorarem os pods do sistema.

O que se segue?