On-Device-Personalisierung – deterministischer Build durch föderiertes Computing

Deterministische Builds sind für die Arbeitslastattestierung auf dem Gerät erforderlich Trusted Execution Environment (TEE) zur Personalisierung (ODP), öffentlich verfügbar auf Google Cloud als Confidential Space (CS).

Die Arbeitslast-Images müssen einen deterministischen Image-Hash generieren, der von CS für die Attestierung von Arbeitslasten (verwendet RFC 9334-Remote-ATtestation von NIST) Prozedur-Architektur (RATS-Architektur).

In diesem Dokument werden die Implementierung und Unterstützung für deterministische in der odp-federatedcompute zu erstellen. Die ODP-Aggregator- und Model Updater-Dienste werden innerhalb von Confidential Space Das Repository unterstützt deterministische Builds für alle Dienste, die für Anwendungsfälle in der Produktion erforderlich sind.

Deterministische Builds

Die deterministischen Builds bestehen aus zwei Hauptkomponenten:

  1. Die Kompilierung der erforderlichen Binärdateien. Dazu gehören JAR-Dateien, gemeinsam genutzte Bibliotheken, und Metadaten.
  2. Die Basis-Image- und Laufzeitabhängigkeiten. Basis der Laufzeitumgebung Image, das zum Ausführen der kompilierten Binärdateien verwendet wird.

Derzeit unterstützt das ODP Federated Compute-Repository die folgenden Arten von Arbeitslasten:

  • Java- und Spring-Arbeitslasten <ph type="x-smartling-placeholder">
      </ph>
    • TaskAssignment, TaskManagement, Collector
  • Java und Spring mit JNI-Tensorflow-Arbeitslasten <ph type="x-smartling-placeholder">
      </ph>
    • ModelUpdater, Aggregator
  • Python-Arbeitslasten <ph type="x-smartling-placeholder">
      </ph>
    • TaskBuilder

Abhängigkeiten

Die folgende Liste enthält Abhängigkeiten, auf die ODP angewiesen ist, um Determinismus aufrechtzuerhalten und Verfügbarkeit:

  • Bazel
  • GitHub
  • Maven
  • PyPi
  • Debian-Snapshots
  • DockerHub-Registry
  • Google Container Registry (GCR)

Deterministische Arbeitslasten

Alle Arbeitslasten werden mit Bazel mit sprachspezifische Toolchains und Container-Images, die mit rules_oci: Der ARBEITSBEREICH Datei definiert alle Abhängigkeiten mit den entsprechenden Versionen und Hashes.

Debian-Snapshots

Alle Arbeitslast-Images sollten innerhalb des bereitgestellten Dockerfile die auf einem Debian-Snapshot basiert. Debian Snapshots liefern einen stabilen Repository-Snapshot mit deterministischem:

  • Systemheader und Bibliotheken
  • Systemarchitektur <ph type="x-smartling-placeholder">
      </ph>
    • linux_x86_64
    • Debian
  • C++-Compiler <ph type="x-smartling-placeholder">

Java Spring-Arbeitslasten

das remotejdk_17 ist wird verwendet, um ein hermetisches Java für die Kompilierung bereitzustellen. Andere Java-Abhängigkeiten sind verwaltet und definiert in ARBEITSBEREICH Datei.

Die Java Spring-Arbeitslasten werden in eine JAR-Datei namens <service>_application.jar Die JAR-Datei enthält Folgendes:

  • Java-Klassendateien
  • META-INF/
    • Bazel-Manifestdaten
  • build-data.properties
    • Bass-Build-Daten
  • BOOT-INF/

Bildebenen

Das Java Spring-Arbeitslast-Image besteht aus zwei Schichten:

  • Basis-Image-Ebene <ph type="x-smartling-placeholder">
  • Arbeitslastebene <ph type="x-smartling-placeholder">
      </ph>
    • binary_tar.tar
      • <service>_application.jar

Image-Konfiguration

  • Einstiegspunkt <ph type="x-smartling-placeholder">
      </ph>
    • java -jar <service>_application.jar

JNI Tensorflow-Arbeitslasten

JNI Tensorflow-Arbeitslasten basieren auf den Java Spring-Arbeitslasten. A Die hermetische Clang+LLVM-Baby-Toolchain wird mit vorkonfiguriertem Clang+LLVM bereitgestellt 16 mit einem sysroot, das vom Debian-Snapshot-Image bereitgestellt wird, um Maschinencode zu kompilieren.

Die JNI-Arbeitslasten werden in eine gemeinsam genutzte Bibliothek mit dem Namen libtensorflow.so kompiliert. durch <service>_application.jar.

Bildebenen

Das JNI-Tensorflow-Arbeitslastbild besteht aus mehreren Schichten:

  • Basis-Image-Ebene <ph type="x-smartling-placeholder">
  • Abhängigkeitsebenen von Debian-Paketen. Die Ebenen werden mit deb generiert. Aus debian-Snapshot heruntergeladene und in Image-Layers umgepackte Archive <ph type="x-smartling-placeholder">
      </ph>
    • libc++1-16_amd64.tar
    • libc++abi1-16_amd64.tar
    • libc6_amd64.tar
    • libunwind-16_amd64.tar
    • libgcc-s1_amd64.tar
    • gcc-13-base_amd64.tar
  • Arbeitslastebene <ph type="x-smartling-placeholder">
      </ph>
    • binary_tar.tar
      • <service>_application.jar
      • libtensorflow-jni.so
      • libaggregation-jni.so

