Imagens de contêiner de várias arquiteturas para dispositivos IoT

Este documento é a primeira parte de uma série que discute a criação de um pipeline de integração contínua (CI) automatizado para criar imagens de contêiner com várias arquiteturas no Google Cloud. Os conceitos explicados neste documento se aplicam a qualquer ambiente de nuvem.

A série consiste neste documento e em um tutorial complementar. Este documento explica a estrutura de um pipeline para criar imagens de contêiner e descreve as etapas de alto nível. O tutorial orienta você na criação de um exemplo de pipeline.

Esta série é destinada a profissionais de TI que querem simplificar e agilizar pipelines complexos para criar imagens de contêiner ou estender esses pipelines para criar imagens com várias arquiteturas. Você precisa conhecer as tecnologias de nuvem e contêineres.

Ao implementar um pipeline de CI, você simplifica os procedimentos de criação de artefatos. Não é necessário manter ferramentas e hardware dedicado para criar imagens de contêiner para uma determinada arquitetura. Por exemplo, se o pipeline atual for executado em uma arquitetura x86_64 e produzir imagens de contêiner somente para essa arquitetura, talvez seja necessário manter ferramentas e hardware adicionais para criar imagens de contêiner para outras arquiteturas, como para a família ARM.

O domínio de Internet das coisas (IoT, na sigla em inglês) geralmente requer compilações de várias arquiteturas. Quando você tem uma grande frota de dispositivos com diferentes pilhas de software e hardware, o processo de criação, teste e gerenciamento de aplicativos de software para um dispositivo específico se torna um grande desafio. O uso de um processo de criação de várias arquiteturas ajuda a simplificar o gerenciamento de aplicativos de IoT.

O desafio da criação de imagens de contêiner de multiarquitetura

Na maioria das implementações, as imagens de contêiner dependem da arquitetura. Por exemplo, se você criar uma imagem de contêiner para a arquitetura x86_64, ela não poderá ser executada em uma arquitetura da família ARM.

Você pode superar essa limitação de várias maneiras:

  1. Crie as imagens de contêiner nas arquiteturas de destino para as quais você precisa da imagem de contêiner.
  2. Mantenha ferramentas dedicadas e uma frota de hardware. Sua frota precisa de pelo menos um dispositivo para cada arquitetura em que você precisa criar uma imagem de contêiner.
  3. Crie imagens de contêineres com várias arquiteturas.

A melhor estratégia depende de vários fatores, incluindo:

  • Complexidade do pipeline
  • Requisitos de automação
  • Recursos disponíveis para projetar, implementar e manter o ambiente para criação de imagens de contêiner

Por exemplo, se o ambiente de execução tiver acesso limitado a uma fonte de alimentação, talvez seja necessário criar as imagens de contêiner em um ambiente separado do ambiente de execução.

O diagrama a seguir ilustra os pontos de decisão na escolha de uma estratégia viável.

Fluxograma para decidir a melhor estratégia para criar imagens de contêiner com várias arquiteturas.

Crie as imagens de contêiner nas arquiteturas de destino

Uma estratégia é criar cada imagem de contêiner necessária diretamente no ambiente de execução compatível com o próprio contêiner, conforme mostrado no diagrama a seguir.

Crie o caminho do repositório de código-fonte para o ambiente de execução.

Para cada build, faça o seguinte:

  1. Faça o download do código-fonte da imagem do contêiner de um repositório de código-fonte em cada dispositivo no ambiente de execução.
  2. Crie a imagem do contêiner no ambiente de execução.
  3. Armazene a imagem do contêiner no repositório de imagens do contêiner local para cada dispositivo no ambiente de execução.

