Editar

Implantação eficiente de imagens do Docker para conectividade de baixa largura de banda

Azure Container Registry
Azure Functions
Azure IoT Edge
Azure IoT Hub
Azure Pipelines

Este artigo descreve uma solução para implantar módulos de borda de Internet das Coisas (IoT) em contêineres em conexões de internet intermitentes ou de baixa largura de banda.

O processamento de borda é um padrão chave de Internet das Coisas (IoT) para fornecer conectividade de baixa latência e conservar a largura de banda, como em cenários móveis. Os sistemas IoT normalmente provisionam dispositivos de borda implantando imagens de contêiner de software. Implantações de contêineres interrompidas em conexões intermitentes de baixa largura de banda podem causar falhas em cenários móveis. Os cenários de IoT com largura de banda limitada, intermitente ou baixa precisam de recursos de implantação confiáveis e resilientes.

Neste exemplo, uma grande empresa de logística queria melhorar o rastreamento de remessas de produtos em todo o mundo. A empresa enviou mercadorias com vários métodos de transporte terrestre, aéreo e marítimo para muitas localidades, incluindo áreas com conectividade intermitente à internet de baixa largura de banda. Dependendo do tipo de mercadoria, as remessas de produtos tinham vários dispositivos de seguro, segurança ou rastreamento de IoT instalados, com diferentes capacidades. Os dispositivos incluíam rastreadores GPS, sensores de temperatura e ferramentas de captura de dados.

A empresa estava tendo problemas para atualizar dispositivos em sua plataforma Azure IoT Edge recentemente desenvolvida. Os principais pontos problemáticos foram:

  • Alto consumo de largura de banda ao implantar software atualizado em dispositivos.
  • Nenhuma implantação automatizada padronizada entre dispositivos.
  • Flexibilidade limitada na seleção de tecnologia.

Para resolver esses problemas, a equipe de desenvolvimento criou uma solução que:

  • Minimiza o tamanho da implantação em cada dispositivo, reduzindo a largura de banda.
  • Implementa uma implantação padronizada de contêiner do Docker da plataforma IoT Edge para dispositivos IoT remotos heterogêneos.
  • Permite um monitoramento confiável da implantação.
  • Tira partido de vários serviços de nuvem e DevOps do Azure e utiliza as ferramentas herdadas preferidas do cliente.

A solução aumentou drasticamente a confiabilidade e a resiliência do processo de provisionamento de dispositivos em ambientes de conectividade limitada. Este artigo descreve os detalhes da solução e o processo de avaliação das opções da solução.

Requisitos do cliente

O cliente tinha os seguintes requisitos:

  • A solução deve suportar conectividade intermitente de nuvem de baixa largura de banda.
  • Os aplicativos implantados devem continuar a ser executados localmente.
  • A equipe local precisa usar a funcionalidade offline ou sem um atraso de ida e volta na nuvem.
  • Quando conectada, a solução deve usar a conexão de nuvem de forma eficiente.
  • A solução deve priorizar o envio de dados de acordo com regras de negócios definidas consistentemente entre produtos.

Havia também os seguintes requisitos detalhados:

  • Os arquivos de imagem são transferidos através de uma conexão via satélite de baixa largura de banda e conectividade intermitente.
  • A quantidade de dados transferidos deve ser minimizada.
  • A transferência de arquivos para dispositivos usa o aplicativo de terceiros preferido do cliente.
  • As cargas de trabalho de dispositivo usam imagens do Docker no IoT Edge.
  • Os tamanhos de imagem variam de dezenas de MB a vários GB.
  • Os módulos do IoT Edge são escritos no .NET Core 2.2.

Potenciais casos de utilização

Esta solução é adequada para cenários de IoT em que os contêineres de software fornecem soluções em conexões intermitentes e de baixa largura de banda. Exemplos incluem:

  • Monitoramento remoto de petróleo, gás e mineração
  • Atualizações automotivas over-the-air
  • Em qualquer lugar uma conexão forte não é garantida

Arquitetura

Em cenários de alta largura de banda, o Azure IoT Edge extrai imagens diretamente de um registro do Docker acessível pela Internet, seja um hub do Docker ou um hub privado como o Azure Container Registry. Essa funcionalidade é a mesma que executar o docker pull <image_name> comando.

