2. 版本申明

版本

修改内容

修改时间

v1.0

初始化

8/15/2022

v1.1

格式调整

9/1/2022

v1.2

更新一些格式以及内容

4/17/2024

v1.3

更新一些格式以及内容

8/8/2024

v1.4

更新efsmi支持版本

11/8/2024

v1.5

更新一些内容

12/5/2024

3. 简介

3.1. 背景

Kubernetes基础设施使用GCU设备时,是不支持多个pod共享GCU的,这样可以实现更好的隔离,保证每个应用的GCU使用不受其它应用的影响,非常适合深度学习模型训练。但是对于想要提高集群中GCU利用率的用户来说,这样通常会造成GCU资源的浪费。比如:

  • 作为集群管理员,在开发过程中,允许多个用户在同一个GCU上共享同一个模型开发环境,以增加集群的GCU使用率。

  • 作为一名应用操作员,希望能够同时在同一个GCU上运行多个推理任务。

针对这些场景,就需要实现GCU设备的共享功能,以满足特定场景下的用户需求。

3.2. 前置依赖

  • efsmi

3.3. 查看版本号

1)执行./gcushare-device-plugin --version,即可查看gcushare-device-plugin版本号;

2)执行./gcushare-scheduler-extender --version, 即可查看gcushare-scheduler-extender版本号;

3)执行./gcushare-config-manager --version, 即可查看gcushare-config-manager版本号。

3.4. GCUShare主要组件

GCUShare通过gcushare-scheduler-extender+gcushare-device-plugin这两个组件实现GCU设备的共享。

1)gcushare-scheduler-extender:共享GCU的扩展调度器,主要负责根据用户的资源请求(enflame.com/gcu-memory字段),计算可调度的节点,并分配GCU设备。

2)gcushare-device-plugin:共享GCU的k8s设备插件,主要负责向kubelet注册enflame.com/gcu-memory资源,并负责实际的GCU设备分配工作。

3)gcushare-config-manager:对接默认调度器的模块,主要负责修改默认调度器的配置,以对接扩展调度器gcushare-scheduler-extender。

3.5. GCUShare功能概要

1)GCUShare依赖于EFML(Enflame Management Library)来获取Enflame GCU的显存信息;

2)GCUShare作为扩展调度程序,将会修改k8s集群的默认调度器配置,但这并不会入侵原有的调度程序。并且GCUShare组件卸载后,将会自动恢复默认的配置信息;

3)按显存(GCU Memory)和按卡(GCU count)调度的方式不可以在集群内并存;

4)GCUShare只支持调度级别的GCU设备共享,暂不支持共享GCU显存资源的隔离。需要用户应用在代码中配置该任务可使用的GCU显存大小;

5)GCUShare依赖于enflame gcu driver和enflame gcu container toolkit,部署GCUShare组件前,必须按顺序部署好这两个依赖组件(gcu-operator2.0已支持GCUShare组件和依赖组件的一键部署);

6)GCUShare提供了inspect接口,用户可以访问该接口来查询集群所有共享GCU的使用情况,从而对整体资源的使用有一个初步的判断;

7)GCUShare不仅支持以显存GB粒度(默认模式)共享GCU,也支持以显存0.1GB粒度共享GCU;

8)通常组件日志都存储在容器中,一旦容器重启或组件卸载,很容易造成日志丢失。GCUShare组件的日志采用本地持久化存储方式,用户可通过日志自行定位问题;

9)GCUShare支持由用户指定部分节点共享GCU。

3.6. GCUShare Chart说明

Chart 是 Helm 的应用打包格式。gcushare 的 chart 由一系列文件组成,这些文件描述了 Kubernetes 部署gcushare应用时所需要的资源,比如 Service、Deployment、Role等。chart 将这些文件放置在预定义的目录结构中,便于 Helm 部署。GCUShare chart 的目录结构以及包含的各类文件如下:

gcushare_<VERSION>/
gcushare-device-plugin/deployments/gcushare-device-plugin-chart/
├── Chart.yaml
├── templates
│   ├── clusterrolebinding.yaml
│   ├── clusterrole.yaml
│   ├── daemonset.yaml
│   └── serviceaccount.yaml
└── values.yaml

