On-Device Personalization の連携コンピューティングの決定的ビルド

決定論的ビルドは、Google Cloud で Confidential Space(CS)として一般公開されている On Device Personalization(ODP)高信頼実行環境(TEE)のワークロード認証に必要です。

ワークロード イメージは、CS がワークロード構成証明に使用できる決定論的なイメージ ハッシュを生成する必要があります(NIST の RFC 9334 Remote ATtestation procedureS(RATS)アーキテクチャを使用)。

このドキュメントでは、odp-federatedcompute リポジトリでの決定論的ビルドの実装とサポートについて説明します。ODP アグリゲータ サービスとモデル アップデータ サービスは、Confidential Space 内で実行されます。このリポジトリは、本番環境のユースケースに必要なすべてのサービスの決定論的ビルドをサポートしています。

決定論的ビルド

決定論的ビルドは、次の 2 つの主要なコンポーネントで構成されています。

  1. 必要なバイナリのコンパイル。これには、jar、共有ライブラリ、メタデータが含まれます。
  2. ベースイメージとランタイムの依存関係。コンパイルされたバイナリの実行に使用されるランタイム環境のベースイメージ。

現在、ODP Federated Compute リポジトリは次のタイプのワークロードをサポートしています。

  • Java + Spring ワークロード
    • TaskAssignment、TaskManagement、Collector
  • JNI tensorflow ワークロードを使用した Java + Spring
    • ModelUpdater、Aggregator
  • Python ワークロード
    • TaskBuilder

依存関係

次のリストは、ODP が決定性と可用性を維持するために依存する依存関係です。

  • Bazel
  • GitHub
  • Maven
  • PyPi
  • Debian スナップショット
  • DockerHub レジストリ
  • Google Container Registry(GCR)

決定論的ワークロード

すべてのワークロードは、rules_oci を使用してビルドされた言語固有のツールチェーンとコンテナ イメージを使用して Bazel でコンパイルされます。WORKSPACE ファイルには、対応するバージョンとハッシュを含むすべての依存関係が定義されています。

Debian スナップショット

すべてのワークロード イメージは、Debian スナップショットの上に構築された、提供された dockerfile 内でビルドする必要があります。Debian スナップショットは、決定論的な安定したリポジトリ スナップショットを提供します。

Java Spring ワークロード

Bazel の remotejdk_17 は、コンパイル用の密閉型 Java を提供するために使用されます。その他の Java 依存関係は、WORKSPACE ファイルで管理および定義されます。

Java Spring ワークロードは、<service>_application.jar という名前の jar ファイルにコンパイルされます。この jar には次のものが含まれています。

  • Java クラスファイル
  • META-INF/
    • Bazel マニフェスト データ
  • build-data.properties
    • Bazel build-data
  • BOOT-INF/
    • rules_spring によって生成されたパッケージ化された jar 依存関係。

画像レイヤ

Java Spring ワークロード イメージは次の 2 つのレイヤで構成されています。

  • ベースイメージ レイヤ
  • ワークロード レイヤ
    • binary_tar.tar
      • <service>_application.jar

イメージの構成

  • エントリ ポイント
    • java -jar <service>_application.jar

JNI TensorFlow ワークロード

JNI Tensorflow ワークロードは、Java Spring ワークロード上に構築されています。マシンコードをコンパイルするために、Debian スナップショット イメージで提供される sysroot を使用したビルド済みの Clang+LLVM 16 を使用して、密閉型の Clang+LLVM Bazel ツールチェーンが提供されます。

JNI ワークロードは、<service>_application.jar とともに libtensorflow.so という名前の共有ライブラリにコンパイルされます。

画像レイヤ

JNI tensorflow ワークロード イメージは、複数のレイヤで構成されています。

  • ベースイメージ レイヤ
  • Debian パッケージの依存関係レイヤ。レイヤは、debian-snapshot からダウンロードされ、イメージレイヤとして再パッケージ化された deb アーカイブを使用して生成されます。
    • 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
  • ワークロード レイヤ
    • binary_tar.tar
      • <service>_application.jar
      • libtensorflow-jni.so
      • libaggregation-jni.so