Com acesso à rede potencialmente intermitente, como uma conexão de internet via satélite, o método de pull do Docker não é confiável. O progresso não será armazenado em cache se a conexão com a Internet cair enquanto o Docker estiver puxando a imagem. Quando a conexão com a Internet é retomada, o Docker deve começar a puxar a imagem novamente desde o início.

A solução usa um mecanismo de implantação alternativo, patch binário de arquivos de imagem do Docker, para reduzir a largura de banda e compensar a conectividade intermitente.

Diagrama mostrando o Azure DevOps e a arquitetura de solução de alto nível do Azure.

Fluxo de dados

  1. Os desenvolvedores interagem com o código-fonte do módulo de borda em um repositório de código-fonte.
  2. O Container Registry armazena as imagens do Docker de cada módulo.
  3. O repositório de manifesto contém os manifestos de implantação para todos os fluxos de trabalho.
  4. Cada módulo tem um pipeline de compilação do Azure Pipelines que usa uma compilação genérica do Docker para criar e registrar módulos automaticamente.
  5. O pipeline de imagem para dispositivo implanta as imagens do Docker nos dispositivos de destino, conforme definido pelo arquivo de manifesto.
  6. O pipeline de manifesto para dispositivo envia o manifesto de implantação para o Hub IoT do Azure adequado para o dispositivo que está sendo atualizado.
  7. Uma solução de transferência rápida de arquivos de terceiros transfere os arquivos de uma conta de Armazenamento do Azure para o dispositivo.
  8. O módulo IoT Edge de reconstrução de imagem aplica os patches recebidos nos dispositivos.
  9. O Hub IoT recebe mensagens de status do módulo Reconstrução de Imagem e define o manifesto de implantação para o dispositivo. O restante do fluxo de pipeline usa esse manifesto de implantação.
  10. O Azure Functions monitora o fluxo de mensagens do Hub IoT, atualiza o banco de dados SQL e notifica o usuário sobre sucesso ou falha.
  11. O Banco de Dados SQL do Azure rastreia ocorrências nos dispositivos de destino e nos serviços baseados no Azure, durante e após a implantação.

Componentes

  • O Azure IoT Edge executa cargas de trabalho em contêineres em dispositivos, fornecendo conectividade de baixa latência e conservando a largura de banda.
  • O Hub IoT do Azure é um serviço gerenciado hospedado na nuvem que atua como um hub de mensagens central entre os aplicativos IoT e os dispositivos que eles controlam.
  • O Registro de Contêiner do Azure é um serviço de registro privado baseado em nuvem para armazenar e gerenciar imagens de contêiner privado do Docker e artefatos relacionados.
  • O Azure Pipelines combina integração contínua (CI) e entrega contínua (CD) para testar e criar código automaticamente e enviá-lo para qualquer destino.
  • O Azure Functions é uma plataforma de computação sem servidor que permite executar código acionado por eventos sem ter que provisionar ou gerenciar a infraestrutura.
  • O Armazenamento do Azure fornece armazenamento altamente escalável, seguro, eficiente e económico para todos os tipos de dados, objetos e ficheiros empresariais.
  • O Banco de Dados SQL do Azure é um serviço de banco de dados relacional multimodelo totalmente gerenciado criado para a nuvem.
  • O Docker é uma plataforma aberta para desenvolver, enviar e executar aplicativos em contêineres.

Alternativas

A equipe de desenvolvimento avaliou várias opções antes de decidir sobre a solução completa de transferência delta de imagem do Docker. As secções seguintes descrevem as alternativas e os resultados da avaliação.

A equipa considerou os seguintes critérios de avaliação para cada opção:

  • Se a solução atendeu ou não aos requisitos.
  • Se uma quantidade baixa, média ou alta de lógica precisava ser implementada nos dispositivos.
  • Se uma quantidade baixa, média ou alta de lógica precisava ser implementada no Azure.
  • Eficiência de largura de banda, ou proporção de dados transferidos para o tamanho total de uma imagem, para transferir uma imagem de contêiner.