gcushare-scheduler-extender/deployments/gcushare-scheduler-extender-chart/
├── Chart.yaml
├── templates
│   ├── clusterrolebinding.yaml
│   ├── clusterrole.yaml
│   ├── daemonset-config-manager.yaml
│   ├── deployment.yaml
│   ├── serviceaccount.yaml
│   └── service.yaml
└── values.yaml

注意:使用chart部署gcushare,依赖于主机上安装有helm组件。在部署过程中,如果helm不存在,部署脚本将直接使用kubectl命令进行部署。

4. 安装GCUShare组件

安装说明:

  • gcushare-scheduler-extender组件依赖于gcushare-device-plugin组件,因此需要先安装gcushare-device-plugin组件;

  • 环境提前安装好k8s,docker,helm3,enflame driver,enflame docker等组件。

本手册所使用测试环境安装了单节点k8s集群。我们称该节点为节点1,下文同。

4.1. 制作gcushare组件镜像

镜像构建工具由”build-image.conf+build-image.sh” 组成,用户可以根据需要修改”build-image.conf”里的内容满足定制化需求, 然后执行 “build-image.sh” 生成容器镜像,基本过程如下:

1)镜像配置文件定制

“build-image.conf”内容如下,用户可以根据实际需要自行完成内容修改:

# Currently supports ubuntu, tlinux, openeuler
OS="ubuntu"

# Currently supports docker, ctr, podman, nerdctl
CLI_NAME="docker"

# The repository name
REPO_NAME="artifact.enflame.cn/enflame_docker_images/enflame"

# The image name
IMAGE_NAME="gcushare-device-plugin"  # IMAGE_NAME="gcushare-scheduler-extender"

# The image tag
TAG="latest"

# The namespace used by nerdctl, ctr
NAMESPACE="k8s.io"

2)镜像构建

“build-image.sh” 使用说明如下:

# ./build-image.sh -h
Usage: ./build-image.sh [OPTIONS]...
Description: This script is used to build and save images.

Options:
  --os        Specify the operating system for the image. \
              Currently supports "ubuntu, tlinux and openeuler", default: "ubuntu".
  --cli       Specify the CLI tool for building the image. \
              Currently supports "docker, ctr, podman and nerdctl", default: "docker".
  --repo      Specify the repository for the image that will be built, \
              default: "artifact.enflame.cn/enflame_docker_images/enflame".
  --name      Specify the name of the image that will be built, \
              default: "gcu-feature-discovery".
  --tag       Specify the tag for the image that will be built, default: "latest".
  --namespace Specify the namespace for the image that will be built by \
              nerdctl and ctr, default: "k8s.io".

Examples:
  ./build-image.sh
  ./build-image.sh --cli podman --os ubuntu
  ./build-image.sh --cli nerdctl --os openeuler
  ./build-image.sh --cli ctr --os ubuntu

用户在完成”build-image.conf”里的内容定制化需求后,可以直接执行 “build-image.sh” 生成容器镜像:

# 默认 CLI: docker, OS: ubuntu
./build-image.sh

对于k8s version >=1.24,推荐采用 nerdctl 或 ctr构建:

./build-image.sh --cli nerdctl
或
./build-image.sh --cli ctr

制作gcushare-device-plugin镜像

切换到gcushare-device-plugin安装包目录下,构建镜像:

# 默认 CLI: docker, OS: ubuntu
./build-image.sh

对于k8s version >=1.24,推荐采用 nerdctl 或 ctr构建。

镜像制作成功后,将会自动载入当前节点,并把镜像包保存到images目录下:

# docker images|grep gcus
artifact.enflame.cn/enflame_docker_images/enflame/gcushare-device-plugin   \
latest              8bda9bbd85ea        3 minutes ago       140MB

# ll images/
total 139992
drwxrwxr-x 2 root root      4096 10月 12 16:16 ./
drwxrwxr-x 6 root root      4096 10月 12 15:42 ../
-rw------- 1 root root 143343616 10月 12 16:16 gcushare-device-plugin.tar

也可以指定需要构建的OS镜像,如:

# ubuntu
./build-image.sh --os ubuntu
# tlinux
./build-image.sh --os tlinux

制作gcushare-scheduler-extender镜像

切换到gcushare-scheduler-extender的安装包目录下,构建镜像:

# 默认 CLI: docker, OS: ubuntu
./build-image.sh

对于k8s version >=1.24,推荐采用 nerdctl 或 ctr构建。

