Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

IoT-Best-Practices im Produktionsmaßstab: Umsetzung mit GCP (Teil 1/3)

By Matthew PorterAug 10, 202113 min read

Diese Seite ist auch in English, Español, Français, Italiano, 日本語 und Português verfügbar.

Sie wollen wissen, wie sich ein vollständig verwalteter, automatisch skalierender und serverloser IoT-Betrieb in der Cloud aufbauen lässt?

In dieser dreiteiligen Reihe IoT auf GCP nehmen wir einen kompletten IoT-Workflow unter die Lupe: von der Geräteregistrierung über das Streaming und die Langzeitspeicherung der Daten bis hin zu deren Analyse und Visualisierung.

IoT-Best-Practices im Produktionsmaßstab

Nach Teil eins wissen Sie, wie Sie Millionen IoT-Geräte sicher registrieren und Telemetriedaten in Ihre Google Cloud-Umgebung streamen.

Dies ist der erste von drei Teilen:

  • Teil zwei behandelt die korrekte Speicherung und Visualisierung solch hochfrequenter Datenströme.
  • Teil drei zeigt, wie Sie ein funktionsfähiges Machine-Learning-Modell auf Basis von IoT-Daten aufbauen.

Als Cloud-Anbieter setzen wir durchgängig auf GCP, als Beispielgeräte dienen Raspberry Pis mit angeschlossenen Temperatursensoren.

Überblick

Der Beitrag gliedert sich in folgende Abschnitte:

  1. Software- und Hardware-Setup des Raspberry Pi
  2. Geräteregistrierung und Bereitstellung von Zugangsdaten in der Praxis
  3. Test der Gerätekonnektivität und Streaming von Temperaturdaten
  4. Einschränkungen bei der Google Cloud IoT-Funktionalität
  5. Speicherung von Streaming-Daten (Teil zwei)
  6. Visualisierung von Streaming-Daten (Teil zwei)
  7. Aufbau eines wirkungsvollen Machine-Learning-Modells mit IoT-Daten (Teil 3)

Um diesen Artikel mitzugehen, brauchen Sie nur Erfahrung mit Bash und Python sowie ein Grundverständnis der Google Cloud Console.

Software und Hardware des Raspberry Pi einrichten

Bringen Sie zunächst mehrere Raspberry Pis zum Laufen — ich verwende hier Pi 3-Geräte. Für die automatisierte Installation des Betriebssystems auf microSD-Karten empfehle ich den Raspbian OS Imager.

Python-Pakete installieren

Sobald Sie auf dem Desktop sind und das Gerät aktualisiert haben, installieren Sie das Google Cloud IoT-spezifische SDK mit folgendem Befehl:

pip3 install -U pyjwt paho-mqtt

Bevor wir weitermachen, lohnt sich ein kurzer Blick darauf, warum wir paho-mqtt statt des allgemeinen Python-SDK google-api-python-client für Google Cloud verwenden. Sowohl das geläufigere Python-SDK als auch die gcloud-CLI von GCP basieren auf HTTP. Für die schnelle Ausführung der meisten Aktionen ist dieses Protokoll bestens geeignet. HTTP eignet sich allerdings nicht, um Nachrichten über langlebige Verbindungen mit häufig unterbrochener Konnektivität zu senden, wenn die Daten überwiegend vom verbundenen Gerät weg fließen.

MQTT ist ein im IoT-Umfeld verbreitetes Protokoll, das über Pakete wie paho-mqtt genutzt wird. Es ist von Grund auf darauf ausgelegt, dass ein Gerät auch unter schwierigen Verbindungsbedingungen häufig Nachrichten veröffentlichen und seltener Nachrichten empfangen kann.

Digitalen Temperatursensor anschließen

Sind die nötigen Python-Pakete auf Ihrem Raspberry Pi installiert, schließen Sie als Nächstes einen digitalen Temperatursensor an. Wer dem Artikel direkt folgen möchte, dem empfehle ich diesen DS18B20-Sensor.

Außerdem benötigen Sie zum Anschluss an den Raspberry Pi:

Falls Sie noch auf die Lieferung warten, lesen Sie ruhig weiter — ein Skript zum Streamen simulierter Temperaturen stellen wir bereit.

Wenn Sie alles zur Hand haben: Die ersten fünf Minuten dieses Tutorials führen Sie Schritt für Schritt durch den Anschluss des Sensors an den Raspberry Pi und zeigen, wie Sie überprüfen, ob er Temperaturwerte liefert.

Ergänzend zum dort beschriebenen Vorgehen empfehle ich, folgende Einträge in /etc/modules aufzunehmen, damit die onewire-Module beim Booten geladen werden und Sie nicht nach jedem Neustart modprobe ausführen müssen:

w1-gpio
w1-therm

IoT-Geräte registrieren

Im Folgenden sehen Sie ein vollständiges, lauffähiges Beispiel, wie Sie Ihre IoT Registry mit sicher registrierten Geräten einrichten, um anschließend Temperaturdaten an die Google Cloud IoT-Plattform zu streamen.

Eine Registry für Ihre Geräte anlegen

In der Google Cloud Console:

  1. Legen Sie ein neues Projekt an (z. B. "IoTTempStreaming").
  2. Öffnen Sie den Dienst IoT Core, um die IoT-API zu aktivieren.
  3. Klicken Sie auf "Create registry", um eine Registry für Ihre IoT-Geräte zu erstellen.

IoT-Geräte, die nach GCP streamen, dürfen ihre Nachrichten nur dann an IoT Core senden, wenn sie als Geräte mit gültigen Anmeldedaten in der IoT Registry validiert sind. Das Anlegen der Registry ist daher ein essenzieller erster Schritt.

Eine brandneue IoT Core-Umgebung wartet darauf, mit Nachrichten gefüllt zu werden

Ein Pub/Sub-Topic erstellen

An IoT Core gesendete Nachrichten werden — zusammen mit kritischen Nachrichten-Metadaten wie der eindeutigen deviceId eines Geräts — im Hintergrund an ein "Topic" in Pub/Sub weitergeleitet, dem vollständig verwalteten, automatisch skalierenden und serverlosen Message-Queue-System von Google Cloud.

Daher legen wir die Pub/Sub-Topics direkt im Dialog für die IoT Registry mit an, damit unsere Telemetriedaten am Ende in Pub/Sub für die nachgelagerte Verarbeitung landen.

So erstellen Sie ein Pub/Sub-Topic aus dem IoT Registry-Dialog heraus:

  1. Vergeben Sie als Registry-ID "RaspberryPiDevices" in der Region us-central1.
  2. Erstellen Sie ein Pub/Sub-Topic mit dem Namen "sensordata", in dem IoT-Telemetrienachrichten standardmäßig eingehen.
  3. Legen Sie unter "Additional topics" ein neues Pub/Sub-Topic namens "temperature" an, in dem Nachrichten ankommen, die in einem ebenfalls "temperature" benannten IoT-Topic-Unterordner veröffentlicht werden.

So ist sichergestellt, dass nur Ihre an einen bestimmten IoT-Unterordner veröffentlichten Temperaturnachrichten im Pub/Sub-Topic "temperature" eintreffen, während alle übrigen (unerwarteten) Telemetrieereignisse im Standard-Topic "sensordata" landen.

Ich empfehle außerdem, die erweiterten Optionen aufzuklappen und ausschließlich MQTT zuzulassen, indem Sie HTTP deaktivieren:

IoT Core Registry-Setup für das Streaming von Temperatursensordaten

Nach der Erstellung sollte Ihre Registry so aussehen:

Eine erfolgreich eingerichtete IoT Core Registry

Ein registriertes Gerät anlegen

Wir haben jetzt eine Geräte-Registry — Zeit, ein registriertes Gerät anzulegen.

Dafür brauchen wir (1) ein öffentlich-privates Schlüsselpaar, das mit dem Gerät verknüpft ist, und (2) das Google-Stammzertifikat.

Im Folgenden finden Sie die Befehle, die Sie auf einem Raspberry Pi ausführen, um Elliptic Curve-Schlüssel zu erzeugen und das Google-Stammzertifikat zu beziehen (die Befehle basieren auf der entsprechenden Google Cloud-Dokumentation). EC-Schlüssel sind kompakter als klassische RSA-Schlüssel und helfen IoT-Geräten, in Regionen mit eingeschränkter Konnektivität einen optimalen Durchsatz zu halten:

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

Nach Ausführung dieser Befehle:

  1. Kopieren Sie den im Terminal angezeigten öffentlichen Schlüssel.
  2. Wechseln Sie in die IoT Registry und navigieren Sie zu Devices.
  3. Klicken Sie auf Add Device.
  4. Vergeben Sie einen Gerätenamen (z. B. "device1") und fügen Sie Ihren öffentlichen ES256-Schlüssel wie unten gezeigt unter Authentication ein.
  5. Klicken Sie auf Create.

IoT-Geräteregistrierung mit Eingabefeld für den Elliptic Curve-Schlüssel

Nach der Erstellung sind die Anmeldedaten für das in IoT Core registrierte Gerät einsatzbereit auf einem Raspberry Pi!

Notieren Sie sich die dem Gerät zugewiesene numerische ID, die Project ID und die Registry ID.

Mit diesen Werten sowie den Schlüsseln und dem Google-Stammzertifikat auf dem Gerät erstellen wir nun eine Konfigurationsdatei namens gcp_iot_config.txt. Sie definiert die Authentifizierungs- und IoT-Endpoint-Details, die ein bestimmtes Gerät verwendet. Etwas weiter unten im Artikel folgt ein Python-Skript, das auf Basis dieser Konfigurationsdatei Temperaturwerte streamt:

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

Et voilà! Ihr Gerät ist nun bereit, Telemetriedaten sicher über die IoT Core-Authentifizierungsplattform von GCP an ein Pub/Sub-Topic zu streamen. Wiederholen Sie den Vorgang, um für jedes weitere Gerät eindeutige Anmeldedaten zu erzeugen und es zu registrieren.

Gerätekonnektivität testen

Testen wir die Gerätekonnektivität mit dem folgenden Skript "publish_temps.py". Es streamt — je nachdem, ob Sie Zeile 107 oder 108 auskommentieren — vom Gerät erfasste oder simulierte Temperaturwerte.

(Das Skript ist eine Adaption zweier Beispielskripte von Google Cloud: #1 und #2.)

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

Hier passiert einiges — ein genauer Blick in den Code lohnt sich, um zu verstehen, wie das Skript sicher verbindet und Daten streamt.

Beim Ausführen sollten Sie eine Ausgabe wie diese sehen:

Echte Temperaturwerte, per MQTT zu GCP IoT Core gestreamt

Wenn Sie das Skript per crontab beim Neustart ausführen (mit einem 30-Sekunden-Sleep davor, damit die onewire-Module beim Boot geladen werden können), nimmt Ihr IoT-Gerät das Streaming nach einem (un)erwarteten Neustart automatisch wieder auf:

$ 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

Wiederholen Sie den Onboarding- und Streaming-Prozess für alle Raspberry Pis, die Sie in Ihrem Zuhause platziert haben. Sie sind auf einem guten Weg, mit IoT-Daten in großem Maßstab zu arbeiten!

Datenstrom überprüfen

Verifizieren wir kurz, dass die Nachrichten in Google Cloud ankommen, indem wir uns die in Pub/Sub eingehenden Telemetriedaten ansehen.

  1. Erstellen Sie eine Pub/Sub-Subscription für das Topic "temperature".
  2. Navigieren Sie zur Subscription.
  3. Klicken Sie auf View Messages und wählen Sie das Optionsfeld Pull.

Sie sehen die Nachrichten, sobald sie eintreffen — inklusive der Temperatur- und Zeitstempelwerte aus dem Nachrichtenkörper sowie der Attribut-Metadaten, die eindeutig identifizieren, welches Gerät die Werte sendet. Diese Attribut-Metadaten sind nicht nur für Analysen und Endbenutzer-Dashboards wertvoll, sondern auch, um missbräuchliche oder gehackte Geräte zu identifizieren und zu sperren.

Anlegen einer Pub/Sub-Subscription, um eingehende Temperatur-Telemetrienachrichten anzuzeigen

So sieht eine Subscription auf das Topic "temperature" aus:

Nachrichten einer Pub/Sub-Subscription auf das Pub/Sub-Topic "temperature" anzeigen

Sobald Sie auf "PULL" klicken, sehen Sie die Nachrichten und ihre Attribute:

Temperaturdaten erreichen ein Pub/Sub-Topic und treffen in einer Pub/Sub-Subscription ein: Nachrichtenkörper

Temperaturdaten erreichen ein Pub/Sub-Topic und treffen in einer Pub/Sub-Subscription ein: Eindeutig identifizierende Attribute

Wenn Sie es bis hierhin geschafft haben — herzlichen Glückwunsch (im Ernst)! So spannend es ist, echte Daten von IoT-Geräten in Pub/Sub eintreffen zu sehen: Wir haben bislang nur an der Oberfläche gekratzt.

Damit diese Daten wirklich nutzbar werden, müssen wir sie optional transformieren, in ein Data Warehouse verschieben bzw. per Batch laden und auswerten. All das in einem Ökosystem von GCP-Diensten, das diesen Datenfluss zuverlässig, skalierbar und kosteneffizient ermöglicht — von ersten Tests bis hin zur Produktion im Petabyte-Bereich und darüber hinaus, mit minimalem Wartungsaufwand für die Infrastruktur. Wer wissen möchte, wie das geht: dranbleiben für Teil zwei und drei!

Als Nächstes: Speicherung und Visualisierung

Bleiben Sie dran für Teil zwei: Dort stelle ich die passenden ETL-, Speicher- und Visualisierungsdienste vor, mit denen sich umfangreiche Streaming-IoT-Daten relativ einfach in handlungsrelevante Erkenntnisse überführen lassen.

Einschränkungen der Google Cloud IoT-Funktionalität

Bessere Behandlung der deviceId in vollständig verwalteten GCP-Diensten

Vielleicht ist Ihnen aufgefallen, dass das Python-Skript ein device_id-Schlüssel-Wert-Paar im Nachrichtenkörper streamt — und damit das deviceId-Attribut dupliziert, das die Pub/Sub-Nachricht von IoT Core ohnehin über die Zuordnung zum eindeutigen Schlüsselpaar des sendenden Geräts erhält.

Warum sollte das Skript also eine device_id mitsenden, die sich auf einem gehackten Gerät leicht fälschen ließe und am Ende — sobald die Nachrichten in den Langzeitspeicher wandern — ein Data Warehouse mit verfälschten Daten zur Folge hätte?

Ich greife etwas vor, aber wie wir in Teil zwei sehen werden, gibt es einen praktischen, vollständig verwalteten, automatisch skalierenden und überwiegend serverlosen Workflow, der Pub/Sub-Nachrichten transformieren und mit Dataflow — der vollständig verwalteten Google Cloud-Variante von Apache Beam — in BigQuery verschieben kann.

Leider bietet die in Dataflow standardmäßig verfügbare, von GCP bereitgestellte Vorlage "Pub/Sub-to-BigQuery" keine Möglichkeit, Nachrichtenattribute nach BigQuery zu übertragen — übertragen wird nur der Inhalt des Nachrichtenkörpers. Mehrere GCP-Engineers haben mir bestätigt, dass sich für die Standardvorlagen keine eigene Dataflow-JavaScript-UDF schreiben lässt, um Nachrichtenattribute in Dataflow-Senken wie BigQuery aufzunehmen. Die Alternative — eigene Java-Dataflow-Jobs zu schreiben, sei es von Grund auf oder als Modifikation bestehender GCP-Vorlagen — ist zeitintensiv und erfordert laufende Wartung und Updates der Vorlage. Das werden die meisten GCP-Kunden vermutlich nicht angehen wollen.

Standardmäßig gibt es daher keinen einfachen und sicheren Weg, eine in Pub/Sub eingehende und an Ziel-Datensenken weitergereichte IoT-Nachricht mit ihrer deviceId zu verknüpfen.

Ich habe diese Lücke an GCP gemeldet, woraufhin dort ein öffentlicher Feature-Request eingereicht wurde, damit die Standardvorlagen die Weitergabe dieser wertvollen — und für IoT-Anwendungsfälle absolut erforderlichen — Werte unterstützen. Sobald der FR umgesetzt ist, aktualisiere ich den Artikel entsprechend. Bis dahin ist es zu Demozwecken deutlich einfacher, die Verwendung von device_id über den Nachrichtenkörper auszuprobieren, als eine Dataflow-Vorlage neu zu schreiben, die eigentlich von Haus aus mitgeliefert sein sollte.

Wie würde ich gerätespezifische Anmeldedaten idealerweise bereitstellen?

Die Registrierung eines einzelnen IoT-Geräts wird typischerweise so beschrieben:

  1. Erstellen eines öffentlich-privaten Schlüsselpaars, das in GCP mit IoT-Berechtigungen verknüpft ist.
  2. Bereitstellen und Ablegen dieser Dateien auf dem Gerät bereits im Werk.
  3. Registrieren dieser Anmeldedaten im Werk in der IoT Registry.
  4. Aktivieren des Schlüsselpaars für IoT-API-Aufrufe, die Daten in die Cloud streamen.

Für sich allein ist ein solches Setup jedoch nicht ideal: Reale IoT-Anwendungsfälle umfassen Millionen Geräte, die in eine Cloud-Umgebung streamen. Jedes Gerät einer solchen Flotte muss eindeutige Anmeldedaten erhalten, damit ein einzelner Datensatz im Falle einer Kompromittierung — etwa durch missbräuchliche Nutzung — deaktiviert werden kann, ohne andere Geräte der Flotte zu beeinträchtigen.

GCP bietet diese Funktionalität und unterstützt — wie im obigen Skript zu sehen — auch, dass ein Gerät ausschließlich in ein für das Gerät eindeutiges Topic veröffentlichen darf. Mit den verfügbaren Methoden zur Bereitstellung von Anmeldedaten wird die Koordination von Schlüsselerstellung, Deployment und Registrierung für Millionen Geräte allerdings zur Herausforderung.

Wie lässt sich die Erstellung gerätespezifischer Anmeldedaten so einfach wie möglich gestalten? Geht es ohne Millionen vorab erzeugter Zertifikate, deren eindeutige Platzierung auf den Geräten während der Fertigung koordiniert werden muss? Möchten Sie sich darauf verlassen, dass ein Hersteller diese Dateien zuverlässig und ohne Duplikate ablegt?

Oder lassen sich Geräteregistrierung und Credential-Vergabe abwickeln, ohne dass der Hersteller bei jedem vom Band laufenden Gerät on-demand API-Aufrufe an Ihre IoT Registry absetzen muss, um neue Anmeldedaten zu erzeugen? Was passiert mit der Produktionslinie, wenn die Verbindung zu Ihrem API-Gateway, das die IoT-Registrierung antreibt, ausfällt?

Ich würde diese Methoden lieber vermeiden — sie sind komplexer, fehleranfälliger und bürden dem Hersteller eine unnötige Last auf.

Ein sicheres und sinnvoll skalierbares Geräteregistrierungssystem, das ich mir von GCP wünschen würde, würde diesen Leitlinien folgen:

  1. Es wird ein einzelnes IoT-Zertifikat erzeugt, das auf allen IoT-Geräten platziert wird. Dieses sogenannte "Bootstrap"-Zertifikat ist mit einer Berechtigungsrichtlinie verknüpft, die einem Gerät nur erlaubt, eine Anfrage zu stellen, um (a) gerätespezifische Anmeldedaten zu erstellen und abzurufen, sofern die Anfrage genehmigt wird, und (b) sich selbst zur IoT Registry hinzuzufügen.
  2. Erhält und genehmigt die GCP IoT Core-Plattform die Anfrage zur Erstellung von Anmeldedaten, erzeugt sie ein neues Schlüsselpaar. Die zugehörigen IoT-Berechtigungen sollten — wie es Google Cloud bereits heute handhabt — einem Gerät nur das Veröffentlichen in einem geräteeindeutigen Topic erlauben.
  3. Die Erlaubnis zur Erstellung gerätespezifischer Anmeldedaten sollte durch einen Validierungsschritt abgesichert sein. Das wäre eine von Ihnen geschriebene Cloud Function, die voraussetzt, dass eindeutige Identifikatoren in der Anfrage übergeben werden, sodass diese gegen eine Whitelist (z. B. eine Liste gefertigter Seriennummern oder verwendeter MAC-Adressen) und/oder eine Blacklist (z. B. eine Liste von Seriennummern kompromittierter, missbräuchlich genutzter oder bereits registrierter Geräte) abgeglichen werden können.
  4. Wird die Anfrage nach einem geräteeindeutigen Zertifikat im Validierungsschritt genehmigt, wird das Gerät in die IoT Registry eingetragen, und die neuen Anmeldedaten-Dateien werden zur Verwendung beim Datenstreaming an das Gerät übermittelt.

Mit diesem Workflow müsste ein IoT-Gerätehersteller jedem Gerät lediglich das Bootstrap-Zertifikat mitgeben. Das geräteeindeutige Schlüsselpaar fürs Datenstreaming ließe sich auf Wunsch sofort in der Fertigungsstätte erzeugen und beziehen — oder erst später, wenn das Gerät beim Endnutzer angekommen ist.

Unabhängig vom Zeitpunkt würde der Hersteller einfach eine von Ihnen bereitgestellte Software auf das Gerät bringen, die den auf dem Bootstrap-Zertifikat basierenden Erstellungsprozess für das geräteeindeutige Schlüsselpaar dann ausführt, wenn:

  • das Gerät hochfährt,
  • eine Internetverbindung verfügbar ist und
  • festgestellt wird, dass ein geräteeindeutiges Schlüsselpaar fehlt.

Leider fehlt eine solche Funktionalität (vorerst). Doch jenseits der Massenregistrierung von Geräten ergibt das Google Cloud IoT-Angebot — gepaart mit nachgelagerten, vollständig verwalteten Diensten zur Nachrichtenverarbeitung (Teil zwei) — insgesamt eine starke, sichere und einfach skalierbare cloud-native Lösung im IoT-Bereich.