全部產品
Search
文件中心

Elastic Compute Service:在TDX執行個體中基於BigDL PPML構建全鏈路安全的分布式Spark巨量資料分析應用

更新時間:Jun 19, 2024

本文介紹在基於Intel® TDX安全特性的g8i執行個體中,使用BigDL PPML解決方案運行分布式的全鏈路安全的Spark巨量資料分析應用。

背景資訊

隨著越來越多的企業選擇將資料和計算資源遷移上雲,如何在雲上保護巨量資料分析和人工智慧應用的資料安全和隱私,是資料科學家和雲端服務供應商共同面臨的挑戰。

基於BigDL PPML解決方案,在阿里雲TDX執行個體中運行標準的人工智慧和巨量資料處理應用(例如Apache Spark、Apache Flink、TensorFlow、PyTorch等),可以保證資料轉送的安全性、資料使用的安全性、應用程式的完整性。更多資訊,請參見BigDL-PPML

  • Intel® Trusted Domain Extension(Intel® TDX)以硬體安全保障資訊安全,不依賴韌體和宿主機的安全狀態,為您提供物理級的加密計算環境。

  • 阿里雲g8i執行個體基於Intel® TDX技術(下文簡稱為TDX執行個體),提供了TDX加密計算能力,打造了基於硬體層級的更高安全等級的可信機密環境,保障應用和資料的機密性與完整性不受惡意軟體的破壞。

  • BigDL PPML(BigDL Privacy Preserving Machine Learning)基於Intel® TDX技術構建了一整套解決方案,能夠讓您進行非常安全的資料分析和AI應用。

技術架構

基於BigDL PPML,您可以在加密資料環境中,運行現有的分布式巨量資料分析和AI應用程式(例如Apache Spark、Apache Flink、TensorFlow、PyTorch、OpenVINO等),無需修改任何代碼。巨量資料分析和AI應用程式運行在基於阿里雲TDX執行個體的Kubernetes叢集上,其計算和記憶體受Intel® TDX保護。在底層,BigDL PPML自動為分布式應用程式啟用端到端安全機制,包括: TDX保護。在底層,BigDL PPML自動為分布式應用程式啟用端到端安全機制,包括:

  • 在基於TDX執行個體的Kubernetes叢集上提供和證明可信叢集環境。

  • 通過KMS進行密鑰管理,用於分布式資料加密、解密。

  • 安全的分散式運算和通訊。

如上圖所示,BigDL PPML方案基於Intel® TDX的阿里雲TDX執行個體,部署Kubernetes叢集環境。從資料流角度,所有資料均以加密方式儲存在資料湖和資料倉儲中。

  1. BigDL PPML Worker節點載入機密資料,通過遠程證明以及密鑰管理系統擷取資料密鑰,在阿里雲TDX執行個體中進行解密。

  2. 使用巨量資料和人工智慧的計算架構,對資料進行分布式預先處理、模型訓練以及模型推理等。

  3. 將最終結果、資料或者模型,以加密方式寫回到分布式儲存中。

另外在各節點之間的資料均被加密傳輸(AES加密、TLS等),從而做到全鏈路的隱私保護和資料安全。

操作步驟

本文以運行Spark巨量資料分析為例,介紹如何基於阿里雲TDX執行個體,運行分布式的端到端安全的巨量資料分析應用(本文以運行Simple Query用例為例)。更多巨量資料AI應用使用說明,請參見BigDL PPML Tutorials & Examples

步驟一:部署Kubernetes叢集及運行環境

本文中Kubernetes叢集使用1個Master節點,2個Worker節點。總節點數量須與購買執行個體數量一致。您可以根據實際業務,選擇節點數量。

  1. 建立具備Intel® TDX安全特性的g8i執行個體。

    具體操作,請參見自訂購買執行個體。您需要注意以下參數:

    • 執行個體規格:運行Simple Query用例的最小執行個體規格為32 vCPU 64 GiB,本文使用ecs.g8i.8xlarge

    • 鏡像:Alibaba Cloud Linux 3.2104 LTS 64位

    • 公網IP:分配公網IPv4地址

    • 購買執行個體數量:3

  2. 遠端連線ECS執行個體。

    具體操作,請參見串連方式概述

  3. 部署Kubernetes叢集並進行安全配置。

    1. 在已建立的g8i執行個體中,部署Kubernetes叢集。

      具體操作,請參見Creating a cluster with kubeadm

    2. 執行如下命令,在Kubernetes叢集的Master節點上進行安全配置(RBAC配置)。

      kubectl create serviceaccount spark
      kubectl create clusterrolebinding spark-role --clusterrole=edit --serviceaccount=default:spark --namespace=default
  4. 建立PersistentVolume。

    1. 以root使用者,執行如下命令,建立pv-volume.yaml。

      vim pv-volume.yaml
    2. i鍵進入編輯模式。

    3. 在pv-volume.yaml中添加如下內容。

      apiVersion: v1
      kind: PersistentVolume
      metadata:
        name: task-pv-volume
        labels:
          type: local
      spec:
        storageClassName: manual
        capacity:
          storage: 10Gi
        accessModes:
          - ReadWriteOnce
        hostPath:
          path: "/mnt/data"
    4. Esc鍵,輸入:wq,儲存並退出編輯模式。

    5. 分別執行如下命令,建立並查看已建立的PersistentVolume。

      kubectl apply -f pv-volume.yaml
      kubectl get pv task-pv-volume
  5. 建立PersistentVolumeClaim。

    1. 以root使用者,執行如下命令,建立pv-claim.yaml。

      vim pv-claim.yaml
    2. i鍵進入編輯模式。

    3. 在pv-claim.yaml中添加如下內容。

      apiVersion: v1
      kind: PersistentVolumeClaim
      metadata:
        name: task-pv-claim
      spec:
        storageClassName: manual
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 3Gi
    4. Esc鍵,輸入:wq,儲存並退出編輯模式。

    5. 分別執行如下命令,建立並查看已建立的PersistentVolumeClaim。

      kubectl apply -f pv-claim.yaml
      kubectl get pvc task-pv-claim

