机密计算是指通过在基于硬件的可信执行环境(TEE)中执行计算来保护数据应用中的隐私安全,是目前最火热的隐私保护技术之一。在云上运行TEE应用也得到了云厂商的广泛支持,包括阿里云,微软Azure云,都提供了基于SGX技术的机密安全实例服务。用户可以在这些云上申请带SGX支持的安全实例,然后部署自己的机密安全服务,既可以避免隐私数据泄露,也无需操心繁琐的基础架构层的配置。
无论哪种云,最流行的分布式部署运行框架都是基于谷歌Kubernetes(K8S)。本文就以阿里云机密安全实例为基座,介绍了基于标准的K8S,部署可扩展的基于Occlum的安全推理(Tensorflow Seving)实例。
阿里云K8S环境搭建及SGX Plugin安装
首先,我们需要一个安装了SGX Plugin的K8S集群环境。在本例中,我们在阿里云申请了两台g7t的ECS实例(ecs.g7t.4xlarge),基本配置如下:
CPU核数 |
内存 |
安全内存(EPC) |
操作系统 |
32 |
64GB |
32GB |
Ubuntu 20.04 LTS 2 |
系统内核需要升级以支持SGX。
$ sudo apt install --install-recommends linux-generic-hwe-20.04
然后,需要在每台实例上配置安装K8S环境,其中一台作为master node,一台作为worker node。细节不再赘述,用户可以使用自己的方式创建集群,或者可以参考谷歌文档 “使用kubedm创建集群”。在本例中,K8S集群使用containerd做运行时,flannel做为网络插件,然后设置主节点也可以参与任务分配以保证有足够的资源应对后面的扩展推理任务。
安装Intel SGX Plugin
为了在K8S上支持SGX,必须安装SGX插件。我们选择DaemonSet的方式,可以参考Intel的文档。
首先部署cert manager并验证。
$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.0/cert-manager.yaml
$ kubectl get pods --namespace cert-manager
NAME READY STATUS RESTARTS AGE
cert-manager-6868fddcb4-97zng 1/1 Running 0 27m
cert-manager-cainjector-6d6bbc7965-vjhdh 1/1 Running 0 27m
cert-manager-webhook-59f66d6c7b-clfrj 1/1 Running 0 27m
然后就可以安装SGX Plugin。
下载Intel Device Plugins 源码 并启用。
$ kubectl apply -k ${INTEL_DEVICE_PLUGINS_SRC}/deployments/sgx_plugin/overlays/epc-register/
一切顺利的话,过一会儿,我们可以得到如下运行的pod列表。
$ kubectl get po -A
NAMESPACE NAME READY STATUS RESTARTS AGE
cert-manager cert-manager-6868fddcb4-97zng 1/1 Running 0 41m
cert-manager cert-manager-cainjector-6d6bbc7965-vjhdh 1/1 Running 0 41m
cert-manager cert-manager-webhook-59f66d6c7b-clfrj 1/1 Running 0 41m
kube-system coredns-7f74c56694-7m96p 1/1 Running 0 84m
kube-system coredns-7f74c56694-vq5lx 1/1 Running 0 84m
kube-system etcd-k8s-master-sh-16c 1/1 Running 12 84m
kube-system intel-sgx-plugin-blth6 1/1 Running 0 20s
kube-system intel-sgx-plugin-mxw26 1/1 Running 0 20s
kube-system kube-apiserver-k8s-master-sh-16c 1/1 Running 10 84m
kube-system kube-controller-manager-k8s-master-sh-16c 1/1 Running 10 84m
kube-system kube-flannel-ds-hzxjr 1/1 Running 0 58m
kube-system kube-flannel-ds-nxn6s 1/1 Running 0 84m
kube-system kube-proxy-vv9lp 1/1 Running 0 58m
kube-system kube-proxy-wmc2k 1/1 Running 0 84m
kube-system kube-scheduler-k8s-master-sh-16c 1/1 Running 12 84m
kube-system sgx-node-init-fpnp7 1/1 Running 0 29s
kube-system sgx-node-init-jxzrr 1/1 Running 0 29s
验证SGX Device Plugin加载成功
最后一步,可以查看node信息来确认SGX插件安装成功。
$ kubectl describe node k8s-master-sh-16c |grep sgx.intel.com
sgx.intel.com/capable=true
sgx.intel.com/enclave: 110
sgx.intel.com/epc: 33285996544
sgx.intel.com/provision: 110
sgx.intel.com/enclave: 110
sgx.intel.com/epc: 33285996544
sgx.intel.com/provision: 110
sgx.intel.com/enclave 0 0
sgx.intel.com/epc 0 0
sgx.intel.com/provision 0 0
编译部署基于Occlum的安全推理Pods
本文选取的例子是从Tensorflow Serving原始应用容器出发,应用本身不修改,应用Occlum远程证明方案Init-RA,实现全流程数据保护的应用实例架构。具体的全流程安全保护的细节介绍可以参考文章“使用Occlum在TEE环境轻松部署Tensorflow Serving推理应用”或者直接查看Occlum github相关页面。
总体架构
对于基于K8S部署的本例来说,总体结构如下图:
各个模块的基本介绍如下:
Key broker service (密钥分发服务)
GRPC-RATLS Server pod 作为密钥分发服务工作。它运行于SGX环境里,保证了密钥的安全性。它会根据通过安全的GRPC-RATLS连接传递的请求,派发相应的密钥。
TF Service (推理服务)
多个Tensorflow Serving pods组成了推理服务。本例中使用NodePort的方式把推理服务暴露给用户。实际的用例里用户也可以根据需要使用云厂商的LoadBalancer方式。具体可以扩展的Tensorflow Serving pods数目是由K8S集群的资源决定的,尤其是安全内存(EPC)的大小。
Client(用户)
用户可以使用服务证书(server.crt) 向推理服务发起推理请求。推理服务会把这个请求转发到某一个Tensorflow Serving pod已完成推理动作。
PCCS Server
远程证明依赖于自建或者云厂商提供的PCCS服务。本例因为是运行在阿里云上,所以可以直接使用阿里云的PCCS服务。
如何编译
本例中使用的容器镜像,可以在docker hub上直接下载。
docker pull occlum/init_ra_server:0.29.2-ubuntu20.04
docker pull occlum/tf_demo:0.29.2-ubuntu20.04
docker pull occlum/tf_demo_client:0.29.2-ubuntu20.04
如果用户需要从源码编译/修改,可以在Occlum github上找到所有信息。
具体步骤如下:
启动Occlum官方的开发容器镜像。
$ sudo docker run --rm -itd --network host \
--device /dev/sgx/enclave --device /dev/sgx/provision \
-v $(which docker):/usr/bin/docker -v /var/run/docker.sock:/var/run/docker.sock \
occlum/occlum:0.29.2-ubuntu20.04
下载Occlum源码,然后进入路径 “example/kubernetes”,里面有一个编译脚本 “build.sh" 可以一键完成所有的编译,包括grpc-ratls库的编译,occlum镜像的编译,以及最终容器镜像的生成。
Build Occlum TF examples container images for k8s deployment.
usage: build.sh [OPTION]...
-r the container image registry
-g container image tag
-d GPRC RA server domain
-p GPRC RA server port
例如,希望容器的registry是“demo”,tag设置成“0.29.2”,可以如下使用。
# ./build.sh -r demo -g 0.29.2
完成编译后,会生成如下三个容器镜像。
demo/init_ra_server:0.29.2
demo/tf_demo:0.29.2
demo/tf_demo_client:0.29.2
如何部署
修改yaml文件模板
在Occlum github上提供了本例的yaml文件模板,不过用户需要根据实际情况做出如下的修改。
根据实际编译情况,修改容器镜像的名字和tag。
根据实际部署环境情况,修改PCCS_URL的环境变量值。
这里我们直接使用阿里云的PCCS service。如果是是其他的PCCS 服务,用户可以修改这个环境变量。
如果有需要,修改资源限制的值。
resources:
limits:
sgx.intel.com/epc: "8000Mi"
cpu: "1000m"
本例中,对于推理服务,因为默认编译里Occlum “user_space_size”设置为7000MB,所以相应的yaml文件里EPC资源限制为“8000Mi”。另外,为了在benchmark环节体现可扩展性带来的性能提升,对于每一个推理pod,CPU限制为“1000m”。
在Occlum v1.0之前,参数“taskset -c 2,3,4,5”是必须要的。这是为了限制Tensorflow Seving应用启动的线程数,使之不超过在Occlum编译阶段设置的SGX线程数 “max_num_of_threads”。当Occlum v1.0引入异步协程后(预计2022年年底发布),这一参数就不再需要了。
启动密钥分发服务
$ kubectl apply -f occlum_init_ra_server.yaml
等一会儿,如果成功的话,可以在对应Pod的log里看到如下信息:
Server listening on 0.0.0.0:5000
启动Tensorflow Serving 推理服务
$ kubectl apply -f occlum_tf_demo.yaml
等一会儿,如果成功的话,可以在对应Pod的log里看到如下信息:
Running gRPC ModelServer at 0.0.0.0:9001 ...
默认情况,只启动了一个Tensorflow Serving pod。
测试发起推理请求
$ docker run --rm --network host sevenzheng/tf_demo_client:0.29.2 python3 inception_client.py --server=localhost:31001 --crt server.crt --image cat.jpg
上面的命令运行了一个预制在demo用户容器镜像里的python程序,它使用编译时生成的server.crt自签名证书,发送一张图片(cat.jpg)请求Tensorflow Serving 服务来做推理。如果成功的话,它会打印出推理的结果。
扩展性benchmark测试
下面的命令会发起一个推理服务的benchmark。
$ docker run --rm --network host demo/tf_demo_client:0.29.2 python3 benchmark.py --server localhost:31001 --crt server.crt --cnum 4 --loop 10 --image cat.jpg
它会打印出benchmark的结果,包括latency和tps。
kubectl scale deploy tf-demo-deployment --replicas 3
尝试扩展推理服务pod从1到3,再次启动benchmark,可以获得更低的latency和更高的tps。
总结
本文的重点放在如何在K8S环境配置Intel SGX插件,如何编译/部署可扩展的Occlum的安全推理实例。至于GRPC-RATLS远程证明密钥分发的细节,各个模块之间的交互,Occlum镜像的编译,Occlum镜像到容器镜像的转换,请参考如下的一些技术文章,或者直接查看Occlum github上的代码和脚本。
《使用Occlum在TEE环境轻松部署远程证明服务和应用》
《使用Occlum在TEE环境轻松部署Tensorflow Serving推理应用》
其他选择
运行环境
本例虽然是在运行在阿里云机密安全实例上自建的K8S集群上,但实际上,它适用于任何支持Intel SGX2的机器/虚机/云上实例。
远程证明方案
本例采用的是开源的GRPC-RATLS远程证明为基础的密钥分发方案。但是,因为Occlum创新的“Occlum -> init ->application”启动流程模型,只要很少的改动,本例就可以适配其他的远程证明密钥分发方案。
要点就是把所有和远程证明相关的实现都放在Occlum init进程里,实际的应用本身(如本例的Tensorflow Serving)无需改动或者只要极小的改动就行。
把远程证明放到Occlum init进程里,可以参考示例“maa_init”。然后用户可以配置 Azure Key Vault 作为密钥分发服务。
这是一个开源的方案,包括密钥分发服务和用户端接口。同样的,配置启动AECS server作为密钥分发服务,把AECS客户端接口实现在用户应用(例如本例中的Tensorflow Serving)的Occlum init进程里。