Справочник Platform Package

Справочник по Cozystack Platform Package, который задает ключевые параметры конфигурации для установки и эксплуатации Cozystack.

На этой странице описана роль Cozystack Platform Package и приведен полный справочник по его values.

Основная конфигурация Cozystack задается custom resource Package. Этот Package включает вариант Cozystack, настройки компонентов, ключевые сетевые параметры, опубликованные сервисы и другие опции.

Пример

Ниже пример конфигурации для установки Cozystack с вариантом isp-full, root host example.org, а также опубликованными и доступными пользователям Cozystack Dashboard и API:

apiVersion: cozystack.io/v1alpha1
kind: Package
metadata:
  name: cozystack.cozystack-platform
spec:
  variant: isp-full
  components:
    platform:
      values:
        publishing:
          host: "example.org"
          apiServerEndpoint: "https://api.example.org:443"
          exposedServices:
            - dashboard
            - api
        networking:
          podCIDR: "10.244.0.0/16"
          podGateway: "10.244.0.1"
          serviceCIDR: "10.96.0.0/16"
          joinCIDR: "100.64.0.0/16"

Справочник

Поля уровня Package

ПолеОписание
spec.variantВариант, используемый для установки, например isp-full, isp-full-generic, isp-hosted, distro-full.

Platform values (spec.components.platform.values.*)

Публикация

