Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Boas práticas de IoT em escala de produção: implementação com GCP (Parte 1/3)

By Matthew PorterAug 10, 202113 min read

Esta página também está disponível em English, Deutsch, Español, Français, Italiano e 日本語.

Quer aprender a montar uma operação de IoT na nuvem totalmente gerenciada, com auto scaling e serverless?

Nesta série de três artigos, IoT no GCP, vamos cobrir um fluxo de IoT completo: do registro do dispositivo ao streaming e armazenamento de longo prazo dos dados, passando pela análise e visualização dessas informações.

Boas práticas de IoT em escala de produção

Ao terminar a Parte Um, você vai saber como registrar com segurança milhões de dispositivos IoT que transmitem dados de telemetria para o seu ambiente Google Cloud.

Esta é a primeira de uma série de três partes:

  • O armazenamento e a visualização adequados desses fluxos de dados de alta vazão serão abordados na Parte Dois;
  • A construção de um modelo funcional de machine learning sobre dados de IoT será abordada na Parte Três.

Ao longo da série, vamos usar o GCP como provedor de nuvem e dispositivos Raspberry Pi com sensores de temperatura como exemplo de dispositivos IoT.

Visão geral

Este conteúdo está dividido nas seguintes seções:

  1. Configuração de software e hardware do Raspberry Pi
  2. Registro prático de dispositivos e provisionamento de credenciais
  3. Teste de conectividade do dispositivo e streaming de dados de temperatura
  4. Ressalvas sobre as funcionalidades do Google Cloud IoT
  5. Armazenamento dos dados em streaming (na Parte Dois)
  6. Visualização dos dados em streaming (na Parte Dois)
  7. Construção de um modelo eficaz de machine learning com dados de IoT (na Parte 3)

Para acompanhar este artigo, basta ter experiência com Bash e Python e uma noção básica de como navegar no Google Cloud Console.

Configurando o software e o hardware do Raspberry Pi

Primeiro, deixe vários Raspberry Pi prontos para uso — vou usar dispositivos Pi 3. Recomendo o Raspbian OS Imager para automatizar a instalação do sistema operacional em cartões microSD.

Instale os pacotes Python

Depois de chegar à área de trabalho e atualizar o dispositivo, execute o comando a seguir para instalar o SDK específico do Google Cloud IoT:

pip3 install -U pyjwt paho-mqtt

Antes de seguir em frente, vale entender por que estamos instalando o paho-mqtt em vez do SDK Python de uso geral google-api-python-client para Google Cloud. O SDK Python mais comum, assim como a CLI gcloud do GCP, são baseados em HTTP. Esse protocolo é útil para executar a maioria das ações com agilidade. Só que o HTTP não é adequado para enviar mensagens em conexões de longa duração com alta probabilidade de instabilidade, em que os dados fluem majoritariamente para fora do dispositivo conectado.

O MQTT é um protocolo usado em IoT, por meio de pacotes como o paho-mqtt, justamente porque foi projetado para que um dispositivo consiga publicar mensagens com frequência e receber mensagens esporadicamente, mesmo diante de problemas de conectividade.

Conecte um sensor de temperatura digital

Agora que o seu Raspberry Pi tem os pacotes Python necessários instalados, é hora de conectar um sensor de temperatura digital a ele. Recomendo este sensor DS18B20 caso queira acompanhar o artigo.

Você também vai precisar dos seguintes itens para conectar o sensor ao Raspberry Pi:

Se precisar esperar esses itens chegarem, fique à vontade para continuar a leitura, porque vamos disponibilizar um script para enviar temperaturas simuladas.

Se você já tem os componentes em mãos, os primeiros cinco minutos deste tutorial mostram como conectar o sensor ao Raspberry Pi e validar se ele está recebendo valores de temperatura.

Além do processo descrito no tutorial acima, recomendo adicionar o seguinte ao /etc/modules para garantir que os módulos onewire sejam carregados na inicialização, em vez de rodar modprobe a cada reinicialização:

