Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Best practice IoT in produzione: implementazione su Google Cloud (Parte 1/3)

By Matthew PorterJan 5, 202113 min read

Questa pagina è disponibile anche in English, Deutsch, Español, Français, 日本語 e Português.

1 mzhmgbzadzlrio1 pmnv8w

Vuole scoprire come realizzare nel cloud un'infrastruttura IoT completamente gestita, con auto-scaling e serverless?

In questa serie in tre puntate, IoT su GCP, percorreremo l'intero workflow IoT: dalla registrazione dei dispositivi allo streaming e all'archiviazione a lungo termine dei dati, fino alla loro analisi e visualizzazione.

Best practice per l'IoT in produzione

Al termine della Parte Uno saprà come registrare in modo sicuro milioni di dispositivi IoT che inviano dati di telemetria in streaming al proprio ambiente Google Cloud.

Questo è il primo di tre articoli; nei successivi vedremo:

  • come archiviare e visualizzare correttamente flussi di dati ad alto throughput (Parte Due);
  • come costruire un modello di machine learning funzionante sui dati IoT (Parte Tre).

Lungo l'intera serie useremo GCP come cloud provider e dispositivi Raspberry Pi con sensori di temperatura come esempio di dispositivi IoT.

Panoramica

L'argomento è suddiviso nelle seguenti sezioni:

  1. Configurazione software e hardware del Raspberry Pi
  2. Registrazione pratica dei dispositivi e provisioning delle credenziali
  3. Test di connettività dei dispositivi e streaming dei dati di temperatura
  4. Limiti e accorgimenti delle funzionalità IoT di Google Cloud
  5. Archiviazione dei dati in streaming (nella Parte Due)
  6. Visualizzazione dei dati in streaming (nella Parte Due)
  7. Costruzione di un modello di machine learning efficace sui dati IoT (nella Parte 3)

Per seguire questo articolo bastano un po' di esperienza con Bash e Python e una conoscenza di base della Google Cloud Console.

Configurare software e hardware del Raspberry Pi

Per prima cosa, prepari alcuni Raspberry Pi pronti all'uso — io userò dei Pi 3. Consiglio di affidarsi al Raspbian OS Imager per automatizzare l'installazione del sistema operativo sulle schede microSD.

Installare i pacchetti Python

Una volta arrivato al desktop e aggiornato il dispositivo, esegua il comando seguente per installare l'SDK specifico per Google Cloud IoT:

pip3 install -U pyjwt paho-mqtt

Prima di proseguire, è bene capire perché stiamo installando paho-mqtt e non l'SDK Python google-api-python-client per Google Cloud, di uso più generale. L'SDK Python più diffuso, così come la CLI gcloud di GCP, sono basati su HTTP. È un protocollo utile per eseguire rapidamente la maggior parte delle azioni, ma non è adatto a inviare messaggi su connessioni di lunga durata con elevata probabilità di interruzioni, dove i dati fluiscono prevalentemente dal dispositivo verso l'esterno.

MQTT è invece un protocollo molto usato in ambito IoT — tramite pacchetti come paho-mqtt — proprio perché è progettato per consentire a un dispositivo di pubblicare messaggi di frequente e riceverne raramente, anche in presenza di problemi di connettività.

Collegare un sensore di temperatura digitale

Ora che il Raspberry Pi ha i pacchetti Python necessari, dovrà collegarvi un sensore di temperatura digitale. Se vuole seguire l'articolo passo passo, consiglio questo sensore DS18B20.

Per collegare il sensore al Raspberry Pi le servono inoltre:

Se deve attendere l'arrivo dei componenti, può comunque proseguire con la lettura: più avanti forniremo uno script per simulare lo streaming dei valori di temperatura.

Se ha già tutto il materiale, i primi cinque minuti di questo tutorial mostrano come collegare il sensore al Raspberry Pi e verificare che riceva correttamente i valori di temperatura.

Oltre alla procedura descritta nel tutorial, consiglio di aggiungere quanto segue a /etc/modules, così da caricare i moduli onewire all'avvio ed evitare di lanciare modprobe dopo ogni riavvio:

