Установка и настройка Cozystack

Установка и настройка Cozystack

3. Установка и настройка Cozystack

Цели

Это руководство описывает установку Cozystack как готовой к использованию платформы. Если вы хотите собрать собственную платформу, устанавливая только нужные компоненты, см. руководство BYOP (Build Your Own Platform).

На этом шаге мы установим Cozystack поверх Kubernetes-кластера, подготовленного на предыдущем шаге.

Руководство проведёт вас через следующие этапы:

  1. Установка оператора Cozystack
  2. Подготовка файла конфигурации Cozystack и его применение
  3. Настройка хранилища
  4. Настройка сети
  5. Развёртывание etcd, ingress и стека мониторинга в корневом tenant’е
  6. Завершение развёртывания и вход в дашборд Cozystack

1. Установка оператора Cozystack

Установите оператор Cozystack с помощью Helm chart из OCI-реестра. Оператор управляет всеми компонентами платформы.

helm upgrade --install cozystack oci://ghcr.io/cozystack/cozystack/cozy-installer \
  --version X.Y.Z \
  --namespace cozy-system

Замените X.Y.Z на нужную версию Cozystack. Доступные версии перечислены на странице релизов Cozystack.

Если установка прерывается из-за того, что cozy-system уже существует: Helm отказывается забирать себе namespace, который создал не он, и выводит ошибку invalid ownership metadata (или namespaces в зависимости от версии Helm), если cozy-system остался после ранее прерванной установки или был создан вручную для этой цели.

Если namespace не управляется другим инструментом (Terraform, Argo CD, другим Helm release и т. д.), повторите команду с флагом --take-ownership (требуется Helm 3.17+), чтобы Helm смог принять его под управление:

helm upgrade --install cozystack oci://ghcr.io/cozystack/cozystack/cozy-installer \
  --version X.Y.Z \
  --namespace cozy-system \
  --create-namespace \
  --take-ownership

[!CAUTION] Не используйте --take-ownership, если cozy-system уже принадлежит другой системе — Helm незаметно станет новым владельцем, а последующие обновления или удаление релиза Cozystack могут изменить или удалить namespace (и всё, что было принято под управление этим флагом) вопреки ожиданиям этой системы.

2. Подготовка и применение Platform Package

2.1. Подготовьте файл конфигурации

Теперь, когда оператор запущен, подготовим для него файл конфигурации. Возьмите пример ниже и сохраните его в файл cozystack-platform.yaml:

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

Что нужно сделать:

  1. Замените example.org в publishing.host и publishing.apiServerEndpoint на маршрутизируемое полное доменное имя (FQDN), которым вы управляете. Если у вас есть только публичные IP-адреса, вы можете использовать сервис nip.io с dash-нотацией.
  2. Используйте для networking.* те же значения, что и на предыдущем шаге, где вы выполняли bootstrap Kubernetes-кластера через Talos. Чтобы узнать эти значения, вы можете проверить конфигурационные файлы Talos или выполнить команды talosctl. Значения из примера — это разумные значения по умолчанию, которые подходят для большинства случаев.

В этой конфигурации есть и другие значения, которые в рамках руководства менять не требуется. Тем не менее, вот что они означают:

  • metadata.name должен быть равен cozystack.cozystack-platform, чтобы совпасть с PackageSource, созданным установщиком.
  • publishing.host используется как основной домен для всех сервисов, создаваемых в Cozystack, например дашборда, Grafana и т. д.
  • publishing.apiServerEndpoint — это endpoint Cluster API. Он используется для генерации kubeconfig-файлов для пользователей. Рекомендуется использовать поддомен от publishing.host.
  • spec.variant: isp-full означает, что используется наиболее полный набор компонентов Cozystack. Подробнее о вариантах см. в справочнике по вариантам Cozystack.
  • publishing.exposedServices перечисляет сервисы, которые должны быть доступны пользователям — здесь это дашборд (UI) и API.
  • networking.* — это внутренняя сетевая конфигурация базового Kubernetes-кластера:
    • networking.podCIDR — диапазон CIDR, из которого Kube-OVN выделяет IP-адреса pod’ам. Он не должен пересекаться ни с одной физической сетью.
    • networking.podGateway — адрес шлюза, который Kube-OVN назначает подсети pod’ов по умолчанию. Используйте адрес .1 сети podCIDR (например, 10.244.0.1 для 10.244.0.0/16).
    • networking.serviceCIDR — диапазон CIDR для сервисов ClusterIP. Он обязательно должен совпадать со значением cluster.network.serviceSubnets, которое вы использовали при bootstrap Kubernetes-кластера: это значение вшивается в kube-apiserver и не может быть легко изменено позже.
    • networking.joinCIDR — диапазон CIDR для join подсети Kube-OVN, внутренней сети, которая переносит трафик между узлами кластера и pod’ами. Значение по умолчанию 100.64.0.0/16 входит в общее адресное пространство RFC 6598 (100.64.0.0/10), зарезервированное для такого внутреннего использования. Меняйте его только если оно пересекается с вашей физической сетью. Подробнее см. в справочнике по Kube-OVN join subnet.

