Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Bonnes pratiques IoT à l'échelle de production : mise en œuvre avec Google Cloud (Partie 1/3)

By Matthew PorterJan 5, 202113 min read

Cette page est également disponible en English, Deutsch, Español, Italiano, 日本語 et Português.

1 mzhmgbzadzlrio1 pmnv8w

Vous voulez savoir comment bâtir dans le cloud une infrastructure IoT entièrement gérée, auto-scalable et serverless ?

Cette série en trois volets, IoT sur GCP, couvre l'intégralité d'un workflow IoT : de l'enregistrement des appareils au streaming et au stockage long terme des données, jusqu'à leur analyse et leur visualisation.

Bonnes pratiques IoT à l'échelle de production

À l'issue de la Partie 1, vous saurez enregistrer en toute sécurité des millions d'appareils IoT qui transmettent leurs données de télémétrie vers votre environnement Google Cloud.

Voici le premier volet d'une série de trois articles :

  • Le stockage et la visualisation de ces flux à haut débit seront abordés dans la Partie 2 ;
  • La construction d'un modèle de machine learning fonctionnel sur des données IoT sera traitée dans la Partie 3.

Tout au long de la série, nous utiliserons GCP comme fournisseur cloud et des Raspberry Pi équipés de capteurs de température en guise d'appareils IoT d'exemple.

Vue d'ensemble

L'article s'articule autour des sections suivantes :

  1. Configuration logicielle et matérielle du Raspberry Pi
  2. Enregistrement pratique des appareils et provisionnement des identifiants
  3. Test de connectivité et streaming des données de température
  4. Limites des fonctionnalités IoT de Google Cloud
  5. Stockage des données en streaming (traité dans la Partie 2)
  6. Visualisation des données en streaming (traitée dans la Partie 2)
  7. Construction d'un modèle de machine learning efficace à partir de données IoT (traité dans la Partie 3)

Pour suivre cet article, une expérience de Bash et de Python suffit, ainsi qu'une connaissance de base de la Google Cloud Console.

Configuration logicielle et matérielle du Raspberry Pi

Commencez par mettre en service plusieurs Raspberry Pi — pour ma part, j'utiliserai des Pi 3. Je recommande le Raspbian OS Imager pour automatiser l'installation de l'OS sur les cartes microSD.

Installer les paquets Python

Une fois le bureau atteint et l'appareil mis à jour, exécutez la commande suivante pour installer le SDK dédié à Google Cloud IoT :

pip3 install -U pyjwt paho-mqtt

Avant d'aller plus loin, il est important de comprendre pourquoi nous installons paho-mqtt plutôt que le SDK Python google-api-python-client à usage général pour Google Cloud. Le SDK Python le plus couramment utilisé, tout comme la CLI gcloud de GCP, repose sur HTTP. Ce protocole est très pratique pour exécuter rapidement la plupart des actions. En revanche, HTTP n'est pas adapté à l'envoi de messages sur des connexions de longue durée présentant un risque élevé de connectivité intermittente, où les données circulent principalement depuis l'appareil connecté.

MQTT est un protocole utilisé dans l'IoT, via des paquets tels que paho-mqtt, car il est conçu pour permettre à un appareil de publier fréquemment des messages et d'en recevoir occasionnellement, malgré les aléas de connectivité.

Connecter un capteur de température numérique

Maintenant que votre Raspberry Pi dispose des paquets Python requis, il faut y connecter un capteur de température numérique. Je recommande ce capteur DS18B20 si vous souhaitez suivre l'article pas à pas.

Vous aurez également besoin du matériel suivant pour brancher le capteur sur votre Raspberry Pi :

Si vous devez patienter pour la livraison, poursuivez la lecture sans souci : un script de streaming de températures simulées est fourni.

Si vous avez tout le matériel, les cinq premières minutes de ce tutoriel expliquent comment connecter le capteur au Raspberry Pi et vérifier qu'il remonte bien les valeurs de température.