w1-gpio
w1-therm

Registrare i dispositivi IoT

Di seguito un esempio completo e funzionante di come configurare l'IoT Registry con dispositivi registrati in modo sicuro, dai quali invieremo i dati di temperatura in streaming alla piattaforma Google Cloud IoT.

Creare un registry per i dispositivi

Nella Google Cloud Console:

  1. Crei un nuovo progetto (ad esempio "IoTTempStreaming")
  2. Vada al servizio IoT Core per abilitare l'API IoT
  3. Clicchi su "Create registry" per creare un registry in cui inserire i dispositivi IoT.

I dispositivi IoT che inviano dati a GCP possono trasmettere i propri messaggi a IoT Core soltanto se vengono validati come dispositivi credenziati registrati nell'IoT Registry: la creazione del registry è quindi un primo passo imprescindibile.

1 x6ytdhxs pffshahwra2mqUn ambiente IoT Core appena creato, in attesa dei primi messaggi

Creare un topic Pub/Sub

I messaggi inviati a IoT Core — insieme a metadati critici come il deviceId univoco di ciascun dispositivo — vengono inoltrati dietro le quinte a un "topic" in Pub/Sub, il sistema di code di messaggi di Google Cloud completamente gestito, con auto-scaling e serverless.

Per questo motivo creeremo anche dei topic Pub/Sub all'interno del prompt dell'IoT Registry, in modo che i dati di telemetria arrivino infine in Pub/Sub per l'elaborazione a valle.

Per creare un topic Pub/Sub dal prompt dell'IoT registry, segua questi passaggi:

  1. Assegni al Registry ID il nome "RaspberryPiDevices" nella regione us-central1
  2. Crei un topic Pub/Sub denominato "sensordata", in cui per impostazione predefinita confluiranno i messaggi di telemetria IoT.
  3. In "Additional topics" crei un nuovo topic Pub/Sub denominato "temperature", in cui arriveranno i messaggi pubblicati su una sottocartella di topic IoT — anch'essa chiamata "temperature".

Questa configurazione garantisce che solo i messaggi di temperatura pubblicati sulla specifica sottocartella IoT arrivino al topic Pub/Sub temperature, mentre tutti gli altri eventi di telemetria (inattesi) confluiranno nel topic predefinito "sensordata".

Consiglio inoltre di espandere le opzioni avanzate e di consentire solo il protocollo MQTT, deselezionando HTTP:

1 hehi7hqvsqephvxoaagvsqConfigurazione del registry IoT Core per lo streaming dei dati del sensore di temperatura

Una volta creato, il registry dovrebbe presentarsi così:

1 mydo62tfghtw76giklkc6qConfigurazione del registry IoT Core completata con successo

Creare un dispositivo registrato

Ora che abbiamo un registry, creiamo un dispositivo registrato.

Per iniziare ci servono (1) una coppia di chiavi pubblica-privata da associare al dispositivo e (2) il certificato root di Google.

Di seguito i comandi da eseguire su un Raspberry Pi per generare le chiavi Elliptic Curve e scaricare il certificato root di Google (i comandi sono basati sulla relativa documentazione di Google Cloud). Le chiavi EC hanno un'impronta dati inferiore rispetto alle tradizionali chiavi RSA e aiutano i dispositivi IoT a mantenere un throughput ottimale anche in aree con connettività difficile:

$ mkdir -p /home/pi/GCP/iot_keys/
$ cd /home/pi/GCP/iot_keys/
$ wget

https://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 ../

Eseguiti i comandi:

  1. Copi la chiave pubblica visualizzata nel terminale
  2. Vada all'IoT Registry e selezioni Devices
  3. Clicchi su Add Device
  4. Assegni un nome al dispositivo (ad esempio "device1") e incolli la chiave pubblica ES256 in Authentication, come mostrato di seguito.
  5. Clicchi su Create

1 vkia4oezrnypz6y1knxdsgRegistrazione di un dispositivo IoT con richiesta di una chiave Elliptic Curve

Una volta creato, le credenziali associate al dispositivo registrato in IoT Core sono pronte per essere usate sul Raspberry Pi.

