ऑन-डिवाइस पर लोगों के अनुभव को मनमुताबिक बनाने की सुविधा देने वाले कंप्यूट डिटरमिनिस्टिक बिल्ड

डिटरमिनिस्टिक बिल्ड, डिवाइस पर निजी डेटा को सुरक्षित रखने वाली सुविधा (ओडीपी) के भरोसेमंद एक्ज़ीक्यूशन एनवायरमेंट (टीईई) में वर्कलोड की पुष्टि करने के लिए ज़रूरी होते हैं. यह सुविधा, Google Cloud पर Confidential Space (सीएस) के तौर पर सार्वजनिक तौर पर उपलब्ध है.

वर्कलोड इमेज को एक ऐसा इमेज हैश जनरेट करना होगा जिसका इस्तेमाल सीएस, वर्कलोड की पुष्टि करने के लिए कर सके. इसके लिए, सीएस को NIST के RFC 9334 Remote ATtestation procedureS (RATS) Architecture का इस्तेमाल करना होगा.

इस दस्तावेज़ में, odp-federatedcompute रिपॉज़िटरी में डिटरमिनिस्टिक बिल्ड को लागू करने और उनसे जुड़ी सहायता के बारे में बताया गया है. ओडीपी एग्रीगेटर और मॉडल अपडेटर सेवाएं, कॉन्फ़िडेंशियल स्पेस में काम करेंगी. यह रिपॉज़िटरी, हमारी सभी सेवाओं के लिए डिटरमिनिस्टिक बिल्ड का समर्थन करती है. ये बिल्ड, प्रोडक्शन के इस्तेमाल के उदाहरणों के लिए ज़रूरी होते हैं.

डिटरमिनिस्टिक बिल्ड

डिटरमिनिस्टिक बिल्ड में दो मुख्य कॉम्पोनेंट होते हैं:

  1. ज़रूरी बाइनरी का कंपाइलेशन. इसमें जार, शेयर की गई लाइब्रेरी, और मेटाडेटा शामिल है.
  2. बेस इमेज और रनटाइम डिपेंडेंसी. यह रनटाइम एनवायरमेंट का बेस इमेज होता है. इसका इस्तेमाल, कंपाइल किए गए बाइनरी को एक्ज़ीक्यूट करने के लिए किया जाता है.

फ़िलहाल, ODP फ़ेडरेटेड कंप्यूट रिपॉज़िटरी में इस तरह के वर्कलोड इस्तेमाल किए जा सकते हैं:

  • Java + Spring वर्कलोड
    • TaskAssignment, TaskManagement, Collector
  • Java + Spring with JNI tensorflow workloads
    • ModelUpdater, Aggregator
  • Python वर्कलोड
    • TaskBuilder

डिपेंडेंसी

यहां दी गई सूची में, उन डिपेंडेंसी के बारे में बताया गया है जिन पर ODP, डिटरमिनिज़्म और उपलब्धता बनाए रखने के लिए निर्भर करता है:

  • Bazel
  • GitHub
  • Maven
  • PyPi
  • Debian स्नैपशॉट
  • DockerHub Registry
  • Google Container Registry (GCR)

डिटरमिनिस्टिक वर्कलोड

सभी वर्कलोड को Bazel का इस्तेमाल करके कंपाइल किया जाता है. इसके लिए, भाषा के हिसाब से टूलचेन और rules_oci का इस्तेमाल करके बनाई गई कंटेनर इमेज का इस्तेमाल किया जाता है. WORKSPACE file में, सभी डिपेंडेंसी के साथ-साथ उनके वर्शन और हैश तय किए जाते हैं.

Debian स्नैपशॉट

सभी वर्कलोड इमेज, दिए गए dockerfile में बनाई जानी चाहिए. यह Debian स्नैपशॉट पर आधारित होना चाहिए. Debian के स्नैपशॉट, स्टेबल रिपॉज़िटरी स्नैपशॉट उपलब्ध कराते हैं. इनमें ये शामिल हैं:

  • सिस्टम हेडर और लाइब्रेरी
  • सिस्टम आर्किटेक्चर
    • linux_x86_64
    • Debian
  • C++ कंपाइलर

Java Spring वर्कलोड

Bazel के remotejdk_17 का इस्तेमाल, कंपाइल करने के लिए हर्मेटिक Java उपलब्ध कराने के लिए किया जाता है. अन्य Java डिपेंडेंसी को WORKSPACE फ़ाइल में मैनेज और तय किया जाता है.

Java Spring वर्कलोड, <service>_application.jar नाम की जार फ़ाइल में कंपाइल होते हैं. जार में ये चीज़ें शामिल हैं:

  • Java क्लास फ़ाइलें
  • META-INF/
    • Bazel मेनिफ़ेस्ट डेटा
  • build-data.properties
    • Bazel build-data
  • BOOT-INF/
    • पैक की गई जार डिपेंडेंसी, जिसे rules_spring ने जनरेट किया है.

इमेज लेयर

Java Spring वर्कलोड इमेज में दो लेयर होती हैं:

  • बेस इमेज लेयर
  • वर्कलोड लेयर
    • binary_tar.tar
      • <service>_application.jar

इमेज कॉन्फ़िगरेशन

  • Entrypoint
    • java -jar <service>_application.jar

JNI Tensorflow वर्कलोड

JNI Tensorflow वर्कलोड, Java Spring वर्कलोड के ऊपर बनाए जाते हैं. मशीन कोड को कंपाइल करने के लिए, प्रीबिल्ट Clang+LLVM 16 का इस्तेमाल करके, हर्मेटिक Clang+LLVM Bazel टूलचेन उपलब्ध कराया जाता है. साथ ही, Debian स्नैपशॉट इमेज से उपलब्ध कराया गया sysroot भी उपलब्ध कराया जाता है.

JNI वर्कलोड, libtensorflow.so नाम की शेयर की गई लाइब्रेरी में कंपाइल होते हैं. साथ ही, <service>_application.jar में भी कंपाइल होते हैं.

इमेज लेयर

JNI tensorflow वर्कलोड इमेज में कई लेयर होती हैं:

  • बेस इमेज लेयर
  • Debian पैकेज की डिपेंडेंसी लेयर. लेयर, debian-snapshot से डाउनलोड किए गए debarchives का इस्तेमाल करके जनरेट की जाती हैं. इन्हें इमेज लेयर के तौर पर फिर से पैक किया जाता है
    • 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.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"
  • Entrypoint
    • java -Djava.library.path=. -jar <service>_application.jar

Python वर्कलोड

Bazel के rules_python का इस्तेमाल, Python 3.10 टूलचेन उपलब्ध कराने के लिए किया जाता है. pip डिपेंडेंसी को तय तरीके से फ़ेच करने के लिए, लॉक की गई pip requirements फ़ाइल का इस्तेमाल किया जाता है. 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 वर्कलोड इमेज में चार लेयर होती हैं:

  • बेस इमेज लेयर
  • इंटरप्रेटर लेयर
    • 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/**

इमेज कॉन्फ़िगरेशन

  • Entrypoint
    • /<service>/<service>

इमेज बनाना

वर्कलोड चुनने के बाद, इमेज बनाई और पब्लिश की जा सकती हैं.

ज़रूरी शर्तें

  • Bazel 6.4.0
    • इसके लिए, Java और C++ इंस्टॉल करना ज़रूरी है
  • Docker

काम का तरीका

इमेज, दिए गए dockerfile से बनाए गए डॉकर कंटेनर में बनाई जानी चाहिए. फ़ाइनल डिटरमिनिस्टिक इमेज बनाने में मदद करने के लिए, दो स्क्रिप्ट दी गई हैं.

  • docker_run.sh
    • docker_run.sh, dockerfile से डॉकर इमेज बनाएगा, वर्क डायरेक्ट्री को माउंट करेगा, होस्ट डॉकर डेमॉन को माउंट करेगा, और दी गई बैश कमांड के साथ डॉकर को चलाएगा. bash कमांड से पहले पास किए गए किसी भी वैरिएबल को docker run फ़्लैग के तौर पर माना जाएगा.
  • build_images.sh
    • build_images.sh सभी इमेज के लिए bazel build चलाएगा और बनाई गई हर इमेज के लिए, जनरेट किए गए इमेज हैश आउटपुट करेगा.

सभी इमेज बनाना

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

हर रिलीज़ के लिए इमेज हैश, odp-federatedcompute GitHub रिलीज़ में जाकर देखे जा सकते हैं.

इमेज पब्लिश करना

पब्लिश करने की सुविधा, Bazel के oci_push नियमों का इस्तेमाल करके कॉन्फ़िगर की जाती है. हर सेवा के लिए, टारगेट रिपॉज़िटरी को इन सभी के लिए कॉन्फ़िगर किया जाना चाहिए:

  • एग्रीगेटर
  • कलेक्टर
  • model_updater
  • task_assignment
  • task_management
  • task_scheduler
  • task_builder

एक इमेज पब्लिश करना

कोई एक इमेज पब्लिश करने के लिए:

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

बनाई गई इमेज

बनाई गई सभी इमेज को क्रिएटर को सेव और होस्ट करना होगा. जैसे, GCP आर्टफ़ैक्ट रजिस्ट्री में.