Вы просматриваете документацию для Cozystack v1.4. Документация последней версии доступна по ссылке: v1.5.

Управляемый (тенант) Kubernetes

Как развернуть и использовать изолированные управляемые Kubernetes-кластеры в Cozystack.

Управляемый Kubernetes в Cozystack

Если вам нужно развернуть собственное контейнеризованное приложение в 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-кластер

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.

Справочные материалы по компонентам, которые используются в этом сервисе:

Breaking Changes

  • 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.

Parameters

Общие параметры

ИмяОписаниеТипЗначение
storageClassStorageClass, используемый для хранения данных.stringreplicated

Параметры приложения

ИмяОписаниеТипЗначение
nodeGroupsКарта конфигурации worker-нод.map[string]object{...}
nodeGroups[name].minReplicasМинимальное число реплик.int0
nodeGroups[name].maxReplicasМаксимальное число реплик.int10
nodeGroups[name].instanceTypeТип инстанса виртуальной машины.stringu1.medium
nodeGroups[name].diskSizeРазмер постоянного диска для данных kubelet и containerd.quantity20Gi
nodeGroups[name].storageClassStorageClass для постоянных дисков 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.systemReservedCpuCPU, зарезервированный для host OS. Если пусто, вычисляется автоматически из instanceType.string""
nodeGroups[name].kubelet.kubeReservedCpuCPU, зарезервированный для kubelet и container runtime. Если пусто, вычисляется автоматически из instanceType.string""
nodeGroups[name].kubelet.evictionHardMemoryЖёсткий порог вытеснения по памяти (абсолютное значение, например 200Mi, или процент, например 7%).string7%
nodeGroups[name].kubelet.evictionSoftMemoryМягкий порог вытеснения по памяти (абсолютное значение, например 1Gi, или процент, например 10%).string10%
versionВерсия Kubernetes major.minor для развёртывания.stringv1.35
hostВнешнее имя хоста для Kubernetes-кластера. По умолчанию <cluster-name>.<tenant-host>, если пусто.string""

Расширения кластера

ИмяОписаниеТипЗначение
addonsКонфигурация расширений кластера.object{}
addons.certManagerРасширение cert-manager.object{}
addons.certManager.enabledВключить cert-manager.boolfalse
addons.certManager.valuesOverrideПользовательские переопределения значений Helm.object{}
addons.ciliumCilium CNI плагин.object{}
addons.cilium.valuesOverrideПользовательские переопределения значений Helm.object{}
addons.gatewayAPIРасширение Gateway API.object{}
addons.gatewayAPI.enabledВключить Gateway API.boolfalse
addons.ingressNginxРасширение Controller Ingress-NGINX.object{}
addons.ingressNginx.enabledВключить controller (требует ноды с label ingress-nginx).boolfalse
addons.ingressNginx.exposeMethodМетод публикации controller. Допустимые значения: Proxied, LoadBalancer.stringProxied
addons.ingressNginx.hostsДомены, которые направляются в этот тенант-кластер, когда exposeMethod равен Proxied.[]string[]
addons.ingressNginx.valuesOverrideПользовательские переопределения значений Helm.object{}
addons.gpuOperatorNVIDIA GPU Operator.object{}
addons.gpuOperator.enabledВключить GPU Operator.boolfalse
addons.gpuOperator.valuesOverrideПользовательские переопределения значений Helm.object{}
addons.hamiHAMi GPU virtualization middleware.object{}
addons.hami.enabledВключить HAMi (требует GPU Operator).boolfalse
addons.hami.valuesOverrideПользовательские переопределения значений Helm.object{}
addons.fluxcdFluxCD GitOps operator.object{}
addons.fluxcd.enabledВключить FluxCD.boolfalse
addons.fluxcd.valuesOverrideПользовательские переопределения значений Helm.object{}
addons.monitoringAgentsагенты системы мониторинга.object{}
addons.monitoringAgents.enabledВключить агенты системы мониторинга .boolfalse
addons.monitoringAgents.valuesOverrideПользовательские переопределения значений Helm.object{}
addons.verticalPodAutoscalerVertical Pod Autoscaler.object{}
addons.verticalPodAutoscaler.valuesOverrideПользовательские переопределения значений Helm.object{}
addons.veleroРасширение Velero для backup/restore.object{}
addons.velero.enabledВключить Velero.boolfalse
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.boolfalse
addons.ouroboros.valuesOverrideПользовательские переопределения значений Helm. Operator-key имеет приоритет над defaults Cozystack.object{}