A eficiência da largura de banda incluiu cenários em que:

  • Não existiam imagens no dispositivo.
  • Uma imagem com a mesma base existia no dispositivo.
  • Uma imagem de uma versão anterior do aplicativo existia no dispositivo.
  • Uma imagem para o aplicativo construída em uma imagem base anterior existia no dispositivo.

A equipe usou os seguintes cenários para avaliar a eficiência da largura de banda:

Cenário Description
Transferir imagem com camada de base já no dispositivo Transfira uma nova imagem quando outra imagem já existente no dispositivo partilhar a imagem base. Este cenário representa a implantação de um novo aplicativo pela primeira vez, quando outro aplicativo já existe no mesmo sistema operacional e estrutura.
Atualizar a camada de aplicativo Altere apenas o código da imagem de um aplicativo existente. Esse cenário representa uma alteração típica quando um usuário confirma um novo recurso.
Atualizar a imagem de base Altere a versão da imagem base na qual o aplicativo foi criado.

Opção Transferir camadas do Docker

Uma imagem de contêiner do Docker é uma montagem UnionFS de diferenças de sistema de arquivos somente leitura, com outra camada gravável para alterações feitas enquanto o contêiner está em execução. Os sistemas de arquivos são chamados de camadas, que são basicamente pastas e arquivos. As camadas são empilhadas para formar a base do sistema de arquivos raiz do contêiner. Como as camadas são somente leitura, várias imagens podem compartilhar a mesma camada se tiverem a camada em comum.

A opção de transferência de camadas do Docker reutiliza as camadas entre imagens e transfere apenas novas camadas para o dispositivo. Essa opção seria mais útil para imagens que compartilham a mesma camada base, geralmente o sistema operacional, ou para atualizar versões de imagens existentes.

As desvantagens deste método incluem:

  • O orquestrador deve manter informações sobre quais camadas existem em quais dispositivos.
  • As alterações na camada base fazem com que todos os hashes das camadas subsequentes sejam alterados.
  • A comparação requer hashes de camada consistentes.
  • Pode haver dependências no Docker save e no Docker load.

Modificar a opção do cliente Docker

Essa opção se concentra em modificar ou encapsular o cliente Docker para que ele retome o download da camada após uma interrupção. Por padrão, um pull do Docker retoma um download se a conexão com a Internet for restaurada dentro de cerca de 30 minutos após a interrupção. Caso contrário, o cliente sai e perde todo o progresso do download.

Este método é viável, mas teve complicações, incluindo:

  • Todas as imagens no dispositivo têm de ser registadas com o daemon Docker que puxa as imagens, para maximizar a eficiência da largura de banda.
  • O projeto Docker de código aberto teria que ser modificado para suportar essa funcionalidade, apresentando um risco de rejeição por mantenedores de código aberto.
  • A transferência de dados por HTTP em vez da solução de transferência rápida de arquivos preferida do cliente exigiria o desenvolvimento de uma lógica de repetição personalizada.
  • Todas as camadas devem ser retransmitidas quando uma imagem base é alterada.

Opção de dispositivo de construção na borda

Essa abordagem move o ambiente de construção de imagem para os dispositivos. Os seguintes dados são enviados para o dispositivo:

  • O código-fonte do aplicativo que está sendo criado
  • Uma cópia de todos os pacotes NuGet dos quais o código depende
  • As imagens de base do Docker para o ambiente de compilação e tempo de execução do .NET Core
  • Metadados sobre a imagem final

Em seguida, um agente de compilação no dispositivo cria a imagem e a registra no Docker Manager do dispositivo.

Esta solução foi rejeitada porque:

  • Ainda precisaria haver uma maneira de mover imagens grandes do Docker para os dispositivos. As imagens para criar aplicativos .NET são maiores do que as próprias imagens do aplicativo.
  • Este método funciona apenas para aplicações em que a equipa tem o código-fonte, pelo que não pode utilizar imagens de terceiros.
  • A opção requer empacotar pacotes NuGet e rastrear seu movimento para os dispositivos.
  • Se uma imagem não fosse compilada no dispositivo, a equipe teria que depurar remotamente o ambiente de compilação e a imagem criada. A depuração remota exigiria um alto uso da conexão de internet potencialmente limitada.

