k8s volcano + deepspeed多机练习 + RDMA ROCE+ 用户权限安全方案【发起收 ...

打印 上一主题 下一主题

主题 834|帖子 834|积分 2502

目录
一、k8s情况配置
1.安装gpu-operator
2. 安装 rdma-shared-plugin
3. 安装volcano调度器
4. 创建research rbac认证
 二、宿主机情况配置
1. 安装docker 客户端
2. 创建系统用户
3. 修改docker /etc/docker/daemon.json 文件如下
4. 修改系统 /etc/subuid 和subgid
5. 设置cuda情况
6. 安装conda情况
三、制作基于deepspeed的基础镜像
1. Dockerfile
2. ssh_config  
3. sshd_config
4. start.sh
 四、k8s yaml文件


前提:nvidia、cuda、nvidia-fabricmanager等相关的组件已经在宿主机正确安装,如果没有安装可以参考我之前发的文章
GPU A800 A100系列NVIDIA情况和PyTorch2.0基础情况配置【发起收藏】_a800多卡运行情况配置-CSDN博客文章浏览阅读1.1k次,点赞8次,收藏16次。Ant系列GPU支持 NvLink & NvSwitch,若您利用多GPU卡的机型,需额外安装与驱动版本对应的nvidia-fabricmanager服务使GPU卡间能够互联,否则大概无法正常利用GPU实例。【摘要】 Nvidia A系列裸金属服务器安装NVIDIA和CUDA驱动,安装conda和pytorch2.0并验证cuda的有效性。选择安装情况相关版本: GPU驱动版本为530.30.02、CUDA版本为12.1.0。留意事项: 不能选择Driver, 否则会覆盖已安装的NVIDIA驱动._a800多卡运行情况配置
https://blog.csdn.net/weixin_43798031/article/details/136853839?spm=1001.2014.3001.5501
一、k8s情况配置

1.安装gpu-operator

利用官方的helm chart举行安装 gpu-operator-v24.3.0.tgz
  1. # 创建namespace
  2. kubectl  create  ns gpu-operator
  3. # 下载chart
  4. wget https://github.com/NVIDIA/gpu-operator/releases/download/v24.3.0/gpu-operator-v24.3.0.tgz
  5. # 解压
  6. tar xf gpu-operator-v24.3.0.tgz
  7. # 其中有一些插件是可选择的,可以根据环境的情况进行修改
  8. # 安装
  9. helm isntall -f values.yaml  gpu-operator -n gpu-operator
复制代码

2. 安装 rdma-shared-plugin

特此说明一下,这篇文章用的是RDMA ROCE方案,采用的宿主机网络模式所以下面的这个插件可以选择性的安装,
  1. k8s-rdma-shared-dev-plugin-config-map.yaml
复制代码
  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4.   name: rdma-devices
  5.   namespace: kube-system
  6. data:
  7.   config.json: |
  8.     {
  9.         "periodicUpdateInterval": 300,
  10.         "configList": [
  11.            {
  12.              "resourceName": "shared_ibs",
  13.              "rdmaHcaMax": 1000,
  14.              "selectors": {
  15.                "ifNames": ["GPU0", "GPU1", "GPU2", "GPU3"]  #根据实际的ib网卡名称修改
  16.              }
  17.            }
  18.         ]
  19.     }
复制代码
  1. k8s-rdma-shared-dev-plugin-ds.yaml
