GPU Sharing с HAMi
Как включить дробное разделение GPU в tenant-кластерах Kubernetes с помощью HAMi.
Вы просматриваете документацию для Cozystack v1.4. Документация последней версии доступна по ссылке: v1.5.
Если вам нужно развернуть собственное контейнеризованное приложение в Cozystack, лучше всего размещать его в управляемом Kubernetes-кластере.
Cozystack разворачивает Kubernetes-as-a-Service и управляет им как самостоятельным приложением внутри изолированной среды каждого тенант. В Cozystack такие кластеры называются тенант-кластерами Kubernetes, а базовый кластер Cozystack — management-кластером или root-кластером. Тенант-кластеры полностью отделены от management-кластера и предназначены для приложений конкретного tenant или приложений, разработанных заказчиком.
Внутри тенант-кластера пользователи могут использовать сервисы LoadBalancer и быстро заказывать persistent volumes по мере необходимости. Control plane работает в контейнерах, а worker nodes разворачиваются как виртуальные машины; всем этим управляет приложение.
Версия Kubernetes в тенант-кластерах не зависит от версии Kubernetes в management-кластере. Пользователи могут выбирать поддерживаемые patch-версии от 1.30 до 1.35.
Kubernetes стал отраслевым стандартом: он предоставляет единый и понятный API, а для конфигурации в основном использует YAML. Благодаря этому команды проще понимают Kubernetes и работают с ним, а управление инфраструктурой становится более предсказуемым.
Kubernetes использует устойчивые архитектурные паттерны и обеспечивает непрерывное восстановление системы в любых сценариях за счёт механизма reconciliation. Кроме того, он позволяет прозрачно масштабироваться на множество серверов и снимает проблемы, характерные для сложных и устаревших API традиционных платформ виртуализации. Управляемый сервис убирает необходимость разрабатывать собственные решения или изменять исходный код, экономя время и усилия.
Управляемый сервис Kubernetes в Cozystack дает удобный способ эффективно управлять серверными рабочими нагрузками.
Когда тенант-кластер Kubernetes готов, получите kubeconfig для работы с ним.
Это можно сделать через UI или запросом kubectl:
Откройте дашборд Cozystack, переключитесь в свой тенант, найдите и откройте страницу приложения. Скопируйте один из config-файлов из раздела Secrets.
Выполните следующую команду, используя kubeconfig management-кластера:
kubectl get secret -n tenant-<name> kubernetes-<clusterName>-admin-kubeconfig -o go-template='{{ printf "%s\n" (index .data "admin.conf" | base64decode) }}' > admin.conf
Доступно несколько вариантов kubeconfig:
admin.conf — стандартный kubeconfig для доступа к новому кластеру.
С его помощью можно создавать дополнительных пользователей Kubernetes.admin.svc — тот же token, что и в admin.conf, но адрес API server указывает на внутреннее имя service.
Используйте его для приложений, которые работают внутри кластера и которым нужен доступ к API.super-admin.conf — похож на admin.conf, но с расширенными административными правами.
Предназначен для диагностики неисправностей и задач обслуживания кластера.super-admin.svc — то же, что super-admin.conf, но с указанием на внутренний адрес API server.Тенант-кластер Kubernetes в Cozystack по сути является Kubernetes-in-Kubernetes. При его развертывании используются следующие компоненты:
Kamaji Control Plane:
Kamaji — open-source проект, который упрощает развертывание
Kubernetes control planes в виде pod внутри root-кластера.
Каждый control plane pod включает базовые компоненты вроде kube-apiserver, controller-manager и scheduler,
что помогает эффективно использовать multi-tenancy и ресурсы.
Etcd Cluster: выделенный кластер etcd разворачивается с помощью etcd-operator от Ænix. Он предоставляет надежное и масштабируемое key-value хранилище для Kubernetes control plane.
Worker Nodes: виртуальные машины создаются через KubeVirt и используются как worker nodes.
Эти ноды настроены на присоединение к тенант-кластеру Kubernetes, что позволяет разворачивать workload и управлять ими.
Диски worker нод автоматически определяют размер блока базового тома и подстраиваются под него
(blockSize.matchVolume), чтобы обеспечить совместимость с backend-системами хранения данных, которые используют
секторы не по 512 байт, например LINSTOR DRBD с 4Kn-дисками.
Cluster API: Cozystack использует Kubernetes Cluster API для подготовки компонентов кластера.
Такая архитектура обеспечивает изолированные, масштабируемые и эффективные тенант-среды Kubernetes.
Справочные материалы по компонентам, которые используются в этом сервисе:
ephemeralStorage переименован в diskSize (v1.4): поле nodeGroups[name].ephemeralStorage переименовано в nodeGroups[name].diskSize, чтобы точнее отражать его назначение (постоянный диск для данных kubelet и containerd). Существующие кластеры мигрируют прозрачно с помощью platform migration 41 в pre-upgrade hook — никаких ручных действий не требуется. В новых значениях следует использовать diskSize. Существующие VM будут автоматически обновлены методом rolling-update через CAPI при применении новых значений. Состояние сохраняется при перезагрузках той же VM (перезапуск virt-launcher, перезагрузка гостевой ОС, отказ ноды); замена VM силами CAPI (например, изменение поля nodeGroup, remediation через MachineHealthCheck) выделяет новый PVC.| Имя | Описание | Тип | Значение |
|---|---|---|---|
storageClass | StorageClass, используемый для хранения данных. | string | replicated |
| Имя | Описание | Тип | Значение |
|---|---|---|---|
nodeGroups | Карта конфигурации worker-нод. | map[string]object | {...} |
nodeGroups[name].minReplicas | Минимальное число реплик. | int | 0 |
nodeGroups[name].maxReplicas | Максимальное число реплик. | int | 10 |
nodeGroups[name].instanceType | Тип инстанса виртуальной машины. | string | u1.medium |
nodeGroups[name].diskSize | Размер постоянного диска для данных kubelet и containerd. | quantity | 20Gi |
nodeGroups[name].storageClass | StorageClass для постоянных дисков worker-нод. Если пусто, используется StorageClass по умолчанию management-кластера (тот, что помечен аннотацией storageclass.kubernetes.io/is-default-class: true). | string | "" |
nodeGroups[name].roles | Список ролей ноды. | []string | [] |
nodeGroups[name].resources | Явное указание CPU и памяти для каждой worker-ноды как альтернатива определению размера через instanceType. Необязательно: если не задано, размер ноды определяется по instanceType. Если заданы оба значения cpu и memory, они имеют приоритет, а instanceType для этой группы нод игнорируется (instancetype опускается в VM, так как KubeVirt не может переопределить CPU/memory у instancetype). Задавайте cpu и memory вместе или ни одно из них; указание только одного отклоняется при рендеринге. | object | {} |
nodeGroups[name].resources.cpu | Доступный CPU. | quantity | "" |
nodeGroups[name].resources.memory | Доступная память (RAM). | quantity | "" |
nodeGroups[name].gpus | Список GPU для подключения (драйверу NVIDIA требуется минимум 4 GiB RAM). | []object | [] |
nodeGroups[name].gpus[i].name | Имя GPU, например “nvidia.com/AD102GL_L40S”. | string | "" |
nodeGroups[name].kubelet | Резервирование ресурсов kubelet для этой группы нод. | object | {} |
nodeGroups[name].kubelet.systemReservedMemory | Память, зарезервированная для host OS. Если пусто, вычисляется автоматически из instanceType. | string | "" |
nodeGroups[name].kubelet.kubeReservedMemory | Память, зарезервированная для kubelet и container runtime. Если пусто, вычисляется автоматически из instanceType. | string | "" |
nodeGroups[name].kubelet.systemReservedCpu | CPU, зарезервированный для host OS. Если пусто, вычисляется автоматически из instanceType. | string | "" |
nodeGroups[name].kubelet.kubeReservedCpu | CPU, зарезервированный для kubelet и container runtime. Если пусто, вычисляется автоматически из instanceType. | string | "" |
nodeGroups[name].kubelet.evictionHardMemory | Жёсткий порог вытеснения по памяти (абсолютное значение, например 200Mi, или процент, например 7%). | string | 7% |
nodeGroups[name].kubelet.evictionSoftMemory | Мягкий порог вытеснения по памяти (абсолютное значение, например 1Gi, или процент, например 10%). | string | 10% |
version | Версия Kubernetes major.minor для развёртывания. | string | v1.35 |
host | Внешнее имя хоста для Kubernetes-кластера. По умолчанию <cluster-name>.<tenant-host>, если пусто. | string | "" |
| Имя | Описание | Тип | Значение |
|---|---|---|---|
addons | Конфигурация расширений кластера. | object | {} |
addons.certManager | Расширение cert-manager. | object | {} |
addons.certManager.enabled | Включить cert-manager. | bool | false |
addons.certManager.valuesOverride | Пользовательские переопределения значений Helm. | object | {} |
addons.cilium | Cilium CNI плагин. | object | {} |
addons.cilium.valuesOverride | Пользовательские переопределения значений Helm. | object | {} |
addons.gatewayAPI | Расширение Gateway API. | object | {} |
addons.gatewayAPI.enabled | Включить Gateway API. | bool | false |
addons.ingressNginx | Расширение Controller Ingress-NGINX. | object | {} |
addons.ingressNginx.enabled | Включить controller (требует ноды с label ingress-nginx). | bool | false |
addons.ingressNginx.exposeMethod | Метод публикации controller. Допустимые значения: Proxied, LoadBalancer. | string | Proxied |
addons.ingressNginx.hosts | Домены, которые направляются в этот тенант-кластер, когда exposeMethod равен Proxied. | []string | [] |
addons.ingressNginx.valuesOverride | Пользовательские переопределения значений Helm. | object | {} |
addons.gpuOperator | NVIDIA GPU Operator. | object | {} |
addons.gpuOperator.enabled | Включить GPU Operator. | bool | false |
addons.gpuOperator.valuesOverride | Пользовательские переопределения значений Helm. | object | {} |
addons.hami | HAMi GPU virtualization middleware. | object | {} |
addons.hami.enabled | Включить HAMi (требует GPU Operator). | bool | false |
addons.hami.valuesOverride | Пользовательские переопределения значений Helm. | object | {} |
addons.fluxcd | FluxCD GitOps operator. | object | {} |
addons.fluxcd.enabled | Включить FluxCD. | bool | false |
addons.fluxcd.valuesOverride | Пользовательские переопределения значений Helm. | object | {} |
addons.monitoringAgents | агенты системы мониторинга. | object | {} |
addons.monitoringAgents.enabled | Включить агенты системы мониторинга . | bool | false |
addons.monitoringAgents.valuesOverride | Пользовательские переопределения значений Helm. | object | {} |
addons.verticalPodAutoscaler | Vertical Pod Autoscaler. | object | {} |
addons.verticalPodAutoscaler.valuesOverride | Пользовательские переопределения значений Helm. | object | {} |
addons.velero | Расширение Velero для backup/restore. | object | {} |
addons.velero.enabled | Включить Velero. | bool | false |
addons.velero.valuesOverride | Пользовательские переопределения значений Helm. | object | {} |
addons.coredns | Расширение CoreDNS. | object | {} |
addons.coredns.valuesOverride | Пользовательские переопределения значений Helm. | object | {} |
addons.ouroboros | Исправление Hairpin-NAT для ingress-nginx с PROXY-protocol. | object | {} |
addons.ouroboros.enabled | Включить ouroboros. Требует addons.ingressNginx.enabled, иначе chart-render завершится ошибкой. Полезно только когда PROXY-protocol подключен в тенант ingress-nginx через valuesOverride. | bool | false |
addons.ouroboros.valuesOverride | Пользовательские переопределения значений Helm. Operator-key имеет приоритет над defaults Cozystack. | object | {} |
| Имя | Описание | Тип | Значение |
|---|---|---|---|
controlPlane | Конфигурация Kubernetes control plane. | object | {} |
controlPlane.replicas | Количество реплик control plane. | int | 2 |
controlPlane.apiServer | Конфигурация API Server. | object | {} |
controlPlane.apiServer.resources | CPU и memory resources для API Server. | object | {} |
controlPlane.apiServer.resources.cpu | Доступный CPU. | quantity | "" |
controlPlane.apiServer.resources.memory | Доступная память (RAM). | quantity | "" |
controlPlane.apiServer.resourcesPreset | Preset, если resources не указаны. | string | c1.medium |
controlPlane.controllerManager | Конфигурация Controller Manager. | object | {} |
controlPlane.controllerManager.resources | CPU и memory resources для Controller Manager. | object | {} |
controlPlane.controllerManager.resources.cpu | Доступный CPU. | quantity | "" |
controlPlane.controllerManager.resources.memory | Доступная память (RAM). | quantity | "" |
controlPlane.controllerManager.resourcesPreset | Preset, если resources не указаны. | string | t1.micro |
controlPlane.scheduler | Конфигурация Scheduler. | object | {} |
controlPlane.scheduler.resources | CPU и memory resources для Scheduler. | object | {} |
controlPlane.scheduler.resources.cpu | Доступный CPU. | quantity | "" |
controlPlane.scheduler.resources.memory | Доступная память (RAM). | quantity | "" |
controlPlane.scheduler.resourcesPreset | Preset, если resources не указаны. | string | t1.micro |
controlPlane.konnectivity | Конфигурация Konnectivity. | object | {} |
controlPlane.konnectivity.server | Конфигурация Konnectivity Server. | object | {} |
controlPlane.konnectivity.server.resources | CPU и memory resources для Konnectivity. | object | {} |
controlPlane.konnectivity.server.resources.cpu | Доступный CPU. | quantity | "" |
controlPlane.konnectivity.server.resources.memory | Доступная память (RAM). | quantity | "" |
controlPlane.konnectivity.server.resourcesPreset | Preset, если resources не указаны. | string | t1.micro |
images | Необязательные переопределения образов для изолированных сред или реестров с ограничением частоты запросов. | object | {} |
images.waitForKubeconfig | Образ для init container wait-for-kubeconfig. Если пусто, используется images/busybox.tag. | string | "" |
resources задает явную конфигурацию CPU и memory для каждой реплики.
Если значение пустое, применяется preset из resourcesPreset.
resources:
cpu: 4000m
memory: 4Gi
resourcesPreset задает именованную конфигурацию CPU и memory для каждой реплики.
Эта настройка игнорируется, если задано соответствующее значение resources.
Пресеты используют соглашение об именовании в стиле облачных провайдеров <series>.<size>. Пять серий покрывают весь диапазон CPU-to-memory соотношений (t1 1:0.5, c1 1:1, s1 1:2, u1 1:4, m1 1:8), и в каждой серии есть восемь размеров (от nano до 4xlarge). Устаревшие имена (nano, micro, small, medium, large, xlarge, 2xlarge) по-прежнему принимаются как устаревшие алиасы для соответствующих типов инстансов с соотношением 1:1.
Полную матрицу размеров и привязки устаревших имен к типам инстансов см. в
docs/operations/resource-presets.md.
В Cozystack доступны следующие ресурсы для типов инстансов:
| Имя | vCPUs | Память |
|---|---|---|
cx1.2xlarge | 8 | 16Gi |
cx1.4xlarge | 16 | 32Gi |
cx1.8xlarge | 32 | 64Gi |
cx1.large | 2 | 4Gi |
cx1.medium | 1 | 2Gi |
cx1.xlarge | 4 | 8Gi |
gn1.2xlarge | 8 | 32Gi |
gn1.4xlarge | 16 | 64Gi |
gn1.8xlarge | 32 | 128Gi |
gn1.xlarge | 4 | 16Gi |
m1.2xlarge | 8 | 64Gi |
m1.4xlarge | 16 | 128Gi |
m1.8xlarge | 32 | 256Gi |
m1.large | 2 | 16Gi |
m1.xlarge | 4 | 32Gi |
n1.2xlarge | 16 | 32Gi |
n1.4xlarge | 32 | 64Gi |
n1.8xlarge | 64 | 128Gi |
n1.large | 4 | 8Gi |
n1.medium | 4 | 4Gi |
n1.xlarge | 8 | 16Gi |
o1.2xlarge | 8 | 32Gi |
o1.4xlarge | 16 | 64Gi |
o1.8xlarge | 32 | 128Gi |
o1.large | 2 | 8Gi |
o1.medium | 1 | 4Gi |
o1.micro | 1 | 1Gi |
o1.nano | 1 | 512Mi |
o1.small | 1 | 2Gi |
o1.xlarge | 4 | 16Gi |
rt1.2xlarge | 8 | 32Gi |
rt1.4xlarge | 16 | 64Gi |
rt1.8xlarge | 32 | 128Gi |
rt1.large | 2 | 8Gi |
rt1.medium | 1 | 4Gi |
rt1.micro | 1 | 1Gi |
rt1.small | 1 | 2Gi |
rt1.xlarge | 4 | 16Gi |
u1.2xlarge | 8 | 32Gi |
u1.2xmedium | 2 | 4Gi |
u1.4xlarge | 16 | 64Gi |
u1.8xlarge | 32 | 128Gi |
u1.large | 2 | 8Gi |
u1.medium | 1 | 4Gi |
u1.micro | 1 | 1Gi |
u1.nano | 1 | 512Mi |
u1.small | 1 | 2Gi |
u1.xlarge | 4 | 16Gi |
Каждая группа нод поддерживает объект kubelet, который задает, сколько памяти и CPU kubelet резервирует для host OS и Kubernetes/system компонентов, работающих на worker ноде.
Если systemReservedMemory или kubeReservedMemory оставлены пустыми, они вычисляются автоматически по следующей формуле:
resources.memory задан явно, используется это значение.instanceType и используется его значение memory.guest.По умолчанию systemReservedMemory и kubeReservedMemory получают одинаковое автоматически вычисленное значение.
CPU резервирование (systemReservedCpu, kubeReservedCpu) работают по той же схеме: 5% от effective CPU с ограничением диапазоном [50m, 500m]. Оба значения вычисляются автоматически, если оставлены пустыми.
| Параметр | По умолчанию | Описание |
|---|---|---|
systemReservedMemory | auto-computed | Память, зарезервированная для host OS |
kubeReservedMemory | auto-computed | Память, зарезервированная для kubelet и container runtime |
systemReservedCpu | auto-computed | CPU, зарезервированный для host OS |
kubeReservedCpu | auto-computed | CPU, зарезервированный для kubelet и container runtime |
evictionHardMemory | 7% | Жёсткий порог вытеснения по памяти |
evictionSoftMemory | 10% | Мягкий порог вытеснения по памяти |
evictionSoftGracePeriod | 1m30s (hardcoded) | Время, в течение которого мягкий порог вытеснения по памяти должен быть нарушен перед запуском вытеснения |
evictionMinimumReclaim | 256Mi (hardcoded) | Минимальный объем памяти, освобождаемый за одно действие вытеснения |
Порог вытеснения можно задавать в процентах (например, 7%) или абсолютных значениях (например, 200Mi). Оба порога должны использовать один тип единиц. Жёсткий порог вытеснения должен быть строго меньше мягкого порога.
Параметры evictionSoftGracePeriod и evictionMinimumReclaim сейчас жёстко заданы в шаблоне и не могут быть переопределены через values.
Когда настроены резервации ресурсов kubelet, аннотации capacity.cluster-autoscaler.kubernetes.io/memory и capacity.cluster-autoscaler.kubernetes.io/cpu на MachineDeployments показывают распределяемые значения вместо полных ресурсов ноды. Доступная для подов память вычисляется как общий объём памяти за вычетом system-reserved, kube-reserved и eviction-hard. Доступное для подов CPU вычисляется как общее количество за вычетом system-reserved и kube-reserved. Так аннотации соответствуют значениям, которые cluster autoscaler использует в расчетах масштабирования.
При обновлении с версии без этой возможности autoscaler после обновления аннотации может увидеть уменьшенную капасити для каждой ноды, что способно запустить дополнительные операции scale-up. Обычно никаких действий не требуется — новые значения отражают фактическую память, доступную для scheduling workload.
Note: Если не задан ни
resources.memory, ниinstanceType, порог вытеснения (по умолчанию 7% hard / 10% soft) все равно применяются kubelet во время выполнения, но capacity аннотации не рендерится. Без этой аннотации cluster-autoscaler не учитывает эти резервации и может запланировать на ноду слишком много подов, что приведёт к срабатыванию вытеснения.
nodeGroups:
md0:
instanceType: "u1.large"
kubelet:
systemReservedMemory: "256Mi"
kubeReservedMemory: "256Mi"
evictionHardMemory: "500Mi"
evictionSoftMemory: "1Gi"
Серия U имеет сбалансированный профиль и предоставляет ресурсы для приложений общего назначения.
U — сокращение от “Universal”, то есть серия рассчитана на универсальные рабочие нагрузки.
VM этих типов инстансов делят физические CPU-ядра с другими VM по принципу разделения процессорного времени.
Особенности этой серии:
Серия O основана на серии U; единственное отличие — избыточное выделение памяти.
O — сокращение от “Overcommitted”.
Особенности этой серии:
Серия CX предоставляет выделенные вычислительные ресурсы для приложений с высокой нагрузкой на CPU.
CX — сокращение от “Compute Exclusive”.
Выделенные ресурсы предоставляются вычислительным потокам виртуальной машины. Чтобы это обеспечить, запрашиваются дополнительные ядра (в зависимости от количества дисков и NIC), которые разгружают IO потоки с ядрами, выделенных под рабочие нагрузки. Кроме того, в этой серии топологии NUMA используемых ядер передается в VM.
Особенности этой серии:
Серия M предоставляет ресурсы для приложений с высокой нагрузкой на память.
M — сокращение от “Memory”.
Особенности этой серии:
Серия RT предоставляет ресурсы для приложений реального времени, например Oslat.
RT — сокращение от “realtime”.
Эта серия типов инстансов требует нод, способных запускать приложения реального времени.
Особенности этой серии:
Как включить дробное разделение GPU в tenant-кластерах Kubernetes с помощью HAMi.
Как включить расширение Velero в tenant-кластере Kubernetes, направить его в bucket SeaweedFS, а затем создавать и восстанавливать бэкапы workload.
Как перенести реплики tenant-кластеров etcd, которые используются tenant-кластерами Kubernetes.