w1-gpio
w1-therm

Registrando seus dispositivos IoT

Veja abaixo um exemplo completo e funcional de como configurar o seu IoT Registry com dispositivos registrados de forma segura, a partir dos quais vamos transmitir dados de temperatura para a plataforma Google Cloud IoT.

Crie um registry para os seus dispositivos

No Google Cloud Console:

  1. Crie um novo projeto (por exemplo, "IoTTempStreaming")
  2. Acesse o serviço IoT Core para habilitar a IoT API
  3. Clique em "Create registry" para criar um registry e adicionar seus dispositivos IoT.

Os dispositivos IoT que enviam dados via streaming para o GCP só conseguem mandar mensagens para o IoT Core se forem validados como dispositivos credenciados armazenados no IoT Registry — por isso a criação do registry é uma primeira etapa essencial.

Um ambiente IoT Core novinho em folha, esperando para ser preenchido com mensagens

Crie um tópico no Pub/Sub

As mensagens enviadas ao IoT Core — junto de metadados críticos, como o deviceId exclusivo do dispositivo — são encaminhadas, nos bastidores, para um "tópico" no Pub/Sub, o sistema de fila de mensagens do Google Cloud, totalmente gerenciado, com auto scaling e serverless.

Por isso, também vamos criar tópicos no Pub/Sub a partir do prompt do IoT Registry, para que os dados de telemetria cheguem ao Pub/Sub e sigam para processamento downstream.

Siga estes passos para criar um tópico Pub/Sub a partir do prompt do IoT Registry:

  1. Defina o Registry ID como "RaspberryPiDevices" na região us-central1
  2. Crie um tópico Pub/Sub chamado "sensordata", para onde as mensagens de telemetria de IoT chegam por padrão.
  3. Em "Additional topics", crie um novo tópico Pub/Sub chamado "temperature", para onde chegarão as mensagens publicadas em uma subpasta de tópico IoT — também chamada "temperature".

Essa configuração garante que apenas as mensagens de temperatura publicadas em uma subpasta IoT específica cheguem ao tópico Pub/Sub temperature, e que todos os outros eventos de telemetria (inesperados) caiam no tópico padrão "sensordata".

Também recomendo expandir as opções avançadas e permitir somente o protocolo MQTT, desmarcando HTTP:

Configuração do IoT Core Registry para streaming de dados do sensor de temperatura

Depois de criado, o seu registry deve ficar assim:

Configuração bem-sucedida do IoT Core Registry

Crie um dispositivo registrado

Agora que temos um registry de dispositivos, vamos criar um dispositivo registrado.

Para começar, precisamos de (1) um par de chaves pública-privada associado ao dispositivo e (2) o certificado raiz do Google.

Veja abaixo os comandos a executar em um Raspberry Pi para gerar chaves de Curva Elíptica e baixar o certificado raiz do Google (os comandos seguem a documentação oficial do Google Cloud). As chaves EC têm um footprint de dados menor que as tradicionais chaves RSA e ajudam os dispositivos IoT a manter um throughput ideal em áreas com conectividade ruim:

$ mkdir -p /home/pi/GCP/iot_keys/
$ cd /home/pi/GCP/iot_keys/
$ wget http://pki.goog/roots.pem
$ openssl ecparam -genkey -name prime256v1 -noout -out ec_private.pem
$ openssl ec -in ec_private.pem -pubout -out ec_public.pem
$ cat ec_public.pem
$ cd ../

Depois de executar os comandos acima:

  1. Copie a chave pública exibida no terminal
  2. Vá até o IoT Registry e acesse Devices
  3. Clique em Add Device
  4. Dê um nome ao dispositivo (por exemplo, "device1") e cole sua chave pública ES256 em Authentication, conforme mostrado abaixo.
  5. Clique em Create

Registro de dispositivo IoT solicitando uma chave de Curva Elíptica