En complément du tutoriel ci-dessus, je recommande d'ajouter les lignes suivantes dans /etc/modules pour que les modules onewire soient chargés au démarrage, plutôt que d'avoir à exécuter modprobe après chaque redémarrage :

w1-gpio
w1-therm

Enregistrer vos appareils IoT

Vous trouverez ci-dessous un exemple complet et fonctionnel pour configurer votre IoT Registry avec des appareils enregistrés en toute sécurité, à partir desquels nous diffuserons les données de température vers la plateforme Google Cloud IoT.

Créer un registre pour vos appareils

Dans la Google Cloud Console :

  1. Créez un nouveau projet (par exemple " IoTTempStreaming ")
  2. Accédez au service IoT Core pour activer l'API IoT
  3. Cliquez sur " Créer un registre " pour créer un registre destiné à accueillir vos appareils IoT.

Les appareils IoT qui transmettent vers GCP ne peuvent envoyer leurs messages à IoT Core que s'ils sont validés en tant qu'appareils authentifiés stockés dans l'IoT Registry. La création du registre est donc une étape indispensable.

1 x6ytdhxs pffshahwra2mqUn environnement IoT Core flambant neuf, en attente de messages

Créer un topic Pub/Sub

Les messages envoyés à IoT Core — accompagnés de métadonnées critiques telles que le deviceId unique de l'appareil — sont transférés en arrière-plan vers un " topic " dans Pub/Sub, le système de file d'attente de messages de Google Cloud, entièrement géré, auto-scalable et serverless.

Nous allons donc également créer des topics Pub/Sub depuis l'interface de création de l'IoT Registry, afin que nos données de télémétrie arrivent bien dans Pub/Sub pour traitement en aval.

Suivez ces étapes pour créer un topic Pub/Sub depuis l'interface de l'IoT Registry :

  1. Nommez votre Registry ID " RaspberryPiDevices " dans la région us-central1
  2. Créez un topic Pub/Sub nommé " sensordata " dans lequel les messages de télémétrie IoT arriveront par défaut.
  3. Sous " Topics supplémentaires ", créez un nouveau topic Pub/Sub nommé " temperature " qui recevra les messages publiés vers un sous-dossier de topic IoT — également nommé " temperature ".

Cette configuration garantit que seuls vos messages de température publiés dans un sous-dossier IoT spécifique arriveront dans le topic Pub/Sub temperature, tandis que tous les autres événements de télémétrie (inattendus) seront dirigés vers le topic " sensordata " par défaut.

Je recommande aussi de déplier les options avancées et de n'autoriser que le protocole MQTT en décochant HTTP :

1 hehi7hqvsqephvxoaagvsqConfiguration de l'IoT Core Registry pour le streaming des données du capteur de température

Une fois créé, votre registre devrait ressembler à ceci :

1 mydo62tfghtw76giklkc6qUne configuration réussie de l'IoT Core Registry

Créer un appareil enregistré

Maintenant que nous disposons d'un registre, créons un appareil enregistré.

Pour démarrer, il nous faut (1) une paire de clés publique-privée à associer à l'appareil et (2) le certificat racine Google.