复制代码
  1. apiVersion: apps/v1
  2. kind: DaemonSet
  3. metadata:
  4.   name: rdma-shared-dp-ds
  5.   namespace: kube-system
  6. spec:
  7.   selector:
  8.     matchLabels:
  9.       name: rdma-shared-dp-ds
  10.   template:
  11.     metadata:
  12.       labels:
  13.         name: rdma-shared-dp-ds
  14.     spec:
  15.       hostNetwork: true
  16.       priorityClassName: system-node-critical
  17.       containers:
  18.       - image: mellanox/k8s-rdma-shared-dev-plugin
  19.         name: k8s-rdma-shared-dp-ds
  20.         imagePullPolicy: IfNotPresent
  21.         securityContext:
  22.           privileged: true
  23.         volumeMounts:
  24.           - name: device-plugin
  25.             mountPath: /var/lib/kubelet/
  26.           - name: config
  27.             mountPath: /k8s-rdma-shared-dev-plugin
  28.           - name: devs
  29.             mountPath: /dev/
  30.       volumes:
  31.         - name: device-plugin
  32.           hostPath:
  33.             path: /var/lib/kubelet/
  34.         - name: config
  35.           configMap:
  36.             name: rdma-devices
  37.             items:
  38.             - key: config.json
  39.               path: config.json
  40.         - name: devs
  41.           hostPath:
  42.             path: /dev/
复制代码
  1. 测试是否安装成功,登陆到容器中查看ib网卡
  2. rdma-test-pod.yaml
复制代码
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4.   name: mofed-test-pod
  5. spec:
  6.   restartPolicy: OnFailure
  7.   containers:
  8.   - image: mellanox/rping-test
  9.     name: mofed-test-ctr
  10.     securityContext:
  11.       capabilities:
  12.         add: [ "IPC_LOCK" ]
  13.     resources:
  14.       limits:
  15.         rdma/shared_ibs: 1
  16.     command:
  17.     - sh
  18.     - -c
  19.     - |
  20.       ls -l /dev/infiniband /sys/class/infiniband /sys/class/net
  21.       sleep 1000000
复制代码
3. 安装volcano调度器

相关的部署文件在这里,具体的调度规则各人可以根据实际的情况去配置,第一次打仗volcano的同砚大概要增加一些学习成本
https://download.csdn.net/download/weixin_43798031/89397746
https://download.csdn.net/download/weixin_43798031/89397746
  1. kubectl  apply -f volcano-development.yaml
  2. #测试一下
  3. kubectl  apply -f  test-job.yaml
  4. apiVersion: batch.volcano.sh/v1alpha1
  5. kind: Job
  6. metadata:
  7.   name: test-job4
  8. spec:
  9.   minAvailable: 1
  10.   schedulerName: volcano
  11.   policies:
  12.     - event: PodEvicted
  13.       action: RestartJob
  14.   plugins:
  15.     ssh: []
  16.     env: []
  17.     svc: []
  18.   maxRetry: 5
  19.   queue: default
  20.   tasks:
  21.     - name: "postproc"
  22.       replicas: 1
  23.       template:
  24.         metadata:
  25.           name: postproc
  26.         spec:
  27.           containers:
  28.             - image: nginx
  29.               imagePullPolicy: IfNotPresent
  30.               name: postproc
  31.               resources:
  32.                 requests:
  33.                   cpu: "1"
  34.           restartPolicy: OnFailure
  35.     - name: "agent"
  36.       replicas: 1
  37.       template:
  38.         metadata:
  39.           name: agent
  40.         spec:
  41.           containers:
  42.             - image: nginx
  43.               imagePullPolicy: IfNotPresent
  44.               name: agent
  45.               resources:
  46.                 requests:
  47.                   cpu: "1"
  48.           restartPolicy: OnFailure
复制代码
4. 创建research rbac认证

可以参考我的这篇文章
k8s rbac 权限管理控制创建过程+理论知识_子账号无权限执行kubectl config get-contexts命令-CSDN博客
  1. openssl genrsa -out research.key 2048
  2. opensopenssl req -new -key research.key -out research.csr -subj "/CN=research/O=default"
  3. openssl x509 -req -in research.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out research.crt -days 3650
  4.    
  5. kubectl config set-credentials research --client-certificate=research.crt --client-key=research.key
  6.    
  7. kubectl config set-context research-context --cluster=kubernetes --namespace=default --user=research --kubeconfig=research.conf
  8. 切到research-context 用户上下文
  9. kubectl config use-context research-context
  10. 显示当前上下文
  11. kubectl config get-contexts
  12. 切回admin
  13. kubectl config use-context kubernetes-admin@kubernetes