Image-Konfiguration

  • Labels (nur für Images, die für die Ausführung in TEE erstellt wurden) <ph type="x-smartling-placeholder">
      </ph>
    • "tee.launch_policy.allow_env_override": "FCP_OPTS"
      • Ermöglicht es, die Umgebungsvariable FCP_OPTS festzulegen in vertraulich Gruppenbereich. Die Arbeitslast verbraucht beim Start FCP_OPTS zum Konfigurieren erforderlichen Parameter.
      • Die Umgebungsvariable FCP_OPTS wird beim Ausführen des Images festgelegt (anstatt erstellt), um den Build-Determinismus beizubehalten.
    • "tee.launch_policy.log_redirect": "always"
    • "tee.launch_policy.monitoring_memory_allow": "always"
  • Einstiegspunkt <ph type="x-smartling-placeholder">
      </ph>
    • java -Djava.library.path=. -jar <service>_application.jar

Python-Arbeitslasten

rules_python von Bazel wird verwendet, um eine hermetische Python 3.10-Toolchain bereitstellen. Anforderungen an gesperrte pip Datei wird zum deterministischen Abrufen von pip-Abhängigkeiten verwendet. Der Debian-Snapshot Bild stellt sicher, dass deterministische Verteilungen auf Basis der Plattform Kompatibilität und bietet eine C++-Toolchain zum Kompilieren von Quellverteilungen.

Die Python-Arbeitslasten werden in eine Reihe heruntergeladener pip-Pakete gepackt, Python 3.10-Distribution, der ODP-Python-Quellcode und ein Python-Start-up .

  • <service>.runfiles/
    • Python-Distribution wird unter python_x86_64-unknown-linux-gnu/ gespeichert
    • Quellcode wird gespeichert unter com_google_ondevicepersonalization_federatedcompute/
    • BiB-Pakete werden unter pypi_<dependency_name>/ gespeichert
  • <service>.runfiles_manifest
    • Manifestdatei für das Verzeichnis <service>.runfiles/
  • <service>
    • Python-Skript zum Ausführen der Python-Arbeitslast mit den Runfiles

Bildebenen

Das Python-Arbeitslast-Image besteht aus vier Schichten:

  • Basis-Image-Ebene <ph type="x-smartling-placeholder">
  • Dolmetscherebene <ph type="x-smartling-placeholder">
      </ph>
    • interpreter_layer.jar
      • <service>/<service>.runfiles/python_x86_64-unknown-linux-gnu/**
  • Paketebene <ph type="x-smartling-placeholder">
      </ph>
    • packages_layer.jar
      • <service>/<service>.runfiles/**/site-packages/**
  • Arbeitslastebene <ph type="x-smartling-placeholder">
      </ph>
    • app_tar_manifest.tar
      • Enthält Quellcode, Startskript und Manifest.
        • <service>/<service>.runfiles_manifest
        • <service>/<service>
        • <service>/<service>.runfiles/com_google_ondevicepersonalization_federatedcompute/**

Image-Konfiguration

  • Einstiegspunkt <ph type="x-smartling-placeholder">
      </ph>
    • /<service>/<service>

Build-Images

Sobald Sie Ihre Arbeitslasten ausgewählt haben, können Sie Ihre Bilder.

Vorbereitung

  • Bazel 6.4.0 <ph type="x-smartling-placeholder">
      </ph>
    • Erfordert Java- und C++-Installationen
  • Docker

Vorgehensweise

Images sollten im Docker-Container mit dem bereitgestellten dockerfile. Es werden zwei Skripts bereitgestellt, um die endgültigen deterministischen Bilder zu erstellen.

  • docker_run.sh <ph type="x-smartling-placeholder">
      </ph>
    • docker_run.sh erstellt das Docker-Image aus dem Dockerfile das Arbeitsverzeichnis, stellen Sie den Docker-Daemon für den Host bereit und führen Sie "docker" mit dem angegebenen Bash-Befehl. Alle vor dem bash-Befehl übergebenen Variablen werden als Docker-Ausführungsflags behandelt.
  • build_images.sh <ph type="x-smartling-placeholder">
      </ph>
    • build_images.sh führt bazel build für alle Bilder aus und gibt Folgendes aus: generierte Image-Hashes für jedes erstellte Image.

Alle Images erstellen

./scripts/docker/docker_run.sh "./scripts/build_images.sh"

Die erwarteten Image-Hashes für jeden Release finden Sie unter odp-federatedcompute GitHub Releases.

Bilder veröffentlichen

Die Veröffentlichung wird mit oci_push Bazel-Regeln. Für jeden Dienst sollte das Ziel-Repository so konfiguriert werden, Alle:

  • Aggregator
  • Collector
  • model_updater
  • task_assignment
  • task_management
  • task_scheduler
  • task_builder

Einzelnes Bild veröffentlichen

./scripts/docker/docker_run.sh "bazel run //shuffler/services/<servicename_no_underscore>:<servicename_with_underscore>_image_publish"

Erstellte Images

Alle erstellten Images müssen vom Ersteller gespeichert und gehostet werden, beispielsweise in einem GCP Artifact Registry.