Ван Цинкан и Чжан Кай

Предисловие

Серия Расширяющаяся система планирования Kubernetes представляет пользователям и разработчикам Kubernetes наш опыт, техническое мышление и детали реализации. Мы надеемся, что статьи помогут вам понять мощные возможности и будущие тенденции системы планирования Kubernetes.

Первые две статьи в этой серии: Развитая система планирования Kubernetes — Часть 1: Структура планирования и Развитая система планирования Kubernetes — Часть 2: Совместное планирование и групповое планирование, поддерживающее пакетные задания. ».

В этих двух статьях представлена ​​структура планирования Kubernetes и реализация политик совместного планирования и группового планирования путем расширения платформы планирования соответственно. При работе с пакетным заданием в кластере нам нужно сосредоточиться на использовании ресурсов. В частности, карты GPU слишком дороги, чтобы тратить ресурсы впустую. В этой статье описывается, как использовать Binpack для уменьшения фрагментации ресурсов и улучшения использования графического процессора при планировании пакетных заданий.

Почему Бинпак?

Политика планирования ресурсов Kubernetes по умолчанию — LeastRequestedPriority. Первыми планируются наименее потребляемые узлы, поэтому ресурсы всего кластера распределяются равномерно между всеми узлами. Однако эта политика планирования часто создает больше фрагментов ресурсов на одном узле.

Ниже приведен простой пример. Как показано на следующем рисунке, ресурсы используются равномерно среди узлов. Каждый узел использует три карты GPU, при этом два узла остаются на одном ресурсе GPU. В это время новое задание подано для двух графических процессоров, а затем отправляется планировщику. Из-за нехватки ресурсов происходит сбой планирования.

Как показано выше, каждый узел имеет один резервный графический процессор, но он не работает, что приводит к дорогостоящей трате ресурсов. Однако после использования политики планирования ресурсов Binpack описанная выше фрагментация ресурсов решена. Binpack сначала заполняет ресурсы на узле, а затем планирует следующий узел. Задание, которое применяется для двух графических процессоров, может быть успешно запланировано для узла, что улучшает использование ресурсов кластера.

Метод реализации

Реализация Binpack была абстрагирована в подключаемый модуль Score для Kubernetes Scheduler Framework (называемый RequestedToCapacityRatio). Он используется для оценки узлов на этапе предпочтений в соответствии с самоопределяемыми конфигурациями. Конкретную реализацию можно разделить на две части: построение функции подсчета очков и подсчет очков.

Построение скоринговой функции

Процесс построения скоринговой функции прост. Пользователи могут определить оценку, соответствующую разным коэффициентам использования, чтобы определить процесс принятия решения о планировании.

Если пользователи задают определение, как показано на следующем рисунке, более высокие показатели использования ресурсов получают более высокие оценки. Например, если коэффициент использования ресурсов равен 0, оценка равна 0, а если коэффициент использования ресурсов равна 100, оценка равна 10. Это метод распределения ресурсов Binpack.

Пользователи также могут установить коэффициент использования 0 с оценкой 10 баллов и коэффициент использования 100 с 0 баллами. Это означает, что чем ниже коэффициент использования ресурсов, тем выше оценка. Это метод распределения ресурсов для распространения.

Пользователи могут добавлять дополнительные точки, и соответствующие отношения не обязательно должны быть линейными. Например, оценка 8 может быть получена при коэффициенте использования ресурсов 50. Таким образом, оценка делится на два интервала: 0–50 и 50–100.

Подсчет очков

Пользователи могут определять ссылочные ресурсы и значения веса в расчете Binpack. Например, они могут устанавливать значения и веса GPU и CPU.

resourcetoweightmap: 
    "cpu": 1
    "nvidia.com/gpu": 1

Затем в процессе скоринга получают коэффициенты использования соответствующих ресурсов по результатам расчета (pod.Request + node.Allocated)/node.Total. Затем коэффициенты использования добавляются к функции оценки для получения соответствующих оценок. Окончательные баллы получаются путем взвешивания значения веса всех ресурсов.

Score = line(resource1_utilization) * weight1 + line(resource2_utilization) * weight2 ....) / (weight1 + weight2 ....)

Использование бинпака

Конфигурация

1. Создайте a/etc/kubernetes/scheduler-config.yaml. Пользователи могут настраивать другие политики приоритетов в соответствии со своими потребностями.

apiVersion: kubescheduler.config.k8s.io/v1alpha1
kind: KubeSchedulerConfiguration
leaderElection:
  leaderElect: false
clientConnection:
  kubeconfig: "REPLACE_ME_WITH_KUBE_CONFIG_PATH"
plugins:
  score:
    enabled:
    - name: RequestedToCapacityRatio
      weight: 100
    disabled:
    - name: LeastRequestedPriority
pluginConfig:
- name: RequestedToCapacityRatio
  args:
    functionshape:
      - utilization: 0
        score: 0
      - utilization: 100
        score: 100
    resourcetoweightmap: # Define the type of resources for Binpack operations. Users can set weight for multiple resources.
      "cpu": 1
      "nvidia.com/gpu": 1

Демонстрационный пример

Это результат демонстрации Binpack после запуска распределенной работы TensorFlow. В тестируемом кластере есть две машины с 4 видеокартами.

1. Используйте Kubeflow’s Arena для развертывания tf-оператора в существующем кластере Kubernetes.

Арена — один из подпроектов на базе Kubeflow, сообщества с открытым исходным кодом для систем машинного обучения в Kubernetes. Arena поддерживает управление основным жизненным циклом заданий машинного обучения с помощью командной строки и SDK. Управление жизненным циклом включает в себя установку среды, подготовку данных, разработку модели, обучение модели и прогнозирование модели. С Arena повышается эффективность работы специалистов по данным.