步驟二:加密訓練資料

  1. 在Kubernetes叢集的每個節點上,執行如下命令,擷取BigDL PPML鏡像。

    該鏡像用於運行標準的Spark應用,提供資料加密、解密等功能。

    docker pull intelanalytics/bigdl-ppml-trusted-bigdata-gramine-reference-16g:2.3.0-SNAPSHOT
  2. 產生訓練資料people.csv。

    1. 在Kubernetes叢集的Master節點上,下載訓練資料指令碼generate_people_csv.py。

      wget https://github.com/intel-analytics/BigDL/raw/main/ppml/scripts/generate_people_csv.py
    2. 執行如下命令,產生訓練資料people.csv。

      python generate_people_csv.py </save/path/of/people.csv> <num_lines>
      說明
      • </save/path/of/people.csv>請修改為實際的people.csv路徑,如/home/user。

      • <num_lines>請修改為訓練資料people.csv的行數,如500。

    3. 執行如下命令,將訓練資料people.csv移到指定目錄。

      sudo scp /home/user/people.csv /mnt/data/simplekms/
      重要
      • /home/user請替換成實際的使用者目錄。

      • /mnt/data/simplekms/僅為樣本,本文中/mnt/data/simplekms/用於存放加密、解密資料,後文中存在/mnt/data/simplekms/時不再單獨說明。

  3. 在Master節點上,執行如下命令,運行bigdl-ppml-client容器。

    該容器用來加密、解密訓練資料。

    說明

    /home/user/kuberconfig:/root/.kube/config請根據實際運行程式的使用者進行修改,例如:

    • 使用root時:/root/kuberconfig:/root/.kube/config

    • 使用普通使用者(如test)時:/home/test/kuberconfig:/root/.kube/config

    export K8S_MASTER=k8s://$(kubectl cluster-info | grep 'https.*6443' -o -m 1)
    echo The k8s master is $K8S_MASTER .
    export SPARK_IMAGE=intelanalytics/bigdl-ppml-trusted-bigdata-gramine-reference-16g:2.3.0-SNAPSHOT
    
    sudo docker run -itd --net=host \
    -v /etc/kubernetes:/etc/kubernetes \
    -v /home/user/kuberconfig:/root/.kube/config \
    -v /mnt/data:/mnt/data \
    -e RUNTIME_SPARK_MASTER=$K8S_MASTER \
    -e RUNTIME_K8S_SPARK_IMAGE=$SPARK_IMAGE \
    -e RUNTIME_PERSISTENT_VOLUME_CLAIM=task-pv-claim \
    --name bigdl-ppml-client \
    $SPARK_IMAGE bash
    
    docker exec -it bigdl-ppml-client bash
  4. 在Master節點上,加密訓練資料people.csv。

    1. 執行如下命令,使用APPID、APIKEY產生primarykey。

      您可以使用simple kms自行產生1~12位長度的APPID、APIKEY。本樣本中,APPID為98463816****,APIKEY為15780936****,--primaryKeyPath指定primarykey儲存的位置。

      java -cp '/ppml/spark-3.1.3/conf/:/ppml/spark-3.1.3/jars/*:/ppml/bigdl-2.3.0-SNAPSHOT/jars/*' \
      com.intel.analytics.bigdl.ppml.examples.GeneratePrimaryKey \
       --primaryKeyPath /mnt/data/simplekms/primaryKey \
       --kmsType SimpleKeyManagementService \
       --simpleAPPID 98463816**** \
       --simpleAPIKEY 15780936****
    2. 建立加密指令碼encrypt.py。

      1. 執行如下命令,切換到/mnt/data/simplekms目錄下。

        cd /mnt/data/simplekms
      2. 執行如下命令,建立並開啟encrypt.py檔案。

        sudo vim encrypt.py
      3. i進入編輯模式。

      4. 在encrypt.py檔案中,添加如下內容。

        # encrypt.py
        from bigdl.ppml.ppml_context import *
        args = {"kms_type": "SimpleKeyManagementService",
         "app_id": "98463816****",
         "api_key": "15780936****",
         "primary_key_material": "/mnt/data/simplekms/primaryKey"
         }
        
        sc = PPMLContext("PPMLTest", args)
        
        csv_plain_path = "/mnt/data/simplekms/people.csv"
        
        csv_plain_df = sc.read(CryptoMode.PLAIN_TEXT) \
         .option("header", "true") \
         .csv(csv_plain_path)
        csv_plain_df.show()
        
        output_path = "/mnt/data/simplekms/encrypted-input"
        
        sc.write(csv_plain_df, CryptoMode.AES_CBC_PKCS5PADDING) \
         .mode('overwrite') \
         .option("header", True) \
         .csv(output_path)
      5. Esc鍵,輸入:wq,儲存並退出編輯模式。

    3. 在bigdl-ppml-client容器中,執行如下命令,使用APPID、APIKEY、primarykey加密people.csv。

      加密後的資料儲存在/mnt/data/simplekms/encrypted-output下。

      java \
       -cp '/ppml/spark-3.1.3/conf/:/ppml/spark-3.1.3/jars/*:/ppml/bigdl-2.3.0-SNAPSHOT/jars/*' \
       -Xmx1g org.apache.spark.deploy.SparkSubmit \
       --master 'local[4]' \
       --conf spark.network.timeout=10000000 \
       --conf spark.executor.heartbeatInterval=10000000 \
       --conf spark.python.use.daemon=false \
       --conf spark.python.worker.reuse=false \
       --py-files /ppml/bigdl-2.3.0-SNAPSHOT/python/bigdl-ppml-spark_3.1.3-2.3.0-SNAPSHOT-python-api.zip,/ppml/bigdl-2.3.0-SNAPSHOT/python/bigdl-spark_3.1.3-2.3.0-SNAPSHOT-python-api.zip,/ppml/bigdl-2.3.0-SNAPSHOT/python/bigdl-dllib-spark_3.1.3-2.3.0-SNAPSHOT-python-api.zip \
       /mnt/data/simplekms/encrypt.py
  5. 在每個Worker節點,分別執行如下命令,複製Master節點的/mnt/data/simplekms到每個Worker節點上。

    cd /mnt/data
    sudo scp -r user@192.168.XXX.XXX:/mnt/data/simplekms .
    說明

    user請替換成實際的Master節點使用者名稱,192.168.XXX.XXX請修改為實際的Master節點IP。

