点击上方入口立即【自由构建 探索无限】
一起共赴年度科技盛宴!
前言
随着机器学习的不断发展和在各个行业的使用,很多企业已经从最初关注构建模型、算法选择到了现在如何构建自己的机器学习平台,在该平台上实现从数据处理、模型训练、模型部署和 CI/CD。现在机器学习平台有很多,比较受欢迎的机器学习平台有亚马逊云科技的托管服务 SageMaker 和开源的 Kubeflow, MLflow 等。本文结合用户的场景,使用 Kubeflow 构建一个弹性可灵活扩展的机器学习平台。
Kubeflow (https://www.kubeflow.org) 是 Kubernetes 的机器学习工具包,目标是利用 Kubernetes 的优点,尽可能简单地扩展机器学习 (ML) 模型并将它们部署到生产环境。在 Kubernetes 部署选择上,我们根据用户的使用情况选择了 Amazon Elastic Kubernetes Service
(https://aws.amazon.com/cn/eks/?nc1=h_ls) (Amazon EKS) ,它是一项托管容器服务,可以在云中和本地运行和扩展 Kubernetes 应用程序。最后我们会选择三剑客中的第三项,Karpenter, Karpenter (https://karpenter.sh) 是使用亚马逊云科技构建的开源、灵活、高性能的 Kubernetes 集群自动扩缩程序。它通过快速启动适当规模的计算资源来响应不断变化的应用程序负载,从而帮助提高应用程序可用性和集群效率。Karpenter 特别适合该用户在机器学习中对于成本优化的需求,在无需配置任何 GPU 节点组情况下,快速的获得 GPU 资源进行模型训练和在训练结束后快速释放 GPU 资源。本方案中,我们会专注于使用这三个服务,构建弹性的机器学习平台。
本方案部署在北京区域进行,本文通过四个部分总结如何在中国区搭建 Kubeflow 1.5.1并利用 Karpenter 进行动态的 GPU 资源的扩展满足 Kubeflow ML 训练的需求。
准备环境
部署 Kubeflow
验证 Kubeflow 的安装,包含实验
利用 Karpenter 进行动态的资源扩展满足 Kubeflow ML 训练的需求
需要的服务和架构如下图:
准备环境
准备环境主要分为四部分:
安装必要的工具
创建 EKS 集群
下载源码
配置 image 拉取工具
安装必要的工具
在正式安装 Kubeflow 前,需要准备一些必要的工具,具体也可参考 Kubeflow on EKS
(https://awslabs.github.io/kubeflow-manifests/docs/deployment/prerequisites/) 官网。安装时请一定注意工具版本,Python 3.8 和 Kustomize 3.2.0。
Amazon CLI
(https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
eksctl (https://eksctl.io/introduction/#installation)
kubectl (https://kubernetes.io/docs/tasks/tools)
yq (https://mikefarah.gitbook.io/yq)
jq (https://stedolan.github.io/jq/download/)
kustomize version 3.2.0
(https://github.com/kubernetes-sigs/kustomize/releases/tag/v3.2.0)
python 3.8+ (https://www.python.org/downloads/)
pip (https://pip.pypa.io/en/stable/installation/)
创建 EKS 集群
创建一个新的集群为Kubeflow使用,关于EKS的版本选择,可以参考 Amazon EKS 和 Kubeflow 兼容性
(https://awslabs.github.io/kubeflow-manifests/docs/about/eks-compatibility/) 网站。
首先设置环境变量,EKS 集群名称和指定北京 Region。
export CLUSTER_NAME=kubeflow151
export CLUSTER_REGION=cn-north-1
创建集群:
eksctl create cluster --name ${CLUSTER_NAME} --version 1.21 --region ${CLUSTER_REGION} --nodegroup-name kf --node-type m5.xlarge --nodes 4 --nodes-min 4 --nodes-max 8 --managed --with-oidc
左滑查看更多
下载源码
此次实验基于1.5.1 进行,下载1.5.1相关的源码:
export KUBEFLOW_RELEASE_VERSION=v1.5.1
export AWS_RELEASE_VERSION=v1.5.1-aws-b1.0.0
git clone https://github.com/awslabs/kubeflow-manifests.git && cd kubeflow-manifests
git checkout ${AWS_RELEASE_VERSION}
git clone --branch ${KUBEFLOW_RELEASE_VERSION} https://github.com/kubeflow/manifests.git upstream
左滑查看更多
配置 image 拉取工具
在安装 Kubeflow 的时候,比较困难的一个问题是 image 的拉取,例如 k8s.gcr.io (https://k8s.gcr.io), gcr.io (http://gcr.io), quay.io (https://quay.io) 等源的 image 拉取。关于这部分,我们在 Amazon API Gateway Mutating Webhook For K8S (https://github.com/aws-samples/amazon-api-gateway-mutating-webhook-for-k8) 基础上做了一些修改,具体可以参考自动化拉取 image
(https://github.com/walkingerica/automate-pulling-and-mutating-webhook-for-k8),概括来说,原理是在需要 gcr.io 等镜像的时候,该工具自动通过 Amazon Global 区域的 CodeBuild 拉取镜像并添加到中国区的 ECR 中。
部署 KubeFlow
在部署 KubeFlow on EKS 的时候有多种选择,除了原始安装方法外,Amazon 发行了Kubeflow on EKS 开源版本,允许客户使用现成的 Amazon 服务集成构建机器学习系统并提供安装文档, 包括 RDS 和 S3 安装方法,Cognito, RDS 和 S3 安装方法等。本篇是使用的 RDS 和S3 安装方法。此部署方法用到的服务包含:
RDS:代替 KFP 和 Katib 使用的 MySQL pod,用于持久化 KFP 数据(例如实验、pipelines、job 信息等)和 Katib 日志信息。
S3:代替 MinIO 存储对象, 例如一些日志文件。
Secret Manager:存储 RDS 相关信息,像用户名密码和 Endpoint 等。
准备工作
因为代码中没有考虑对中国区的支持,需要手动修改一些代码。
在 auto-rds-s3-setup.py 文件中需要修改两处:
iam_policies 部分,需要把 aws 替换成 aws-cn
s3_params 部分,需要把 amazonaws.com
(http://s3.amazonaws.com.cn) 换成 s3.amazonaws.com.cn (http://s3.amazonaws.com.cn)
def create_secrets_iam_service_account():
print("Creating secrets IAM service account...")
iam_policies = [
"arn:aws-cn:iam::aws:policy/AmazonSSMReadOnlyAccess",
"arn:aws-cn:iam::aws:policy/SecretsManagerReadWrite",
]
create_iam_service_account(
service_account_name="kubeflow-secrets-manager-sa",
namespace="kubeflow",
cluster_name=CLUSTER_NAME,
region=CLUSTER_REGION,
iam_policy_arns=iam_policies,
)
print("Secrets IAM service account created!")
def setup_kubeflow_pipeline():
print("Setting up Kubeflow Pipeline...")
print("Retrieving DB instance info...")
db_instance_info = get_db_instance_info()
pipeline_rds_params_env_file = "../../awsconfigs/apps/pipeline/rds/params.env"
pipeline_rds_secret_provider_class_file = (
"../../awsconfigs/common/aws-secrets-manager/rds/secret-provider.yaml"
)
rds_params = {
"dbHost": db_instance_info["Endpoint"]["Address"],
"mlmdDb": "metadb",
}
edit_pipeline_params_env_file(rds_params, pipeline_rds_params_env_file)
update_secret_provider_class(
pipeline_rds_secret_provider_class_file, RDS_SECRET_NAME
)
pipeline_s3_params_env_file = "../../awsconfigs/apps/pipeline/s3/params.env"
pipeline_s3_secret_provider_class_file = (
"../../awsconfigs/common/aws-secrets-manager/s3/secret-provider.yaml"
)
s3_params = {
"bucketName": S3_BUCKET_NAME,
"minioServiceRegion": CLUSTER_REGION,
"minioServiceHost": "s3.amazonaws.com.cn",
}
左滑查看更多
在 config 文件中 s3 endpoint 需要修改:
{
artifactRepository:
{
s3: {
bucket: $(kfp-artifact-bucket-name),
keyPrefix: artifacts,
endpoint: s3.cn-north-1.amazonaws.com.cn,
insecure: true,
accessKeySecret: {
name: mlpipeline-minio-artifact,
key: accesskey
},
secretKeySecret: {
name: mlpipeline-minio-artifact,
key: secretkey
}
},
archiveLogs: true
}
}
左滑查看更多
准备 RDS, S3 和
Secret Manager 环境
1. 首先确保从代码的根目录开始。
export REPO_ROOT=$(pwd)
2. 进入 tests/e2e 目录并安装依赖。
cd tests/e2e
pip install -r requirements.txt
3. 准备需要使用的环境变量。
export CLUSTER_REGION=cn-north-1
export CLUSTER_NAME=kubeflow151
export S3_BUCKET=
export MINIO_AWS_ACCESS_KEY_ID=
export MINIO_AWS_SECRET_ACCESS_KEY=
左滑查看更多
4. 配置 RDS, S3 和 Secret Manager 环境,安装 auto-rds-s3-setup.py。此步骤包含:
RDS 数据库创建
S3 桶创建
Secret Manager 设置
Serviceaccounts 创建
Secret Store CSI driver 设置等
PYTHONPATH=.. python utils/rds-s3/auto-rds-s3-setup.py --region $CLUSTER_REGION --cluster $CLUSTER_NAME --bucket $S3_BUCKET --s3_aws_access_key_id $MINIO_AWS_ACCESS_KEY_ID --s3_aws_secret_access_key $MINIO_AWS_SECRET_ACCESS_KEY
左滑查看更多
Python 脚本执行后,会看到上面的 log 输出,为了确保安装过程成功,可以分别查看 pod 运行的状态、serviceaccounts 和 CSI driver 等。
kubectl get pods —all-namespaces
kubectl describe serviceaccounts kubeflow-secrets-manager-sa -n kubeflow;
左滑查看更多
kubectl get csidriver
Kubeflow 安装
执行如下命令安装,安装后也可以建议查看 pod 状态。
cd $REPO_ROOT
while ! kustomize build deployments/rds-s3 | kubectl apply -f -; do echo "Retrying to apply resources"; sleep 30; done
kubectl get pods --all-namespaces
左滑查看更多
如果各个 Pod 运行没有问题的话,执行如下命令后,就可通过 http://localhost:8080 访问 Kubeflow Dashboard, 默认用户名为 [email protected],密码为12341234。因为涉及到 RDS 和 S3 的使用,请参考下一步验证安全结果。
kubectl port-forward svc/istio-ingressgateway -n istio-system 8080:80
左滑查看更多
登陆后,可以看到 Kubeflow 的控制台界面如下。Kubeflow 支持的主要功能可以在界面上找到,用户编程测试工作台 (Jupyter Notebook),超参调优 (Experiment(AutoML)), 机器学习工作流(Pipeline)等。
验证安装结果
在 Kubeflow 安装之后,我们通过两个方面进行验证,RDS 和 S3 的验证,这两个角度的验证也是在侧面验证超参调优和工作流工作。
验证 RDS数据库
RDS 中会存储
1. 连接 RDS 数据库。
kubectl run -it —rm —image=mysql:5.7 —restart=Never mysql-client — mysql -h -u -p
左滑查看更多
2. 连接成功后,查看 kubeflow 和mlpipeline 数据是否存在, 同时查看在mlpipeline中是否有如下的表。
show databases;
use mlpipeline; show tables;
3. 登录进入到 Kubeflow Dashboard,使用此 yaml
(https://github.com/awslabs/kubeflow-manifests/blob/main/tests/e2e/resources/custom-resource-templates/katib-experiment-random.yaml) 文件(注意需要更改 namespace) 运行一个实验。具体操作为 Dashboard –> Experiments (AutoML) –> New Experiment。
实验成功后,RDS 中表中会有相关的实验执行信息。
验证 S3
在 Kubeflow Dashboard 中,创建一个 Experiment 并运行,运行结束之后,我们可以去到第二步部署的 S3 bucket 中,如果可以查看到 log, S3 部分没有问题。可以参考下图:
利用 Karpenter 进行动态的资源扩展
满足 Kubeflow ML 训练的需求
在 Karpenter 之前,EKS 用户使用 Cluster Autoscaler 动态调整集群的计算容量,他的原理是使用 Amazon EC2 Auto Scaling 组
(https://docs.aws.amazon.com/autoscaling/ec2/userguide/auto-scaling-groups.html)进行扩展底层的 EC2 资源。Karpenter 会观察未调度的一组容器 (pod) 的总资源请求,然后向 Amazon EC2 直接发送命令并作出启动和终止新节点的决策,从而减少调度延迟并降低基础设施成本。在机器学习场景下,用户可以像该文中一样使用一个 EKS 节点组安装和管理 Kubeflow,在提交训练任务时,通过 Karpenter 开启 GPU 资源,在训练结束后终止 GPU 资源。
Karpenter 的安装不在此介绍了,可以参考官方文档安装 (https://karpenter.sh/v0.5.5/getting-started/)。我们主要演示在 Karpenter 部署后,Kubeflow 中如何使用。使用验证 RDS 的例子,在 spec 中添加 resource 为 nvidia.com/gpu
(https://www.nvidia.com/gpu/), 添加后在 Kubeflow Dashboard 中 Experiments (AutoML) 部分运行修改后的 yaml 文件。
.......
trialSpec:
apiVersion: batch/v1
kind: Job
spec:
template:
metadata:
annotations:
sidecar.istio.io/inject: 'false'
spec:
containers:
- name: training-container
image: docker.io/kubeflowkatib/mxnet-mnist:v1beta1-45c5727
command:
- "python3"
- "/opt/mxnet-mnist/mnist.py"
- "--batch-size=64"
- "--lr=${trialParameters.learningRate}"
- "--num-layers=${trialParameters.numberLayers}"
- "--optimizer=${trialParameters.optimizer}"
resources:
limits:
nvidia.com/gpu: 1
restartPolicy: Never
左滑查看更多
在提交了这个 Experiment 后,可以通过命令行查看 Karpenter 的日志。我们可以看到 GPU 机器可快速创建起来。
kubectl logs -f -n karpenter -l app.kubernetes.io/name=karpenter -c controller
左滑查看更多
在任务执行完毕后,可以看到创建的 GPU EC2 被删除。通过 Karpenter,我们可以随时扩展资源进行训练,不需要提前配置很多 GPU 资源。
总结
通过使用 EKS, Kubeflow, Karpenter 可以建立弹性扩展性强的机器学习平台,在安装中需要注意的问题包含:
1. Kubeflow 中使用了很多源是 io 的 image,可通过这个工具自动化拉取Image。
2. 在中国区 Kubeflow 和 Karpenter 安装的时候,需要修改一些服务的 endpoint 和 ARN 像是 amazonaws.com 到 s3.cn-north-1.amazonaws.com.cn。Kubeflow 的配置文件代码量比较大,在部署前通过检索的方式发现需要修改的 endpoint 外。最好的办法是通过查看 Pod 运行状态进行 Troubleshooting,一般这几个配置都在 configmap 中,修改 configmap 即可。
3. 在使用 Karpenter 调度 GPU 资源前,记得安装 NVIDIA 设备的插件,kubectl apply -f
https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.9.0/nvidia-device-plugin.yml。
参考文档
Kubeflow on Amazon:
https://awslabs.github.io/kubeflow-manifests/docs/deployment/rds-s3/guide/#42-verify-s3
Karpenter 介绍:
https://aws.amazon.com/cn/blogs/china/karpenter-new-generation-kubernetes-auto-scaling-tools/
Karpenter 安装:
https://karpenter.sh/v0.12.1/getting-started/getting-started-with-eksctl/
本篇作者
冯秋爽
亚马逊云科技解决方案架构师,负责跨国企业级客户基于 Amazon 的技术架构设计、咨询和设计优化工作。在加入 Amazon 之前曾就职于 IBM、甲骨文等 IT 企业,积累了丰富的程序开发和数据库的实践经验。
黄德滨
亚马逊云科技资深解决方案架构师,服务于全球客户销售团队,负责技术架构设计和咨询,致力于企业级应用在 Amazon 云服务的运用和部署,对于大型企业级应用开发和实施拥有近二十年的丰富经验,在云计算领域工作多年,拥有大量帮助各种类型企业上云的经验,在加入 Amazon 之前先后服务于百度、甲骨文等国内外知名 IT 企业。
点击上方【立即报名】
直通大咖云集的亚马逊云科技中国峰会!
听说,点完下面4个按钮
就不会碰到bug了!