Compilación determinista de procesamiento federado de personalización integrada en el dispositivo

Se requieren compilaciones determinísticas para la certificación de carga de trabajo en la integración en el dispositivo. Entorno de ejecución confiable (TEE) de personalización (ODP), disponible de forma pública en Google Cloud como Confidential Space (CS).

Las imágenes de carga de trabajo deben generar un hash de imagen determinista CS para la certificación de carga de trabajo (que usa la certificación remota RFC 9334 de NIST) procedimientos (RATS)).

En este documento, se repasa la implementación y la asistencia de los modelos compilaciones en la odp-federatedcompute en un repositorio de confianza. Los servicios del Agregador de ODP y del Actualizador de modelos se ejecutarán en Confidential Space. El repositorio admite compilaciones deterministas para todos nuestros servicios, que se requieren en los casos de uso de producción.

Compilaciones deterministas

Las compilaciones deterministas constan de dos componentes principales:

  1. La compilación de los objetos binarios necesarios. lo que incluye archivos jar, bibliotecas compartidas, y metadatos.
  2. La imagen base y las dependencias del entorno de ejecución La base del entorno de ejecución que se usa para ejecutar los objetos binarios compilados.

A partir de ahora, el repositorio de procesamiento federado de ODP admite los siguientes tipos cargas de trabajo:

  • Cargas de trabajo Java y Spring
    • Asignación de tareas, Administración de tareas y Recopilador
  • Java y Spring con cargas de trabajo de TensorFlow de JNI
    • Actualizador de modelos y agregador
  • Cargas de trabajo de Python
    • TaskBuilder

Dependencias

La siguiente lista son dependencias en las que se basa la ODP para mantener el determinismo y disponibilidad:

  • Bazel
  • GitHub
  • Maven
  • PyPi
  • Instantáneas de Debian
  • Registro de DockerHub
  • Google Container Registry (GCR)

Cargas de trabajo deterministas

Todas las cargas de trabajo se compilan usando Bazel con imágenes de contenedores y cadenas de herramientas específicas de cada lenguaje compiladas con rules_oci. El WORKSPACE . define todas las dependencias con las versiones y los hashes correspondientes.

Instantáneas de Debian

Todas las imágenes de cargas de trabajo deben compilarse según Archivo Docker compilada a partir de una instantánea de Debian. Debian proporcionan una instantánea de repositorio estable con características determinísticas:

Cargas de trabajo de Java Spring

Bazel remotejdk_17 es que se usa para proporcionar un Java hermético para la compilación. Otras dependencias de Java son se administran y definen en WORKSPACE predeterminado.

Las cargas de trabajo de Java Spring se compilan en un archivo JAR llamado <service>_application.jar El jar contiene lo siguiente:

  • Archivos de clase de Java
  • META-INF/
    • Datos del manifiesto de Bazel
  • build-data.properties
    • Datos de compilación de Bazel
  • BOOT-INF/
    • Dependencias jar empaquetadas, generadas por rules_spring.

Capas de imagen

La imagen de la carga de trabajo de Java Spring consta de dos capas:

Configuración de la imagen

  • Punto de entrada
    • java -jar <service>_application.jar

Cargas de trabajo de JNI Tensorflow

Las cargas de trabajo de JNI Tensorflow se basan en las cargas de trabajo de Java Spring. R La cadena de herramientas hermética de Bazel y Clang+LLVM se proporciona usando Clang+LLVM compilado previamente. 16 con un valor sysroot que proporciona la imagen de instantánea de Debian para compilar código máquina.

Las cargas de trabajo de JNI se compilan en una biblioteca compartida llamada libtensorflow.so junto con con el <service>_application.jar.

Capas de imagen

La imagen de la carga de trabajo de TensorFlow de JNI consta de varias capas:

  • Capa de la imagen base
  • Capas de dependencia del paquete Debian. Las capas se generan usando deb archivos descargados de debian-snapshot y reempaquetados como capas de imágenes
    • 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
  • Capa de carga de trabajo
    • binary_tar.tar
      • <service>_application.jar
      • libtensorflow-jni.so
      • libaggregation-jni.so

Configuración de la imagen

  • Etiquetas (solo para las imágenes compiladas para ejecutarse dentro del TEE)
    • "tee.launch_policy.allow_env_override": "FCP_OPTS"
      • Permite que la variable de entorno FCP_OPTS se establezca en confidencial espacio. La carga de trabajo consumirá FCP_OPTS al inicio para configurarse. los parámetros obligatorios.
      • La variable de entorno FCP_OPTS se establece cuando se ejecuta la imagen. (en lugar de compilarse) para mantener el determinismo de la compilación.
    • "tee.launch_policy.log_redirect": "always"
    • "tee.launch_policy.monitoring_memory_allow": "always"
  • Punto de entrada
    • java -Djava.library.path=. -jar <service>_application.jar

Cargas de trabajo de Python

Se usa rules_python de Bazel para proporcionar una cadena de herramientas hermética de Python 3.10. Requisitos de una pip bloqueada archivo se usa para la recuperación determinista de dependencias de pip. La instantánea de Debian La imagen garantiza que las distribuciones deterministas se recuperen según la plataforma. compatibilidad y proporciona una cadena de herramientas de C++ para compilar distribuciones de fuente.

Las cargas de trabajo de Python se empaquetarán en un conjunto de paquetes de pip descargados, un Distribución de Python 3.10, código fuente de ODP de Python y una startup de Python secuencia de comandos.

  • <service>.runfiles/
    • La distribución de Python se almacena en python_x86_64-unknown-linux-gnu/
    • El código fuente se almacena en com_google_ondevicepersonalization_federatedcompute/
    • Los paquetes de Pip se almacenan en pypi_<dependency_name>/
  • <service>.runfiles_manifest
    • Archivo de manifiesto para el directorio <service>.runfiles/
  • <service>
    • Secuencia de comandos de Python para ejecutar la carga de trabajo de Python con los archivos de ejecución

Capas de imagen

La imagen de carga de trabajo de Python consta de cuatro capas:

  • Capa de la imagen base
  • Capa de intérprete
    • interpreter_layer.jar
      • <service>/<service>.runfiles/python_x86_64-unknown-linux-gnu/**
  • Capa de paquetes
    • packages_layer.jar
      • <service>/<service>.runfiles/**/site-packages/**
  • Capa de carga de trabajo
    • app_tar_manifest.tar
      • Contiene el código fuente, la secuencia de comandos de inicio y el manifiesto.
        • <service>/<service>.runfiles_manifest
        • <service>/<service>
        • <service>/<service>.runfiles/com_google_ondevicepersonalization_federatedcompute/**

Configuración de la imagen

  • Punto de entrada
    • /<service>/<service>

Compila imágenes

Una vez elegidas tus cargas de trabajo, estarás listo para compilar y publicar tu imágenes de contenedores.

Requisitos previos

  • Bazel 6.4.0
    • Requiere instalaciones de Java y C++
  • Docker

Procedimiento

Las imágenes se deben compilar dentro del contenedor de Docker que compila la dockerfile Se proporcionan dos secuencias de comandos para ayudar a compilar las imágenes determinísticas finales.

  • docker_run.sh
    • docker_run.sh compilará la imagen de Docker a partir del dockerfile, se activará el directorio de trabajo, activar el daemon de Docker del host y ejecutar Docker con el comando bash proporcionado. Cualquier variable pasada antes del comando Bash tratarse como marcas de ejecución de Docker.
  • build_images.sh
    • build_images.sh ejecutará bazel build para todas las imágenes y generará el resultado hash de imagen generada para cada imagen compilada.

Compila todas las imágenes

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

Puedes encontrar los hashes de imagen esperados de cada versión en la siguiente sección odp-federationdcompute en GitHub versiones.

Publica imágenes

La publicación se configura con oci_push Reglas de Bazel. Para cada servicio, el repositorio de destino se debe configurar todos:

  • agregador
  • recopilador
  • model_updater
  • task_assignment
  • task_management
  • task_scheduler
  • task_builder

Publica una sola imagen

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

Imágenes compiladas

El creador deberá almacenar y alojar todas las imágenes compiladas, por ejemplo, en un Artifact Registry de GCP.