步驟三:運行基於BigDL PPML的巨量資料分析用例

  1. 在bigdl-ppml-client容器中,向Kubernetes叢集提交Spark任務,運行Simple Query用例。

    說明

    spark.driver.host=192.168.XXX.XXX請修改為實際的Master節點IP地址。

    ${SPARK_HOME}/bin/spark-submit \
        --master $RUNTIME_SPARK_MASTER \
        --deploy-mode client \
        --name spark-simplequery-tdx \
        --conf spark.driver.memory=4g \
        --conf spark.executor.cores=4 \
        --conf spark.executor.memory=4g \
        --conf spark.executor.instances=2 \
        --conf spark.driver.host=192.168.XXX.XXX \
        --conf spark.kubernetes.authenticate.driver.serviceAccountName=spark \
        --conf spark.cores.max=8 \
        --conf spark.kubernetes.container.image=$RUNTIME_K8S_SPARK_IMAGE \
        --class com.intel.analytics.bigdl.ppml.examples.SimpleQuerySparkExample \
        --conf spark.network.timeout=10000000 \
        --conf spark.executor.heartbeatInterval=10000000 \
        --conf spark.kubernetes.executor.deleteOnTermination=false \
        --conf spark.driver.extraClassPath=local://${BIGDL_HOME}/jars/* \
        --conf spark.executor.extraClassPath=local://${BIGDL_HOME}/jars/* \
        --conf spark.kubernetes.file.upload.path=/mnt/data \
        --conf spark.kubernetes.driver.volumes.persistentVolumeClaim.${RUNTIME_PERSISTENT_VOLUME_CLAIM}.options.claimName=${RUNTIME_PERSISTENT_VOLUME_CLAIM} \
        --conf spark.kubernetes.driver.volumes.persistentVolumeClaim.${RUNTIME_PERSISTENT_VOLUME_CLAIM}.mount.path=/mnt/data \
        --conf spark.kubernetes.executor.volumes.persistentVolumeClaim.${RUNTIME_PERSISTENT_VOLUME_CLAIM}.options.claimName=${RUNTIME_PERSISTENT_VOLUME_CLAIM} \
        --conf spark.kubernetes.executor.volumes.persistentVolumeClaim.${RUNTIME_PERSISTENT_VOLUME_CLAIM}.mount.path=/mnt/data \
        --jars local:///ppml/bigdl-2.3.0-SNAPSHOT/jars/bigdl-ppml-spark_3.1.3-2.3.0-SNAPSHOT.jar \
        local:///ppml/bigdl-2.3.0-SNAPSHOT/jars/bigdl-ppml-spark_3.1.3-2.3.0-SNAPSHOT.jar \
        --inputPartitionNum 8 \
        --outputPartitionNum 8 \
        --inputEncryptModeValue AES/CBC/PKCS5Padding \
        --outputEncryptModeValue AES/CBC/PKCS5Padding \
        --inputPath /mnt/data/simplekms/encrypted-input \
        --outputPath /mnt/data/simplekms/encrypted-output \
        --primaryKeyPath /mnt/data/simplekms/primaryKey \
        --kmsType SimpleKeyManagementService \
        --simpleAPPID 98463816**** \
        --simpleAPIKEY 15780936****
  2. 在Master節點上,監控任務運行狀態。

    1. 執行如下命令,查看driver和executor名和運行狀態。

      kubectl get pod

      當運行狀態由Running變成Completed實,說明Spark任務已運行完成。

      get pod

    2. 執行如下命令,查看pod日誌。

      kubectl logs simplequery-xxx-exec-1
      說明

      simplequery-xxx-exec-1請替換為上一步查詢到的simplequery名。

      當pod日誌中限制Finished時,說明Spark任務已運行完成。

      pod日誌

