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 determinísticos 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 son necesarios para los casos de uso de producción.
Compilaciones deterministas
Las compilaciones deterministas constan de dos componentes principales:
- La compilación de los objetos binarios necesarios. lo que incluye archivos jar, bibliotecas compartidas, y metadatos.
- 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 de Java y Spring
- TaskAssignment, 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 archivo 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 dockerfile compilada a partir de una instantánea de Debian. Debian proporcionan una instantánea de repositorio estable con características determinísticas:
- Bibliotecas y encabezados del sistema
- Arquitectura del sistema
- linux_x86_64
- Debian
- Compilador C++
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:
- Capa de la imagen base
- Imagen base de Java:
gcr.io/distroless/java17-debian11
- Imagen base de Java:
- Capa de carga de trabajo
binary_tar.tar
<service>_application.jar
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
- Imagen base de Java:
gcr.io/distroless/java17-debian11
- Imagen base de Java:
- 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.
- Permite que la variable de entorno
"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>/
- La distribución de Python se almacena en
<service>.runfiles_manifest
- Archivo de manifiesto para el directorio
<service>.runfiles/
- Archivo de manifiesto para el directorio
<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
- Imagen base de Python python:slim
- 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/**
- Contiene el código fuente, la secuencia de comandos de inicio y el manifiesto.
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
Procedimiento
Las imágenes se deben compilar dentro del contenedor de Docker que compila el 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
Para publicar una sola imagen, sigue estos pasos:
./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.