Pronto: as credenciais associadas a um dispositivo registrado no IoT Core já podem ser usadas em um Raspberry Pi!

Anote o Numeric ID atribuído ao dispositivo, o Project ID e o Registry ID.

Com esses valores, mais as chaves e o certificado raiz do Google no dispositivo, precisamos criar um arquivo de configuração chamado gcp_iot_config.txt. Esse arquivo define os detalhes de autenticação e do endpoint IoT que cada dispositivo vai usar. Logo mais no artigo, mostramos um script Python que faz streaming dos valores de temperatura usando esse arquivo de configuração:

$ pwd
/home/pi/GCP/
$ cat gcp_iot_config.txt
# Set the path to the location containing your keys
KEY_PATH = /home/pi/GCP/iot_keys/# Specify the private key and Google root cert names
PRIVATE_KEY      = ec_private.pem
GOOGLE_ROOT_CERT = roots.pem# Set the details required for using your IoT endpoint
REGISTRY_ID = <REGISTRY_ID>
DEVICE_ID   = <DEVICE_NUMERIC_ID>
REGION      = us-central1
PROJECT_ID  = <PROJECT_ID>

E voilà! O seu dispositivo já está pronto para transmitir dados de telemetria com segurança a um tópico Pub/Sub via plataforma de autenticação do IoT Core do GCP. Repita o processo acima para gerar credenciais únicas e registrar cada novo dispositivo.

Teste a conectividade do dispositivo

Vamos testar a conectividade do dispositivo executando o seguinte script, chamado "publish_temps.py", que faz streaming de valores de temperatura reais (do dispositivo) ou simulados, dependendo de qual linha (107 ou 108) está comentada.