Opção de transferência delta de imagem completa

A abordagem escolhida trata uma imagem do Docker como um único arquivo binário. O comando Docker save exporta a imagem como um arquivo .tar . A solução exporta as imagens existentes e novas do Docker e calcula o delta binário que, quando aplicado, transforma a imagem existente na nova.

A solução rastreia as imagens existentes do Docker nos dispositivos e cria patches delta binários para transformar as imagens existentes nas novas imagens. O sistema transfere apenas os patches delta através da conexão de internet de baixa largura de banda. Esta solução exigia alguma lógica personalizada para construir os patches binários, mas enviava a menor quantidade de dados para os dispositivos.

Resultados da avaliação

A tabela a seguir mostra como cada uma das soluções acima foi medida em relação aos critérios de avaliação.

Atende reqs Lógica do dispositivo Lógica do Azure Transporte Primeira imagem Base no dispositivo Atualizar camada de aplicativo Atualizar camada base
Transferir camadas do Docker Sim Baixo Médio FileCatalyst 100% 10.5% 22.4% 100%
Modificar o cliente Docker Sim Médio Baixo HTTP 100% 10.5% 22.4% 100%
Construa no dispositivo de borda Não Alto Médio FileCatalyst N/A N/D N/D N/A
Transferência delta de imagem completa Sim Baixa Alta FileCatalyst 100% 3.2% 0.01% 16.1%

Considerações

Essas considerações implementam pilares do Azure Well-Architected Framework, um conjunto de princípios orientadores que melhoram a qualidade da carga de trabalho. Para obter mais informações, consulte Microsoft Azure Well-Architected Framework.

Eficiência de desempenho

Essa solução reduziu drasticamente a largura de banda consumida pelas atualizações de dispositivos IoT. Os quadros seguintes apresentam uma repartição das diferenças em termos de eficiência de transferência.

Image Reconstructor como fonte:

Nome da imagem Tamanho da imagem Tamanho do patch Redução de dados
Visualização de dados 228 MB 79,6 MB 65.1%
WCD Simulado 188 MB 1,5 MB 99.2%
Proxy 258 MB 29,9 MB 88.4%

Versão anterior como fonte:

Nome da imagem Tamanho da imagem Tamanho do patch Redução de dados
Visualização de dados 228 MB 0,01 MB 99,9%
WCD Simulado 188 MB 0,5 MB 99.7%
Proxy 258 MB 0,04 MB 99,9%

Excelência operacional

As seções a seguir fornecem um passo a passo detalhado da solução.

Repositório de código-fonte

Os desenvolvedores interagem com o código-fonte do módulo de borda em um repositório de código-fonte. O repositório consiste em pastas que contêm o código para cada módulo, da seguinte forma:


\- repository root
    - modulea
    - modulea.csproj
    - module.json
    - Program.cs
    - Dockerfile

\- moduleb
    - moduleb.csproj
    - module.json
    - Program.cs
    - Dockerfile

O número recomendado de repositórios de código-fonte é:

  • Um repositório para todos os módulos em todos os fluxos de trabalho.
  • Um repositório de código-fonte para cada fluxo de trabalho.

Instâncias do Registro de Contêiner

O Container Registry armazena as imagens do Docker de cada módulo. Há duas configurações possíveis para o Registro de Contêiner:

  • Uma única instância do Registro de Contêiner que armazena todas as imagens.
  • Duas instâncias do Registro de Contêiner, uma para armazenar as imagens de desenvolvimento, teste e depuração e outra que contém apenas imagens marcadas como prontas para produção.

Repositório de manifesto

O repositório de manifesto contém os manifestos de implantação para todos os fluxos de trabalho. Os modelos estão em pastas com base em seu fluxo de trabalho. Neste exemplo, os dois fluxos de trabalho são a infraestrutura compartilhada e o aplicativo em contêiner.


\- repository root
     - Workstream1
         - deployment.template.json
     - Workstream2
         - deployment.template.json

Pipeline de construção de imagem do Docker

