Вступление
Если вы когда-либо пытались запустить рабочую нагрузку графического процессора в кластере Kubernetes, вы знаете, что эта задача требует нетривиальной конфигурации и имеет высокую стоимость (экземпляры графического процессора довольно дороги).
В этом посте показано, как экономично запустить рабочую нагрузку графического процессора в кластере Kubernetes, используя кластер Amazon EKS, AWS Auto Scaling, Спотовые инстансы Amazon EC2, а также некоторые ресурсы и конфигурации Kubernetes.
Кластерный план EKS
Во-первых, нам нужно создать кластер Kubernetes, состоящий из смешанных узлов: узлов без графического процессора для управления и общей рабочей нагрузки Kubernetes и более дорогих узлов на базе графического процессора для выполнения задач с интенсивным использованием графического процессора, таких как машинное обучение, медицинский анализ, сейсмические исследования и т. Д. перекодирование видео и другие.
Эти группы узлов должны иметь возможность масштабирования по запросу (масштабирование и масштабирование) для общих узлов и от 0 до необходимого числа и обратно до 0 для дорогих экземпляров графического процессора. Более того, чтобы сделать это экономически эффективным способом, мы собираемся использовать спотовые инстансы Amazon EC2 как для общих узлов, так и для узлов GPU.
Спотовые инстансы AWS EC2
С инстансами Спотовые инстансы Amazon EC2 вы можете сэкономить до 90% по сравнению с ценой по запросу. Ранее спотовые инстансы завершались в порядке возрастания ставок. Из-за этого рыночные цены часто колебались. В текущей модели спотовые цены более предсказуемы, обновляются реже и определяются резервными мощностями Amazon EC2, а не ценами заявок. Сервис AWS EC2 может восстанавливать спотовые инстансы, если для конкретного инстанса в определенной зоне доступности недостаточно ресурсов. Спотовые инстансы получают двухминутное предупреждение, когда они собираются быть восстановлены службой Amazon EC2, и могут использовать это время для постепенного завершения работы и изменения состояния.
Рабочий процесс
1. Создайте кластер EKS.
Кластер Amazon EKS можно создать, используя Amazon EKS CLI, CloudFormation или Terraform, AWS CDK или eksctl.
инструмент командной строки eksctl
В этом посте используется eksctl
(инструмент CLI для создания кластеров на EKS). Можно передать все параметры инструменту в виде флагов интерфейса командной строки или файла конфигурации. Использование файла конфигурации делает процесс более повторяемым и удобным для автоматизации.
eksctl
может создавать или обновлять кластер EKS и дополнительные необходимые ресурсы AWS, используя стеки CloudFormation.
Настройте свой кластер с помощью файла конфигурации. Просто беги
eksctl create cluster -f cluster.yaml
чтобы применить cluster.yaml
файл:
apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig
metadata: name: test-cluster region: us-west-2
nodeGroups: - name: ng instanceType: t3.micro desiredCapacity: 10
Будет создан новый кластер EKS с 10 t3.micro
рабочими узлами EC2 по требованию, а учетные данные кластера будут добавлены в ~/.kube/config
файл.
2. Создание групп узлов
Как и планировалось, мы собираемся создать две группы узлов для рабочих узлов Kubernetes:
- Общая группа узлов - группа автомасштабирования со спотовыми экземплярами для запуска системной рабочей нагрузки Kubernetes и рабочей нагрузки, не связанной с графическим процессором.
- Группы узлов GPU - группа автомасштабирования со спотовыми инстансами на GPU, которые могут масштабироваться от 0 до необходимого количества экземпляров и обратно до 0.
К счастью, eksctl
поддерживает добавление групп узлов Kubernetes в кластер EKS, и эти группы могут состоять из спотовых инстансов или смеси спотовых инстансов и инстансов по требованию.
2.1 Общая группа узлов
Файл конфигурации eksctl
содержит кластер EKS в us-west-2
в 3 зонах доступности и первую группу узлов с автомасштабированием General (от 2 до 20 узлов), работающую на диверсифицированных спотовых экземплярах.
--- apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: gaia-kube region: us-west-2 availabilityZones: ["us-west-2a", "us-west-2b", "us-west-2c"] nodeGroups: # spot workers NG - multi AZ, scale from 3 - name: spot-ng ami: auto instanceType: mixed desiredCapacity: 2 minSize: 2 maxSize: 20 volumeSize: 100 volumeType: gp2 volumeEncrypted: true iam: attachPolicyARNs: - arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly withAddonPolicies: autoScaler: true ebs: true albIngress: true cloudWatch: true instancesDistribution: onDemandPercentageAboveBaseCapacity: 0 instanceTypes: - m4.2xlarge - m4.4xlarge - m5.2xlarge - m5.4xlarge - m5a.2xlarge - m5a.4xlarge - c4.2xlarge - c4.4xlarge - c5.2xlarge - c5.4xlarge spotInstancePools: 15 tags: k8s.io/cluster-autoscaler/enabled: 'true' labels: lifecycle: Ec2Spot privateNetworking: true availabilityZones: ["us-west-2a", "us-west-2b", "us-west-2c"] # next: GPU node groups ...
Теперь пришло время объяснить некоторые параметры, используемые в приведенном выше файле конфигурации.
ami: auto
-eksctl
автоматически обнаруживает последний оптимизированный для EKS образ AMI для рабочих узлов на основе указанного региона AWS, версии EKS и типа инстанса. См. Главу AMI, оптимизированный для Amazon EKS в Руководстве пользователя.instanceType: mixed
- укажите, что фактический тип экземпляра будет одним из типов экземпляров, определенных в разделеinstancesDistribution
iam
содержит список предопределенных и действующих политик IAM;eksctl
создает новую Роль IAM с указанными политиками и прикрепляет эту роль к каждому рабочему узлу EKS. Существует несколько политик IAM, которые необходимо прикрепить к каждому рабочему узлу EKS, см. Раздел Роль IAM рабочего узла Amazon EKS в Руководстве пользователя и документациюeksctl
Политики IAM.instancesDistribution
- укажите политику смешанного экземпляра для групп автоматического масштабирования EC2, прочтите документацию AWS MixedInstancesPolicyspotInstancePools
- указывает количество используемых пулов спотовых инстансов, подробнееtags
- теги AWS добавлены в рабочие узлы EKSk8s.io/cluster-autoscaler/enabled
будет использовать этот тег для автоматического обнаружения Kubernetes Cluster Autoscaler.privateNetworking: true
- все рабочие узлы EKS будут размещены в частных подсетях
Пулы спотовых инстансов
Когда вы используете спотовые инстансы в качестве рабочих узлов, вам необходимо диверсифицировать использование до как можно большего числа пулов спотовых инстансов. Пул спотовых инстансов - это набор неиспользуемых инстансов EC2 с одинаковым типом инстанса (например, m5.large
), операционной системой, зоной доступности и сетевыми платформами.
eksctl
в настоящее время поддерживает единую спотовую модель выделения ресурсов: lowestPrice
стратегию распределения. Эта стратегия позволяет создать парк спотовых инстансов, который будет дешевым и разнообразным. ASG автоматически развертывает самую дешевую комбинацию типов инстансов и зон доступности на основе текущей спотовой цены для указанного вами количества спотовых пулов. Эта комбинация позволяет избежать использования самых дорогих спотовых инстансов.
Диверсификация спотовых инстансов также увеличивает доступность рабочих узлов, обычно не все пулы спотовых инстансов будут прерваны одновременно, поэтому только небольшая часть вашей рабочей нагрузки будет прервана, а группа автоматического масштабирования EC2 заменит прерванные экземпляры из других пулов спотовых инстансов.
Пожалуйста, также подумайте о том, чтобы использовать специальный том для наборов данных, прогресса обучения (контрольных точек) и журналов. Этот том должен быть постоянным, и на него не должно влиять завершение работы экземпляра.
2.2 Группа узлов с питанием от GPU
Следующая часть нашего eksctl
файла конфигурации содержит первую группу узлов автомасштабирования GPU (от 0
до 10
узлов), работающую на различных спотовых инстансах с GPU.
При использовании спотовых инстансов на базе GPU рекомендуется создать группу узлов GPU для каждой зоны доступности и настроить Kubernetes Cluster Autoscaler, чтобы избежать автоматической ребалансировки ASG.
Почему это важно? Некоторые спотовые инстансы EC2 на базе графического процессора имеют относительно высокую частоту прерывания (>20%
для некоторых типов инстансов графического процессора; отметьте Советчик по спотовым инстансам), а использование нескольких зон доступности и отключение автоматической балансировки кластерного автомасштабирования может помочь свести к минимуму перерывы в работе графического процессора.
# ... EKS cluster and General node group ... # spot GPU NG - west-2a AZ, scale from 0 - name: gpu-spot-ng-a ami: auto instanceType: mixed desiredCapacity: 0 minSize: 0 maxSize: 10 volumeSize: 100 volumeType: gp2 volumeEncrypted: true iam: attachPolicyARNs: - arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly withAddonPolicies: autoScaler: true ebs: true fsx: true efs: true albIngress: true cloudWatch: true instancesDistribution: onDemandPercentageAboveBaseCapacity: 0 instanceTypes: - p3.2xlarge - p3.8xlarge - p3.16xlarge - p2.xlarge - p2.8xlarge - p2.16xlarge spotInstancePools: 5 tags: k8s.io/cluster-autoscaler/node-template/taint/dedicated: nvidia.com/gpu=true k8s.io/cluster-autoscaler/node-template/label/nvidia.com/gpu: 'true' k8s.io/cluster-autoscaler/enabled: 'true' labels: lifecycle: Ec2Spot nvidia.com/gpu: 'true' k8s.amazonaws.com/accelerator: nvidia-tesla taints: nvidia.com/gpu: "true:NoSchedule" privateNetworking: true availabilityZones: ["us-west-2a"] # create additional node groups for `us-west-2b` and `us-west-2c` availability zones ...
Теперь пришло время объяснить некоторые параметры, используемые для настройки группы узлов на базе графического процессора.
ami: auto
-eksctl
автоматически обнаруживает последний оптимизированный для EKS образ AMI с поддержкой графического процессора для рабочих узлов в зависимости от указанного региона AWS, версии EKS и типа инстанса. См. Руководство пользователя AMI, оптимизированный для Amazon EKS с поддержкой графического процессора.iam: withAddonPolicies
- если запланированная рабочая нагрузка требует доступа к сервисам хранения AWS, важно включить дополнительные политики IAM (автоматически создаютсяeksctl
)tags
- теги AWS добавлены в рабочие узлы EKSk8s.io/cluster-autoscaler/node-template/taint/dedicated: nvidia.com/gpu=true
- заражение узла Kubernetesk8s.io/cluster-autoscaler/node-template/label/nvidia.com/gpu: 'true'
- Метка узла Kubernetes, используемая Cluster Autoscaler для масштабирования ASG от / до 0nvidia.com/gpu: “true:NoSchedule”
- повреждение узла GPU Kubernetes; помогает избежать размещения рабочей нагрузки, не связанной с GPU, на дорогих узлах GPU
Оптимизированное изображение AMI для EKS с поддержкой графического процессора
Помимо стандартной конфигурации AMI, оптимизированной для Amazon EKS, AMI графического процессора включает в себя следующее:
- Драйверы NVIDIA
- Пакет
nvidia-docker2
nvidia-container-runtime
(как среда выполнения по умолчанию)
Масштабирование группы узлов до / от 0
Из Kubernetes Cluster Autoscaler 0.6.1 - можно масштабировать группу узлов до / от 0, предполагая, что все условия увеличения и уменьшения выполняются.
Если вы используете nodeSelector
, вам нужно пометить ASG ключом шаблона узла k8s.io/cluster-autoscaler/node-template/label/
и k8s.io/cluster-autoscaler/node-template/taint/
, если вы используете taints.
3. Планирование рабочей нагрузки графического процессора.
3.1 Расписание на основе ресурсов GPU
Плагин NVIDIA для устройств Kubernetes показывает количество графических процессоров на каждом узле вашего кластера. После установки плагина можно использовать nvidia/gpu
ресурс Kubernetes на узлах GPU и для рабочих нагрузок Kubernetes.
Выполните эту команду, чтобы применить подключаемый модуль устройства Nvidia Kubernetes как daemonset
, работающий только на рабочих узлах AWS с GPU, используя tolerations
и nodeAffinity
kubectl create -f kubernetes/nvidia-device-plugin.yaml kubectl get daemonset -nkube-system
с использованием nvidia-device-plugin.yaml
файла ресурсов Kubernetes
apiVersion: extensions/v1beta1 kind: DaemonSet metadata: name: nvidia-device-plugin-daemonset-1.12 namespace: kube-system spec: updateStrategy: type: RollingUpdate template: metadata: labels: name: nvidia-device-plugin-ds spec: tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule containers: - image: nvidia/k8s-device-plugin:1.11 name: nvidia-device-plugin-ctr securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL"] volumeMounts: - name: device-plugin mountPath: /var/lib/kubelet/device-plugins volumes: - name: device-plugin hostPath: path: /var/lib/kubelet/device-plugins affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: beta.kubernetes.io/instance-type operator: In values: - p3.2xlarge - p3.8xlarge - p3.16xlarge - p3dn.24xlarge - p2.xlarge - p2.8xlarge - p2.16xlarge
3.2 Пороки и терпимость
Kubernetes портит позволяет узлу отражать набор подов. Ошибки и допуски работают вместе, чтобы гарантировать, что поды не будут запланированы на несоответствующие узлы. На узел наносится один или несколько порчи; это означает, что узел не должен принимать никакие стручки, не терпящие порчи. Допуски применяются к модулям и позволяют (но не требуют) планировать модули на узлах с соответствующими загрязнениями.
См. Документацию Kubernetes Taints and Tolerations для более подробной информации.
Чтобы запустить рабочую нагрузку GPU на узлах спотовых инстансов с питанием от GPU, с nvidia.com/gpu: "true:NoSchedule"
taint, рабочая нагрузка должна включать в себя обе совпадающие конфигурации tolerations
и nodeSelector
.
Развертывание Kubernetes с 10
репликами pod с nvidia/gpu: 1
лимитом:
apiVersion: apps/v1 kind: Deployment metadata: name: cuda-vector-add labels: app: cuda-vector-add spec: replicas: 10 selector: matchLabels: app: cuda-vector-add template: metadata: name: cuda-vector-add labels: app: cuda-vector-add spec: nodeSelector: nvidia.com/gpu: "true" tolerations: - key: "nvidia.com/gpu" operator: "Exists" effect: "NoSchedule" containers: - name: cuda-vector-add image: "k8s.gcr.io/cuda-vector-add:v0.1" resources: limits: nvidia.com/gpu: 1 # requesting 1 GPU
Разверните cuda-vector-add
развертывание и посмотрите, как новые узлы на базе графического процессора добавляются в кластер EKS.
# list Kubernetes nodes before running GPU workload kubectl get nodes --output="custom- columns=NAME:.metadata.name,TYPE:.metadata.labels.beta\.kubernetes\.io\/instance-type" NAME TYPE ip-192-168-151-104.us-west-2.compute.internal c4.4xlarge ip-192-168-171-140.us-west-2.compute.internal c4.4xlarge # deploy GPU workload on EKS cluster with tolerations for nvidia/gpu=true kubectl create -f kubernetes/examples/vector/vector-add-dpl.yaml # list Kubernetes nodes after several minutes to see new GPU nodes added to the cluster kubectl get nodes --output="custom-columns=NAME:.metadata.name,TYPE:.metadata.labels.beta\.kubernetes\.io\/instance-type" NAME TYPE ip-192-168-101-60.us-west-2.compute.internal p2.16xlarge ip-192-168-139-227.us-west-2.compute.internal p2.16xlarge ip-192-168-151-104.us-west-2.compute.internal c4.4xlarge ip-192-168-171-140.us-west-2.compute.internal c4.4xlarge ip-192-168-179-248.us-west-2.compute.internal p2.16xlarge
Как видите, в кластер были добавлены 3 новых узла с графическим процессором (p2.16xlarge
) в 3 зонах доступности. Когда вы удаляете рабочую нагрузку GPU, кластер уменьшит группу узлов GPU до 0 через 10 минут.
Резюме
Следуйте этому руководству, чтобы создать кластер EKS (Kubernetes) с группой узлов на базе графического процессора, работающий на спотовых экземплярах и масштабируемый от / до 0 узлов.
использованная литература
- Репозиторий EKS Spot Cluster на GitHub с кодом для этого блога
- Полное руководство по запуску спотовых инстансов EC2 в качестве рабочих узлов Kubernetes от Рана Шейнберга
- Kubernetes Cluster Autoscaler
- Пороки и терпимости Документация Kubernetes
Отказ от ответственности
Неважно, где я работаю, все мои мнения - мои собственные.
Черновик опубликован на https://alexei-led.github.io.