(O script é uma adaptação de dois exemplos do Google Cloud: #1 e #2)

$ pwd
/home/pi/GCP/
$ ./publish_temps.py

Tem bastante coisa rolando aqui — recomendo muito revisar o código para entender melhor como ele se conecta e faz o streaming dos dados de forma segura.

Ao executar o script, você deve ver uma saída parecida com esta:

Valores reais de temperatura sendo transmitidos ao GCP IoT Core via MQTT

Se você rodar esse script no boot via uma tarefa do crontab (com um sleep de 30s antes, para dar tempo de os módulos onewire carregarem na inicialização), o dispositivo IoT vai retomar o streaming após qualquer reinicialização (esperada ou não):

$ crontab -e
@reboot sleep 30 && /home/pi/GCP/publish_temps.py -c /home/pi/GCP/gcp_iot_config.txt >> /home/pi/GCP/publish_temps.log 2>&1

Repita os processos de onboarding e streaming para todos os Raspberry Pi espalhados pela casa. Você está bem encaminhado para trabalhar com dados de IoT em escala!

Confira se os dados estão chegando

Vamos verificar rapidinho se as mensagens estão chegando ao Google Cloud, conferindo os dados de telemetria que aterrissam no Pub/Sub.

  1. Crie uma assinatura no Pub/Sub para o tópico "temperature"
  2. Acesse a assinatura
  3. Clique em View Messages e selecione a opção Pull

Você vai ver as mensagens conforme elas chegam, com as informações de temperatura e timestamp no corpo, além dos metadados de atributos que identificam de forma única qual dispositivo está enviando esses valores. Esses metadados são úteis não só para análises e dashboards de usuários finais, mas também para identificar e bloquear dispositivos abusivos ou comprometidos.

Criação de uma assinatura Pub/Sub usada para visualizar as mensagens de telemetria de temperatura recebidas

Veja como fica uma assinatura do tópico temperature:

Visualizando mensagens de uma assinatura Pub/Sub do tópico Pub/Sub "temperature"

Depois de clicar em "PULL", você vai começar a ver as mensagens e seus atributos:

Dados de temperatura chegando a um tópico Pub/Sub e a uma assinatura Pub/Sub: corpo da mensagem

Dados de temperatura chegando a um tópico Pub/Sub e a uma assinatura Pub/Sub: atributos que identificam o dispositivo de forma única

Se você chegou até aqui, parabéns (sério mesmo)! Por mais empolgante que seja ver dados reais de dispositivos IoT chegando ao Pub/Sub, mal arranhamos a superfície.

Para realmente extrair valor desses dados, talvez seja preciso transformá-los, movê-los/carregá-los em lote para um data warehouse e analisá-los. Tudo isso precisa rodar sobre um ecossistema de serviços do GCP que viabilize esse fluxo de dados de forma confiável, em escala e com bom custo-benefício, em todas as etapas do desenvolvimento — dos testes iniciais ao uso em produção em escala de petabytes e além —, com pouca ou nenhuma manutenção de infraestrutura. Quer ver como isso é feito? Fique de olho nas partes dois e três!

A seguir: armazenamento e visualização

Fique ligado na parte dois, em que vou falar sobre os serviços de ETL, armazenamento e visualização certos para viabilizar, com relativa facilidade, o uso prático de dados de IoT em larga escala via streaming.

Ressalvas sobre as funcionalidades do Google Cloud IoT

Tratamento melhor do deviceId pelo serviço totalmente gerenciado do GCP

Você deve ter notado que o script Python envia um par chave:valor device_id no corpo da mensagem, o que, na prática, duplica o atributo deviceId presente na mensagem do Pub/Sub — atributo esse atribuído pelo IoT Core via associação da mensagem ao par chave-valor único do dispositivo que está fazendo o streaming.

Por que faria sentido o script enviar um device_id que poderia ser facilmente forjado em um dispositivo comprometido, contaminando o data warehouse com dados envenenados quando essas mensagens fossem movidas para o armazenamento de longo prazo?

Bom, estou me adiantando um pouco aqui, mas, como vamos ver na Parte Dois, existe um workflow conveniente, totalmente gerenciado, com auto scaling e majoritariamente serverless, capaz de transformar e mover mensagens do Pub/Sub para o BigQuery usando o Dataflow, a versão totalmente gerenciada do Apache Beam no Google Cloud.

Infelizmente, o template padrão "Pub/Sub-to-BigQuery" escrito pelo GCP e disponível no Dataflow não oferece nenhuma maneira de levar atributos de mensagem para o BigQuery; só é possível mover o conteúdo do corpo. Confirmei com vários engenheiros do GCP que não dá para escrever uma UDF Javascript personalizada para os templates padrão deles que adicione atributos de mensagem aos sinks do Dataflow, como o BigQuery. Como alternativa, escrever jobs Java de Dataflow — seja do zero ou modificando templates existentes do GCP — é uma empreitada demorada, que exige manutenção e atualizações contínuas dos templates, algo que, imagino, a maioria dos clientes do GCP não vai querer assumir.

Portanto, por padrão, não há uma forma simples e segura de associar uma mensagem IoT que chega ao Pub/Sub e segue para os sinks de dados de destino com o deviceId dessa mensagem.

Levantei essa lacuna com o GCP e, desde então, eles abriram uma solicitação pública de funcionalidade para garantir que os templates padrão suportem o repasse desses valores valiosos — e absolutamente necessários — para atender ao caso de uso de IoT. Vou atualizar o artigo assim que essa solicitação for atendida; até lá, para fins de demonstração, é muito mais fácil testar o uso do device_id enviando-o pelo corpo da mensagem do que reescrever um template do Dataflow que deveria já vir pronto.

Como eu provisionaria credenciais únicas por dispositivo, idealmente?

O processo para registrar um único dispositivo IoT costuma ser explicado assim:

  1. Crie um par de chaves pública-privada associado no GCP às permissões de IoT
  2. Provisione e coloque esses arquivos no dispositivo, na fábrica
  3. Faça com que a fábrica registre essas credenciais no IoT Registry
  4. Habilite o par de chaves para fazer chamadas à IoT API que transmitem dados para a nuvem.

Esse esquema, por si só, não é o ideal, já que casos reais de uso de IoT envolvem milhões de dispositivos transmitindo dados para um ambiente de nuvem. Cada dispositivo dessa frota precisa receber um conjunto único de credenciais, para que, se um dispositivo ou suas credenciais do Google Cloud forem comprometidos e usados para fins ilegítimos, esse conjunto possa ser desativado sem afetar os demais dispositivos da frota.

O GCP oferece essa funcionalidade e, como visto no script acima, também permite que um dispositivo só publique em um tópico exclusivo dele. Mesmo assim, considerando as metodologias de provisionamento de credenciais disponíveis hoje, coordenar a criação, implantação e registro de chaves para milhões de dispositivos é um desafio.

Como tornar a criação de credenciais específicas por dispositivo o mais simples possível? Dá para fazer isso sem criar milhões de certificados antecipadamente e coordenar sua colocação única nos dispositivos durante a fabricação? Você quer mesmo depender de um fabricante para colocar esses arquivos de forma confiável e sem duplicações?

Por outro lado, dá para fazer o registro e a credenciação dos dispositivos sem exigir que o fabricante chame a sua IoT Registry para criar novas credenciais sob demanda toda vez que um dispositivo desce a linha de produção para receber software e credenciais? E o que acontece com a linha de produção se a conexão com o seu API Gateway responsável pelo registro IoT cair?

Eu prefiro evitar esses métodos porque são mais complexos, propensos a erros e impõem um ônus desnecessário ao fabricante.

Um sistema de registro de dispositivos seguro e com escalabilidade razoável que eu gostaria de ver suportado pelo GCP seguiria estas diretrizes:

  1. Cria-se um único certificado IoT que será colocado em todos os dispositivos IoT. Esse certificado, batizado de "bootstrap", estaria associado a uma política de permissões que só permite ao dispositivo fazer uma requisição para (a) criar e obter credenciais específicas do dispositivo, caso a requisição seja aprovada, e (b) adicionar a si mesmo ao IoT Registry de dispositivos.
  2. A plataforma GCP IoT Core, ao receber e aprovar a requisição de criação de credenciais, criaria um novo par de chaves. As permissões IoT associadas — assim como o Google Cloud já faz hoje — devem permitir apenas que um dispositivo publique mensagens em um tópico exclusivo dele.
  3. A criação das credenciais únicas por dispositivo deveria passar por uma etapa de validação. Essa etapa seria uma Cloud Function escrita por você que exige identificadores únicos na requisição, para que possam ser conferidos contra uma whitelist (por exemplo, uma lista de números de série fabricados ou endereços MAC utilizados) e/ou uma blacklist (por exemplo, uma lista de números de série associados a dispositivos comprometidos, abusivos ou já registrados).
  4. Se a requisição de certificado único for aprovada na validação, o dispositivo é adicionado ao IoT Registry e os novos arquivos de credenciais são entregues ao dispositivo para uso no streaming de dados.

Com esse workflow, um fabricante de dispositivos IoT precisaria apenas embarcar o certificado bootstrap em cada dispositivo. O par de chaves específico do dispositivo, que viabiliza o streaming de dados, poderia ser criado e obtido na própria fábrica, se desejado, ou depois, quando o dispositivo já estivesse com o usuário final.

Independentemente de quando as credenciais são obtidas, o fabricante simplesmente embarcaria, no dispositivo, o software fornecido por você, que executa o processo de criação do par de chaves único — baseado no certificado bootstrap — quando:

  • O dispositivo é ligado
  • Há conexão com a Internet, e
  • Não é encontrado um par de chaves específico do dispositivo

Infelizmente, essa funcionalidade ainda não existe (por enquanto). Mas, fora a questão do registro de dispositivos em massa, a oferta de IoT do Google Cloud — combinada com os serviços downstream de processamento de mensagens totalmente gerenciados (abordados na Parte Dois) — forma, no conjunto, uma solução robusta, segura e facilmente escalável baseada em nuvem para o universo de IoT.