Конфигурация Kubernetes Control Plane

ИмяОписаниеТипЗначение
controlPlaneКонфигурация Kubernetes control plane.object{}
controlPlane.replicasКоличество реплик control plane.int2
controlPlane.apiServerКонфигурация API Server.object{}
controlPlane.apiServer.resourcesCPU и memory resources для API Server.object{}
controlPlane.apiServer.resources.cpuДоступный CPU.quantity""
controlPlane.apiServer.resources.memoryДоступная память (RAM).quantity""
controlPlane.apiServer.resourcesPresetPreset, если resources не указаны.stringc1.medium
controlPlane.controllerManagerКонфигурация Controller Manager.object{}
controlPlane.controllerManager.resourcesCPU и memory resources для Controller Manager.object{}
controlPlane.controllerManager.resources.cpuДоступный CPU.quantity""
controlPlane.controllerManager.resources.memoryДоступная память (RAM).quantity""
controlPlane.controllerManager.resourcesPresetPreset, если resources не указаны.stringt1.micro
controlPlane.schedulerКонфигурация Scheduler.object{}
controlPlane.scheduler.resourcesCPU и memory resources для Scheduler.object{}
controlPlane.scheduler.resources.cpuДоступный CPU.quantity""
controlPlane.scheduler.resources.memoryДоступная память (RAM).quantity""
controlPlane.scheduler.resourcesPresetPreset, если resources не указаны.stringt1.micro
controlPlane.konnectivityКонфигурация Konnectivity.object{}
controlPlane.konnectivity.serverКонфигурация Konnectivity Server.object{}
controlPlane.konnectivity.server.resourcesCPU и memory resources для Konnectivity.object{}
controlPlane.konnectivity.server.resources.cpuДоступный CPU.quantity""
controlPlane.konnectivity.server.resources.memoryДоступная память (RAM).quantity""
controlPlane.konnectivity.server.resourcesPresetPreset, если resources не указаны.stringt1.micro
imagesНеобязательные переопределения образов для изолированных сред или реестров с ограничением частоты запросов.object{}
images.waitForKubeconfigОбраз для init container wait-for-kubeconfig. Если пусто, используется images/busybox.tag.string""

Примеры параметров и справочник

resources and resourcesPreset

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.2xlarge816Gi
cx1.4xlarge1632Gi
cx1.8xlarge3264Gi
cx1.large24Gi
cx1.medium12Gi
cx1.xlarge48Gi
gn1.2xlarge832Gi
gn1.4xlarge1664Gi
gn1.8xlarge32128Gi
gn1.xlarge416Gi
m1.2xlarge864Gi
m1.4xlarge16128Gi
m1.8xlarge32256Gi
m1.large216Gi
m1.xlarge432Gi
n1.2xlarge1632Gi
n1.4xlarge3264Gi
n1.8xlarge64128Gi
n1.large48Gi
n1.medium44Gi
n1.xlarge816Gi
o1.2xlarge832Gi
o1.4xlarge1664Gi
o1.8xlarge32128Gi
o1.large28Gi
o1.medium14Gi
o1.micro11Gi
o1.nano1512Mi
o1.small12Gi
o1.xlarge416Gi
rt1.2xlarge832Gi
rt1.4xlarge1664Gi
rt1.8xlarge32128Gi
rt1.large28Gi
rt1.medium14Gi
rt1.micro11Gi
rt1.small12Gi
rt1.xlarge416Gi
u1.2xlarge832Gi
u1.2xmedium24Gi
u1.4xlarge1664Gi
u1.8xlarge32128Gi
u1.large28Gi
u1.medium14Gi
u1.micro11Gi
u1.nano1512Mi
u1.small12Gi
u1.xlarge416Gi