步驟四:解密結果

  1. 將各個Worker節點上的encrypted-output目錄下的.metapart-XXXX.csv.cbc檔案上傳到Master節點encrypted-output目錄中。

    上傳完成後,Master節點上的encrypted-output資料如下所示。

    encrypted-output

  2. 在Master節點上的/mnt/data/simplekms目錄下,建立decrypt.py檔案。

    1. 執行如下命令,切換到/mnt/data/simplekms目錄。

      cd /mnt/data/simplekms
    2. 執行如下命令,建立並開啟decrypt.py檔案。

      sudo vim decrypt.py
    3. i進入編輯模式。

    4. 在decrypt.py檔案中,添加如下內容。

      from bigdl.ppml.ppml_context import *
      args = {"kms_type": "SimpleKeyManagementService",
              "app_id": "98463816****",
              "api_key": "15780936****",
              "primary_key_material": "/mnt/data/simplekms/primaryKey"
              }
      sc = PPMLContext("PPMLTest", args)
      encrypted_csv_path = "/mnt/data/simplekms/encrypted-output"
      csv_plain_df = sc.read(CryptoMode.AES_CBC_PKCS5PADDING) \
          .option("header", "true") \
          .csv(encrypted_csv_path)
      csv_plain_df.show()
      output_path = "/mnt/data/simplekms/decrypted-output"
      sc.write(csv_plain_df, CryptoMode.PLAIN_TEXT) \
          .mode('overwrite') \
          .option("header", True)\
          .csv(output_path)
    5. Esc鍵,輸入:wq,儲存並退出編輯模式。

  3. 在Master節點上,執行如下命令,解密encrypted_csv_path目錄下的資料。

    使用APPID、APIKEY、primarykey進行解密,解密後的資料part-XXXX.csv儲存在/mnt/data/simplekms/decrypted-output目錄下。

    java \
        -cp '/ppml/spark-3.1.3/conf/:/ppml/spark-3.1.3/jars/*:/ppml/bigdl-2.3.0-SNAPSHOT/jars/*' \
        -Xmx1g org.apache.spark.deploy.SparkSubmit \
        --master 'local[4]' \
        --conf spark.network.timeout=10000000 \
        --conf spark.executor.heartbeatInterval=10000000 \
        --conf spark.python.use.daemon=false \
        --conf spark.python.worker.reuse=false \
        --py-files /ppml/bigdl-2.3.0-SNAPSHOT/python/bigdl-ppml-spark_3.1.3-2.3.0-SNAPSHOT-python-api.zip,/ppml/bigdl-2.3.0-SNAPSHOT/python/bigdl-spark_3.1.3-2.3.0-SNAPSHOT-python-api.zip,/ppml/bigdl-2.3.0-SNAPSHOT/python/bigdl-dllib-spark_3.1.3-2.3.0-SNAPSHOT-python-api.zip \
        /mnt/data/simplekms/decrypt.py

    在Windows系統中查看該解密後資料,顯示如下:

    解密資料