Подробнее об этом файле конфигурации см. в справочнике Platform Package.

По умолчанию Cozystack собирает анонимную статистику использования. Подробнее о том, какие данные собираются и как это отключить, см. в документации по телеметрии.

2.2. Примените Platform Package

Примените файл конфигурации:

kubectl apply -f cozystack-platform.yaml

Во время установки можно следить за логами оператора:

kubectl logs -n cozy-system -l app.kubernetes.io/name=cozy-installer -f

2.3. Проверьте статус установки

Подождите немного, затем проверьте статус установки:

kubectl get packages.cozystack.io cozystack.cozystack-platform

Повторяйте проверку, пока во всех строках не появится True, как в этом примере:

kubectl get cozystack -A

Пример вывода:

cozy-cert-manager                cert-manager                4m1s   True    Release reconciliation succeeded
cozy-cert-manager                cert-manager-issuers        4m1s   True    Release reconciliation succeeded
cozy-cilium                      cilium                      4m1s   True    Release reconciliation succeeded
cozy-cluster-api                 capi-operator               4m1s   True    Release reconciliation succeeded
cozy-cluster-api                 capi-providers              4m1s   True    Release reconciliation succeeded
cozy-dashboard                   dashboard                   4m1s   True    Release reconciliation succeeded
cozy-grafana-operator            grafana-operator            4m1s   True    Release reconciliation succeeded
cozy-kamaji                      kamaji                      4m1s   True    Release reconciliation succeeded
cozy-kubeovn                     kubeovn                     4m1s   True    Release reconciliation succeeded
cozy-kubevirt-cdi                kubevirt-cdi                4m1s   True    Release reconciliation succeeded
cozy-kubevirt-cdi                kubevirt-cdi-operator       4m1s   True    Release reconciliation succeeded
cozy-kubevirt                    kubevirt                    4m1s   True    Release reconciliation succeeded
cozy-kubevirt                    kubevirt-operator           4m1s   True    Release reconciliation succeeded
cozy-linstor                     linstor                     4m1s   True    Release reconciliation succeeded
cozy-linstor                     piraeus-operator            4m1s   True    Release reconciliation succeeded
cozy-mariadb-operator            mariadb-operator            4m1s   True    Release reconciliation succeeded
cozy-metallb                     metallb                     4m1s   True    Release reconciliation succeeded
cozy-monitoring                  monitoring                  4m1s   True    Release reconciliation succeeded
cozy-postgres-operator           postgres-operator           4m1s   True    Release reconciliation succeeded
cozy-rabbitmq-operator           rabbitmq-operator           4m1s   True    Release reconciliation succeeded
cozy-redis-operator              redis-operator              4m1s   True    Release reconciliation succeeded
cozy-telepresence                telepresence                4m1s   True    Release reconciliation succeeded
cozy-victoria-metrics-operator   victoria-metrics-operator   4m1s   True    Release reconciliation succeeded
tenant-root                      tenant-root                 4m1s   True    Release reconciliation succeeded

Список компонентов в вашей установке может отличаться от приведённого выше, так как он зависит от выбранного варианта и версии Cozystack. Когда у всех компонентов появится READY: True, можно переходить к настройке подсистем.

3. Настройка хранилища

Kubernetes нужен слой хранилища для предоставления persistent volumes приложениям, но собственного такого механизма у него нет. В качестве подсистемы хранения Cozystack использует LINSTOR. Далее мы получим доступ к интерфейсу LINSTOR, создадим storage pool’ы и определим storage class’ы.