镜像制作成功后,将会自动载入当前节点,并把镜像包保存到images目录下:

gcushare-scheduler-extender_{VERSION} # docker images|grep gcus
artifact.enflame.cn/enflame_docker_images/enflame/gcushare-scheduler-extender   \
latest              ba7540816cdc        38 seconds ago      130MB
artifact.enflame.cn/enflame_docker_images/enflame/gcushare-device-plugin        \
latest              8bda9bbd85ea        4 minutes ago       140MB

gcushare-scheduler-extender_{VERSION} # ll images/
total 130400
drwxrwxr-x 2 root root      4096 10月 12 16:21 ./
drwxrwxr-x 5 root root      4096 10月 12 15:41 ../
-rw------- 1 root root 133517824 10月 12 16:21 gcushare-scheduler-extender.tar

制作gcushare-config-manager镜像

切换到config-manager的目录下,直接构建镜像:

gcushare-scheduler-extender_{VERSION}/config-manager # ./build-image.sh

镜像制作成功后,将会自动载入当前节点,并把镜像包保存到images目录下:

gcushare-scheduler-extender_{VERSION} # docker images|grep gcus
artifact.enflame.cn/enflame_docker_images/enflame/gcushare-scheduler-extender   \
latest              ba7540816cdc        38 seconds ago      130MB
artifact.enflame.cn/enflame_docker_images/enflame/gcushare-device-plugin        \
latest              8bda9bbd85ea        4 minutes ago       140MB
artifact.enflame.cn/enflame_docker_images/enflame/gcushare-config-manager       \
1.2.2           de1cd9409997   7 days ago           106MB


gcushare-scheduler-extender_{VERSION} # ll images/
total 130400
drwxrwxr-x 2 root root      4096 10月 12 16:21 ./
drwxrwxr-x 5 root root      4096 10月 12 15:41 ../
-rw------- 1 root root 133517824 10月 12 16:21 gcushare-scheduler-extender.tar
-rw------- 1 root root 108012032 Aug  8  10:30 gcushare-config-manager.tar

4.2. 安装gcushare组件

安装gcushare-device-plugin

gcushare-device-plugin依赖于libefml,因此安装gcushare-device-plugin之前,请检查主机上的libefml存在且可用,检查方法:

gcushare-device-plugin_<VERSION> # ll /usr/lib/libefml.so
lrwxrwxrwx 1 root root 50 Mar  2 02:22 /usr/lib/libefml.so -> \
        /usr/local/efsmi/efsmi-1.14.0/lib/libefml.so.1.0.0*

gcushare-device-plugin组件安装时,支持用户指定要在哪些节点共享GCU设备。声明使用共享GCU资源的pod只会调度到这些节点上。

在gcushare-device-plugin安装包目录下,执行./deploy.sh一键安装gcushare-device-plugin组件。

gcushare-device-plugin_{VERSION} # ./deploy.sh
Try to push component image to enflame repo...
Untagged: artifact.enflame.cn/enflame_docker_images/enflame/gcushare-device-plugin:latest
.......................................

deploy.sh主要做了两件事:

  • 询问并请用户输入需要共享GCU设备的节点名称,并给这些节点自动打上”enflame.com/gcushare”: “true”标签。只有打了该标签的节点才会部署gcushare-device-plugin组件;

  • 使用helm部署gcushare-device-plugin的release。

可以通过查看gcushare-device-plugin的pod信息,来确认gcushare-device-plugin是够运行正常:

# kubectl get pod -A
NAMESPACE        NAME                                       \
READY STATUS  RESTARTS AGE
......
kube-system      gcushare-device-plugin-n6c5w               \
1/1   Running 0        26h
......

再检查下节点的”enflame.com/gcu-count”字段和”enflame.com/gcu-memory”字段是否更新:

# kubectl get node
NAME                 STATUS   ROLES                  AGE   VERSION
sse-lab-inspur-048   Ready    control-plane,master   27h   v1.20.0
gcushare-device-plugin # kubectl describe node sse-lab-inspur-048
......
Capacity:
  cpu:                     80
  enflame.com/gcu-count:   8             # 当前节点有8张gcu卡
  enflame.com/gcu-memory:  128           # 当前节点的gcu总显存为128GB,每张卡为16GB
  ephemeral-storage:       1345603940Ki
  hugepages-1Gi:           0
  hugepages-2Mi:           0
  memory:                  394869612Ki
  pods:                    110