イメージの構成

  • ラベル(TEE 内で実行するようにビルドされたイメージのみ)
    • "tee.launch_policy.allow_env_override": "FCP_OPTS"
      • FCP_OPTS 環境変数を機密領域に設定できるようにします。ワークロードは起動時に FCP_OPTS を使用して、必要なパラメータを構成します。
      • FCP_OPTS 環境変数は、ビルドの決定性を維持するために、イメージの実行時(ビルド時ではなく)に設定されます。
    • "tee.launch_policy.log_redirect": "always"
    • "tee.launch_policy.monitoring_memory_allow": "always"
  • エントリ ポイント
    • java -Djava.library.path=. -jar <service>_application.jar

Python ワークロード

Bazel の rules_python は、密閉型の Python 3.10 ツールチェーンを提供するために使用されます。ロックされた pip 要件ファイルは、pip 依存関係の決定論的取得に使用されます。Debian スナップショット イメージにより、プラットフォームの互換性に基づいて決定論的なディストリビューションが確実に取得され、ソース ディストリビューションをコンパイルするための C++ ツールチェーンが提供されます。

Python ワークロードは、ダウンロードされた pip パッケージのセット、Python 3.10 ディストリビューション、ODP Python ソースコード、Python スタートアップ スクリプトにパッケージ化されます。

  • <service>.runfiles/
    • Python ディストリビューションは python_x86_64-unknown-linux-gnu/ に保存されます
    • ソースコードは com_google_ondevicepersonalization_federatedcompute/ に保存されます。
    • Pip パッケージは pypi_<dependency_name>/ に保存されます
  • <service>.runfiles_manifest
    • <service>.runfiles/ ディレクトリのマニフェスト ファイル
  • <service>
    • runfiles を使用して Python ワークロードを実行する Python スクリプト

画像レイヤ

Python ワークロード イメージは 4 つのレイヤで構成されています。

  • ベースイメージ レイヤ
  • インタープリタ レイヤ
    • interpreter_layer.jar
      • <service>/<service>.runfiles/python_x86_64-unknown-linux-gnu/**
  • パッケージ レイヤ
    • packages_layer.jar
      • <service>/<service>.runfiles/**/site-packages/**
  • ワークロード レイヤ
    • app_tar_manifest.tar
      • ソースコード、スタートアップ スクリプト、マニフェストが含まれています。
        • <service>/<service>.runfiles_manifest
        • <service>/<service>
        • <service>/<service>.runfiles/com_google_ondevicepersonalization_federatedcompute/**

イメージの構成

  • エントリ ポイント
    • /<service>/<service>

ビルドイメージ

ワークロードを選択したら、イメージをビルドして公開する準備が整います。

前提条件

  • Bazel 6.4.0
    • Java と C++ のインストールが必要
  • Docker

手順

イメージは、提供された dockerfile によってビルドされた Docker コンテナ内でビルドする必要があります。最終的な決定論的イメージのビルドに役立つ 2 つのスクリプトが用意されています。

  • docker_run.sh
    • docker_run.sh は、Dockerfile から Docker イメージをビルドし、作業ディレクトリをマウントし、ホスト Docker デーモンをマウントして、指定された bash コマンドで Docker を実行します。bash コマンドの前に渡された変数は、docker run フラグとして扱われます。
  • build_images.sh
    • build_images.sh はすべての画像に対して bazel build を実行し、ビルドされた各画像の生成された画像ハッシュを出力します。

すべてのイメージをビルドする

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

各リリースの想定されるイメージ ハッシュは、odp-federatedcompute GitHub リリースで確認できます。

画像を公開する

公開は、oci_push Bazel ルールを使用して構成されます。各サービスについて、ターゲット リポジトリは次のすべてに対して構成する必要があります。

  • 情報集約サイト
  • コレクタ
  • model_updater
  • task_assignment
  • task_management
  • task_scheduler
  • task_builder

1 枚の画像を公開する

1 枚の画像を公開するには:

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

ビルドされたイメージ

ビルドされたイメージはすべて、クリエイターが保存してホストする必要があります(GCP アーティファクト レジストリなど)。