复制代码
 二、宿主机情况配置

1. 安装docker 客户端

由于我们已经利用containerd 为runtime,
2. 创建系统用户

  1. # 创建research用户并指定uid和gid, 指定uid和gid时一定要选择一个没有占用的,因为我们要在每台机器都要指定
  2. ansible -i ip.txt all -m shell -a 'sudo useradd -m -s /bin/bash -u 2000 -g 2000 research'
  3. # 将research用户加入到docker 组,这样research 用户就可以使用docker命令了
  4. ansible -i ip.txt all -m shell -a 'sudo usermod -aG docker research'
  5. # 创建.kube目录
  6. ansible -i ip.txt all -m shell -a 'mkdir /home/research/.kube/'
  7. # 将上面的k8s config 发送到每台机器
  8. ansible -i ip.txt  all -m copy -a 'src=/home/sunwenbo/rbac/research.conf dest=/home/research/.kube/config'
  9. # 修改权限
  10. ansible -i ip.txt all -m shell -a 'chown -R research:research /home/research/.kube/'
复制代码
3. 修改docker /etc/docker/daemon.json 文件如下

平凡用户启动docker 挂载宿主机目录,如果容器利用的root用户,则输出的文件权限为root,那么平凡用户在宿主机则无法读取和利用则会有问题
 
  1. {
  2.   "userns-remap": "research",   
  3.   "max-concurrent-downloads": 10,
  4.   "log-driver": "json-file",
  5.   "log-level": "warn",
  6.   "log-opts": {
  7.     "max-size": "10m",
  8.     "max-file": "5"
  9.     },
  10.   "data-root": "/var/lib/data/docker",
  11.   "exec-opts": ["native.cgroupdriver=systemd"],
  12.   "registry-mirrors": ["https://uyah70su.mirror.aliyuncs.com"],
  13.   "insecure-registries": [ "a800-harbor.bigmodel.cn"],
  14.   "storage-driver": "overlay2",
  15.   "storage-opts": [
  16.     "overlay2.override_kernel_check=true"
  17.   ]
  18. }
复制代码
 配置说明: "userns-remap": "research",   这个配置代表Docker将会利用research用户和组举行用户定名空间映射,说白了就是将系统的research用户映射到容器里,但是这么设置会有一个问题就是root导入到镜像大概是容器就看不到了。
4. 修改系统 /etc/subuid 和subgid

每台机器都要修改research的uid为2000
research:2000:65536
  1. ansible -i ip.txt all -m shell -a "sed  -i  's/^research:[0-9]\+:65536/research:2000:65536/' /etc/subuid"
  2. ansible -i ip.txt all -m shell -a "sed  -i  's/^research:[0-9]\+:65536/research:2000:65536/' /etc/subgid"
复制代码
简单描述一下3,4步骤,重要目标就是为了解决当启动一个容器挂载宿主机数据时解决文件权限的问题。通过3,4的设置我们在容器中产生的数据的权限会保持为research
5. 设置cuda情况

playbook
update_baashrc.yml
  1. - name: Update .bashrc for research user
  2.   hosts: all
  3.   become: yes
  4.   tasks:
  5.     - name: Ensure the CUDA paths are added to .bashrc
  6.       blockinfile:
  7.         path: /home/research/.bashrc
  8.         block: |
  9.           export PATH=$PATH:/usr/local/cuda-12.1/bin
  10.           export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda-12.1/lib64
  11.           export LIBRARY_PATH=$LIBRARY_PATH:/usr/local/cuda-12.1/lib64
  12.         insertafter: EOF
  13.       become_user: research
复制代码
  1. # 执行命令
  2. ansible-playbook  -i ip.txt  update_baashrc.yml
复制代码
6. 安装conda情况