Резервирование ресурсов Kubelet

Каждая группа нод поддерживает объект kubelet, который задает, сколько памяти и CPU kubelet резервирует для host OS и Kubernetes/system компонентов, работающих на worker ноде.

Если systemReservedMemory или kubeReservedMemory оставлены пустыми, они вычисляются автоматически по следующей формуле:

  1. Определяется эффективный объем памяти ноды:
    • Если resources.memory задан явно, используется это значение.
    • Иначе ищется instanceType и используется его значение memory.guest.
    • Если недоступно ни то ни другое, используется минимальная резервация (256Mi).
  2. Вычисляется 5% от эффективного объема памяти (в MiB, с округлением вниз).
  3. Результат ограничивается диапазоном [256Mi, 1Gi]:
    • Ноды с 5 GiB или меньше получают минимальный резерв 256Mi.
    • Ноды с 20 GiB или больше получают максимальный резерв 1Gi.

По умолчанию systemReservedMemory и kubeReservedMemory получают одинаковое автоматически вычисленное значение.

CPU резервирование (systemReservedCpu, kubeReservedCpu) работают по той же схеме: 5% от effective CPU с ограничением диапазоном [50m, 500m]. Оба значения вычисляются автоматически, если оставлены пустыми.

Значения kubelet по умолчанию

ПараметрПо умолчаниюОписание
systemReservedMemoryauto-computedПамять, зарезервированная для host OS
kubeReservedMemoryauto-computedПамять, зарезервированная для kubelet и container runtime
systemReservedCpuauto-computedCPU, зарезервированный для host OS
kubeReservedCpuauto-computedCPU, зарезервированный для kubelet и container runtime
evictionHardMemory7%Жёсткий порог вытеснения по памяти
evictionSoftMemory10%Мягкий порог вытеснения по памяти
evictionSoftGracePeriod1m30s (hardcoded)Время, в течение которого мягкий порог вытеснения по памяти должен быть нарушен перед запуском вытеснения
evictionMinimumReclaim256Mi (hardcoded)Минимальный объем памяти, освобождаемый за одно действие вытеснения

Порог вытеснения можно задавать в процентах (например, 7%) или абсолютных значениях (например, 200Mi). Оба порога должны использовать один тип единиц. Жёсткий порог вытеснения должен быть строго меньше мягкого порога.

Параметры evictionSoftGracePeriod и evictionMinimumReclaim сейчас жёстко заданы в шаблоне и не могут быть переопределены через values.

Capacity Аннотации

Когда настроены резервации ресурсов 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 не учитывает эти резервации и может запланировать на ноду слишком много подов, что приведёт к срабатыванию вытеснения.

Пример: переопределение резерваций kubelet

nodeGroups:
  md0:
    instanceType: "u1.large"
    kubelet:
      systemReservedMemory: "256Mi"
      kubeReservedMemory: "256Mi"
      evictionHardMemory: "500Mi"
      evictionSoftMemory: "1Gi"

Серия U: Universal

Серия U имеет сбалансированный профиль и предоставляет ресурсы для приложений общего назначения.

U — сокращение от “Universal”, то есть серия рассчитана на универсальные рабочие нагрузки.

VM этих типов инстансов делят физические CPU-ядра с другими VM по принципу разделения процессорного времени.

Характеристики серии U