Annoti il Numeric ID assegnato al dispositivo, il Project ID e il Registry ID.

Con questi valori, oltre alle chiavi e al certificato root di Google sul dispositivo, dobbiamo creare un file di configurazione chiamato gcp_iot_config.txt. Questo file definirà i dettagli di autenticazione e gli endpoint IoT da utilizzare per uno specifico dispositivo. Più avanti descriveremo uno script Python che invia in streaming i valori di temperatura sfruttando questo file di configurazione:

$ pwd
/home/pi/GCP/
$ cat gcp_iot_config.txt
[SETTINGS]
KEY_PATH = /home/pi/GCP/iot_keys/
PRIVATE_KEY = ec_private.pem
GOOGLE_ROOT_CERT = roots.pem
REGISTRY_ID = <REGISTRY_ID>
DEVICE_ID = <DEVICE_NUMERIC_ID>
REGION = us-central1
PROJECT_ID = <PROJECT_ID>

Et voilà! Il dispositivo è ora pronto a inviare in modo sicuro i dati di telemetria a un topic Pub/Sub tramite la piattaforma di autenticazione IoT Core di GCP. Ripeta la procedura per generare credenziali univoche e registrare ogni nuovo dispositivo.

Testare la connettività dei dispositivi

Verifichiamo la connettività del dispositivo eseguendo lo script seguente, denominato "publish_temps.py", che invia in streaming valori di temperatura reali (letti dal dispositivo) o simulati, a seconda che la riga 107 o la 108 sia commentata.