ЗначениеПо умолчаниюОписание
publishing.host"example.org"Основной домен для всех сервисов, создаваемых в Cozystack: dashboard, Grafana, Keycloak и других.
publishing.apiServerEndpoint""Используется для генерации kubeconfig-файлов для пользователей. Рекомендуется использовать маршрутизируемый FQDN или IP-адрес вместо адресов, доступных только локально. Пример: "https://api.example.org".
publishing.exposedServices[api, dashboard, vm-exportproxy, cdi-uploadproxy]Список сервисов для публикации. Возможные значения: api, dashboard, cdi-uploadproxy, vm-exportproxy.
publishing.ingressName"tenant-root"Ingress controller, используемый для публикации сервисов.
publishing.externalIPs[]Список external IP, используемых указанным ingress controller. Если не задан, по умолчанию используется сервис LoadBalancer.
publishing.ingressNameAdmin""Имя отдельного административного ingress, к которому системные компоненты подключают свои административные маршруты (на данный момент только Keycloak) — например, привязанного к приватному IP и недоступного из интернета. На пути через Gateway значение — это namespace (для Gateway с именем cozystack); на пути через ingress-nginx это ingressClassName. Эти два варианта совпадают, потому что Cozystack называет каждый ingressClass по имени namespace тенанта. Пустое значение (по умолчанию) оставляет административные эндпоинты на publishing.ingressName. Два предостережения: Cozystack не создаёт административный Gateway — его нужно предварительно подготовить отдельно, иначе административные маршруты окажутся ни к чему не подключены; а также административные маршруты рендерятся только когда у Keycloak установлен ingress.adminHost, поэтому установка одного этого ключа сама по себе ничего не даёт.
publishing.exposureClass.name""Логическое имя кластерного ресурса ExposureClass, который нужно отрендерить. Пустое значение (по умолчанию) оставляет путь publishing.externalIPs без изменений. Когда значение задано, host ingress — при пустом publishing.externalIPs — публикует свой Service как type: LoadBalancer, а cozystack-controller транслирует класс в пул VIP выбранного backend и его анонсировщик. Это путь миграции с Service.spec.externalIPs, устаревшего начиная с Kubernetes v1.36 (KEP-5707). Удаление происходит поэтапно: feature gate AllowServiceExternalIPs поставляется включённым в v1.36, затем по умолчанию становится false (цель KEP: v1.40), после чего kube-proxy перестаёт программировать правила для этого поля — API всё ещё принимает его, поэтому Service выглядит здоровым, хотя трафик никуда не приходит. На последующих этапах gate блокируется в выключенном состоянии, а поддержка в kube-proxy полностью удаляется, и в итоге сам gate и admission-контроллер DenyServiceExternalIPs убираются. KEP указывает эти более поздние релизы как приблизительные, а объявление для v1.36 обещает лишь «будущий минорный релиз», поэтому переключение значения по умолчанию на false стоит воспринимать как дедлайн и мигрировать на класс до этого обновления, а не ориентироваться на конкретную версию.
publishing.exposureClass.backend"externalIPs"Механизм LoadBalancer, стоящий за классом. externalIPs фиксирует IP узлов без пула или анонсировщика (историческое поведение); metallb рендерит IPAddressPool + L2Advertisement; cilium рендерит CiliumLoadBalancerIPPool + CiliumL2AnnouncementPolicy; robotlb использует облачный (Hetzner) load balancer, где выделение и анонсирование происходят вне кластера. Как только publishing.exposureClass.name задан, backend с пулом или облачный backend (metallb, cilium, robotlb) взаимно исключает непустой publishing.externalIPs — рендер платформы завершится явной ошибкой, а не отправит нерабочий вариант в production, потому что Service host ingress остался бы ClusterIP + externalIPs, никогда не стал бы type: LoadBalancer, а выделенный пул остался бы неиспользованным.
publishing.exposureClass.addresses[]VIP CIDR или диапазоны вида start-end для backend’ов с пулом (metallb, cilium).
publishing.exposureClass.l2trueАнонсирование L2 (ARP / NDP) для bare-metal backend’ов.
publishing.exposureClass.isDefaulttrueДелает этот класс используемым по умолчанию для любого ServiceExposure, который не указывает имя класса. ServiceExposure — это внутрикластерный ресурс, который cozystack-controller реконсилирует, чтобы опубликовать Service через backend класса; рабочие нагрузки не создают его напрямую. Поскольку по умолчанию это значение true, ручное создание второго ExposureClass без снятия у него флага default оставляет два класса по умолчанию, и контроллер тогда завершает с ошибкой AmbiguousDefaultClass каждый ServiceExposure без указанного имени — необходимо поддерживать ровно один класс по умолчанию.
publishing.certificates.solver"http01"Тип ACME challenge solver для letsencrypt issuer по умолчанию. Возможные значения: http01, dns01.
publishing.certificates.issuerName"letsencrypt-prod"Имя ClusterIssuer для TLS-сертификатов, используемых в системных Helm releases.
publishing.certificates.wildcardfalseОпциональное включение общего wildcard-сертификата на пути ingress-nginx по умолчанию (gateway.enabled=false). Когда значение true при solver=dns01 и без указания publishing.certificates.wildcardSecretName, платформа выпускает один Certificate вида *.<root-host> + <root-host> через DNS-01 ClusterIssuer и использует его как SSL-сертификат по умолчанию для ingress-контроллера — таким образом системные сервисы перестают выпускать отдельный ACME-сертификат на каждый хост, что позволяет избежать лимитов Let’s Encrypt при масштабировании (аналогично поведению на пути Gateway API). Игнорируется при http01 (wildcard-сертификаты выпускать нельзя) и при gateway.enabled=true (в этом случае wildcard-сертификат выпускает контроллер TenantGateway). При включении имя выпущенного Secret передаётся в тот же канал значений кластера, что и publishing.certificates.wildcardSecretName, поэтому возникает та же проблема с дочерними тенантами и та же открытая ошибка ( cozystack/cozystack#3296): у всех тенантов системные ingress-ресурсы во всём кластере теряют собственный ACME-сертификат на каждый хост, но wildcard-сертификат обслуживается только контроллером публикации. Дочерний тенант, запускающий собственный ingress-контроллер (ingress: true), в результате остаётся без сертификата и обслуживается встроенным самоподписанным сертификатом ingress-nginx; наследующий дочерний тенант на общем контроллере вместо этого получает несовпадение имени хоста, поскольку однокомпонентный wildcard *.<root-host> не покрывает вложенный хост вида <service>.<tenant>.<root-host> или произвольный ingress.host на другом домене. Включайте эту опцию только тогда, когда покрыты все публикуемые хосты и ни один дочерний тенант не запускает собственный ingress-контроллер. По умолчанию отключено, чтобы кластер с dns01 никогда не переключался незаметно при обновлении.
publishing.certificates.wildcardSecretName""Wildcard TLS Secret, предоставленный оператором. Если задан, системные сервисы платформы и ingress/Gateway корневого тенанта используют этот заранее существующий Secret вместо выпуска отдельных ACME-сертификатов на каждый хост (по каналу значений передаётся только ИМЯ — но никогда сам ключевой материал), и этот параметр имеет приоритет над publishing.certificates.wildcard. Secret должен существовать в namespace публикации (по умолчанию tenant-root), содержать корректный PEM в полях tls.crt / tls.key (создан как kubernetes.io/tls, хотя проверяется только сам материал) и покрывать обслуживаемые хосты. Область действия ограничена корневым тенантом, но это не проверяется принудительно — имя достигает всех тенантов, из-за чего дочерний тенант, запускающий собственный ingress-контроллер, может остаться с самоподписанным сертификатом ( cozystack/cozystack#3296). Полное описание поведения и трёх случаев для дочерних тенантов см. в разделе Gateway API → Certificates. Оставьте пустым, чтобы сохранить выпуск сертификатов через ACME.
publishing.certificates.dns01.provider"cloudflare"DNS-01 provider, когда solver=dns01. Возможные значения: cloudflare, route53, digitalocean, rfc2136. Это значение читают и per-tenant Issuer (формируемый cozystack-controller из CR TenantGateway), и общекластерные ClusterIssuer letsencrypt-prod / letsencrypt-stage, используемые прежним ingress-механизмом.
publishing.certificates.dns01.cloudflare.secretName"cloudflare-api-token-secret"Имя Secret с Cloudflare API token, имеющим права Zone:Read + Zone:DNS:Edit на apex-зону.
publishing.certificates.dns01.cloudflare.secretKey"api-token"Ключ внутри Secret, содержащий API token.
publishing.certificates.dns01.route53.region""AWS-регион hosted zone Route53. Требуется, когда provider=route53.
publishing.certificates.dns01.route53.accessKeyID""IAM access key ID. Необязателен при работе с IRSA / instance profile.
publishing.certificates.dns01.route53.secretName""Имя Secret с IAM secret access key. Необязателен при работе с IRSA / instance profile.
publishing.certificates.dns01.route53.secretKey"secret-access-key"Ключ внутри Secret Route53, содержащий secret access key.
publishing.certificates.dns01.digitalocean.secretName"digitalocean-api-token-secret"Имя Secret с DigitalOcean API token, имеющим доступ на запись к apex-домену.
publishing.certificates.dns01.digitalocean.secretKey"access-token"Ключ внутри Secret, содержащий DigitalOcean token.
publishing.certificates.dns01.rfc2136.nameserver""host:port авторитетного nameserver, принимающего динамические обновления RFC 2136. Требуется, когда provider=rfc2136.
publishing.certificates.dns01.rfc2136.tsigKeyName""Имя TSIG-ключа, авторизующего динамические обновления. Требуется, когда provider=rfc2136.
publishing.certificates.dns01.rfc2136.tsigAlgorithm"HMACSHA256"HMAC-алгоритм TSIG.
publishing.certificates.dns01.rfc2136.secretName""Имя Secret с материалом TSIG-ключа. Требуется, когда provider=rfc2136.
publishing.certificates.dns01.rfc2136.secretKey"tsig-secret-key"Ключ внутри Secret, содержащий TSIG-ключ.
publishing.proxyProtocolfalseВключает PROXY-протокол на хост-инстансе ingress-nginx и автоматически развёртывает ouroboros для устранения возникающей проблемы hairpin-NAT. Вышестоящий L4-балансировщик перед ingress-nginx должен уже внедрять заголовки PROXY-v1 до включения этого флага; см. связанную страницу для рецептов проверки и пути отключения.
publishing.proxyProtocolAcknowledgeUncleanfalseФлаг подтверждения для асимметрии helm.sh/resource-policy: keep на пути отключения хоста. Переключение publishing.proxyProtocol с true обратно на false прекращает генерацию Package CR cozystack.ouroboros, но не удаляет уже существующий — рендеринг платформы завершается с ошибкой до тех пор, пока либо Package CR не будет удалён (что запускает pre-delete cleanup хук чарта), либо этот флаг не будет установлен в true, подтверждая, что оператор обработал асимметрию. См. hairpin-proxy-protocol → Disable path для полной последовательности действий.

publishing.exposure намеренно не указан выше: этот ключ существовал только в v1.4 и был удалён до выхода v1.5. Он всё ещё работает на кластере v1.4, но начиная с v1.5 не имеет никакого эффекта — его преемником является publishing.exposureClass. Удалите этот ключ при обновлении с v1.4 — и проверьте, во что превращается Service хост-ingress. Кластер v1.4 с publishing.exposure: loadBalancer имел Service типа LoadBalancer с externalTrafficPolicy: Local; начиная с v1.5 ключ игнорируется, поэтому кластер с установленным publishing.externalIPs незаметно откатывается к Service типа ClusterIP с externalTrafficPolicy: Cluster и перестаёт сохранять исходный IP клиента.

Сеть

ЗначениеПо умолчаниюОписание
networking.clusterDomain"cozy.local"Внутреннее доменное имя кластера.
networking.podCIDR"10.244.0.0/16"Pod-подсеть, из которой Pods получают IP-адреса.
networking.podGateway"10.244.0.1"Адрес gateway для pod-подсети.
networking.serviceCIDR"10.96.0.0/16"Service-подсеть, из которой Services получают IP-адреса.
networking.joinCIDR"100.64.0.0/16"Подсеть join для сетевого взаимодействия между Node и Pod. Подробнее см. в документации kube-ovn.
networking.kubeovn.MASTER_NODES""Разделённый запятыми список IP-адресов master-узлов KubeOVN. По умолчанию KubeOVN использует lookup, чтобы найти control-plane-узлы по label node-role.kubernetes.io/control-plane. На новых кластерах lookup может вернуть пустой результат. Задайте это значение, чтобы переопределить поведение.

Bundles

ЗначениеПо умолчаниюОписание
bundles.system.enabledfalseВключить system bundle. Управляется оператором на основе spec.variant.
bundles.system.variant"isp-full"Вариант system bundle. Варианты: isp-full, isp-full-generic, isp-hosted. Управляется оператором на основе spec.variant.
bundles.iaas.enabledfalseВключить IaaS bundle. Управляется оператором на основе spec.variant.
bundles.paas.enabledfalseВключить PaaS bundle. Управляется оператором на основе spec.variant.
bundles.naas.enabledfalseВключить NaaS bundle. Управляется оператором на основе spec.variant.
bundles.enabledPackages[]Список опциональных компонентов bundle, которые нужно включить в установку. Подробнее см. “Как включать и отключать компоненты bundle”.
bundles.disabledPackages[]Список компонентов bundle, которые нужно исключить из установки. Подробнее см. “Как включать и отключать компоненты bundle”.

Аутентификация

ЗначениеПо умолчаниюОписание
authentication.oidc.enabledfalseВключить функцию OIDC в Cozystack.
authentication.oidc.insecureSkipVerifyfalseПропускать проверку TLS-сертификата OIDC provider.
authentication.oidc.keycloakExtraRedirectUri""Дополнительный redirect URI для Keycloak OIDC client.
authentication.oidc.keycloakInternalUrl""Внутренний URL для backend-to-backend-запросов к Keycloak. Когда он задан, oauth2-proxy dashboard пропускает OIDC discovery и направляет запросы token, JWKS, userinfo и logout через этот URL, сохраняя browser redirects на внешний URL. Пример: http://keycloak-http.cozy-keycloak.svc:8080/realms/cozy.

Gateway

Общеплатформенная интеграция Gateway API. Фактический per-tenant Gateway создаётся только для тенантов, которые явно включают его через tenant.spec.gateway: true (обычно tenant-root плюс любой тенант, которому нужен собственный LB IP, кастомный apex или отдельный ACME-аккаунт). Все остальные тенанты в дереве публикуются через Gateway ближайшего предка, который им владеет — так же, как наследование _namespace.ingress. Полную архитектуру и путь миграции см. в руководстве по Gateway API.

ЗначениеПо умолчаниюОписание
gateway.enabledfalseВключить поддержку Gateway API на всей платформе. Когда true, ClusterIssuer cert-manager используют solver http01.gatewayHTTPRoute, привязанный к Gateway публикующего тенанта, а опубликованные сервисы (dashboard, keycloak, grafana, alerta, harbor, bucket, cozystack-api, vm-exportproxy, cdi-uploadproxy) формируют HTTPRoute/TLSRoute вместо Ingress. Создание фактического per-tenant Gateway по-прежнему требует, чтобы владеющий тенант задал tenant.spec.gateway: true.
gateway.http2trueАнонсировать HTTP/2 через TLS ALPN (h2, затем http/1.1) на каждом listener’е Gateway API, обслуживаемом встроенным дataplane Cilium. Браузеры договариваются об использовании HTTP/2 исключительно через ALPN, поэтому при отключении этой опции каждый клиент незаметно откатывается на HTTP/1.1 — предыдущий путь через ingress-nginx (до появления Gateway) анонсировал h2 из коробки, поэтому по умолчанию эта опция включена. Влияет только на участок клиент↔gateway: соединения gateway↔backend остаются на HTTP/1.1, если только Service явно не подключит это через GEP-1911, указав appProtocol: kubernetes.io/h2c на своём порту (поддержка этого backend-протокола включается одновременно с ALPN). Соответствует общекластерной настройке агента Cilium enable-gateway-api-alpn, поэтому покрывает сразу root и все tenant Gateway без возможности настройки на уровне отдельного Gateway; действует только на сборках, где Cozystack управляет Cilium (isp-full, isp-full-generic). Переключение этой опции приведёт к перезапуску DaemonSet cilium при следующем обновлении платформы — тот же профиль нарушения работы, что и при любом другом изменении конфигурации Cilium.
gateway.attachedNamespaces(см. ниже)Namespaces, чьи ресурсы HTTPRoute / TLSRoute должны публиковаться через Gateway владеющего тенанта. Контроллер проставляет namespace.cozystack.io/gateway = <owner> на каждый перечисленный namespace, чтобы его routes проходили label-селектор allowedRoutes у listeners HTTPS и TLS-passthrough. HTTP-listener на порту 80 использует отдельный, более узкий whitelist (только <owner-tenant-ns> и cozy-cert-manager) и НЕ допускает routes из attachedNamespaces. Собственный namespace публикующего тенанта и его потомки допускаются через тот же label, проставляемый чартом тенанта. Namespaces тенантов (tenant-*) тоже можно перечислять — они просто получают label привязки к gateway наряду с системными namespaces cozy-*. Namespace default включён по умолчанию, потому что TLSRoute для Kubernetes API живёт рядом с Service kubernetes в default.

gateway.attachedNamespaces по умолчанию:

gateway:
  attachedNamespaces:
    - cozy-cert-manager
    - cozy-dashboard
    - cozy-keycloak
    - cozy-system
    - cozy-harbor
    - cozy-bucket
    - cozy-kubevirt
    - cozy-kubevirt-cdi
    - cozy-monitoring
    - cozy-linstor-gui
    - default

Планирование

ЗначениеПо умолчаниюОписание
scheduling.globalAppTopologySpreadConstraints""Глобальные pod topology spread constraints, применяемые ко всем managed applications.

Backup storage

ValueDefaultDescription
backupStorage{}Координаты S3 для управляемого платформой класса резервного копирования cozy-default (BackupClass). Весь этот блок передаётся в компонент backupstrategy-controller и глубоко объединяется (deep-merge) со значениями по умолчанию из чарта; ключи включают provisionBucket, bucketName, endpoint, region, forcePathStyle, systemSecretName и systemNamespaces. См. Классы резервного копирования для подробного описания каждого параметра.

Брендинг

ЗначениеПо умолчаниюОписание
branding{}Объект конфигурации UI branding. Доступные поля и использование описаны в руководстве White Labeling. У отдельных полей, например titleText, logoSvg, есть собственные значения по умолчанию, если они не заданы.

Registries

Конфигурация mirrors для container registry. Позволяет направлять image pulls через локальные mirrors.

ЗначениеПо умолчаниюОписание
registries.mirrors{}Карта имён registry hostnames к mirror endpoints. Каждая запись сопоставляет registry, например docker.io, со списком mirror endpoints.
registries.config{}Конфигурация для отдельных endpoints, например настройки TLS.

Пример:

registries:
  mirrors:
    docker.io:
      endpoints:
        - http://10.0.0.1:8082
    ghcr.io:
      endpoints:
        - http://10.0.0.1:8083
  config:
    "10.0.0.1:8082":
      tls:
        insecureSkipVerify: true

Ресурсы

ЗначениеПо умолчаниюОписание
resources.cpuAllocationRatio10CPU allocation ratio: на 1 vCPU запрашивается 1/cpuAllocationRatio CPU. Подробное объяснение и примеры см. в Resource Management.
resources.memoryAllocationRatio1Memory allocation ratio: на единицу настроенной памяти запрашивается 1/memoryAllocationRatio памяти.
resources.ephemeralStorageAllocationRatio40Ephemeral storage allocation ratio: на единицу настроенного хранилища запрашивается 1/ephemeralStorageAllocationRatio ephemeral storage.

Внутренние поля

Этими полями автоматически управляет оператор Cozystack, их не следует изменять вручную.

ЗначениеПо умолчаниюОписание
sourceRef.kind"OCIRepository"Kind source reference для platform package.
sourceRef.name"cozystack-platform"Имя source reference.
sourceRef.namespace"cozy-system"Namespace source reference.
sourceRef.path"/"Path source reference.
migrations.enabledfalseВключены ли platform migrations.
migrations.imageContainer image, используемый для запуска platform migrations.
migrations.targetVersionНомер целевой версии миграции.