Vous trouverez ci-dessous les commandes à exécuter sur un Raspberry Pi pour générer des clés Elliptic Curve et récupérer le certificat racine Google (ces commandes s'appuient sur la documentation Google Cloud correspondante). Les clés EC ont une empreinte plus réduite que les clés RSA traditionnelles, ce qui aide les appareils IoT à conserver un débit optimal dans les zones à connectivité limitée :

$ 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 ../

Une fois ces commandes exécutées :

  1. Copiez la clé publique affichée dans le terminal
  2. Rendez-vous dans l'IoT Registry et accédez à Devices
  3. Cliquez sur Add Device
  4. Nommez votre appareil (par exemple " device1 ") et collez votre clé publique ES256 sous Authentication, comme illustré ci-dessous.
  5. Cliquez sur Create

1 vkia4oezrnypz6y1knxdsgEnregistrement d'un appareil IoT demandant une clé Elliptic Curve

Une fois créés, les identifiants associés à un appareil enregistré dans IoT Core sont prêts à être utilisés sur un Raspberry Pi !

Notez l'ID numérique attribué à l'appareil, le Project ID et le Registry ID.

Avec ces valeurs, ainsi que les clés et le certificat racine Google présents sur l'appareil, il faut créer un fichier de configuration nommé gcp_iot_config.txt. Ce fichier définira les paramètres d'authentification et d'endpoint IoT propres à un appareil. Un peu plus loin, vous trouverez un script Python qui transmet les valeurs de température en s'appuyant sur ce fichier :

$ 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à ! Votre appareil est prêt à transmettre en toute sécurité ses données de télémétrie vers un topic Pub/Sub via la plateforme d'authentification IoT Core de GCP. Répétez le processus ci-dessus pour générer des identifiants uniques et enregistrer chaque nouvel appareil.

Tester la connectivité des appareils

Testons la connectivité en exécutant le script suivant, intitulé " publish_temps.py ", qui transmet des valeurs de température réelles ou simulées selon que la ligne 107 ou 108 est commentée.

(Ce script est une adaptation de deux exemples Google Cloud : #1 et #2.)

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

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

Il se passe pas mal de choses dans ce script — je vous recommande vivement de le parcourir pour bien comprendre comment il établit une connexion sécurisée et transmet les données.

À l'exécution, vous devriez obtenir un résultat semblable à celui-ci :

1 xwupjjvzrfeowndrus3kgaValeurs de température réelles transmises vers GCP IoT Core via MQTT

Si vous lancez ce script au démarrage via une tâche crontab (précédée d'un sleep de 30 s pour laisser aux modules onewire le temps de se charger au boot), votre appareil IoT reprendra automatiquement le streaming en cas de redémarrage (in)attendu :

$ 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

Répétez l'onboarding et le streaming pour tous les Raspberry Pi disposés chez vous. Vous êtes en bonne voie pour exploiter des données IoT à grande échelle !

Vérifier que les données sont bien transmises

Vérifions rapidement que les messages arrivent dans Google Cloud en consultant les données de télémétrie qui atteignent Pub/Sub.

  1. Créez un abonnement Pub/Sub au topic " temperature "
  2. Accédez à cet abonnement
  3. Cliquez sur View Messages, puis sélectionnez le bouton radio Pull

Vous devriez voir les messages au fur et à mesure de leur arrivée, accompagnés des informations de température et d'horodatage transmises dans le corps du message, ainsi que des métadonnées d'attribut identifiant de manière unique l'appareil émetteur. Ces métadonnées sont précieuses pour l'analytique et les dashboards utilisateurs, mais aussi pour repérer et bannir les appareils malveillants ou compromis.

1 upi0lt7zazoqrrpyarx8fgCréation d'un abonnement Pub/Sub destiné à visualiser les messages de télémétrie de température entrants

Voici à quoi ressemble un abonnement au topic temperature :

1 gqxuwk5oyv0q8bpaits7nqVisualisation des messages d'un abonnement Pub/Sub au topic Pub/Sub " temperature "

Une fois que vous cliquez sur " PULL ", les messages et leurs attributs commencent à apparaître :

1 1aj1ua6vjuje1s0rdqmtaDonnées de température arrivant sur un topic Pub/Sub puis dans un abonnement Pub/Sub : corps du message1 j3pbnwvayyqmr0cgkgz1sgDonnées de température arrivant sur un topic Pub/Sub puis dans un abonnement Pub/Sub : attributs d'identification unique

Si vous êtes arrivé jusqu'ici, félicitations (sincèrement) ! Voir des données réelles d'appareils IoT atterrir dans Pub/Sub est enthousiasmant, mais ce n'est que la partie émergée de l'iceberg.

Pour exploiter pleinement ces données, il faut éventuellement les transformer, les déplacer ou les charger par lots dans un data warehouse, puis les analyser. Tout cela doit reposer sur un écosystème de services GCP capable de garantir un flux de données fiable, scalable et économique, à toutes les étapes du cycle — du test initial à l'usage en production à l'échelle pétaoctet et au-delà — avec une maintenance d'infrastructure minimale, voire nulle. Pour découvrir comment y parvenir, ne manquez pas les parties 2 et 3 !

À suivre : stockage et visualisation

Rendez-vous dans la deuxième partie, où je présenterai les services d'ETL, de stockage et de visualisation adaptés, qui permettent d'exploiter facilement et concrètement des données IoT en streaming à grande échelle.

Limites des fonctionnalités IoT de Google Cloud

Une meilleure prise en charge du deviceId par les services GCP entièrement gérés

Vous avez peut-être remarqué que le script Python transmet une paire clé:valeur device_id dans le corps du message, ce qui duplique en réalité l'attribut deviceId présent dans le message Pub/Sub, attribué par IoT Core via l'association du message avec la paire clé-valeur unique de l'appareil émetteur.

Pourquoi le script enverrait-il un device_id facilement falsifiable sur un appareil compromis, au risque de polluer le data warehouse lorsque ces messages seront déplacés vers un stockage long terme ?

Je grille un peu les étapes, mais comme nous le verrons dans la Partie 2, il existe un workflow pratique, entièrement géré, auto-scalable et largement serverless qui permet de transformer et de déplacer les messages Pub/Sub vers BigQuery à l'aide de Dataflow, la version entièrement gérée d'Apache Beam par Google Cloud.

Malheureusement, le template par défaut " Pub/Sub-to-BigQuery " fourni par GCP dans Dataflow ne permet pas de transférer les attributs de message vers BigQuery ; seul le contenu du corps du message peut l'être. Plusieurs ingénieurs GCP m'ont confirmé qu'il n'est pas possible d'écrire une UDF Dataflow Javascript personnalisée pour leurs templates par défaut afin d'ajouter les attributs de message dans des destinations Dataflow telles que BigQuery. À l'inverse, écrire des jobs Dataflow en Java — que ce soit à partir de zéro ou en modifiant les templates existants fournis par GCP — représente un investissement conséquent, qui exige une maintenance et des mises à jour continues du template ; une tâche que la plupart des clients GCP préféreront éviter.

Ainsi, par défaut, il n'existe pas de moyen simple et sécurisé pour associer un message IoT arrivant dans Pub/Sub et acheminé vers ses destinations finales avec le deviceId de ce message.

J'ai signalé cet oubli à GCP qui, depuis, a lancé une demande publique de fonctionnalité afin que les templates par défaut prennent en charge la transmission de ces valeurs précieuses — et absolument indispensables — pour répondre au cas d'usage IoT. Je mettrai cet article à jour dès que cette demande aura été honorée mais, en attendant, à des fins de démonstration, il est bien plus simple de tester l'usage de device_id en l'envoyant dans le corps du message que de réécrire un template Dataflow qui devrait être disponible par défaut.

Comment provisionner idéalement des identifiants uniques par appareil ?

Le processus d'enregistrement d'un appareil IoT est généralement présenté ainsi :

  1. Créer une paire de clés publique-privée associée dans GCP à des permissions IoT
  2. Provisionner et déposer ces fichiers sur l'appareil en usine
  3. Faire enregistrer ces identifiants dans l'IoT Registry par l'usine
  4. Activer la paire de clés afin de permettre des appels à l'API IoT qui transmettent les données vers le cloud.

Une telle configuration n'est cependant pas idéale en soi, car les cas d'usage IoT réels mobilisent des millions d'appareils transmettant vers un environnement cloud. Chaque appareil d'une telle flotte doit recevoir un jeu d'identifiants unique afin que, si un appareil ou ses identifiants Google Cloud venaient à être compromis et utilisés à des fins illégitimes, ce jeu puisse être désactivé sans impacter les autres appareils de la flotte.

GCP propose cette fonctionnalité et, comme on le voit dans le script ci-dessus, prend également en charge le fait de n'autoriser un appareil qu'à publier sur un topic qui lui est propre. Toutefois, compte tenu des méthodes de provisionnement disponibles, coordonner la création, le déploiement et l'enregistrement des clés pour des millions d'appareils reste un défi.

Comment simplifier au maximum la création d'identifiants spécifiques à chaque appareil ? Est-il possible de s'y prendre sans créer à l'avance des millions de certificats et sans coordonner leur placement unique sur les appareils en usine ? Voulez-vous vraiment confier au fabricant la responsabilité de placer ces fichiers de manière fiable et sans doublons ?

À l'inverse, l'enregistrement et la délivrance des identifiants peuvent-ils être effectués sans contraindre le fabricant à émettre des appels API vers votre IoT Registry pour créer des identifiants à la demande, au moment où un appareil sort de la chaîne de production pour être bootstrappé avec logiciel et identifiants ? Que se passe-t-il pour la chaîne de production si la connexion à votre API Gateway gérant l'enregistrement IoT tombe en panne ?

Je préfère éviter ces approches : elles sont plus complexes, sujettes aux erreurs, et imposent une charge inutile au fabricant.

Voici les principes que devrait, selon moi, suivre un système d'enregistrement d'appareils sécurisé et raisonnablement scalable que GCP devrait prendre en charge :

  1. Un certificat IoT unique est créé et placé sur tous les appareils IoT. Ce certificat, baptisé certificat " bootstrap ", serait associé à une politique de permissions n'autorisant un appareil qu'à émettre une requête pour (a) créer et récupérer des identifiants spécifiques à l'appareil si la requête est acceptée, et (b) s'ajouter lui-même à l'IoT Registry.
  2. La plateforme GCP IoT Core, à la réception et à l'acceptation de la demande de création d'identifiants, génère une nouvelle paire de clés. Les permissions IoT associées — comme c'est déjà le cas dans Google Cloud — ne devraient autoriser l'appareil qu'à publier des messages sur un topic qui lui est propre.
  3. L'autorisation de créer des identifiants spécifiques à un appareil devrait être conditionnée par une étape de validation. Il s'agirait d'une Cloud Function que vous écrivez et qui exige des identifiants uniques dans la requête, afin de pouvoir les confronter à une whitelist (par exemple, une liste de numéros de série fabriqués ou d'adresses MAC utilisées) et/ou à une blacklist (par exemple, une liste de numéros de série associés à des appareils compromis, malveillants ou déjà enregistrés).
  4. Si la demande de certificat unique est validée, l'appareil est ajouté à l'IoT Registry et les nouveaux fichiers d'identifiants lui sont remis pour qu'il puisse les utiliser pour le streaming de données.

Avec ce workflow, un fabricant d'appareils IoT n'aurait plus qu'à fournir à chaque appareil le certificat bootstrap. La paire de clés unique permettant le streaming pourrait être créée et obtenue immédiatement en usine si nécessaire, ou plus tard, lorsque l'appareil est entre les mains de l'utilisateur final.

Quel que soit le moment où ces identifiants sont obtenus, le fabricant n'aurait qu'à installer sur l'appareil le logiciel que vous fournissez, lequel exécute le processus de création de la paire de clés unique fondé sur le certificat bootstrap lorsque :

  • L'appareil démarre
  • Une connexion Internet est disponible, et
  • Aucune paire de clés unique n'est trouvée sur l'appareil

Malheureusement, cette fonctionnalité fait défaut (pour l'instant). Mais en dehors de l'enregistrement de masse, l'offre IoT de Google Cloud — couplée à des services de traitement des messages en aval entièrement gérés (traités dans la Partie 2) — constitue une solution cloud robuste, sécurisée et facilement scalable dans le domaine de l'IoT.