install_conda.yml
  1. ---
  2. - name: Install Miniconda for research user
  3.   hosts: all  # 这里可以替换为你的目标主机组,比如具体的IP地址或者其他定义的组名
  4.   become: true  # 使用sudo进行安装
  5.   tasks:
  6.     - name: Install Miniconda for research user
  7.       become_user: research  # 切换到research用户进行安装
  8.       shell: "/home/bmm-system/data/private/sunwenbo/env-install/Miniconda3-py310_23.1.0-1-Linux-x86_64.sh -b -p /home/research/miniconda3"
  9.       args:
  10.         executable: /bin/bash
  11.       environment:
  12.         PATH: "/home/research/miniconda3/bin:{{ ansible_env.PATH }}"
  13.     - name: Add Conda binaries to PATH for research user
  14.       become_user: research
  15.       lineinfile:
  16.         dest: /home/research/.bashrc
  17.         line: 'export PATH="/home/research/miniconda3/bin:$PATH"'
  18.         create: yes
  19.     - name: Source .bashrc for research user
  20.       become_user: research
  21.       shell: source /home/research/.bashrc
复制代码
  1. ansible-playbook  -i ip.txt  install_conda.yml
复制代码

三、制作基于deepspeed的基础镜像

所必要的文件
  1. Dockerfile  ssh  ssh_config  sshd_config  start.sh
  2. ./ssh:
  3. authorized_keys  id_rsa  id_rsa.pub  known_hosts  known_hosts.old
复制代码
文件说明:
Dockerfile:制作镜像
ssh: 我们必要提前创建好公钥和私钥并下发给集群的每台机器,实现可以免密ssh登陆
ssh_config:  镜像中sshd服务的客户端配置文件,必要指定连接时利用的默认端口和关闭登录时验证
sshd_config: 镜像中sshd服务的服务端配置文件, 必要修改默认端口
start.sh: 镜像启动脚本


1. Dockerfile