Особенности этой серии:

  • Burstable CPU performance - рабочая нагрузка имеет базовый уровень вычислительной производительности, но может кратковременно превышать его при наличии свободных вычислительных ресурсов.
  • vCPU-To-Memory Ratio (1:4) - соотношение vCPU к memory 1:4, чтобы снизить уровень шума на каждой ноде.

Серия O: Overcommitted

Серия O основана на серии U; единственное отличие — избыточное выделение памяти.

O — сокращение от “Overcommitted”.

Характеристики Серии O

Особенности этой серии:

  • Burstable CPU performance - рабочая нагрузка имеет базовый уровень вычислительной производительности, но может кратковременно превышать его при наличии свободных ресурсов хоста.
  • Overcommitted Memory - память используется с избытком, чтобы получить более высокую плотность размещения рабочей нагрузки.
  • vCPU-To-Memory Ratio (1:4) - соотношение vCPU к memory 1:4, чтобы снизить уровень шума каждой ноды.

Серия CX: Compute Exclusive

Серия CX предоставляет выделенные вычислительные ресурсы для приложений с высокой нагрузкой на CPU.

CX — сокращение от “Compute Exclusive”.

Выделенные ресурсы предоставляются вычислительным потокам виртуальной машины. Чтобы это обеспечить, запрашиваются дополнительные ядра (в зависимости от количества дисков и NIC), которые разгружают IO потоки с ядрами, выделенных под рабочие нагрузки. Кроме того, в этой серии топологии NUMA используемых ядер передается в VM.

Характеристики серии CX

Особенности этой серии:

  • Hugepages - hugepages используются для повышения производительности памяти.
  • Dedicated CPU - физические ядра эксклюзивно назначаются каждому vCPU, чтобы дать рабочей нагрузки фиксированные и высокие гарантии вычислительной мощности.
  • Isolated emulator threads - потоки эмулятора гипервизора изолируются от vCPU, чтобы снизить влияние эмуляции на рабочую нагрузку.
  • vNUMA - физическая топология NUMA отражается внутри гостевой VM, чтобы оптимизировать использование кеша на стороне гостевой VM.
  • vCPU-To-Memory Ratio (1:2) - соотношение vCPU к memory 1:2.

Серия M: Memory

Серия M предоставляет ресурсы для приложений с высокой нагрузкой на память.

M — сокращение от “Memory”.

Характеристики серии M

Особенности этой серии:

  • Hugepages - hugepages используются для повышения производительности памяти.
  • Burstable CPU performance - рабочая нагрузка имеет базовый уровень вычислительной производительности, но может кратковременно превышать его при наличии свободных ресурсов хоста.
  • vCPU-To-Memory Ratio (1:8) - соотношение vCPU к memory 1:8, чтобы заметно снизить уровень шума каждой ноды.

Серия RT: RealTime

Серия RT предоставляет ресурсы для приложений реального времени, например Oslat.

RT — сокращение от “realtime”.

Эта серия типов инстансов требует нод, способных запускать приложения реального времени.

Характеристики серии RT

Особенности этой серии:

  • Hugepages - hugepages используются для повышения производительности памяти.
  • Dedicated CPU - физические ядра эксклюзивно назначаются каждому vCPU, чтобы дать рабочей нагрузки фиксированные и высокие гарантии вычислительной мощности.
  • Isolated emulator threads - потоки эмулятора гипервизора изолируются от vCPU, чтобы снизить влияние эмуляции на рабочую нагрузку.
  • vCPU-To-Memory Ratio (1:4) - соотношение vCPU к memory 1:4 начиная с размера medium.

GPU Sharing с HAMi

Как включить дробное разделение GPU в tenant-кластерах Kubernetes с помощью HAMi.

Бэкапы с расширением Velero

Как включить расширение Velero в tenant-кластере Kubernetes, направить его в bucket SeaweedFS, а затем создавать и восстанавливать бэкапы workload.

Как перенести реплики etcd в tenant-кластерах

Как перенести реплики tenant-кластеров etcd, которые используются tenant-кластерами Kubernetes.