Cada módulo tem um pipeline de compilação do Azure Pipelines. O pipeline usa uma compilação genérica do Docker para criar e registrar módulos. O gasoduto é responsável por:

  • Verificação de segurança do código-fonte.
  • Verificação de segurança da imagem base para criar a imagem do Docker.
  • Execução de testes de unidade para o módulo.
  • Criando a fonte em uma imagem do Docker. A tag image contém o BUILD_BUILDID, para que a imagem sempre possa ser vinculada de volta ao código-fonte que a criou.
  • Empurrando a imagem para uma instância do Registro de Contêiner.
  • Criando o arquivo delta.
  • Criar um arquivo de assinatura para a imagem e salvá-lo em uma conta de armazenamento do Azure.

Todas as instâncias de pipeline são baseadas em uma única definição de pipeline YAML. O pipeline pode atuar nos módulos usando variáveis de ambiente. Os filtros acionam cada pipeline somente quando as alterações são confirmadas em uma determinada pasta. Este filtro evita a criação de todos os módulos quando apenas um módulo é atualizado.

Pipeline de imagem para dispositivo

O pipeline de imagem para dispositivo implanta as imagens do Docker nos dispositivos de destino, conforme definido por um arquivo de manifesto. O acionamento manual do pipeline inicia a implantação.

A definição de pipeline especifica a execução dessas implantações em um contêiner. Os pipelines suportam entrada variável para as imagens para basear contêineres. Uma única variável pode controlar implantações para todos os pipelines.

A imagem contém o código que determina quais patches criar, cria os patches e os distribui para o lado do Azure da ferramenta de transferência de arquivos.

A ferramenta de distribuição de imagens precisa das seguintes informações:

  • Qual(is) imagem(ns) implantar, fornecida pelo manifesto no repositório.
  • Em quais dispositivos implantar, fornecidos pelo usuário que aciona o pipeline.
  • Quais imagens já estão nos dispositivos de destino, fornecidas por um banco de dados SQL do Azure.

As saídas do pipeline são:

  • Pacotes de patches enviados para o lado do Azure da ferramenta de transferência de ficheiros, para serem distribuídos aos dispositivos.
  • Entradas do banco de dados SQL que marcam quais imagens começaram a ser transferidas para cada dispositivo.
  • Entradas do banco de dados SQL para os novos conjuntos de implantação. Essas entradas incluem o nome e o endereço de e-mail do usuário que ordenou a implantação.

Esse pipeline executa as seguintes etapas:

  1. Determina as imagens necessárias, com base no manifesto de implantação.
  2. Consulta SQL para ver quais imagens já estão nos dispositivos. Se todas as imagens já estiverem presentes, o pipeline será encerrado com êxito.
  3. Determina quais pacotes de patch criar. O algoritmo determina qual imagem inicial gera o menor pacote de patches.
    • Entradas: um arquivo de .tar contendo a nova imagem a ser implantada e arquivos de assinatura para as imagens existentes nos dispositivos.
    • Saída: Uma classificação das imagens existentes para determinar o menor patch a ser criado.
  4. Cria os pacotes de patches necessários para cada dispositivo. Cria patches semelhantes uma vez e copia-os para todos os dispositivos que precisam deles.
  5. Distribui os patches para a conta de armazenamento da ferramenta de transferência de arquivos para implantação.
  6. Atualiza o SQL para marcar as novas imagens como in transit para cada um dos dispositivos de destino.
  7. Adiciona as informações do conjunto de implantação ao SQL, com o nome e o email de contato da pessoa que está implantando a imagem.

Diagrama mostrando o arquivo original para o arquivo alterado para o fluxo de trabalho de dados resultante.

Pipeline de manifesto para dispositivo

O pipeline de manifesto para dispositivo envia o manifesto de implantação para a conexão adequada do Hub IoT para o dispositivo que está sendo atualizado. Um usuário aciona o pipeline manualmente e especifica uma variável de ambiente para a instância do Hub IoT de destino.

O gasoduto:

  • Determina quais imagens a implantação precisa.
  • Consulta SQL para certificar-se de que as imagens necessárias estão todas nos dispositivos de destino. Caso contrário, o pipeline termina com um failed status.
  • Envia o novo manifesto de implantação para o Hub IoT adequado.

Solução rápida de transferência de ficheiros