3.1. Проверьте устройства хранения

Настройте alias для доступа к LINSTOR:

alias linstor='kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor'

Выведите список узлов и проверьте их готовность:

linstor node list

Выведите список доступных пустых устройств:

linstor physical-disk list

3.2. Создайте storage pool’ы

Создайте storage pool’ы на основе ZFS:

linstor storage-pool create zfs srv1 data data
linstor storage-pool create zfs srv2 data data
linstor storage-pool create zfs srv3 data data

Рекомендуется установить для ZFS storage pool’ов failmode=continue, чтобы обработкой отказов диска занимался DRBD, а не ZFS.

kubectl exec -ti -n cozy-linstor ds/linstor-satellite.srv1 -- zpool set failmode=continue data
kubectl exec -ti -n cozy-linstor ds/linstor-satellite.srv2 -- zpool set failmode=continue data
kubectl exec -ti -n cozy-linstor ds/linstor-satellite.srv3 -- zpool set failmode=continue data

Проверьте результат, выведя список storage pool’ов:

linstor storage-pool list

Пример вывода:

StoragePoolNodeDriverPoolNameFreeCapacityTotalCapacityCanSnapshots
DfltDisklessStorPoolsrv1DISKLESSFalse
DfltDisklessStorPoolsrv2DISKLESSFalse
DfltDisklessStorPoolsrv3DISKLESSFalse
datasrv1ZFSdata96.41 GiB99.50 GiBTrue
datasrv2ZFSdata96.41 GiB99.50 GiBTrue
datasrv3ZFSdata96.41 GiB99.50 GiBTrue

3.3. Создайте storage class’ы

Наконец, можно создать несколько storage class’ов, один из которых будет классом по умолчанию. Создайте файл с описанием storage class’ов. Ниже приведён разумный пример по умолчанию с двумя классами: local (по умолчанию) и replicated.

storageclasses.yaml:

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: linstor.csi.linbit.com
parameters:
  linstor.csi.linbit.com/storagePool: data
  linstor.csi.linbit.com/layerList: storage
  linstor.csi.linbit.com/allowRemoteVolumeAccess: "true"
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: replicated
provisioner: linstor.csi.linbit.com
parameters:
  linstor.csi.linbit.com/storagePool: data
  linstor.csi.linbit.com/autoPlace: "3"
  linstor.csi.linbit.com/layerList: drbd storage
  linstor.csi.linbit.com/allowRemoteVolumeAccess: "true"
  property.linstor.csi.linbit.com/DrbdOptions/auto-quorum: suspend-io
  property.linstor.csi.linbit.com/DrbdOptions/Resource/on-no-data-accessible: suspend-io
  property.linstor.csi.linbit.com/DrbdOptions/Resource/on-suspended-primary-outdated: force-secondary
  property.linstor.csi.linbit.com/DrbdOptions/Net/rr-conflict: retry-connect
volumeBindingMode: Immediate
allowVolumeExpansion: true

Примените конфигурацию storage class’ов:

kubectl apply -f storageclasses.yaml

Убедитесь, что storage class’ы были успешно созданы:

kubectl get storageclasses

Пример вывода:

NAMEPROVISIONERRECLAIMPOLICYVOLUMEBINDINGMODEALLOWVOLUMEEXPANSION
local (default)linstor.csi.linbit.comDeleteWaitForFirstConsumertrue
replicatedlinstor.csi.linbit.comDeleteImmediatetrue

4. Настройка сети

Далее мы настроим способ доступа к кластеру Cozystack. На этом шаге есть два варианта в зависимости от доступной инфраструктуры:

Загляните в раздел provider-specific installation. Возможно, там уже есть инструкции для вашего провайдера, подходящие для развёртывания production-ready кластера.

4.a Настройка MetalLB

В Cozystack используются три типа IP-адресов:

  1. IP-адреса узлов: постоянные и действуют только внутри кластера.
  2. Виртуальный floating IP: используется для доступа к одному из узлов кластера и также действует только внутри кластера.
  3. IP-адреса внешнего доступа: используются LoadBalancer’ами для публикации сервисов за пределами кластера.

Сервисы с внешними IP могут публиковаться в двух режимах: L2 и BGP. Режим L2 проще, но требует, чтобы все узлы находились в одном L2-сегменте. Режим BGP более надёжен и масштабируем, но требует поддержки BGP со стороны сетевого оборудования.