Allocatable:
  cpu:                     80
  enflame.com/gcu-count:   8
  enflame.com/gcu-memory:  128
  ephemeral-storage:       1240108589051
  hugepages-1Gi:           0
  hugepages-2Mi:           0
  memory:                  394767212Ki
  pods:                    110

安装gcushare-scheduler-extender组件

在gcushare-scheduler-extender安装包目录下,执行./deploy.sh一键安装gcushare-scheduler-extender组件:

gcushare-scheduler-extender_{VERSION} # ./deploy.sh
Try to push component image to enflame repo...
Untagged: artifact.enflame.cn/enflame_docker_images/enflame/ \
        gcushare-scheduler-extender:latest
.....................................

deploy.sh主要做了一件事:

  • 使用helm部署gcushare-scheduler-extender的release。

同样的,我们可以通过查询pod确定gcushare-scheduler-extender运行正常:

gcushare-scheduler-extender/deployments # kubectl get pod -A
NAMESPACE        NAME                                        \
READY STATUS  RESTARTS AGE
......
kube-system      gcushare-device-plugin-n6c5w                \
1/1   Running 0        26h
kube-system      gcushare-scheduler-extender-9b57bd745-rxd6r \
1/1   Running 0        26h
kube-system      kube-scheduler-sse-lab-inspur-048           \
1/1   Running 0        26h
......

我们也可以通过简单的接口访问来测试下组件是否能正常提供服务:

# kubectl get svc -A|grep gcushare-scheduler-extender
kube-system        gcushare-scheduler-extender       ClusterIP   \
10.96.1.37     <none>        32766/TCP                106s

# curl 10.96.1.37:32766/version
v1.0.0

gcushare-scheduler-extender组件使用service转发访问,目标端口为32766。访问上述URL,将会返回gcushare-scheduler-extender版本号信息,说明组件正常运行。

5. 使用共享GCU

使用共享GCU需要在容器内编排”enflame.com/gcu-memory”字段,示例:

{
    "apiVersion": "v1",
    "kind": "Pod",
    "metadata": {
        "name": "gcushare-pod-1",
        "namespace": "kube-system"
    },
    "spec": {
        "containers": [{
            "resources": {
                "limits": {
                    "enflame.com/gcu-memory": 4   # 声明申请共享GCU,使用4个共享GCU
                }
            }
        }]
    }
}

注意,“enflame.com/gcu-memory”: 4,表示申请4个共享GCU,实际单位取决于部署gcushare-device-plugin时的共享方式。如果按GB共享(默认共享方式),则4表示申请4GB显存;如果以0.1GB共享,则4表示申请4*0.1GB=0.4GB显存。

5.1. 场景示例

gcushare-device-plugin提供了pod的示例json文件,目录:deployments/example/gcushare-pod.json。以下场景的测试文件均为基于该模板修改。

1)部署一个pod,使用4GB内存,pod可以正常运行

blueprints # kubectl create -f gcushare-pod-1.json
pod/gcushare-pod-1 created
blueprints # kubectl get pod -A
NAMESPACE   NAME                                        \
READY STATUS RESTARTS AGE
......
kube-system gcushare-device-plugin-n6c5w                \
1/1   Running 0        27h
kube-system gcushare-pod-1                              \
1/1   Running 0        4s
kube-system gcushare-scheduler-extender-9b57bd745-rxd6r \
1/1   Running 0        27h
blueprints # kubectl exec -it gcushare-pod-1 -n kube-system bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version.
Use kubectl exec [POD] -- [COMMAND] instead.
# ls /dev
core  gcu0  fd  full  mqueue  null  ptmx  pts  random  shm  stderr  stdin  stdout
termination-log  tty  urandom  zero

pod运行正常,并且成功挂载了GCU0。

gcushare-scheduler-extender组件提供了inspect接口可以用来查询集群所有节点的GCU使用情况。使用示例:

inspect.sh <node-name>

其中,node-name为可选参数,为空将输出所有节点的gcu使用信息;否则输出指定节点的gcu使用信息。

gcushare-scheduler-extender_{VERSION} # ./inspect.sh
inspect GCU usage of all nodes from scheduler cache
{
  "nodes": [
        {
            "name": "sse-lab-inspur-048",
            "totalGCU": 128,                # 节点总的GCU显存
            "usedGCU": 4,                   # 已经使用的GCU显存
            "availableGCU": 124,            # 当前节点剩余的总GCU显存
            "devices": [                    # 每个GCU设备的使用情况
                {
                    "id": 0,
                    "totalGCU": 16,         # GCU0卡总显存
                    "usedGCU": 4,           # GCU0卡已使用显存
                    "availableGCU": 12,     # 当前设备剩余的GCU显存
                    "pods": [               # 使用GCU0卡的全部pod信息
                        {
                            "name": "gcushare-pod-1",
                            "namespace": "kube-system",
                            "uid": "2713cdab-6ec7-40be-a0e6-bf144efb0098",
                            "createTime": "2022-09-06T07:40:43Z",
                            "usedGCU": 4
                        }
                    ]
                },
                {
                    "id": 1,
                    "totalGCU": 16,
                    "usedGCU": 0,
                    "availableGCU": 16,
                    "pods": []
                },
                ......
                {
                    "id": 7,
                    "totalGCU": 16,
                    "usedGCU": 0,
                    "availableGCU": 16,
                    "pods": []
                }
            ]
        }
    ]
}

2)再部署一个pod,申请8GB内存,则该pod将优先使用节点1的GCU0卡。

blueprints # kubectl create -f gcushare-pod-1.json
pod/gcushare-pod-1 created
blueprints # kubectl get pod -A
NAMESPACE    NAME                                        \
                    READY STATUS  RESTARTS AGE
......
kube-system  gcushare-device-plugin-n6c5w                \
                    1/1   Running 0        27h
kube-system  gcushare-pod-1                              \
                    1/1   Running 0        4s
kube-system  gcushare-pod-2                              \
                    1/1   Running 0        5s
kube-system  gcushare-scheduler-extender-9b57bd745-rxd6r \
                    1/1   Running 0        27h
blueprints # kubectl exec -it gcushare-pod-2 -n kube-system bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version.
Use kubectl exec [POD] -- [COMMAND] instead.
# ls /dev
core  gcu0  fd  full  mqueue  null  ptmx  pts  random  shm  stderr  stdin  stdout \
termination-log  tty  urandom  zero

可以看到,pod2也成功被调度到了节点1,并绑定了GCU0卡。查看节点的GCU使用信息:

gcushare-scheduler-extender_{VERSION} # ./inspect.sh sse-lab-inspur-048
inspect GCU usage of node sse-lab-inspur-048 from scheduler cache
{
  "nodes": [
        {
            "name": "sse-lab-inspur-048",
            "totalGCU": 128,
            "usedGCU": 12,
            "availableGCU": 116,
            "devices": [
                {
                    "id": 0,
                    "totalGCU": 16,
                    "usedGCU": 12,
                    "availableGCU": 4,
                    "pods": [
                        {
                            "name": "gcushare-pod-1",
                            "namespace": "kube-system",
                            "uid": "2713cdab-6ec7-40be-a0e6-bf144efb0098",
                            "createTime": "2022-09-06T07:40:43Z",
                            "usedGCU": 4
                        },
                        {
                            "name": "gcushare-pod-2",
                            "namespace": "kube-system",
                            "uid": "62b070a4-0c77-4371-adfa-b20b17e90657",
                            "createTime": "2022-09-06T08:28:09Z",
                            "usedGCU": 8
                        }
                    ]
                },
                {
                    "id": 1,
                    "totalGCU": 16,
                    "usedGCU": 0,
                    "availableGCU": 16,
                    "pods": []
                },
                {
                    "id": 2,
                    "totalGCU": 16,
                    "usedGCU": 0,
                    "availableGCU": 16,
                    "pods": []
                },
        ......
}

3)部署第3个pod,申请12G显存,此时尽管GCU0卡仍剩余4GB显存,该pod也无法使用它,因为GCUShare不支持跨卡分配。该pod将使用另一张GCU卡。

blueprints # kubectl create -f gcushare-pod-3.json
pod/gcushare-pod-3 created
blueprints # kubectl get pod -A
NAMESPACE    NAME                                         \
            READY STATUS    RESTARTS AGE
...................................................
kube-system  gcushare-device-plugin-n6c5w                 \
            1/1   Running   0        27h
kube-system  gcushare-pod-1                               \
            1/1   Running   0        4s
kube-system  gcushare-pod-2                               \
            1/1   Running   0        5s
kube-system  gcushare-pod-3                               \
            1/1   Running   0        3s
kube-system  gcushare-scheduler-extender-9b57bd745-rxd6r  \
            1/1   Running   0        27h
blueprints # kubectl exec -it gcushare-pod-3 -n kube-system bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version.
Use kubectl exec [POD] -- [COMMAND] instead.
# ls /dev
core  gcu1  fd  full  mqueue  null  ptmx  pts  random  shm  stderr  stdin  stdout \
termination-log  tty  urandom  zero

可以看到pod3使用了GCU1卡。查看节点GCU使用情况:

gcushare-scheduler-extender_{VERSION} # ./inspect.sh sse-lab-inspur-048
inspect GCU usage of node sse-lab-inspur-048 from scheduler cache
{
  "nodes": [
    {
        "name": "sse-lab-inspur-048",
        "totalGCU": 128,
        "usedGCU": 24,
        "availableGCU": 104,
        "devices": [
            {
                "id": 0,
                "totalGCU": 16,
                "usedGCU": 12,
                "availableGCU": 4,
                "pods": [
                    {
                        "name": "gcushare-pod-1",
                        "namespace": "kube-system",
                        "uid": "2713cdab-6ec7-40be-a0e6-bf144efb0098",
                        "createTime": "2022-09-06T07:40:43Z",
                        "usedGCU": 4
                    },
                    {
                        "name": "gcushare-pod-2",
                        "namespace": "kube-system",
                        "uid": "62b070a4-0c77-4371-adfa-b20b17e90657",
                        "createTime": "2022-09-06T08:28:09Z",
                        "usedGCU": 8
                    }
                ]
            },
            {
                "id": 1,
                "totalGCU": 16,
                "usedGCU": 12,
                "availableGCU": 4,
                "pods": [
                    {
                        "name": "gcushare-pod-3",
                        "namespace": "kube-system",
                        "uid": "b2b0701d-9664-4763-a1eb-5892579bcb7a",
                        "createTime": "2022-09-06T08:33:52Z",
                        "usedGCU": 12
                    }
                ]
            },
            {
                "id": 2,
                "totalGCU": 16,
                "usedGCU": 0,
                "availableGCU": 16,
                "pods": []
            },
    ......
}

4)部署pod4,使用20G显存,此时pod将无法调度到节点,因为GCUShare限定了单个pod最大可申请的显存数为单张整卡。

blueprints # kubectl create -f gcushare-pod-4.json
pod/gcushare-pod-4 created
blueprints # kubectl get pod -A
NAMESPACE    NAME                                        \
            READY STATUS  RESTARTS AGE
...............................
kube-system  gcushare-device-plugin-n6c5w                \
            1/1   Running 0        27h
kube-system  gcushare-pod-1                              \
            1/1   Running 0        4s
kube-system  gcushare-pod-2                              \
            1/1   Running 0        5s
kube-system  gcushare-pod-3                              \
            1/1   Running 0        3s
kube-system  gcushare-pod-4                              \
            0/1   Pending 0        6s # pod无法被调度到节点
kube-system  gcushare-scheduler-extender-9b57bd745-rxd6r \
            1/1   Running 0        27h

查看pod事件,显示单个GCU卡显存不足。

blueprints # kubectl describe pod gcushare-pod-4 -n kube-system
Name:         gcushare-pod-4
Namespace:    kube-system
......
Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  22s   default-scheduler  0/1 nodes are available: \
  1 insufficient GCU Memory in one gcu device.
  Warning  FailedScheduling  22s   default-scheduler  0/1 nodes are available: \
  1 insufficient GCU Memory in one gcu device.

5.2. 以更细粒度共享GCU

GCUShare支持多种GCU共享粒度,分别为1GB(默认模式)、0.1GB、0.01GB以及0.001GB。如果你想要以0.1GB模式共享GCU设备,那么在安装gcushare-device-plugin组件前,只需要修改gcushare-device-plugin-chart中values文件的memoryUnit字段即可:

gcushare-device-plugin_{VERSION} # vim gcushare-device-plugin-chart/values.yaml
# Default values for gcushare-device-plugin-chart.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 1

image:
  repository: artifact.enflame.cn/enflame_docker_images/enflame
  name: gcushare-device-plugin
  pullPolicy: IfNotPresent
  # Overrides the image tag whose default is the chart appVersion.
  tag: "latest"

imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
deployName: "gcushare-device-plugin"
memoryUnit: "0.1"              # 该字段表示共享GCU粒度,枚举值:1,0.1,0.01和0.001,默认为1

修改后保存values文件,然后再部署gcushare-device-plugin组件即可生效。使用方式仍然为:

"enflame.com/gcu-memory": 40             # 表示申请GCU显存大小为40*0.1GB=4GB。

注意:

1)memoryUnit是在部署组件前要确定好的,如果你已经部署成功了gcushare相关组件,那么在运行过程中,请不要再去修改memoryUnit字段,否则可能会造成缓存数据混乱。

2)如果在运行过程中一定要修改memoryUnit字段,由于两种共享粒度是不可以共存的,所以你必须先把正在使用共享GCU的pod全部清除,然后重新安装gcushare的两个组件。

5.3. 查看日志

通常组件的运行日志都存放在容器中,这样就容易带来一些问题,一是一旦容器重启或者组件被卸载,会造成日志的丢失;二是难以根据异常信息找到代码的调用栈。这些问题都将增大故障排查的复杂程度,而用户则完全无从下手进行排查,进而大大增大了开发人员的运维负担。而GCUShare提供了日志的本地存储功能,如果你的组件运行异常,或者使用GCUShare出现了问题,都可以通过查看日志,进行初步定位。

日志存放目录:/var/log/enflame/gcushare。

1)查看gcushare-scheduler-extender组件日志:

/var/log/enflame/gcushare # vim gcushare-scheduler-extender.log

2)查看gcushare-device-plugin组件日志:

/var/log/enflame/gcushare # vim gcushare-device-plugin.log

6. 组件卸载

通过release目录下delete.sh一键卸载gcushare组件。

6.1. gcushare-scheduler-extender卸载

gcushare-scheduler-extender_{VERSION} # ./delete.sh
start recover scheduler config...
check current k8s cluster version is v1.20.0
recover default scheduler success, for detail, see /etc/kubernetes/manifests/kube-scheduler.yaml
stat /etc/kubernetes/kube-scheduler.back.yaml: no such file or directory
stat /etc/kubernetes/kube-scheduler.yaml: no such file or directory
stat /etc/kubernetes/scheduler-extender-config.json: no such file or directory
stat /etc/kubernetes/scheduler-extender-config-v1.23+.yaml: no such file or directory
delete all scheduler config file success, for detail, see /etc/kubernetes
uninstall gcushare scheduler extender release in namespace:kube-system start...
release "gcushare-scheduler-extender" uninstalled

组件卸载后,k8s集群将自动恢复默认的调度器配置。

6.2. gcushare-device-plugin卸载

gcushare-device-plugin_{VERSION} # ./delete.sh
uninstall gcushare device plugin release in namespace:kube-system start...
release "gcushare-device-plugin" uninstalled
node/sse-lab-inspur-048 labeled

组件卸载后,节点上的”enflame.com/gcushare”: “true”标签将自动清除。

7. 常见问题

1)按卡调度和共享调度为什么不可以共存?

整卡调度和共享调度采用的是两个完全没有关联的k8s设备插件。二者有自己的调度逻辑,而且无法感知到对方的调度缓存,若同时存在,将造成调度混乱。

2)gcushare如何实现底层的显存分配?

gcushare不关注pod实际使用时的显存分配。gcushare是通过存储在gcushare-scheduler-extender组件的GCU缓存,实现pod在调度级别的GCU设备共享,而不是在底层对GCU显存进行划分。所以用户需要自己保证业务实际使用的GCU显存不超过pod声明的申请数目。

3)组件卸载后,已经使用共享GCU的pod业务会受影响吗?

不会。如问题2,gcushare只负责调度层级的GCU共享,已经调度并分配过GCU设备的pod不再受GCUShare影响。

4)gcushare组件重启后缓存会消失吗?如果消失的话是否会影响后续的调度?

组件重启会导致缓存丢失,但这并不会影响后续调度,因为gcushare组件上电后会先进行缓存同步。

5)gcushare支持单个pod内多个容器申请共享GCU吗?

支持,但单个pod内所有申请共享GCU的容器的申请总和不得超过单张GCU卡的内存大小。