O cliente queria continuar usando sua solução de transferência rápida de arquivos de terceiros, chamada FileCatalyst, para fornecer a conexão entre o Azure e seus dispositivos IoT. Esta solução é uma ferramenta de transferência de arquivos eventualmente consistente , o que significa que uma transferência pode levar muito tempo, mas acabará sendo concluída sem perder nenhuma informação de arquivo.

A solução usou uma conta de Armazenamento do Azure no lado do Azure da conexão e a VM de host de transferência de arquivos existente do cliente para cada dispositivo que recebe imagens. Os pacotes de patch são transferidos para uma VM Linux que executa o Hub IoT.

Módulo de reconstrução de imagem

O módulo IoT Edge de reconstrução de imagem aplica os patches recebidos nos dispositivos. Cada dispositivo hospeda seu próprio registro de contêiner local, usando o registro de código aberto do Docker. O processo de reconstrução de imagem é executado na VM do host, que é o mesmo que a VM de transferência de arquivos.

O módulo:

  1. Recebe o pacote de patches em uma pasta montada no contêiner.
  2. Descompacta o conteúdo do patch para ler o arquivo de configuração.
  3. Extrai a imagem base do registro de contêiner local por hash.
  4. Salva a imagem base como um arquivo .tar .
  5. Aplica o patch à imagem base.
  6. Carrega o arquivo de .tar que contém a nova imagem no Docker.
  7. Envia a nova imagem para o registro de contêiner local, com um arquivo de configuração que inclui um nome e uma tag amigáveis.
  8. Envia uma mensagem de sucesso para o Hub IoT.

Se o processo falhar a qualquer momento, o módulo enviará uma mensagem de falha para o Hub IoT, para que o usuário que disparou a implantação possa ser notificado.

Hub IoT

Vários dos processos de implantação usam o Hub IoT. Além de receber mensagens de status do módulo de reconstrução de imagem, o Hub IoT define o manifesto de implantação para o dispositivo. O restante do fluxo do pipeline usa esse manifesto.

Diagrama mostrando o patch do Centro de Operações e do dispositivo IoT para o fluxo de trabalho do Image Reconstructor.

Funções do Azure

O Azure Functions monitora o fluxo de mensagens provenientes do Hub IoT e executa ações na nuvem.

Para uma mensagem de sucesso:

  • A função atualiza o status da entrada SQL para a imagem no dispositivo de in transit para succeeded.
  • Se esta imagem for a última a chegar em um conjunto de implantação:
    • A função notifica o usuário sobre o sucesso da implantação.
    • A função atualiza o pipeline de manifesto para dispositivo para começar a usar as novas imagens.

Para uma mensagem de falha:

  • A função atualiza o status da entrada SQL para a imagem no dispositivo de in transit para failed.
  • A função notifica o usuário da falha de transferência de imagem.

Centro de Operações e fluxo de trabalho de mensagens do reconstrutor de imagens de dispositivos IoT

Base de Dados SQL

Um banco de dados SQL rastreia ocorrências nos dispositivos de destino e nos serviços de implantação baseados no Azure durante e após a implantação. O Azure Functions e o Azure Pipelines usam um pacote NuGet privado criado para interagir com o banco de dados.

O Banco de dados SQL armazena os seguintes dados:

  • Quais imagens estão em cada dispositivo.
  • Que imagens estão a caminho de cada dispositivo.
  • Quais imagens que estão sendo implantadas pertencem a um conjunto.
  • O usuário que ordenou as implantações.

O objetivo deste exemplo era garantir que o sistema gerasse os dados necessários para futuros painéis de dados. Consultar o Hub IoT pode fornecer os seguintes dados sobre o pipeline de manifesto para dispositivo:

  • O estado de uma implantação.
  • As imagens em um determinado dispositivo.
  • Os dispositivos que têm uma imagem.
  • Dados de séries cronológicas sobre transferências bem-sucedidas e falhadas.
  • Consultas de implantações com base no usuário.

Contribuidores

Este artigo é mantido pela Microsoft. Foi originalmente escrito pelos seguintes contribuidores.

Autor principal:

  • Kanio Dimitrov - Brasil | Líder Principal de Engenharia de Software

Próximos passos