在Intel 第四代至强可扩展处理器(SPR)上
基于BigDL PPML构建全链路安全的分布式Spark大数据分析应用
一、背景信息
本文介绍基于Intel® SGX的BigDL PPML解决方案,以及如何运用BigDL PPML解决方案在Intel 第四代至强可扩展处理器(SPR)上运行分布式的全链路安全的Spark大数据分析案例。
随着越来越多的公司将数据和计算迁移到云端,如何在云环境保护大数据分析和人工智能应用的数据安全和隐私,是数据科学家和云服务提供商共同面临的话题。英特尔® SGX 是英特尔的受信任执行环境(TEE),它提供基于硬件的内存加密,隔离内存中的特定应用代码和数据。英特尔® SGX 使得用户层代码可以分配内存中的受保护区域,即 “飞地”,这些区域不受更高权限等级程序运行的任何影响。Intel 第四代至强可扩展处理器(SPR)基于Intel® SGX技术,提供了SGX加密计算能力,打造了基于硬件级别的更高安全等级的可信机密环境,保障应用和数据的机密性与完整性不受恶意软件的破坏。
BigDL PPML(Privacy Preserving Machine Learning)基于Intel® SGX技术构建了一整套的解决方案,能够让用户即使没有处于极度信任的公有或私有云中也仍然可以进行非常安全的数据分析和AI应用。基于BigDL PPML解决方案,在公有云中运行标准的人工智能和大数据处理应用(比如Apache Spark、Apache Flink、TensorFlow、PyTorch),可以保证数据传输的安全性、数据使用的安全性、以及应用程序的完整性。
二、技术架构
借助BigDL PPML,用户可以在加密数据上运行现有的分布式大数据分析和AI应用程序(例如Apache Spark、Apache Flink、TensorFlow、PyTorch、OpenVINO等),无需任何代码修改。大数据分析和AI应用程序运行在Intel® SGX节点的K8s集群之上,其计算和内存受Intel® SGX保护。在底层,BigDL PPML自动为分布式应用程序启用端到端安全机制,包括:
- 在K8s(Intel® SGX节点)上提供和证明“可信集群环境”
- 通过KMS进行密钥管理,用于分布式数据解密/加密
- 安全的分布式计算和通信(通过加密、TLS等)
如上图所示,BigDL PPML方案基于Intel® SGX的Intel 第四代至强可扩展处理器(SPR),部署Kubernetes 集群环境。从数据流角度,所有数据均以加密方式存储在数据湖和数据仓库中。BigDL PPML Worker加载这些机密数据,通过远程证明以及密钥管理系统获取数据密钥,置于SGX可信执行环境中进行解密,再使用大数据和人工智能的计算框架,对数据进行分布式预处理,模型训练以及模型推理等。最后,再把最终结果、数据或者模型,以加密方式写回到分布式存储中。另外在节点之间,计算节点之间的数据均被加密传输(AES加密、TLS等),从而做到全链路的隐私保护和数据安全。
三、操作步骤
本文以运行Spark大数据分析为例,介绍如何基于SGX实例,运行分布式的端到端安全的大数据分析应用(本文以运行Simple Query用例为例)。
步骤一:环境准备
- 准备好SGX实例。您可以根据实际业务,准备多台实例。
- 安装DCAP-driver。参考https://download.01.org/intel-sgx/latest/linux-latest/docs/Intel_SGX_SW_Installation_Guide_for_Linux.pdf
- 安装PCCS。参考https://download.01.org/intel-sgx/latest/linux-latest/docs/Intel_SGX_SW_Installation_Guide_for_Linux.pdf
- 安装AESM。参考https://download.01.org/intel-sgx/latest/linux-latest/docs/Intel_SGX_SW_Installation_Guide_for_Linux.pdf
步骤二:部署Kubernetes集群及NFS分布式存储系统
本文中Kubernetes集群使用1个Master节点,2个Worker节点。您可以根据实际业务,选择节点数量。
- 部署Kubernetes集群并进行安全配置。
- 在已创建的SGX实例中,部署Kubernetes集群。
- 执行如下命令,在Kubernetes集群的Master节点上进行安全配置(RBAC配置)。
```
kubectl create serviceaccount spark
kubectl create clusterrolebinding spark-role --clusterrole=edit --serviceaccount=default:spark --namespace=default
```
- 安装SGX deviceplugin
参考https://bigdl.readthedocs.io/en/latest/doc/PPML/QuickStart/deploy_intel_sgx_device_plugin_for_kubernetes.html 为Kubernetes部署SGX Device Plugin。
- 搭建NFS分布式文件系统
- 创建deployment-nfs.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
namespace: default
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: quay.io/external_storage/nfs-client-provisioner:latest
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: fuseim.pri/ifs
- name: NFS_SERVER
value: 172.16.0.1 # replace NFS_SERVER with yours
- name: NFS_PATH
value: /disk1/nfsdata # set nfs path
volumes:
- name: nfs-client-root
nfs:
server: 172.16.0.1 # replace NFS_SERVER with yours
path: /disk1/nfsdata # set nfs path
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nfsvolumeclaim
namespace: default
annotations:
volume.beta.kubernetes.io/storage-class: "managed-nfs-storage"
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 100Gi
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: nfs-client-provisioner-runner
namespace: default
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: run-nfs-client-provisioner
namespace: default
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
namespace: default
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
- 修改deployment-nfs.yaml文件
需要修改的地方只有NFS服务器所在的IP地址(172.16.0.1),以及NFS服务器共享的路径(/disk1/nfsdata),两处都需要修改为你实际的NFS服务器和共享目录
- 部署deployment-nfs.yaml
```
kubectl apply -f deployment-nfs.yaml
```
- 查看pvc状态
```
Kubectl get pvc
```
步骤三:加密训练数据
- 在Kubernetes集群的每个节点上,执行如下命令,获取BigDL PPML镜像。该镜像用于运行标准的Spark应用,提供数据加密、解密等功能。
```
docker pull intelanalytics/bigdl-ppml-trusted-bigdata-gramine-reference-16g:2.3.0-SNAPSHOT
```
- 生成训练数据csv。
- 在Kubernetes集群的Master节点上,下载训练数据脚本py。
```
wget https://github.com/intel-analytics/BigDL/raw/main/ppml/scripts/generate_people_csv.py
```
- 执行如下命令,生成训练数据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。
- 在Master节点上,执行如下命令,运行bigdl-ppml-client容器。该容器用来加密、解密训练数据。
docker exec -it bigdl-ppml-client bash
- 在bigdl-ppml-client容器中,加密训练数据csv。
- 执行如下命令,使用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****
- 创建加密脚本py。
- 执行如下命令,使用APPID、APIKEY、primarykey加密csv
```
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
```
步骤四:运行基于BigDL PPML的大数据分析用例
- 在bigdl-ppml-client容器中,向Kubernetes集群提交Spark任务,运行Simple Query用例。
- 在Master节点上,监控任务运行状态。
- 执行如下命令,查看driver和executor名和运行状态。
```
Kubectl get pod
```
当运行状态由Running变成Completed实,说明Spark任务已运行完成。
- 执行如下命令,查看pod日志。
```
Kubectl logs simplequery-xxx-exec-1
```
当pod日志中限制Finished时,说明Spark任务已运行完成。
步骤五:解密结果
- 训练结果存放在/mnt/data/simplekms/encrypted-output目录下
- 在/mnt/data/simplekms目录下,创建decrypt.py文件。py文件内容如下所示。
- 在bigdl-ppml-client容器中,执行如下命令,使用APPID、APIKEY、primarykey解密encrypted_csv_path目录下的数据。解密后的数据part-XXXX.csv储存在/mnt/data/simplekms/decrypted-output目录下。
- 查看该解密后数据,显示如下:
四、总结
本文介绍了基于Intel® SGX的BigDL PPML解决方案,以及如何在Intel 第四代至强可扩展处理器(SPR)上,基于BigDL PPML构建全链路安全的分布式Spark大数据分析应用的操作步骤。更多大数据分析和 AI 应用程序(例如 Apache Spark、Apache Flink、TensorFlow、PyTorch、OpenVINO 等)使用说明,请参见BigDL PPML Tutorials & Examples。
Intel® SGX将大大扩展机密计算的支持应用程序和范围。我们将探索其他新的安全技术,如同态加密、差分隐私、混合解决方案等,帮助用户在不损害隐私的情况下实现更安全的数据集成,加速数据价值挖掘。