Выберите диапазон неиспользуемых IP-адресов для сервисов; в примере используется диапазон 192.168.100.200-192.168.100.250. Если вы используете режим L2, эти IP должны либо принадлежать той же сети, что и узлы, либо до них должен быть настроен проброс трафика (маршрутизация).

Для режима BGP также потребуются IP-адреса BGP peer’ов и локальные и удалённые номера AS. В примере ниже используется 192.168.20.254 как IP peer’а и номера AS 65000 и 65001 как локальный и удалённый соответственно.

Создайте и примените файл с описанием пула адресов metallb-ip-address-pool.yml:

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: cozystack
  namespace: cozy-metallb
spec:
  addresses:
  # используется для публикации сервисов за пределами кластера
  - 192.168.100.200-192.168.100.250
  autoAssign: true
  avoidBuggyIPs: false
kubectl apply -f metallb-ip-address-pool.yml

Создайте и примените ресурсы, необходимые для L2- или BGP-анонса. L2Advertisement использует имя ресурса IPAddressPool, который мы создали на предыдущем шаге.

metallb-l2-advertisement.yml:

apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: cozystack
  namespace: cozy-metallb
spec:
  ipAddressPools:
  - cozystack

Примените изменения:

kubectl apply -f metallb-l2-advertisement.yml

Теперь, когда MetalLB настроен, включите ingress в tenant-root:

kubectl patch -n tenant-root tenants.apps.cozystack.io root --type=merge -p '{"spec":{"components":{"ingress":{"enabled":true}}}}'

Чтобы убедиться, что всё настроено корректно, проверьте HelmRelease’ы ingress и ingress-nginx-system:

kubectl get hr -n tenant-root

Пример корректного вывода:

ingress                47m   True    Helm upgrade succeeded for release tenant-root/ingress.v3 with...
ingress-nginx-system   47m   True    Helm upgrade succeeded for release tenant-root/ingress-nginx-s...

Затем проверьте состояние сервиса root-ingress-controller:

kubectl get svc -n tenant-root root-ingress-controller

Сервис должен быть развёрнут как TYPE: LoadBalancer и иметь корректный внешний IP:

NAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)
root-ingress-controllerLoadBalancer10.96.16.141192.168.100.20080:31632/TCP, 443:30113/TCP

4.b. Настройка публичных IP узлов

Если ваш облачный провайдер не поддерживает MetalLB, вы можете опубликовать ingress controller через externalIPs напрямую. Если публичные IP привязаны непосредственно к узлам, укажите их. Если публичные IP предоставляются облаком как виртуальные (Elastic IP), укажите IP-адреса внешних сетевых интерфейсов. В примере используются 192.168.100.11, 192.168.100.12 и 192.168.100.13.

Сначала добавьте внешние IP в Platform Package:

kubectl patch packages.cozystack.io cozystack.cozystack-platform --type=merge -p '{"spec":{"components":{"platform":{"values":{"publishing":{"externalIPs":["192.168.100.11","192.168.100.12","192.168.100.13"]}}}}}}'

Затем включите ingress для корневого tenant’а:

kubectl patch -n tenant-root tenants.apps.cozystack.io root --type=merge -p '{"spec":{"components":{"ingress":{"enabled":true}}}}'

Наконец, добавьте внешние IP-адреса в список externalIPs в конфигурации Ingress:

kubectl patch -n tenant-root ingresses.apps.cozystack.io ingress --type=merge -p '{"spec":{"externalIPs":["192.168.100.11","192.168.100.12","192.168.100.13"]}}'

После этого ваш Ingress будет доступен по указанным IP-адресам. Проверьте это так:

kubectl get svc -n tenant-root root-ingress-controller

Сервис должен быть развёрнут как TYPE: ClusterIP и содержать полный список внешних IP:

NAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)
root-ingress-controllerClusterIP10.96.91.83192.168.100.11, 192.168.100.12, 192.168.100.1380/TCP, 443/TCP

5. Завершение установки

5.1. Настройте сервисы корневого tenant’а

Включите etcd и monitoring для корневого tenant’а:

kubectl patch -n tenant-root tenants.apps.cozystack.io root --type=merge -p '{"spec":{"components":{"monitoring":{"enabled":true},"etcd":{"enabled":true}}}}'

5.2. Проверьте состояние и состав кластера

Проверьте созданные persistent volume’ы:

kubectl get pvc -A

Пример вывода:

NAMESTATUSVOLUMECAPACITY
data-etcd-0Boundpvc-4cbd29cc-a29f-453d-b412-451647cd04bf10Gi
data-etcd-1Boundpvc-1579f95a-a69d-4a26-bcc2-b15ccdbede0d10Gi
data-etcd-2Boundpvc-907009e5-88bf-4d18-91e7-b56b0dbfb97e10Gi
grafana-db-1Boundpvc-7b3f4e23-228a-46fd-b820-d033ef4679af10Gi
grafana-db-2Boundpvc-ac9b72a4-f40e-47e8-ad24-f50d843b55e410Gi
vmselect-cachedir-vmselect-longterm-0Boundpvc-622fa398-2104-459f-8744-565eee0a13f12Gi
vmselect-cachedir-vmselect-longterm-1Boundpvc-fc9349f5-02b2-4e25-8bef-6cbc5cc6d6902Gi
vmselect-cachedir-vmselect-shortterm-0Boundpvc-7acc7ff6-6b9b-4676-bd1f-6867ea7165e22Gi
vmselect-cachedir-vmselect-shortterm-1Boundpvc-e514f12b-f1f6-40ff-9838-a6bda3580eb72Gi
vmstorage-db-vmstorage-longterm-0Boundpvc-e8ac7fc3-df0d-4692-aebf-9f66f72f9fef10Gi
vmstorage-db-vmstorage-longterm-1Boundpvc-68b5ceaf-3ed1-4e5a-9568-6b95911c7c3a10Gi
vmstorage-db-vmstorage-shortterm-0Boundpvc-cee3a2a4-5680-4880-bc2a-85c14dba938010Gi
vmstorage-db-vmstorage-shortterm-1Boundpvc-d55c235d-cada-4c4a-8299-e5fc3f16178910Gi

Убедитесь, что все pod’ы запущены:

kubectl get pod -n tenant-root

пример вывода:

NAMEREADYSTATUSRESTARTSAGE
etcd-01/1Running02m1s
etcd-11/1Running0106s
etcd-21/1Running082s
grafana-db-11/1Running0119s
grafana-db-21/1Running013s
grafana-deployment-74b5656d6-5dcvn1/1Running090s
grafana-deployment-74b5656d6-q55891/1Running1 (105s ago)111s

Получите публичный IP ingress controller:

kubectl get svc -n tenant-root root-ingress-controller

Пример вывода:

NAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)
root-ingress-controllerLoadBalancer10.96.16.141192.168.100.20080:31632/TCP, 443:30113/TCP

5.3 Доступ к дашборду Cozystack

Если вы включили dashboard в список publishing.exposedServices вашего Platform Package (как показано на шаге 2), дашборд Cozystack уже доступен. Если в исходной конфигурации его не было, обновите Platform Package:

kubectl patch packages.cozystack.io cozystack.cozystack-platform --type=json -p '[{"op":"add","path":"/spec/components/platform/values/publishing/exposedServices/-","value":"dashboard"}]'

Откройте dashboard.example.org, чтобы перейти в системный дашборд, где example.org — домен, указанный вами для tenant-root. Там вы увидите окно входа, ожидающее токен аутентификации.

Получите токен аутентификации для tenant-root:

kubectl get secret -n tenant-root tenant-root -o go-template='{{ printf "%s\n" .data.token | base64decode }}'

Войдите с этим токеном. Теперь вы можете пользоваться дашбордом как администратор. Дальше вы сможете:

  • Настроить OIDC и использовать его вместо токенов для аутентификации.
  • Создавать пользовательские tenant’ы и выдавать пользователям доступ через токены или OIDC.

5.4 Доступ к метрикам в Grafana

Используйте grafana.example.org для доступа к системному мониторингу, где example.org — домен, указанный для tenant-root. В этом примере grafana.example.org доступен по адресу 192.168.100.200.

логин: admin получите пароль:

kubectl get secret -n tenant-root grafana-admin-password -o go-template='{{ printf "%s\n" .data.password | base64decode }}'

Следующий шаг

Продолжите руководство по Cozystack и создайте пользовательский tenant.