Deterministyczne kompilacje są wymagane do atestowania zbioru zadań w zaufanym środowisku wykonawczym (TEE) personalizacji na urządzeniu (ODP), które jest publicznie dostępne w Google Cloud jako Poufna przestrzeń (CS).
Obrazy zadań muszą generować deterministyczny skrót obrazu, który może być używany przez CS do atestowania zadań (które korzysta z architektury RFC 9334 Remote ATtestation procedureS (RATS) opracowanej przez NIST).
W tym dokumencie omówimy wdrażanie i obsługę deterministycznych kompilacji w repozytorium odp-federatedcompute. Usługi ODP Aggregator i Model Updater będą działać w przestrzeni poufnej. Repozytorium obsługuje deterministyczne kompilacje wszystkich naszych usług, które są wymagane w przypadku zastosowań produkcyjnych.
Deterministyczne kompilacje
Deterministyczne kompilacje składają się z 2 głównych komponentów:
- kompilacja wymaganych plików binarnych; Obejmuje to pliki JAR, biblioteki współdzielone i metadane.
- Obraz podstawowy i zależności czasu działania. Obraz bazowy środowiska wykonawczego używany do wykonywania skompilowanych plików binarnych.
Obecnie repozytorium ODP Federated Compute obsługuje te typy zadań:
- Obciążenia Java + Spring
- TaskAssignment, TaskManagement, Collector
- Java + Spring z obciążeniami JNI TensorFlow
- ModelUpdater, Aggregator
- Obciążenia Pythona
- TaskBuilder
Zależności
Poniżej znajdziesz listę zależności, od których zależy determinizm i dostępność ODP:
- Bazel
- GitHub
- Maven
- PyPi
- Zrzuty Debiana
- Rejestr DockerHub
- Google Container Registry (GCR)
Deterministyczne zbiory zadań
Wszystkie zbiory zadań są kompilowane za pomocą Bazel z użyciem łańcuchów narzędzi specyficznych dla danego języka i obrazów kontenerów utworzonych za pomocą rules_oci. Plik WORKSPACE określa wszystkie zależności z odpowiednimi wersjami i hashami.
Zrzuty Debiana
Wszystkie obrazy zadań powinny być tworzone w ramach podanego pliku Dockerfile na podstawie zrzutu Debiana. Zrzuty Debiana zapewniają stabilny zrzut repozytorium z określonymi:
- Nagłówki i biblioteki systemowe
- Architektura systemu
- linux_x86_64
- Debian
- Kompilator C++
Zadania Java Spring
Bazelremotejdk_17 służy do udostępniania hermetycznej Javy do kompilacji. Inne zależności Javy są zarządzane i zdefiniowane w pliku WORKSPACE.
Zbiory zadań Java Spring są kompilowane do pliku jar o nazwie <service>_application.jar. Słoik zawiera:
- pliki klas Java,
META-INF/- Dane pliku manifestu Bazel
build-data.properties- Dane kompilacji Bazel
BOOT-INF/- Zależności w postaci spakowanych plików JAR wygenerowane przez rules_spring.
Warstwy obrazu
Obraz zbioru zadań Java Spring składa się z 2 warstw:
- Warstwa obrazu podstawowego
- Obraz podstawowy Javy:
gcr.io/distroless/java17-debian11
- Obraz podstawowy Javy:
- Warstwa zbioru zadań
binary_tar.tar<service>_application.jar
Konfiguracja obrazu
- Punkt wejścia
java -jar <service>_application.jar
Zadania JNI TensorFlow
Zadania JNI Tensorflow są oparte na zadaniach Java Spring. Hermetyczny łańcuch narzędzi Clang+LLVM Bazel jest udostępniany za pomocą gotowego Clang+LLVM 16 z sysrootem dostarczanym przez obraz zrzutu Debiana do kompilowania kodu maszynowego.
Zbiory zadań JNI są kompilowane do biblioteki współdzielonej o nazwie libtensorflow.so wraz z <service>_application.jar.
Warstwy obrazu
Obraz zadania JNI TensorFlow składa się z kilku warstw:
- Warstwa obrazu podstawowego
- Obraz podstawowy Javy:
gcr.io/distroless/java17-debian11
- Obraz podstawowy Javy:
- Warstwy zależności pakietu Debiana. Warstwy są generowane przy użyciu archiwów deb pobranych z debian-snapshot i przekształconych w warstwy obrazu.
libc++1-16_amd64.tarlibc++abi1-16_amd64.tarlibc6_amd64.tarlibunwind-16_amd64.tarlibgcc-s1_amd64.targcc-13-base_amd64.tar
- Warstwa zbioru zadań
binary_tar.tar<service>_application.jarlibtensorflow-jni.solibaggregation-jni.so
Konfiguracja obrazu
- Etykiety (tylko w przypadku obrazów utworzonych do działania w środowisku TEE)
"tee.launch_policy.allow_env_override": "FCP_OPTS"- Umożliwia
FCP_OPTSustawienie zmiennej środowiskowej w przestrzeni poufnej. Obciążenie będzie zużywaćFCP_OPTSpodczas uruchamiania, aby skonfigurować wymagane parametry. - Zmienna środowiskowa
FCP_OPTSjest ustawiana podczas uruchamiania obrazu (zamiast podczas jego tworzenia), aby zachować determinizm kompilacji.
- Umożliwia
"tee.launch_policy.log_redirect": "always""tee.launch_policy.monitoring_memory_allow": "always"
- Punkt wejścia
java -Djava.library.path=. -jar <service>_application.jar
Zadania w Pythonie
rules_python Bazela służy do udostępniania hermetycznego łańcucha narzędzi Pythona 3.10. Do deterministycznego pobierania zależności pip używany jest zablokowany plik wymagań. Obraz migawki Debiana zapewnia pobieranie deterministycznych dystrybucji na podstawie kompatybilności platformy i udostępnia łańcuch narzędzi C++ do kompilowania dystrybucji źródłowych.
Zadania w Pythonie zostaną spakowane w zestaw pobranych pakietów pip, dystrybucję Pythona 3.10, kod źródłowy Pythona ODP i skrypt uruchamiania Pythona.
<service>.runfiles/- Dystrybucja Pythona jest przechowywana w folderze
python_x86_64-unknown-linux-gnu/ - Kod źródłowy jest przechowywany w katalogu
com_google_ondevicepersonalization_federatedcompute/ - Pakiety pip są przechowywane w folderze
pypi_<dependency_name>/
- Dystrybucja Pythona jest przechowywana w folderze
<service>.runfiles_manifest- Plik manifestu dla katalogu
<service>.runfiles/
- Plik manifestu dla katalogu
<service>- Skrypt w Pythonie do uruchamiania zadania w Pythonie za pomocą plików wykonywalnych
Warstwy obrazu
Obraz zadania w Pythonie składa się z 4 warstw:
- Warstwa obrazu podstawowego
- Obraz bazowy Pythona python:slim
- Warstwa tłumaczenia rozmowy
interpreter_layer.jar<service>/<service>.runfiles/python_x86_64-unknown-linux-gnu/**
- Warstwa pakietów
packages_layer.jar<service>/<service>.runfiles/**/site-packages/**
- Warstwa zbioru zadań
app_tar_manifest.tar- Zawiera kod źródłowy, skrypt startowy i plik manifestu.
<service>/<service>.runfiles_manifest<service>/<service><service>/<service>.runfiles/com_google_ondevicepersonalization_federatedcompute/**
- Zawiera kod źródłowy, skrypt startowy i plik manifestu.
Konfiguracja obrazu
- Punkt wejścia
/<service>/<service>
Tworzenie obrazów
Po wybraniu zbiorów zadań możesz utworzyć i opublikować obrazy.
Wymagania wstępne
Procedura
Obrazy powinny być tworzone w kontenerze Dockera utworzonym przez podany plik Dockerfile. Dostępne są 2 skrypty, które pomagają w tworzeniu ostatecznych obrazów deterministycznych.
- docker_run.sh
docker_run.shutworzy obraz Dockera z pliku Dockerfile, zamontuje katalog roboczy, zamontuje demona Dockera hosta i uruchomi Dockera z podanym poleceniem bash. Wszystkie zmienne przekazane przed poleceniem bash będą traktowane jako flagi polecenia docker run.
- build_images.sh
build_images.shuruchomibazel builddla wszystkich obrazów i wygeneruje skróty obrazów dla każdego utworzonego obrazu.
Kompilowanie wszystkich obrazów
./scripts/docker/docker_run.sh "./scripts/build_images.sh"
Oczekiwane hasze obrazów dla poszczególnych wersji znajdziesz w repozytorium odp-federatedcompute w GitHubie.
Publikowanie obrazów
Publikowanie jest konfigurowane za pomocą reguł Bazel oci_push. W przypadku każdej usługi repozytorium docelowe powinno być skonfigurowane dla wszystkich:
- agregator
- kolektor
- model_updater
- task_assignment
- task_management
- task_scheduler
- task_builder
Publikowanie pojedynczego obrazu
Aby opublikować pojedynczy obraz:
./scripts/docker/docker_run.sh "bazel run //shuffler/services/<servicename_no_underscore>:<servicename_with_underscore>_image_publish"
Utworzone obrazy
Wszystkie utworzone obrazy muszą być przechowywane i hostowane przez twórcę, np. w rejestrze artefaktów GCP.