Imagens em contêineres


Nesta página, você terá mais informações sobre como usar o Container-Optimized OS com containerd (cos_containerd) e o Ubuntu com containerd (ubuntu_containerd) em nós do Google Kubernetes Engine (GKE). As imagens cos_containerd e ubuntu_containerd permitem que você use o Containerd como o ambiente de execução de contêiner em seu cluster do GKE. Para clusters do Autopilot, cos_containerd é o único tipo de imagem compatível.

Sobre o Containerd

O ambiente de execução de contêiner é o software responsável pela execução de contêineres e abstrai o gerenciamento de contêineres para o Kubernetes. Há diferentes tempos de execução de contêiner. O Containerd é um ambiente de execução de contêiner padrão do setor compatível com o Kubernetes que é usado por muitos outros projetos. A containerd fornece a abstração de camadas que permite a implementação de um conjunto avançado de recursos como o gVisor (link em inglês) para estender a funcionalidade do Kubernetes. O containerd é considerado um recurso mais eficiente e seguro quando comparado ao ambiente de execução do Docker.

Como usar imagens de containerd em clusters do GKE

Selecione cos_containerd ou ubuntu_containerd como o tipo de imagem ao criar um novo cluster do GKE, criar um novo pool de nós em um cluster atual ou atualizar um cluster atual. Ambas as imagens exigem o GKE versão 1.14.3 ou posterior.

Como verificar o tipo de imagem do nó

É possível verificar qual tipo de imagem é usado para nós existentes com o Console do Google Cloud, a ferramenta gcloud ou kubectl. Além disso, consulte o Script de migração de amostra neste documento, que se repete em todos os pools de nós e gera as migrações sugeridas.

Console

  1. No Console do Cloud, acesse a página Google Kubernetes Engine.

    Acessar o Google Kubernetes Engine

  2. Na lista de clusters, clique no nome do cluster que você quer verificar.

  3. Selecione a guia Nós.

  4. Na seção Pool de nós, veja o valor na coluna Tipo de imagem.

gcloud

Execute o seguinte comando, substituindo CLUSTER_NAME pelo nome do cluster:

gcloud container node-pools list \
    --cluster CLUSTER_NAME \
    --format="table(name,version,config.imageType)"

A resposta será semelhante a:

NAME          NODE_VERSION    IMAGE_TYPE
default-pool  1.19.6-gke.600  UBUNTU_CONTAINERD

Consulte a documentação da API gcloud container node-pools list para obter mais detalhes.

kubectl

Execute este comando kubectl get nodes:

kubectl get nodes -o wide

A resposta será semelhante a:

# For Docker runtime
NAME         STATUS   VERSION             OS-IMAGE                             CONTAINER-RUNTIME
gke-node-1   Ready    v1.16.15-gke.6000   Container-Optimized OS from Google   docker://19.3.1
gke-node-2   Ready    v1.16.15-gke.6000   Container-Optimized OS from Google   docker://19.3.1
gke-node-3   Ready    v1.16.15-gke.6000   Container-Optimized OS from Google   docker://19.3.1
# For Containerd runtime
NAME         STATUS   VERSION           OS-IMAGE                             CONTAINER-RUNTIME
gke-node-1   Ready    v1.19.6-gke.600   Container-Optimized OS from Google   containerd://1.4.1
gke-node-2   Ready    v1.19.6-gke.600   Container-Optimized OS from Google   containerd://1.4.1
gke-node-3   Ready    v1.19.6-gke.600   Container-Optimized OS from Google   containerd://1.4.1

A coluna CONTAINER-RUNTIME gera o ambiente de execução e a versão dele.

Como migrar do ambiente de execução do Docker para o ambiente de execução do containerd

A maioria das cargas de trabalho do usuário não tem uma dependência no ambiente de execução do contêiner. O ambiente de execução de contêiner é o que executa os contêineres nos pods, e o ambiente de execução do Docker usa o containerd em segundo plano para que ambos se comportem de maneira semelhante.

Mesmo que você use o Docker em sua máquina de desenvolvedor ou como parte de um pipeline de versão que é executado fora do cluster para criar e enviar suas imagens, ele mesmo não é uma dependência no tempo de execução do Docker (como essas ações) fora do cluster).

Há algumas instâncias em que você pode ter uma dependência no Docker: executar pods privilegiados executando comandos do Docker, executar scripts em nós fora da infraestrutura do Kubernetes (por exemplo, usar o ssh para solucionar problemas) ou por meio de ferramentas de terceiros que executam operações similares com privilégios. Também será possível ter uma dependência indireta no Docker se algumas das ferramentas tiverem sido configuradas para reagir a mensagens de registro específicas do Docker no sistema de monitoramento.

Veja informações sobre possíveis dependências no ambiente de execução do Docker em Como migrar do dockershim. Para confirmar a compatibilidade com o Containerd, também é possível consultar os fornecedores que fornecem geração de registros e monitoramento, segurança ou ferramentas de integração contínua que você implanta no cluster.

Recomendamos primeiro implantar a carga de trabalho em um pool de nós de teste com o Containerd para verificar se tudo é executado conforme o esperado. Se você tiver um cluster de canário ou preparo, recomendamos migrar primeiro. Também é possível migrar os nós em etapas com a abordagem explicada em Como migrar cargas de trabalho para tipos de máquinas diferentes.

Como atualizar suas imagens de nó

É possível migrar nós de uma imagem de ambiente de execução do Docker para uma imagem containerd atualizando o pool de nós e definindo outra imagem. Essa migração pode ser feita usando o Console do Google Cloud ou a ferramenta gcloud

Console

  1. No Console do Cloud, acesse a página Google Kubernetes Engine.

    Acessar o Google Kubernetes Engine

  2. Clique no nome do cluster que você quer modificar.

  3. Na página Detalhes do cluster, clique na guia Nós.

  4. Em Pools de nós, clique no nome do pool que você quer modificar.

  5. Na página Detalhes dos pools de nós, clique em Editar.

  6. Na seção Nós, em Tipo de imagem, clique em Alterar.

  7. Selecione uma das variantes de imagem do containerd para seu sistema operacional.

  8. Clique em Alterar.

gcloud

Na ferramenta gcloud, é possível atualizar um pool de nós usando o comando gcloud container clusters upgrade e especificando o parâmetro --image-type.

Por exemplo, para alterar a imagem de um pool de nós para Container-Optimized OS com o Containerd, execute o comando a seguir:

gcloud container clusters upgrade CLUSTER_NAME --image-type COS_CONTAINERD \
    --node-pool POOL_NAME

Se, depois de atualizar a imagem de nó, você perceber um problema e precisar voltar para as variantes de imagem do Docker, execute o mesmo comando, mas selecione uma variante de imagem do Docker.

Consulte a documentação da API gcloud container clusters upgrade para mais detalhes.

Como executar comandos do docker em nós de contêiner

Embora o binário do Docker esteja disponível atualmente em nós do Containerd, não recomendamos usá-lo depois de migrar para o Containerd. O Docker não gerencia os contêineres que o Kubernetes executa em nós containerd. Portanto, não é possível usá-lo para visualizar ou interagir com a execução de contêineres do Kubernetes usando comandos do Docker ou a API Docker.

Solução de problemas de contêineres em nós containerd

Para depurar o nó ou solucionar problemas dele, use o containerd por meio da ferramenta de linha de comando portátil crictl, criada para os ambientes de execução de contêiner do Kubernetes. O crictl é compatível com funcionalidades comuns para visualizar contêineres e imagens, ler registros e executar comandos nos contêineres. Consulte o guia do usuário básico para um conjunto completo de recursos compatíveis e informações de uso.

Como acessar o Docker Engine usando pods privilegiados

Atualmente, alguns usuários acessam o Docker Engine em um nó a partir de pods privilegiados. É recomendável atualizar suas cargas de trabalho para que elas não dependam diretamente do Docker. Por exemplo, se você atualmente extrai registros de aplicativos ou dados de monitoramento do Docker Engine, considere o uso de complementos do sistema do GKE para criação de registros e monitoramento.

Criar imagens

O containerd não é compatível com a criação de imagens, porque o recurso não é aceito pelo próprio Kubernetes.

O Kubernetes não tem conhecimento dos recursos de sistema usados pelos processos locais fora do escopo dele, e o plano de controle do Kubernetes não pode contabilizar esses processos ao alocar recursos. Isso pode prejudicar suas cargas de trabalho de recursos do GKE ou causar instabilidade no nó. Por isso, não é recomendado executar comandos em nós locais. Em vez disso, pense em realizar essas tarefas usando outros serviços fora do escopo do contêiner individual, como o Cloud Build, ou use uma ferramenta como o kaniko (em inglês) para criar imagens como uma carga de trabalho do Kubernetes.

Se nenhuma dessas sugestões funcionar e você entender os riscos, continue a usar o Docker para criar imagens. É preciso enviar as imagens para um registro antes de tentar usá-las em um cluster do GKE. O Kubernetes não tem conhecimento das imagens criadas localmente.

Problemas conhecidos

Não há problemas conhecidos nas versões 1.19 e posteriores do GKE.

O provisionamento automático de nós provisiona apenas o Container-Optimized OS com pools de nós do Docker

O provisionamento automático de nós permite pools de nós com escalonamento automático com qualquer tipo de imagem compatível, mas só pode criar novos pools de nós com o tipo de imagem Container-Optimized OS com o Docker;

Conflito com o intervalo 172.17/16

Versões afetadas do GKE: 1.14, 1.15, 1.16, 1.17.0 a 1.17.17-gke.2800, 1.18.0 a 1.18.14

O intervalo de IP 172.17/16 é ocupado pela interface docker0 na VM do nó com o Containerd ativado. É possível que o tráfego de envio ou origem desse intervalo não seja roteado corretamente. Por exemplo, um pod pode não conseguir se conectar a um host conectado à VPN com um IP em 172.17/16.

Imagens com mais de 56 camadas não podem ser usadas no Containerd

Versões afetadas do GKE: 1.14, 1.15, 1.16, 1.17

Se a imagem tiver mais de 56 camadas, não será possível fazer o download. O seguinte erro ocorre:

info.Labels: label key and value greater than maximum size (4096 bytes), key: containerd: invalid argument

Para obter mais informações, acesse https://github.com/containerd/containerd/issues/4684.

Esse problema foi corrigido no Containerd 1.4.2. O Container-Optimized OS 85 inclui essa correção.

Métricas de GPU não coletadas

Versões afetadas do GKE: 1.14, 1.15, 1.16, 1.17, 1.18

As métricas de uso de GPU não são coletadas ao usar o containerd como um ambiente de execução nas versões do GKE anteriores à 1.19.

Faltam rótulos nas métricas de imagem

Versões afetadas do GKE: todas

As métricas de imagem container_fs_usage_bytes e container_tasks_state não mostram rótulos como image, container_name e nome namespace.

O volume é ativado com a opção noexec

Versões afetadas do GKE: 1.14, 1.15.0 a 1.15.12-gke.17, 1.16.0 a 1.16.13-gke.400

O volume ativado em /var/lib/containerd é ativado com no-exec opções. Isso nega a execução de qualquer executável do volume.

Vazamento de descritor de arquivo no containerd

Versões afetadas do GKE: 1.14, 1.15, 1.16, 1.17.0 a 1.17.12

O containerd tinha um problema conhecido de vazamento de eventfd na v1.3.0+ e foi corrigido pela v1.3.3. Para mais informações, consulte https://github.com/containerd/containerd/issues/3949.

Exemplo de script de migração

O script de amostra a seguir itera em todos os pools de nós nos projetos disponíveis e, para cada pool de nós, é exibida a sugestão sobre a migração do pool de nós para Containerd. Esse script também exibe a versão do pool de nós e o comando de migração sugerido, conforme listado na seção de atualização das imagens de nó. Verifique os problemas conhecidos de uma versão do pool de nós

Exemplo de script: iterar em todos os pools de nós para a migração do containerd

for project in  $(gcloud projects list --format="value(projectId)")
do
  echo "ProjectId:  $project"
  for clusters in $( \
    gcloud container clusters list \
      --project $project \
      --format="csv[no-heading](name,location,autopilot.enabled)")
  do
    IFS=',' read -r -a clustersArray <<< "$clusters"
    cluster_name="${clustersArray[0]}"
    cluster_zone="${clustersArray[1]}"
    cluster_isAutopilot="${clustersArray[2]}"

    if [ "$cluster_isAutopilot" = "True" ]; then
      echo "  Cluster: $cluster_name (autopilot) (zone: $cluster_zone)"
      echo "    Autopilot clusters are running Containerd."
    else
      echo "  Cluster: $cluster_name (zone: $cluster_zone)"
      for nodepools in $( \
        gcloud container node-pools list \
          --project $project \
          --cluster $cluster_name \
          --zone $cluster_zone \
          --format="csv[no-heading](name,version,config.imageType)")
      do
        IFS=',' read -r -a nodepoolsArray <<< "$nodepools"
        nodepool_name="${nodepoolsArray[0]}"
        nodepool_version="${nodepoolsArray[1]}"
        nodepool_imageType="${nodepoolsArray[2]}"

        nodepool_minorVersion=${nodepool_version:0:4}

        echo "    Nodepool: $nodepool_name, version: $nodepool_version ($nodepool_minorVersion), image: $nodepool_imageType"

        suggestedImageType="COS_CONTAINERD"

        if [ "$nodepool_imageType" = "UBUNTU" ]; then
          suggestedImageType="UBUNTU_CONTAINERD"
        fi

        tab=$'\n      ';
        nodepool_message="$tab Please update the nodepool to use Containerd."
        nodepool_message+="$tab Make sure to consult with the list of known issues https://cloud.google.com/kubernetes-engine/docs/concepts/using-containerd#known_issues."
        nodepool_message+="$tab Run the following command to upgrade:"
        nodepool_message+="$tab "
        nodepool_message+="$tab gcloud container clusters upgrade '$cluster_name' --project '$project' --zone '$cluster_zone' --image-type '$suggestedImageType' --node-pool '$nodepool_name'"
        nodepool_message+="$tab "

        # see https://cloud.google.com/kubernetes-engine/docs/concepts/node-images
        if [ "$nodepool_imageType" = "COS_CONTAINERD" ] || [ "$nodepool_imageType" = "UBUNTU_CONTAINERD" ]; then
          nodepool_message="$tab Nodepool is using Containerd already"
        elif [ "$nodepool_imageType" = "WINDOWS_LTSC" ] || [ "$nodepool_imageType" = "WINDOWS_SAC" ]; then
          nodepool_message="$tab Containerd is not currently available for Windows nodepools"
        elif [ "$nodepool_minorVersion" \< "1.14" ]; then
          nodepool_message="$tab Upgrade nodepool to the version that supports Containerd"
        fi
        echo "$nodepool_message"
      done
    fi # not autopilot
  done
done

# Sample output:
#
# ProjectId:  my-project-id
#  Cluster: autopilot-cluster-1 (autopilot) (zone: us-central1)
#    Autopilot clusters are running Containerd.
#  Cluster: cluster-1 (zone: us-central1-c)
#    Nodepool: default-pool, version: 1.18.12-gke.1210 (1.18), image: COS
#
#       Please update the nodepool to use Containerd.
#       Make sure to consult with the list of known issues https://cloud.google.com/kubernetes-engine/docs/concepts/using-containerd#known_issues.
#       Run the following command to upgrade:
#
#       gcloud container clusters upgrade 'cluster-1' --project 'my-project-id' --zone 'us-central1-c' --image-type 'COS_CONTAINERD' --node-pool 'default-pool'
#
#    Nodepool: pool-1, version: 1.18.12-gke.1210 (1.18), image: COS
#
#       Please update the nodepool to use Containerd.
#       Make sure to consult with the list of known issues https://cloud.google.com/kubernetes-engine/docs/concepts/using-containerd#known_issues.
#       Run the following command to upgrade:
#
#       gcloud container clusters upgrade 'cluster-1' --project 'my-project-id' --zone 'us-central1-c' --image-type 'COS_CONTAINERD' --node-pool 'pool-1'
#
#  Cluster: another-test-cluster (zone: us-central1-c)
#    Nodepool: default-pool, version: 1.20.4-gke.400 (1.20), image: COS_CONTAINERD
#
#      Nodepool is using Containerd already
#

A seguir