research用户说明:
思量到安全问题,由于我们在gpu服务器上同时部署了共享存储Glusterfs,我们的每台机器只对算法开放平凡用户权限。
过程中遇到利用k8s时启动练习任务由于挂载了宿主机共享存储的数据,而容器中默认情况下利用的都是root用户,这个时候就会导致练习输出的产物权限变为了root。 系统用户research 则没有权限去对这个文件举行操纵
  1. # 使用基础镜像
  2. FROM nvcr.io/nvidia/pytorch:23.12-py3
  3. # 创建research用户并设置密码
  4. RUN groupadd -g 2000 research && \
  5.     useradd -m -u 2000 -g 2000 -s /bin/bash research
  6. # COPY start script
  7. COPY start.sh /start.sh
  8. #COPY ssh config to /etc/ssh
  9. COPY ssh /home/research/.ssh/
  10. # Install SSH server
  11. RUN apt-get update && apt-get install -y --no-install-recommends openssh-server ssh net-tools pdsh && \
  12.     apt-get clean && \
  13.     chown -R root:root /usr/lib && \
  14.     chown -R research:research /home/research/.ssh && \
  15.     rm -rf /var/lib/apt/lists/* && \
  16.     chmod 600 /home/research/.ssh/authorized_keys && \
  17.     chmod 700 /home/research/.ssh && \
  18.     mkdir /var/run/sshd
  19. # 安装deepspeed
  20. RUN pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple && \                                                                                                      
  21.     pip install deepspeed && \                                                                                                                                                         
  22.     pip install tiktoken && \                                                                                                                                                         
  23.     pip install lmdb  && \                                                                                                                                                         
  24.     pip install sentencepiece   
  25. # 设置环境变量,指定时区
  26. ENV TZ=Asia/Shanghai \
  27.     DEBIAN_FRONTEND=noninteractive
  28. ENV CUDA_DEVICE_MAX_CONNECTIONS="1"
  29. RUN apt update \
  30.     && apt install -y tzdata \
  31.     && ln -fs /usr/share/zoneinfo/${TZ} /etc/localtime \
  32.     && echo ${TZ} > /etc/timezone \
  33.     && dpkg-reconfigure --frontend noninteractive tzdata \
  34.     && rm -rf /var/lib/apt/lists/*
  35. COPY ssh_config sshd_config /etc/ssh/
  36. EXPOSE 2222
  37. CMD ["/start.sh"]
复制代码
2. ssh_config  

  1. Include /etc/ssh/ssh_config.d/*.conf
  2. Host *
  3.     StrictHostKeyChecking no
  4.     Port 2222
  5.     SendEnv LANG LC_*
  6.     HashKnownHosts yes
  7.     GSSAPIAuthentication yes
复制代码
3. sshd_config

  1. Include /etc/ssh/sshd_config.d/*.conf
  2. Port 2222
  3. KbdInteractiveAuthentication no
  4. UsePAM yes
  5. X11Forwarding yes
  6. PrintMotd no
  7. AcceptEnv LANG LC_*
  8. Subsystem       sftp    /usr/lib/openssh/sftp-server
复制代码
4. start.sh

  1. #!/bin/bash
  2. # Start the SSH server
  3. /usr/sbin/sshd -D
  4. # 执行传入的命令
  5. exec "$@"
复制代码
执行docker build后我们会得到一个镜像
  1. docker build -t xxx.service.xxx.cn/xxx/xxx-base:v2 .
复制代码
备注:根据docker 可以看到我们创建了一个research用户,当开始练习时我们必要利用research 用户去连接其他机器。同时必要做到免密登陆和认证 。另外

 四、k8s yaml文件

  1. apiVersion: batch.volcano.sh/v1alpha1
  2. kind: Job
  3. metadata:
  4.   name: xxxxxx  #可以修改名字,防止跟别人冲突导致K8S Pod无法启动
  5.   namespace: default
  6. spec:
  7.   minAvailable: 5
  8.   schedulerName: volcano
  9.   policies:
  10.     - event: PodFailed
  11.       action: TerminateJob
  12.     - event: PodEvicted
  13.       action: TerminateJob
  14.     - event: TaskFailed
  15.       action: TerminateJob
  16.     - event: TaskCompleted
  17.       action: CompleteJob
  18.   plugins:
  19.     env: []
  20.     svc: []
  21.   maxRetry: 5
  22.   queue: default
  23.   ttlSecondsAfterFinished: 10
  24.   tasks:
  25.     - name: "main"
  26.       replicas: 1
  27.       template:
  28.         metadata:
  29.           name: training
  30.         spec:
  31.           securityContext:
  32.             runAsUser: 2000   # research 用户的 UID
  33.             fsGroup: 2000     # research 用户的 GID
  34.           volumes:
  35.             - name: dshm
  36.               emptyDir:
  37.                 medium: Memory
  38.                 sizeLimit: 50Gi
  39.             - name: xxx-code-path
  40.               hostPath:
  41.                 path: /home/bmm-system/data/private/xxx   #挂载代码路径
  42.                 type: Directory
  43.           containers:
  44.             - name: main
  45.               image: xxx.service.xxx.cn/delivery/xxxx:v2.1
  46.                 #imagePullPolicy: IfNotPresent
  47.               imagePullPolicy: Always
  48.               securityContext:
  49.                 capabilities:
  50.                   add:
  51.                   - IPC_LOCK
  52.               volumeMounts:
  53.                 - name: dshm
  54.                   mountPath: /dev/shm
  55.                 - name: xxx-code-path
  56.                   mountPath: /home/bmm-system/data/private/xxx    #挂载代码路径
  57.                     #args: ["/bin/sh", "-c", "cd xxxx"]  #执行的命令
  58.               args: ["/bin/sh", "-c", "sleep 600000"]  # 根据实际运行命令去做修改
  59.               env:
  60.                 - name: NODE_NAME
  61.                   valueFrom:
  62.                     fieldRef:
  63.                       fieldPath: spec.nodeName
  64.                 - name: NODE_IP
  65.                   valueFrom:
  66.                     fieldRef:
  67.                       fieldPath: status.hostIP
  68.                 - name: TRITON_CACHE_DIR
  69.                   value: "/tmp/.triton"
  70.           restartPolicy: OnFailure
  71.           imagePullSecrets:
  72.           - name: xxx-registry
  73.     - name: "worker"
  74.       replicas: 4    #副本数,也就是训练所需要的节点数
  75.       template:
  76.         metadata:
  77.           name: training
  78.         spec:
  79.           hostNetwork: true  # 采用宿主机网络模式
  80.           affinity:
  81.             nodeAffinity:
  82.               requiredDuringSchedulingIgnoredDuringExecution:
  83.                 nodeSelectorTerms:
  84.                 - matchExpressions:
  85.                   - key: TrainingMachine
  86.                     operator: In
  87.                     values: ["5", "6", "7", "8"]        #制定训练用的节点,A800的10台机器按照1,2...10来指定
  88.           volumes:
  89.             - name: dshm
  90.               emptyDir:
  91.                 medium: Memory
  92.                 sizeLimit: 50Gi
  93.             - name: user-root
  94.               hostPath:
  95.                 path: /home/bmm-system/data/private/xxxx   #宿主机挂载路径,指定数据所在位置
  96.                 type: Directory
  97.             - name: xxx-ckpt-path
  98.               hostPath:
  99.                 path: /home/bmm-system/data/ckpt   #宿主机挂载路径,指定到权重所在位置
  100.                 type: Directory
  101.           containers:
  102.             - name: worker
  103.               image: xxx.service.xxx.cn/delivery/xxx-base:v2.1
  104.                 #imagePullPolicy: IfNotPresent
  105.               imagePullPolicy: Always
  106.               securityContext:
  107.                 capabilities:
  108.                   add:
  109.                   - IPC_LOCK
  110.               volumeMounts:
  111.                 - name: dshm
  112.                   mountPath: /dev/shm
  113.                 - name: user-root
  114.                   mountPath: /home/bmm-system/data/private/xxx   #宿主机挂载路径,指定数据所在位置
  115.                 - name: xxx-ckpt-path
  116.                   mountPath: /home/bmm-system/data/ckpt   #宿主机挂载路径,指定到权重所在位置
  117.                   readOnly: true
  118.               command: ["/bin/bash"]
  119.               args: ["-c", "/start.sh"]
  120.               env:
  121.                 - name: NODE_NAME
  122.                   valueFrom:
  123.                     fieldRef:
  124.                       fieldPath: spec.nodeName
  125.                 - name: NODE_IP
  126.                   valueFrom:
  127.                     fieldRef:
  128.                       fieldPath: status.hostIP
  129.                 - name: TRITON_CACHE_DIR
  130.                   value: "/tmp/.triton"
  131.               resources:
  132.                 requests:
  133.                   nvidia.com/gpu: 8
  134.                 limits:
  135.                   nvidia.com/gpu: 8
  136.           restartPolicy: OnFailure
  137.           imagePullSecrets:
  138.           - name: xxx-registry
复制代码
说明:
1. 可以看到该yaml中在main pod 指定了research的uid和gid,即代表利用该用户去启动练习任务       
runAsUser: 2000   # research 用户的 UID
fsGroup: 2000     # research 用户的 GID
如许就可以解决挂载数据权限的问题和上面docker启动容器遇到的问题同理。

2. 还有一个配置得说明一下就是env中的
- name: TRITON_CACHE_DIR
  value: "/tmp/.triton"
由于利用了deepspeed 框架,在启动练习任务时框架内部逻辑会在当前目录下创建一些临时的隐蔽文件,而我们不必要对这些文件举行存储个人发起将这个目录修改为/tmp下。如许当练习任务结束后这个文件就会自动被清理

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

曹旭辉

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表