A vantagem dessa estratégia é que você não precisa provisionar e manter o hardware além do que precisa para seus ambientes de execução. Essa estratégia também tem desvantagens. Primeiro, você precisa repetir o processo de criação em todas as instâncias de hardware do ambiente de execução, desperdiçando recursos. Por exemplo, se você implantar suas cargas de trabalho em contêiner em um ambiente de execução em que os dispositivos não têm acesso a uma fonte de alimentação contínua, você gasta tempo e energia executando tarefas de criação nesses dispositivos sempre que precisar implantar uma nova versão de uma carga de trabalho. Além disso, é necessário manter as ferramentas para acessar o código-fonte de cada imagem de contêiner para criar imagens de contêiner no seu ambiente de execução.

Mantenha ferramentas dedicadas e frotas de hardware

Uma segunda estratégia é manter uma frota de hardware dedicada apenas a tarefas que criam imagens de contêiner. O diagrama a seguir ilustra a arquitetura dessa estratégia.

Caminho da versão do repositório de código-fonte para um ambiente de versão dedicado.

Para cada versão, faça o seguinte:

  1. Faça o download do código-fonte da imagem do contêiner em um dispositivo na frota que tenha a arquitetura de hardware necessária e os recursos para criar a imagem do contêiner.
  2. Crie a imagem do contêiner.
  3. Armazene a imagem do contêiner em um repositório centralizado de imagem de contêiner.
  4. Faça o download da imagem do contêiner em cada dispositivo no ambiente de execução quando você precisar implantar uma nova instância dessa imagem.

Para essa estratégia, provisione pelo menos uma instância de cada arquitetura de hardware para a qual você precisa criar imagens de contêiner. Em um ambiente de produção não simples, você pode ter mais de uma instância para aumentar a tolerância a falhas do seu ambiente e reduzir os tempos de compilação se tiver vários jobs de compilação simultâneos.

Essa estratégia tem algumas vantagens. Primeiro, execute cada job de versão apenas uma vez e armazene a imagem de contêiner resultante em um repositório de imagens de contêiner centralizado, como o Container Registry. Além disso, é possível executar conjuntos de testes nos dispositivos da frota de construções que se assemelham às arquiteturas de hardware que você tem nos ambientes de execução. A principal desvantagem dessa estratégia é que você precisa provisionar e manter uma infraestrutura e ferramentas dedicadas para executar as tarefas que criam imagens de contêiner. Normalmente, cada tarefa de criação não consome muitos recursos ou tempo por design. Portanto, essa infraestrutura fica ociosa na maior parte do tempo.

Crie imagens de contêineres com várias arquiteturas

Nesta terceira estratégia, você usará um pipeline de uso geral para criar imagens de contêiner de multiarquitetura, conforme mostrado no diagrama a seguir.

Crie o caminho do repositório de código-fonte para o pipeline de várias arquiteturas de uso geral.

Para cada versão, faça o seguinte:

  1. Faça o download do código-fonte da imagem do contêiner.
  2. Crie a imagem do contêiner.
  3. Armazene a imagem do contêiner em um repositório centralizado de imagem de contêiner.
  4. Faça o download da imagem do contêiner em cada dispositivo no ambiente de execução quando você precisar implantar uma nova instância dessa imagem.

A principal vantagem dessa estratégia é que você não precisa provisionar e manter ferramentas ou hardware dedicados. Por exemplo, você pode usar os pipelines e as ferramentas de integração contínua/implantação contínua (CI/CD) para criar imagens de contêineres com várias arquiteturas. Você também pode se beneficiar do melhor desempenho de uma arquitetura de hardware de uso geral, como x86_64, em comparação com uma arquitetura de baixo consumo de energia, como a da família ARM.

Essa estratégia também pode fazer parte de uma iniciativa mais ampla, em que você adota os princípios de DevOps. Por exemplo, é possível implementar um pipeline de CI/CD para hardware especializado.

Como implementar um pipeline para criar imagens de contêineres com várias arquiteturas

Nesta seção, descrevemos uma implementação de referência de um pipeline de CI/CD que segue a terceira estratégia: criar imagens de contêineres com várias arquiteturas.

