Kubernetes / Linux Note / 探知未来 / 运维笔记

Kubeflow Volcano 实现典型 AI 训练任务

Einic Yeo · 10月18日 · 2023年 · ·

Kubernetes已经成为云原生应用编排、管理的事实标准, 越来越多的应用选择向Kubernetes迁移。人工智能和机器学习领域天然的包含大量的计算密集型任务,开发者非常愿意基于Kubernetes构建AI平台,充分利用Kubernetes提供的资源管理、应用编排、运维监控能力。

Kubernetes存在的问题

Kubeflow在调度环境使用的是Kubernetes的默认调度器。而Kubernetes默认调度器最初主要是为长期运行的服务设计的,对于AI、大数据等批量和弹性调度方面还有很多的不足。主要存在以下问题:

资源争抢问题

TensorFlow的作业包含Ps和Worker两种不同的角色,这两种角色的Pod要配合起来完成整个作业,如果只是运行一种角色Pod,整个作业是无法正常执行的,而默认调度器对于Pod调度是逐个进行的,对于Kubeflow作业TFJob版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!的Ps和Worker是不感知的。在集群高负载(资源不足)的情况下,会出现多个作业各自分配到部分资源运行一部分Pod,而又无法正执行完成的状况,从而造成资源浪费。以下图为例,集群有4块GPU卡,TFJob1和TFJob2作业各自有4个Worker,TFJob1和TFJob2各自分配到2个GPU。但是TFJob1和TFJob2均需要4块GPU卡才能运行起来版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!。这样TFJob1和TFJob2处于互相等待对方释放资源,这种死锁情况造成了GPU资源的浪费。

亲和调度问题

分布式训练中,Ps和Worker存在很频繁的数据交互,所以Ps和Worker之间的带宽直接影响了训练的效率。 Kubernetes默认调度器并不考虑Ps和Worker的这种逻辑关系,Ps和Worker是被随机调度的。如下图所示,2个TFJob(1个Ps + 2 Worker),使用默认调度器,有可能会出现(a)、(b)、(c)三种情况的任意一种情况,(c)才是最想要的调度结果。因为在(c)中,Ps和Worker版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!可以利用本机网络提供传输效率,缩短训练时间。

Volcano批量调度系统:加速AI计算的利器

Volcano是一款构建于版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!Kubernetes之上的增强型高性能计算任务批量处理系统。作为一个面向高性能计算场景的平台,它弥补了Kubernetes在机器学习、深度学习、HPC、大数据计算等场景下的基本能力缺失,其中包括gang-schedule的调度能力、计算任务队列管理、task-topo版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!logy和GPU亲和性调度。另外,Volcano在原生Kubernetes能力基础上对计算任务的批量创建及生命周期管理、fair-share、binpack调度等方面做了增强。Volcano充分解决了上文提到的Kubeflow分布式训练面临的问题。

实战部署

下载kfctl
首先需要下载kfctl,可以根据系统来选择合适的压缩包文件[1]。

$ tar -xvf kfctl_v1.0.2-0-ga476281_linux.tar.gz
$ sudo mv ./kfctl /usr/local/bin/kfctl
配置环境变量
$ export PATH= $PATH:"<path-to-kfctl>"
$ export KF_NAME=<your choice of name for the Kubeflow deployment>
$ export BASE_DIR=<path to a base directory>
$ export KF_DIR=${BASE_DIR}/${KF_NAME}
$ export CONFIG_URI="https://raw.githubusercontent.com/kubeflow/manifests/v1.0-branch/kfdef/kfctl_k8s_istio.v1.0.2.yaml"
安装kubeflow
$ mkdir -p ${KF_DIR}
$ cd ${KF_DIR}
$ Kfctl apply -V -f ${CONFIG_URI}
通过如下指令确认安装结果

$ kubectl -n kubeflow get all 
部署Mnist示例
首先下载kubuflow官方提供的测试集。

git clone https://github.com/kubeflow/examples.git
pip3 install jupyter notebook
jupyter notebook --allow-root ##启动jupyter
启动使用notebook
提供对外接口服务,这里需要将集群下的节点绑定公网IP。如果没有安装notebook请先使用pip3安装。

