在 Microsoft Azure 上构建安全的 Kubeflow 管道
利用虚拟机上的 Intel® Software Guard Extensions 部署安全、加速的机器学习流水线
许多机器学习应用程序必须确保底层代码和数据的机密性和完整性。直到最近,安全性主要集中在加密静态数据(即存储中的数据)或传输中数据(即在网络上传输的数据),但并未关注正在使用的数据(即主内存中的数据)。Intel® Software Guard Extensions (Intel® SGX) 提供了一组指令,允许您安全地处理和保护应用程序代码和数据。Intel SGX 通过在 CPU 内创建受信任的执行环境来实现这一点。这允许容器中的用户级代码分配私有内存区域(称为 enclave)来执行应用程序代码。
借助 Microsoft Azure* 机密计算平台,您可以部署 Windows* 和 Linux 虚拟机 (VM),利用 Intel SGX 提供的安全性和机密性。本教程将展示如何为 Azure Kubernetes* Services (AKS) 集群设置 Intel SGX 节点。然后,我们将安装 Kubeflow*,这是一个用于 Kubernetes 的机器学习工具包,您可以使用它来构建和部署可扩展的机器学习流水线。最后,我们将演示如何使用Intel® Optimization for XGBoost*、Intel® oneAPI Data Analytics Library (oneDAL) 和Intel® Extension for Scikit-learn* 来加速模型训练和推理。
此优化模块是Intel® Cloud Optimization Modules for Microsoft Azure的一部分,该模块是一组云原生、开源的参考架构,旨在促进在主流云提供商(包括 Amazon Web Services* (AWS)、Microsoft Azure 和 Google Cloud Platform* (GCP))上构建和部署 Intel 优化 AI 解决方案。每个模块或参考架构都包含所有必要的说明和源代码。
此优化模块的云解决方案架构使用 AKS 集群,其中核心组件是 Intel SGX VM。AKS 集群附加了 Azure Container Registry,以便 Kubeflow 流水线可以构建容器化的 Python* 组件。这些 Azure 资源在 Azure Resource Group 中进行管理。然后,Kubeflow 软件层安装在 AKS 集群上。当 Kubeflow 流水线运行时,每个流水线 pod 都将被分配到一个 Intel SGX 节点。云解决方案架构如图 1 所示。
准备工作
在开始本教程之前,请确保您已下载并安装了先决条件。然后,在一个新的终端窗口中,运行以下命令以使用 Azure 命令行界面与您的 Microsoft Azure 帐户进行交互式登录。
az login
接下来,创建一个将保存我们解决方案 Azure 资源的资源组。我们将把资源组命名为 intel-aks-kubeflow
,并将位置设置为 eastus
。
# Set the names of the Resource Group and Location
export RG=intel-aks-kubeflow
export LOC=eastus
# Create the Azure Resource Group
az group create -n $RG -l $LOC
为了设置带有保密计算节点的 AKS 集群,我们将首先创建一个系统节点池并启用保密计算附加组件。保密计算附加组件将为集群配置一个 DaemonSet,以确保每个符合条件的 VM 节点运行一个 Azure 设备插件 pod 的副本,用于 Intel SGX。以下命令将使用来自Dv5 系列的标准 VM 来配置一个节点池,该 VM 使用第三代 Intel® Xeon® 处理器。这是将托管 AKS 系统 pod(如 CoreDNS
和 metrics-server
)的节点。以下命令还将启用集群的托管标识并配置一个标准的 Azure 负载均衡器。
# Set the name of the AKS cluster
export AKS=aks-intel-sgx-kubeflow
# Create the AKS system node pool
az aks create --name $AKS \
--resource-group $RG \
--node-count 1 \
--node-vm-size Standard_D4_v5 \
--enable-addons confcom \
--enable-managed-identity \
--generate-ssh-keys -l $LOC \
--load-balancer-sku standard
请注意,如果您已经设置了 Azure Container Registry,则可以通过添加参数 --attach-acr <registry-name>
来将其附加到集群。
一旦系统节点池部署完毕,我们将把 Intel SGX 节点池添加到集群中。以下命令将配置两个四核 Intel SGX 节点,来自 Azure 的DCSv3 系列。我们已向此节点池添加了一个节点标签,键为 intelvm
,值为 sgx
。此键值对将在 Kubernetes nodeSelector
中引用,以将 Kubeflow 流水线 pod 分配给 Intel SGX 节点。
az aks nodepool add --name intelsgx \
--resource-group $RG \
--cluster-name $AKS \
--node-vm-size Standard_DC4s_v3 \
--node-count 2 \
--labels intelvm=sgx
一旦保密节点池设置完毕,请获取集群访问凭据,并使用以下命令将它们合并到您的本地 .kube/config 文件中
az aks get-credentials -n $AKS -g $RG
我们可以通过执行以下命令来验证集群凭据是否已正确设置。此命令应返回您的 AKS 集群名称。
kubectl config current-context
为了确保 Intel SGX VM 节点已成功创建,请运行
kubectl get nodes
您应该会看到两个以 aks-intelsgx
开头的代理节点正在运行。为了确保 DaemonSet 已成功创建,请运行
kubectl get pods -A
在 kube-system
命名空间中,您应该会看到两个以 sgxplugin
开头的 pod 正在运行。如果您看到上述 pod 和节点池正在运行,则表示您的 AKS 集群现已准备好运行保密应用程序,我们可以开始安装 Kubeflow。
安装 Kubeflow
要在 AKS 集群上安装 Kubeflow,请先克隆 Kubeflow Manifests GitHub 存储库。
git clone https://github.com/kubeflow/manifests.git
将目录更改为新克隆的 manifests 目录。
cd manifests
作为可选步骤,您可以使用以下命令更改访问 Kubeflow 仪表板的默认密码
python3 -c 'from passlib.hash import bcrypt; import getpass; print(bcrypt.using(rounds=12, ident="2y").hash(getpass.getpass()))'
导航到 dex 目录中的 config-map.yaml 文件,并在配置文件大约第 22 行附近的哈希值中粘贴新生成的密码。
nano common/dex/base/config-map.yaml
staticPasswords:
- email: user@example.com
hash:
接下来,将 Istio* 入站网关从 ClusterIP
更改为 LoadBalancer
。这将配置一个外部 IP 地址,我们可以使用该地址从浏览器访问仪表板。导航到 common/istio-1-16/istio-install/base/patches/service.yaml,并在大约第 7 行将规范类型更改为 LoadBalancer
。
apiVersion: v1
kind: Service
metadata:
name: istio-ingressgateway
namespace: istio-system
spec:
type: LoadBalancer
对于 AKS 集群,我们还需要从 Istio Webhook 中禁用 AKS admission enforcer。导航到 Istio install.yaml 文件,并在大约第 2694 行添加以下注释。
nano common/istio-1-16/istio-install/base/install.yaml
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: istio-sidecar-injector
annotations:
admissions.enforcer/disabled: 'true'
labels:
接下来,我们将更新 Istio 网关以配置传输层安全 (TLS) 协议。这将允许我们通过 HTTPS 访问仪表板。导航到 kf-istio-resources.yaml 文件,并在文件末尾大约第 14 行粘贴以下内容
nano common/istio-1-16/kubeflow-istio-resources/base/kf-istio-resources.yaml
tls:
httpsRedirect: true
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- "*"
tls:
mode: SIMPLE
privateKey: /etc/istio/ingressgateway-certs/tls.key
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
现在我们已准备好安装 Kubeflow。我们将使用 kustomize
来通过一个命令安装组件。您也可以单独安装组件。
while ! kustomize build example | awk '!/well-defined/' | kubectl apply -f -; do echo "Retrying to apply resources"; sleep 10; done
所有组件的安装可能需要几分钟时间,有些组件可能在第一次尝试时失败。这是 Kubernetes 和 kubectl 工作方式的固有特性(例如,CR 必须在 CRD 就绪后创建)。解决方法是简单地重新运行命令直到成功。组件安装完成后,使用以下命令验证所有 pod 是否都在运行
kubectl get pods -A
可选:如果您为 Kubeflow 创建了新密码,请重新启动 dex
pod 以确保它正在使用更新后的密码。
kubectl rollout restart deployment dex -n auth
最后,为 TLS 协议创建一个自签名证书,使用 Istio 负载均衡器的外部 IP 地址。要获取外部 IP 地址,请使用以下命令
kubectl get svc -n istio-system
创建 Istio 证书并复制以下内容
nano certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: istio-ingressgateway-certs
namespace: istio-system
spec:
secretName: istio-ingressgateway-certs
ipAddresses:
- <Istio IP address>
isCA: true
issuerRef:
name: kubeflow-self-signing-issuer
kind: ClusterIssuer
group: cert-manager.io
然后,应用证书
kubectl apply -f certificate.yaml
验证证书是否已成功创建
kubectl get certificate -n istio-system
现在,我们准备启动 Kubeflow 仪表板。要登录到仪表板,请在浏览器中输入 Istio IP 地址。首次访问仪表板时,您可能会收到警告。这是因为我们使用的是自签名证书。如果您有 SSL CA 证书,可以替换它,或者点击“高级”并“继续前往网站”。此时应出现 DEX 登录屏幕。输入您的用户名和密码。Kubeflow 的默认用户名是 user@example.com
,默认密码是 12341234
。
登录 Kubeflow 仪表板后,我们现在可以部署 Kubeflow 流水线了。本模块中的 Kubeflow 流水线源自 Intel 与 Accenture 合作构建的贷款违约风险预测 AI 参考套件。通过重构代码,提高了模块化程度,更适合 Kubeflow 流水线。该流水线构建 XGBoost 模型来预测借款人的贷款违约风险,并使用Intel Optimization for XGBoost和 oneDAL 来加速模型训练和推理。完整流水线的图形表示如图 2 所示。
Kubeflow 流水线由以下七个组件组成
- 加载数据:从流水线运行参数中指定的 URL 加载数据集(credit_risk_dataset.csv),并进行合成数据增强。下载 Kaggle 信用风险数据集。
- 创建训练集和测试集:将数据分成训练集和测试集,大约为 75:25 的比例,用于模型评估。
- 预处理特征:使用独热编码转换训练集和测试集的分类特征,此外还填充缺失值并对数值特征进行幂变换。
- 训练 XGBoost 模型:此组件利用 Intel Optimization for XGBoost 提供的加速来训练模型。
- 将 XGBoost 模型转换为 daal4py:将 XGBoost 模型转换为经过推理优化的 daal4py 分类器。
- daal4py 推理:使用经过推理优化的 daal4py 分类器计算预测并评估模型性能。它返回每个类别的精确度、召回率和 F1 分数的输出摘要,以及模型的曲线下面积 (AUC) 和准确度分数。
- 绘制接收器工作特性 (ROC) 曲线:对测试数据进行模型验证,并生成 ROC 曲线图。
流水线的代码可以在名为 intel-xgboost-daal4py-pipeline-azure.py 的 GitHub 存储库的 src 文件夹中找到。在运行 Python 脚本之前,请确保您已安装 Kubeflow Pipelines SDK 的 2.0 或更高版本。要更新您的 SDK 版本,您可以使用
pip install -U kfp
为了确保每个流水线 pod 都被分配到 Intel SGX 节点,已将 Kubernetes nodeSelector
添加到流水线中。在调度 pod 时,节点选择器将查找具有匹配键/值对的节点。使用我们添加到 Intel SGX 节点池的节点标签,以下代码会将数据预处理流水线任务 preprocess_features_op
分配给 Intel SGX 节点。
from kfp import kubernetes
kubernetes.add_node_selector(task = preprocess_features_op,
label_key = 'intelvm', label_value = 'sgx')
流水线组件
流水线中的第一个组件 load_data
从流水线运行参数中提供的 URL 下载信用风险数据集,并合成地将数据增强到指定大小。新数据集将作为输出工件保存在 Kubeflow MinIO volume 中。然后,该数据集被读入组件的下一步 create_train_test_set
,该步骤将数据分割成大约 75:25 的比例用于模型评估。然后,训练集和测试集 X_train
、y_train
、X_test
和 y_test
将作为输出数据集工件保存。
在 preprocess_features
组件中,创建了一个数据预处理流水线来为 XGBoost 模型准备数据。此组件从 MinIO 存储加载 X_train 和 X_test 文件,并使用独热编码转换分类特征,填充缺失值,并对数值特征进行幂变换。
下一个组件训练 XGBoost 模型。在 Intel CPU 上使用 XGBoost 可以利用 oneAPI 提供的软件加速,而无需进行任何代码更改。在对一百万个增量训练更新的初步测试中,Intel Optimization for XGBoost v1.4.2 相对于标准 XGBoost v0.81 提供了高达 1.54 倍的加速。(您可以在 GitHub 上查看贷款违约风险预测参考套件的所有性能结果。)以下代码片段实现在 train_xgboost_model
组件中
# Create the XGBoost DMatrix, which is optimized for memory efficiency and training speed
dtrain = xgb.DMatrix(X_train.values, y_train.values)
# Define model parameters
params = {"objective": "binary:logistic",
"eval_metric": "logloss",
"nthread": 4, # num_cpu
"tree_method": "hist",
"learning_rate": 0.02,
"max_depth": 10,
"min_child_weight": 6,
"n_jobs": 4, # num_cpu
"verbosity": 1}
# Train initial XGBoost model
clf = xgb.train(params = params, dtrain = dtrain, num_boost_round = 500)
为了进一步优化模型预测速度,我们在 convert_xgboost_to_daal4py
组件中将训练好的 XGBoost 模型转换为经过推理优化的 daal4py 分类器。daal4py 是 oneDAL 的 Python API。在对一百万个批次推理的测试中,oneDAL 提供了高达 4.44 倍的加速。您可以仅用一行代码将 XGBoost 模型转换为 daal4py
# Convert XGBoost model to daal4py
daal_model = d4p.get_gbt_model_from_xgboost(clf)
然后,在 daal4py_inference
组件中使用 daal4py 模型在测试集上评估模型的性能。
# Compute both class labels and probabilities
daal_prediction = d4p.gbt_classification_prediction(
nClasses = 2,
resultsToEvaluate = "computeClassLabels|computeClassProbabilities"
).compute(X_test, daal_model)
我们通过调用上面的代码中的 gbt_classification_prediction
方法来计算二元类别标签和概率。您也可以使用此函数计算对数概率。此组件将以 CSV 格式返回分类报告,以及两个 Kubeflow 指标工件:曲线下面积和模型的准确度。这些可以在 metrics
工件的“可视化”选项卡中查看。
在流水线的最后一个组件 plot_roc_curve
中,我们加载了带有概率和真实类别标签的预测数据,以使用来自Intel Extension for Scikit-Learn的 CPU 加速版本来计算 ROC 曲线。当流水线运行完成后,结果将作为 Kubeflow ClassificationMetric Artifact 存储,可以在 roc_curve_daal4py
工件的“可视化”选项卡中查看(图 3)。
后续步骤
您可以在 GitHub 上访问完整的源代码。如果您在实现过程中需要帮助,请注册参加办公时间。您可以在Intel Cloud Optimization Modules 上了解更多信息,并在Intel® DevHub Discord 服务器上与我们聊天,以继续与同行开发者互动。