A implementação de referência tem os seguintes componentes:

  • Um repositório de código-fonte para gerenciar o código-fonte para imagens de contêiner. Por exemplo, use o Cloud Source Repositories ou os repositórios do GitLab.
  • Um ambiente de execução de CI/CD para criar imagens de contêiner, como o Cloud Build.
  • Uma plataforma para gerenciar contêineres e imagens de contêiner compatíveis com imagens de contêiner com várias arquiteturas, como o Docker.
  • um registro de imagem de contêiner, como o Container Registry Se você quiser armazenar suas imagens de contêiner mais perto dos nós em que elas são necessárias, execute um registro de imagem de contêiner, como o Docker Registry, diretamente no ambiente atual.

Esta arquitetura de referência usa Moby BuildKit e QEMU para criar Imagens de contêiner do Docker de várias arquiteturas. Nesse caso, o Moby BuildKit detecta automaticamente as arquiteturas disponíveis por meio da emulação de hardware QEMU e carrega automaticamente os binários apropriados registrados no recurso binfmt_misc do kernel do Linux.

O diagrama a seguir ilustra a pilha técnica responsável por cada versão da imagem de contêiner de várias arquiteturas compatível com essa arquitetura de referência.

Componentes relacionados para esta arquitetura de referência de várias arquiteturas.

Como essa arquitetura de referência usa manifestos de imagem do Docker, não é necessário fornecer uma tag de imagem de contêiner para cada arquitetura de hardware de destino. É possível usar a mesma tag para várias arquiteturas. Por exemplo, se você criar a versão 1.0.0 de uma imagem de contêiner de várias arquiteturas, não será necessária uma tag exclusiva para cada arquitetura de hardware, como 1.0.0-x86_64 ou 1.0.0_ARMv7 (em inglês). Você usa a mesma tag 1.0.0 para todas as arquiteturas de hardware criadas e usa os manifestos de imagem do Docker para identificar corretamente cada imagem de contêiner.

O exemplo a seguir mostra o manifesto de imagem para a imagem oficial do Alpine Linux (em inglês), em que você encontra informações sobre as arquiteturas compatíveis com uma versão específica da imagem de contêiner:

{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
   "manifests": [
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 528,
         "digest": "sha256:ddba4d27a7ffc3f86dd6c2f92041af252a1f23a8e742c90e6e1297bfa1bc0c45",
         "platform": {
            "architecture": "amd64",
            "os": "linux"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 528,
         "digest": "sha256:401f030aa35e86bafd31c6cc292b01659cbde72d77e8c24737bd63283837f02c",
         "platform": {
            "architecture": "arm",
            "os": "linux",
            "variant": "v7"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 528,
         "digest": "sha256:2c26a655f6e38294e859edac46230210bbed3591d6ff57060b8671cda09756d4",
         "platform": {
            "architecture": "arm64",
            "os": "linux"
         }
      }
   ]
}

Ao projetar um pipeline automatizado para criar imagens de contêiner, recomendamos que você inclua conjuntos de testes abrangentes que validem a conformidade com os requisitos de cada imagem de contêiner. Por exemplo, use ferramentas como Chef InSpec, Serverspec e RSpec para executar conjuntos de testes de conformidade nas imagens de contêiner como uma das tarefas do pipeline de compilação.

Como otimizar o pipeline para criar imagens de contêiner

Depois de validar e consolidar os pipelines para criar suas imagens de contêiner, você otimiza os pipelines. Migração para o Google Cloud: como otimizar seu ambiente contém orientações sobre como otimizar esse ambiente. Ele descreve uma estrutura de otimização que você pode adotar para tornar seu ambiente mais eficiente em comparação com o estado atual. Ao seguir a estrutura de otimização, você passa por várias iterações, em que modifica o estado do seu ambiente.

Uma das primeiras atividades de cada iteração de otimização é estabelecer um conjunto de requisitos e metas para essa iteração. Por exemplo, um requisito pode ser modernizar seus processos de implantação, migrando de processos de implantação manual para processos totalmente automatizados e em contêineres. Para mais informações sobre como modernizar seus processos de implantação, consulte Migração para o Google Cloud: como migrar de implantações manuais para implantações automatizadas e em contêiner.

A seguir