Ван Цинкан и Чжан Кай
Предисловие
Серия Расширяющаяся система планирования 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. Таким образом, фрагменты ресурсов могут быть уменьшены, а коэффициент использования графического процессора может быть повышен. Он эффективен, понятен и прост в использовании. В следующих статьях этой серии речь пойдет об улучшении использования ресурсов графического процессора. Мы сосредоточимся на использовании планирования совместного использования графического процессора для повышения коэффициента использования графического процессора.