$ pip3 install jupyter notebook
$ jupyter notebook --allow-root
[W 09:08:03.572 NotebookApp] WARNING: The notebook server is listening on all IP addresses and not using encryption. This is not recommended.
[I 09:08:03.575 NotebookApp] Serving notebooks from local directory: /root/examples
[I 09:08:03.575 NotebookApp] Jupyter Notebook 6.3.0 is running at:
[I 09:08:03.575 NotebookApp] http://mytest-87034:30200/
[I 09:08:03.575 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
访问公网IP:30200,输入配置密码即可进入notebook。

在notebook上运行官方实例[2]
1.打开notebook进行TFJob的部署。Open the notebook mnist/mnist_vanilla_k8s.ipynb ,根据指引来进行分布式Tf Job的部署。

2.添加调度器字段:在mnist/mnist_vanilla_k8s.ipynb 的Tarining job parameters代码块下的TFJob的配置如下所示,添加schedulerName: volcano字段,确保使用volcano进行调度。

train_spec = f"""apiVersion: kubeflow.org/v1
kind: TFJob
metadata:
  name: {train_name}  
spec:
  schedulerName: volcano
  tfReplicaSpecs:
    Ps:
      replicas: {num_ps}
      template:
        metadata:
          annotations:
            sidecar.istio.io/inject: "false"
        spec:
          serviceAccount: default-editor
          containers:
          - name: tensorflow
            command:
            - python
            - /opt/model.py
            - --tf-model-dir={model_dir}
            - --tf-export-dir={export_path}
            - --tf-train-steps={train_steps}
            - --tf-batch-size={batch_size}
            - --tf-learning-rate={learning_rate}
            env:
            - name: S3_ENDPOINT
              value: {s3_endpoint}
            - name: AWS_ENDPOINT_URL
              value: {minio_endpoint}
            - name: AWS_REGION
              value: {minio_region}
            - name: BUCKET_NAME
              value: {mnist_bucket}
            - name: S3_USE_HTTPS
              value: "0"
            - name: S3_VERIFY_SSL
              value: "0"
            - name: AWS_ACCESS_KEY_ID
              value: {minio_username}
            - name: AWS_SECRET_ACCESS_KEY
              value: {minio_key}
            image: {image}
            workingDir: /opt
          restartPolicy: OnFailure
    Chief:
      replicas: 1
      template:
        metadata:
          annotations:
            sidecar.istio.io/inject: "false"
        spec:
          serviceAccount: default-editor
          containers:
          - name: tensorflow
            command:
            - python
            - /opt/model.py
            - --tf-model-dir={model_dir}
            - --tf-export-dir={export_path}
            - --tf-train-steps={train_steps}
            - --tf-batch-size={batch_size}
            - --tf-learning-rate={learning_rate}
            env:
            - name: S3_ENDPOINT
              value: {s3_endpoint}
            - name: AWS_ENDPOINT_URL
              value: {minio_endpoint}
            - name: AWS_REGION
              value: {minio_region}
            - name: BUCKET_NAME
              value: {mnist_bucket}
            - name: S3_USE_HTTPS
              value: "0"
            - name: S3_VERIFY_SSL
              value: "0"
            - name: AWS_ACCESS_KEY_ID
              value: {minio_username}
            - name: AWS_SECRET_ACCESS_KEY
              value: {minio_key}
            image: {image}
            workingDir: /opt
          restartPolicy: OnFailure
    Worker:
      replicas: 1
      template:
        metadata:
          annotations:
            sidecar.istio.io/inject: "false"
        spec:
          serviceAccount: default-editor
          containers:
          - name: tensorflow
            command:
            - python
            - /opt/model.py
            - --tf-model-dir={model_dir}
            - --tf-export-dir={export_path}
            - --tf-train-steps={train_steps}
            - --tf-batch-size={batch_size}
            - --tf-learning-rate={learning_rate}
            env:
            - name: S3_ENDPOINT
              value: {s3_endpoint}
            - name: AWS_ENDPOINT_URL
              value: {minio_endpoint}
            - name: AWS_REGION
              value: {minio_region}
            - name: BUCKET_NAME
              value: {mnist_bucket}
            - name: S3_USE_HTTPS
              value: "0"
            - name: S3_VERIFY_SSL
              value: "0"
            - name: AWS_ACCESS_KEY_ID
              value: {minio_username}
            - name: AWS_SECRET_ACCESS_KEY
              value: {minio_key}
            image: {image}
            workingDir: /opt
          restartPolicy: OnFailure
"""
3.提交作业

kubectl apply -f mnist.yaml

参考文献

[1] 华为云CCE kubeflow on volcano文档
[2] kfctl v1.0.2
[3] kubeflow on k8s 官方文档
[4] 机器学习场景下,Volcano集成调度能力实践
0 条回应