(Lo script è un adattamento di due esempi Google Cloud: #1 e #2)

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

https://gist.github.com/doit-mattporter/7e548158a5dc03b3674282cda19ef663

Qui succedono parecchie cose: consiglio vivamente di leggere il codice per capire meglio come si connette in modo sicuro e invia i dati in streaming.

Eseguendo lo script dovrebbe vedere un output simile al seguente:

1 xwupjjvzrfeowndrus3kgaValori di temperatura reali inviati in streaming a GCP IoT Core via MQTT

Se esegue lo script all'avvio tramite un job di crontab (preceduto da uno sleep di 30 secondi per consentire il caricamento dei moduli onewire al boot), il dispositivo IoT riprenderà lo streaming in caso di riavvio (atteso o imprevisto):

$ 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

Ripeta le procedure di onboarding e streaming per tutti i Raspberry Pi distribuiti in casa. È sulla buona strada per lavorare con dati IoT su larga scala.

Verificare che i dati arrivino in streaming

Verifichiamo rapidamente che i messaggi stiano arrivando in Google Cloud, controllando i dati di telemetria che entrano in Pub/Sub.

  1. Crei una sottoscrizione Pub/Sub al topic "temperature"
  2. Vada alla sottoscrizione
  3. Clicchi su View Messages e selezioni il radio button Pull

Vedrà i messaggi arrivare uno dopo l'altro, completi di temperatura e timestamp inviati nel body del messaggio, oltre ai metadati attributo che identificano in modo univoco il dispositivo che sta inviando quei valori. I metadati attributo sono utili non solo per l'analytics e per le dashboard rivolte agli utenti finali, ma anche per individuare e bloccare dispositivi compromessi o utilizzati in modo abusivo.

1 upi0lt7zazoqrrpyarx8fgCreazione di una sottoscrizione Pub/Sub utilizzata per visualizzare i messaggi di telemetria di temperatura in arrivo

Ecco come si presenta una sottoscrizione al topic temperature:

1 gqxuwk5oyv0q8bpaits7nqVisualizzazione dei messaggi per una sottoscrizione Pub/Sub al topic Pub/Sub "temperature"

Una volta cliccato "PULL", inizierà a vedere i messaggi e i loro attributi:

1 1aj1ua6vjuje1s0rdqmtaDati di temperatura che arrivano a un topic Pub/Sub e a una sottoscrizione Pub/Sub: corpo del messaggio1 j3pbnwvayyqmr0cgkgz1sgDati di temperatura che arrivano a un topic Pub/Sub e a una sottoscrizione Pub/Sub: attributi di identificazione univoca

Se è arrivato fin qui, complimenti (sul serio). Per quanto sia entusiasmante vedere dati reali da dispositivi IoT arrivare in Pub/Sub, abbiamo solo scalfito la superficie.

Per sfruttare davvero questi dati occorre — quando serve — trasformarli, spostarli o caricarli in batch in un data warehouse e infine analizzarli. Tutto questo deve avvenire in un ecosistema di servizi GCP capace di far funzionare il flusso in modo affidabile, scalabile ed economicamente sostenibile in ogni fase dello sviluppo, dai primi test all'utilizzo in produzione su scala petabyte e oltre, con poca o nessuna manutenzione dell'infrastruttura. Per scoprire come si fa, non perda la seconda e la terza parte.

Prossima puntata: archiviazione e visualizzazione

Nella seconda parte parleremo dei servizi di ETL, archiviazione e visualizzazione che permettono di valorizzare in modo relativamente semplice grandi volumi di dati IoT in streaming.

Limiti delle funzionalità Google Cloud IoT

Una migliore gestione del deviceId nei servizi GCP completamente gestiti

Avrà notato che lo script Python invia una coppia chiave:valore device_id nel body del messaggio, duplicando di fatto l'attributo deviceId già presente nel messaggio Pub/Sub e assegnato da IoT Core grazie all'associazione del messaggio con la coppia chiave-valore univoca del dispositivo che sta inviando i dati.

Perché far inviare allo script un device_id che potrebbe essere facilmente falsificato su un dispositivo compromesso, finendo per inquinare il data warehouse quando questi messaggi vengono archiviati a lungo termine?

Anticipo qualcosa, ma come vedremo nella Parte Due esiste un workflow comodo, completamente gestito, con auto-scaling e in larga parte serverless, capace di trasformare e spostare i messaggi Pub/Sub in BigQuery tramite Dataflow, la versione completamente gestita di Apache Beam offerta da Google Cloud.

Purtroppo il template predefinito "Pub/Sub-to-BigQuery" scritto da GCP e disponibile in Dataflow non offre alcun modo per spostare gli attributi dei messaggi in BigQuery: si può trasferire solo il contenuto del body. Ho confermato con diversi engineer di GCP che non è possibile scrivere una UDF Javascript Dataflow personalizzata per i loro template predefiniti che aggiunga gli attributi dei messaggi ai sink Dataflow come BigQuery. In alternativa, scrivere job Java in Dataflow — da zero o modificando i template esistenti scritti da GCP — è un'attività che richiede molto tempo e una manutenzione continua del template, un impegno che immagino la maggior parte dei clienti GCP non vorrà sostenere.

Quindi, di default, non esiste un modo semplice e sicuro per associare un messaggio IoT che arriva a Pub/Sub e viene poi inoltrato ai data sink di destinazione al deviceId di quel messaggio.

Ho segnalato questa lacuna a GCP e, da quando l'ho fatto presente, è stata aperta una feature request pubblica affinché i template predefiniti supportino il passaggio di questi valori — preziosi e assolutamente indispensabili per i casi d'uso IoT. Aggiornerò l'articolo non appena la FR sarà soddisfatta; nel frattempo, a fini dimostrativi, è molto più semplice testare l'utilizzo di device_id inviandolo nel body del messaggio piuttosto che riscrivere un template Dataflow che dovrebbe essere già disponibile di default.

Come vorrei provisionare idealmente le credenziali univoche per dispositivo?

Il processo per registrare un singolo dispositivo IoT viene tipicamente descritto così:

  1. Si crea una coppia di chiavi pubblica-privata associata in GCP a permessi IoT
  2. Si effettua il provisioning di questi file e li si installa sul dispositivo in fabbrica
  3. La fabbrica registra queste credenziali nell'IoT Registry
  4. Si abilita la coppia di chiavi a effettuare chiamate alle API IoT per inviare dati al cloud.

Una configurazione di questo tipo, da sola, non è ideale: nei casi d'uso IoT reali sono coinvolti milioni di dispositivi che inviano dati in streaming a un ambiente cloud. Ogni dispositivo di una flotta di queste dimensioni deve avere un set di credenziali univoco, in modo che, se un dispositivo o le sue credenziali Google Cloud vengono compromessi e usati per scopi illeciti, sia possibile disabilitare quel set di credenziali senza impattare gli altri dispositivi della flotta.

GCP supporta questa funzionalità e, come si vede nello script qui sopra, permette anche di consentire a un dispositivo di pubblicare solo su un topic specifico per quel dispositivo. Tuttavia, date le metodologie di provisioning delle credenziali disponibili, coordinare creazione, distribuzione e registrazione delle chiavi per milioni di dispositivi resta una sfida.

Come si può creare le credenziali specifiche per dispositivo nel modo più semplice possibile? È fattibile senza dover creare in anticipo milioni di certificati e coordinarne il posizionamento univoco sui dispositivi durante la produzione? Vuole davvero affidarsi a un produttore per posizionare in modo affidabile questi file senza duplicazioni?

In alternativa, si può registrare e credenziare i dispositivi senza chiedere al produttore di effettuare chiamate API al proprio IoT Registry per creare nuove credenziali on-demand quando un dispositivo esce dalla linea di produzione e viene inizializzato con software e credenziali? Cosa succede alla linea di produzione se la connessione all'API Gateway che gestisce la registrazione IoT cade?

Preferirei evitare questi metodi perché sono più complessi, soggetti a errori e impongono un onere inutile al produttore.

Un sistema di registrazione dei dispositivi sicuro e ragionevolmente scalabile, che mi piacerebbe vedere supportato da GCP, dovrebbe seguire queste linee guida:

  1. Si crea un singolo certificato IoT, da installare su tutti i dispositivi IoT. Questo certificato, chiamato "bootstrap", sarebbe associato a una policy di permessi che consente al dispositivo unicamente di (a) richiedere e ottenere credenziali specifiche per dispositivo, se la richiesta viene approvata, e (b) aggiungersi al registry IoT.
  2. La piattaforma GCP IoT Core, ricevuta e approvata la richiesta di creazione delle credenziali, genera una nuova coppia di chiavi. I permessi IoT associati — come Google Cloud già fa oggi — dovrebbero consentire al dispositivo di pubblicare messaggi solo su un topic univoco per il dispositivo stesso.
  3. L'approvazione della creazione delle credenziali univoche per dispositivo dovrebbe essere subordinata a una fase di validazione. Si tratterebbe di una Cloud Function scritta da lei, che richiede la presenza nella richiesta di identificatori univoci, da verificare contro una whitelist (ad es. un elenco di numeri di serie prodotti o di indirizzi MAC utilizzati) e/o una blacklist (ad es. un elenco di numeri di serie associati a dispositivi compromessi, abusati o già registrati).
  4. Se la richiesta del certificato univoco viene approvata dalla fase di validazione, il dispositivo viene inserito nell'IoT Registry e i nuovi file di credenziali vengono consegnati al dispositivo per essere usati nello streaming dei dati.

Con questo workflow, un produttore di dispositivi IoT dovrebbe semplicemente fornire a ogni dispositivo il certificato di bootstrap. La coppia di chiavi univoca, che abilita lo streaming dei dati, potrebbe essere creata e ottenuta subito all'interno dello stabilimento di produzione, oppure successivamente, quando il dispositivo è già nelle mani dell'utente finale.

Indipendentemente dal momento in cui vengono ottenute le credenziali, il produttore dovrebbe semplicemente installare sul dispositivo un software, fornito da lei, che esegue il processo di creazione della coppia di chiavi univoca basato sul certificato di bootstrap quando:

  • Il dispositivo si avvia
  • È disponibile una connessione Internet, e
  • Si rileva l'assenza della coppia di chiavi univoca per il dispositivo

Purtroppo, una funzionalità di questo tipo è oggi assente. Ma al di là della registrazione massiva dei dispositivi, l'offerta Google Cloud IoT — abbinata a servizi di elaborazione dei messaggi completamente gestiti a valle (trattati nella Parte Due) — costituisce nel complesso una soluzione cloud solida, sicura e facilmente scalabile nel mondo IoT.