git clone https://github.com/kubeflow/arena.git
kubectl create ns arena-system
kubectl create -f arena/kubernetes-artifacts/jobmon/jobmon-role.yaml
kubectl create -f arena/kubernetes-artifacts/tf-operator/tf-crd.yaml
kubectl create -f arena/kubernetes-artifacts/tf-operator/tf-operator.yaml

Проверьте статус развертывания

$ kubectl  get pods -n arena-system
NAME                                READY   STATUS    RESTARTS   AGE
tf-job-dashboard-56cf48874f-gwlhv   1/1     Running   0          54s
tf-job-operator-66494d88fd-snm9m    1/1     Running   0          54s

2. Пользователь отправляет распределенное задание Tensorflow в кластер, содержащий 1 PS и 4 воркера. Каждому рабочему требуется 1 GPU.

apiVersion: "kubeflow.org/v1"
kind: "TFJob"
metadata:
  name: "tf-smoke-gpu"
spec:
  tfReplicaSpecs:
    PS:
      replicas: 1
      template:
        metadata:
          creationTimestamp: null
          labels:
            pod-group.scheduling.sigs.k8s.io/name: tf-smoke-gpu
            pod-group.scheduling.sigs.k8s.io/min-available: "5"
        spec:
          containers:
          - args:
            - python
            - tf_cnn_benchmarks.py
            - --batch_size=32
            - --model=resnet50
            - --variable_update=parameter_server
            - --flush_stdout=true
            - --num_gpus=1
            - --local_parameter_device=cpu
            - --device=cpu
            - --data_format=NHWC
            image: registry.cn-hangzhou.aliyuncs.com/kubeflow-images-public/tf-benchmarks-cpu:v20171202-bdab599-dirty-284af3
            name: tensorflow
            ports:
            - containerPort: 2222
              name: tfjob-port
            resources:
              limits:
                cpu: '1'
            workingDir: /opt/tf-benchmarks/scripts/tf_cnn_benchmarks
          restartPolicy: OnFailure
    Worker:
      replicas: 4
      template:
        metadata:
          creationTimestamp: null
          labels:
            pod-group.scheduling.sigs.k8s.io/name: tf-smoke-gpu
            pod-group.scheduling.sigs.k8s.io/min-available: "5"
        spec:
          containers:
          - args:
            - python
            - tf_cnn_benchmarks.py
            - --batch_size=32
            - --model=resnet50
            - --variable_update=parameter_server
            - --flush_stdout=true
            - --num_gpus=1
            - --local_parameter_device=cpu
            - --device=gpu
            - --data_format=NHWC
            image: registry.cn-hangzhou.aliyuncs.com/kubeflow-images-public/tf-benchmarks-gpu:v20171202-bdab599-dirty-284af3
            name: tensorflow
            ports:
            - containerPort: 2222
              name: tfjob-port
            resources:
              limits:
                nvidia.com/gpu: 1
            workingDir: /opt/tf-benchmarks/scripts/tf_cnn_benchmarks
          restartPolicy: OnFailure

3. Когда пользователь использует Binpack, 4 воркера назначаются на один и тот же узел GPU: cn-shanghai.192.168.0.129 после отправки задания.

$ kubectl get pods -o wide
NAME                    READY   STATUS    AGE   IP             NODE
tf-smoke-gpu-ps-0       1/1     Running    15s   172.20.0.210   cn-shanghai.192.168.0.129  
tf-smoke-gpu-worker-0   1/1     Running    17s   172.20.0.206   cn-shanghai.192.168.0.129   
tf-smoke-gpu-worker-1   1/1     Running    17s   172.20.0.207   cn-shanghai.192.168.0.129      
tf-smoke-gpu-worker-2   1/1     Running    17s   172.20.0.209   cn-shanghai.192.168.0.129
tf-smoke-gpu-worker-3   1/1     Running    17s   172.20.0.208   cn-shanghai.192.168.0.129

4. Когда пользователь не использует Binpack, 4 воркера назначаются на два узла: cn-shanghai.192.168.0.129 и cn-shanghai.192.168. 6,50 г узлов после отправки задания. Таким образом, происходит фрагментация ресурсов.

$ kubectl get pods -o wide
NAME                    READY   STATUS AGE   IP             NODE
tf-smoke-gpu-ps-0       1/1     Running    7s    172.20.1.72    cn-shanghai.192.168.0.130
tf-smoke-gpu-worker-0   1/1     Running    8s    172.20.0.214   cn-shanghai.192.168.0.129
tf-smoke-gpu-worker-1   1/1     Running    8s    172.20.1.70    cn-shanghai.192.168.0.130
tf-smoke-gpu-worker-2   1/1     Running    8s    172.20.0.215   cn-shanghai.192.168.0.129
tf-smoke-gpu-worker-3   1/1     Running    8s    172.20.1.71    cn-shanghai.192.168.0.130

Резюме

В этой статье рассказывается, как использовать собственную политику планирования Kubernetes (называемую RequestedToCapacityRatio) для включения планирования Binpack. Таким образом, фрагменты ресурсов могут быть уменьшены, а коэффициент использования графического процессора может быть повышен. Он эффективен, понятен и прост в использовании. В следующих статьях этой серии речь пойдет об улучшении использования ресурсов графического процессора. Мы сосредоточимся на использовании планирования совместного использования графического процессора для повышения коэффициента использования графического процессора.

Оригинальный источник: