Установка CodeScoring.Save в Kubernetes

CodeScoring.Save устанавливается с помощью Helm-чарта save. Один и тот же чарт поддерживает два сценария развертывания:

  • стандартную установку в Kubernetes с PostgreSQL, Redis, а также поддержкой S3-совместимого объектного хранилища;
  • hosted-установку в одноузловом кластере k3s с SQLite и файловым хранилищем.

Перед установкой проверьте системные требования.

Установка с помощью Helm-чарта

Адреса Helm-репозитория и реестра контейнерных образов, а также учетные данные предоставляет вендор. В командах ниже используются следующие обозначения:

  • HELM_REPOSITORY_URL — адрес Helm-репозитория;
  • REGISTRY_URL — адрес реестра контейнерных образов;
  • USERNAME и PASSWORD — учетные данные для доступа;
  • CHART_VERSION — версия Helm-чарта и CodeScoring.Save.
  1. Создайте namespace:

    kubectl create namespace codescoring-save --dry-run=client -o yaml | kubectl apply -f -
  2. Создайте Secret для доступа к приватному реестру контейнерных образов:

    kubectl create secret docker-registry codescoring-regcred \
      --namespace codescoring-save \
      --docker-server=REGISTRY_URL \
      --docker-username=USERNAME \
      --docker-password=PASSWORD \
      --dry-run=client -o yaml | kubectl apply -f -

    Имя Secret должно совпадать со значениями image.pullSecrets и osa-proxy.imagePullSecrets в values.yaml.

  3. Установите Helm и добавьте репозиторий CodeScoring.Save:

    helm repo add codescoring-save HELM_REPOSITORY_URL \
      --username USERNAME \
      --password PASSWORD
    helm repo update
  4. Скачайте и распакуйте чарт:

    helm pull codescoring-save/save \
      --version CHART_VERSION \
      --untar \
      --untardir codescoring-save-src
    cd codescoring-save-src/save

Настройка параметров Helm-чарта

Важно

Внесите необходимые изменения до первой установки. Перед обновлением установленной системы создайте резервные копии PostgreSQL и объектного хранилища.

Вся конфигурация инсталляции находится в values.yaml. Примеры ниже содержат только изменяемые фрагменты: остальные параметры из поставляемого файла необходимо сохранить.

Контейнерные образы

Основные компоненты используют общие реестр, тег и Secret для скачивания образов:

image:
  registry: REGISTRY_URL/save-docker
  tag: CHART_VERSION
  pullSecrets:
    - name: codescoring-regcred

OSA Proxy поставляется как зависимость чарта и имеет отдельные настройки образа:

osa-proxy:
  image:
    repository: REGISTRY_URL/save-docker/osa-proxy
    tag: OSA_PROXY_VERSION
  imagePullSecrets:
    - name: codescoring-regcred

Используйте версии образов, указанные в поставляемом values.yaml. Они проверены на совместимость с выбранной версией чарта.

Секреты приложения

Конфиденциальные параметры backend, worker, scheduler и auth находятся в secrets.save-secrets.data:

secrets:
  save-secrets:
    enabled: true
    data:
      SECRETS_ENCRYPTION_KEY: <STABLE_ENCRYPTION_KEY>
      DATABASE_NAME: save_db
      DATABASE_USER: save_user
      DATABASE_PASSWORD: <DATABASE_PASSWORD>
      REDIS_PASSWORD: ""
      S3_ACCESS_KEY: <S3_ACCESS_KEY>
      S3_SECRET_KEY: <S3_SECRET_KEY>
      AUTH_INTERNAL_SECRET: <AUTH_INTERNAL_SECRET>
      AUTH_ADMIN_PASSWORD: <ADMIN_PASSWORD>

SECRETS_ENCRYPTION_KEY используется для шифрования сохраненных учетных данных. Сгенерируйте его один раз, например командой openssl rand -base64 32, сохраните в защищенном хранилище и не меняйте при обновлениях. После смены ключа ранее сохраненные данные невозможно расшифровать.

Не храните рабочие пароли и ключи в системе контроля версий. Для продуктивной установки используйте защищенный файл значений или External Secrets.

Ключ подписи JWT

При первом старте сервис cs-auth создаёт ключ RSA-2048 и сохраняет его в своей базе данных. При перезапуске и на других репликах ключ читается оттуда.

Защитите резервные копии базы данных

Ключ хранится в базе данных без шифрования. Дамп или резервная копия базы (в том числе общей с Save) позволяет выпускать токены от имени любого пользователя — храните их как секреты.

Ротация ключа доступна администратору через API (нужен токен администратора, см. Получение JWT администратора):

# Список ключей и их состояние (без приватной части)
curl -sS https://save.example.com/api/v1/admin/signing-keys \
  -H "Authorization: Bearer $ADMIN_JWT"

# Плановая ротация: никого не разлогинивает
curl -sS -X POST https://save.example.com/api/v1/admin/signing-keys/rotate \
  -H "Authorization: Bearer $ADMIN_JWT"

# Экстренная ротация при утечке ключа: все выданные access-токены сразу становятся недействительны
curl -sS -X POST https://save.example.com/api/v1/admin/signing-keys/rotate \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ADMIN_JWT" \
  -d '{"immediate": true}'

При плановой ротации новый ключ сначала публикуется в JWKS и через 2 минуты начинает подписывать токены. Старый ключ продолжает проверять уже выданные токены, пока они не истекут, затем удаляется сам. При экстренной ротации refresh-токены продолжают работать, поэтому веб-интерфейс просто получит новую пару токенов. Каждая ротация записывается в журнал аудита.

PostgreSQL и Redis из Helm-чарта

По умолчанию чарт создает PostgreSQL и Redis как StatefulSet. Включите эти ресурсы и настройте PersistentVolumeClaim:

statefulSets:
  save-postgresql:
    enabled: true
  save-redis:
    enabled: true

services:
  redis:
    enabled: true

pvcs:
  save-postgresql:
    enabled: true
    accessModes:
      - ReadWriteOnce
    size: 20Gi
    storageClassName: "default"
  save-redis:
    enabled: true
    accessModes:
      - ReadWriteOnce
    size: 2Gi
    storageClassName: "default"

Замените storageClassName и размеры томов в соответствии с конфигурацией кластера и ожидаемым объемом данных.

Учетные данные встроенной PostgreSQL задаются отдельно и должны совпадать с параметрами DATABASE_NAME, DATABASE_USER и DATABASE_PASSWORD в secrets.save-secrets.data:

secrets:
  postgresql-secrets:
    enabled: true
    data:
      POSTGRES_DB: save_db
      POSTGRES_USER: save_user
      POSTGRES_PASSWORD: <DATABASE_PASSWORD>

Параметры подключения приложения к PostgreSQL и Redis находятся в ConfigMap save-backend-envs:

configMaps:
  save-backend-envs:
    enabled: true
    data:
      DATABASE_DRIVER: "postgres"
      DATABASE_HOST: "save-postgresql"
      DATABASE_PORT: "5432"
      REDIS_ENABLED: "true"
      REDIS_ADDR: "save-redis:6379"
      REDIS_DB: "0"
      HEALTH_PORT: "8082"

HEALTH_PORT используется сервисами worker и scheduler для отдельного probe-listener (API backend не использует этот порт). По умолчанию чарт проверяет:

  • startup probe: /health/startup,
  • readiness probe: /health/ready,
  • liveness probe: /health/live.

Если вы меняете HEALTH_PORT, синхронно обновите startupProbe, readinessProbe и livenessProbe в deployments.worker и deployments.scheduler, чтобы порт в probe-конфигурации совпадал с переменной окружения.

ConfigMap и Secret уже подключены к компонентам через deploymentsGeneral.envConfigmaps и deploymentsGeneral.envSecrets. При изменении полного values.yaml сохраните эти ссылки:

deploymentsGeneral:
  envConfigmaps:
    - save-backend-envs
  envSecrets:
    - save-secrets

Внешние PostgreSQL и Redis

Для внешней PostgreSQL отключите встроенный StatefulSet и его PVC, затем измените параметры подключения:

statefulSets:
  save-postgresql:
    enabled: false

pvcs:
  save-postgresql:
    enabled: false

configMaps:
  save-backend-envs:
    data:
      DATABASE_DRIVER: "postgres"
      DATABASE_HOST: "postgresql.example.com"
      DATABASE_PORT: "5432"

secrets:
  save-secrets:
    data:
      DATABASE_NAME: save_db
      DATABASE_USER: save_user
      DATABASE_PASSWORD: <DATABASE_PASSWORD>

База данных и пользователь должны быть созданы до установки CodeScoring.Save.

Для внешнего Redis отключите встроенные StatefulSet, Service и PVC:

statefulSets:
  save-redis:
    enabled: false

services:
  redis:
    enabled: false

pvcs:
  save-redis:
    enabled: false

configMaps:
  save-backend-envs:
    data:
      REDIS_ENABLED: "true"
      REDIS_ADDR: "redis.example.com:6379"
      REDIS_DB: "0"

secrets:
  save-secrets:
    data:
      REDIS_PASSWORD: <REDIS_PASSWORD>

S3-совместимое объектное хранилище

Текущий чарт не разворачивает S3-хранилище. Для стандартной Kubernetes-инсталляции заранее создайте бакет во внешнем S3-совместимом хранилище и укажите параметры подключения:

configMaps:
  save-backend-envs:
    data:
      STORAGE_TYPE: "s3"
      S3_REGION: "us-east-1"
      S3_BUCKET: "save"
      S3_ENDPOINT: "https://s3.example.com"
      S3_FORCE_PATH_STYLE: "true"

secrets:
  save-secrets:
    data:
      S3_ACCESS_KEY: <S3_ACCESS_KEY>
      S3_SECRET_KEY: <S3_SECRET_KEY>

Для хранилища, которое поддерживает virtual-hosted-style URL, установите S3_FORCE_PATH_STYLE: "false".

Параметр S3_REGION обязателен. Для MinIO и других хранилищ без регионов укажите любое значение, например us-east-1. Если в одном бакете нужно разместить несколько инсталляций, задайте каждой свой префикс ключей в S3_PREFIX.

Загрузка больших файлов

Файл не больше одной части (по умолчанию 8 МиБ) Save записывает в S3 одним запросом. Файл больше — multipart-загрузкой: он делится на части, и несколько частей отправляются параллельно. Поэтому Save хранит артефакты больше 5 ГБ (предел S3 — 5 ТиБ на объект) и не упирается в ограничение MinIO на размер фрагмента в 16 МиБ (ошибка chunk too big).

Обычно значения по умолчанию подходят. При необходимости их можно изменить в configMaps.save-backend-envs.data:

ПараметрПо умолчаниюДопустимоЧто задаёт
S3_MULTIPART_PART_SIZE_MB85–5120Размер одной части в МиБ. Файлы не больше этого размера загружаются одним запросом
S3_MULTIPART_CONCURRENCY21–64Сколько частей одного файла отправляется одновременно
S3_MULTIPART_MAX_INFLIGHT16-1, 1…Сколько multipart-загрузок одновременно выполняет один под. Остальные ждут очереди. -1 — без ограничения
configMaps:
  save-backend-envs:
    data:
      S3_MULTIPART_PART_SIZE_MB: "8"
      S3_MULTIPART_CONCURRENCY: "2"
      S3_MULTIPART_MAX_INFLIGHT: "16"

Что важно учесть:

  • Память. Одна multipart-загрузка занимает около (S3_MULTIPART_CONCURRENCY + 2) × S3_MULTIPART_PART_SIZE_MB, а под в худшем случае — S3_MULTIPART_MAX_INFLIGHT таких загрузок. Со значениями по умолчанию это 16 × 4 × 8 МиБ = 512 МиБ. Учитывайте это в resources.limits.memory для backend и worker. S3 допускает не больше 10 000 частей, поэтому для очень больших файлов (с частями по 8 МиБ — больше ~78 ГиБ) размер части увеличивается автоматически, и памяти на такую загрузку нужно пропорционально больше.
  • MinIO. Не задавайте S3_MULTIPART_PART_SIZE_MB больше 16: MinIO по https отклоняет фрагменты крупнее 16 МиБ.
  • Временные файлы. Перед отправкой в S3 Save часто сохраняет входящий файл во временный каталог пода (по умолчанию /tmp): так обрабатываются слои Docker, пакеты RPM и Composer и любые потоки, которые нельзя перечитать. В памяти файл целиком не держится, но на диске нужно свободное место не меньше суммарного размера файлов, которые загружаются одновременно. В Kubernetes это ephemeral storage узла: задайте для backend запас ephemeral-storage или подключите отдельный том и укажите его путь в переменной TMPDIR.
  • Время запроса. Save ждёт один HTTP-запрос не дольше 10 минут — за это время файл должен быть и получен, и записан в S3. Например, для файла 5 ГБ нужна скорость не меньше ~10 МБ/с. Таймауты ingress и балансировщика должны быть не меньше (см. Ingress).
  • Прерванные загрузки. Если загрузка оборвалась, Save отменяет multipart-загрузку в S3. Если отменить не удалось (например, S3 был недоступен), уже загруженные части остаются в бакете и занимают место. В AWS S3 и Yandex Object Storage настройте для бакета правило жизненного цикла AbortIncompleteMultipartUpload (например, 1 день). MinIO удаляет незавершённые загрузки сам (параметр stale_uploads_expiry, по умолчанию 24 часа).
  • Контрольные суммы. Если задан S3_ENDPOINT, Save добавляет контрольные суммы к запросам только тогда, когда хранилище их требует, — так совместимость с MinIO, Ceph и другими S3-хранилищами лучше. Изменить поведение можно стандартными переменными AWS SDK AWS_REQUEST_CHECKSUM_CALCULATION и AWS_RESPONSE_CHECKSUM_VALIDATION (when_supported или when_required).
  • Свой сертификат у S3. Если S3 открыт по https с сертификатом корпоративного центра сертификации, укажите путь к его сертификату в AWS_CA_BUNDLE.

Hosted-установка в k3s

Hosted-вариант предназначен для односерверной установки в k3s и использует SQLite для метаданных и локальную файловую систему для артефактов.

Установите k3s и настройте доступ к кластеру:

curl -sfL https://get.k3s.io | sh -
sudo systemctl status k3s

mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown "$USER:$USER" ~/.kube/config
export KUBECONFIG=~/.kube/config

kubectl get nodes

Чтобы переключить стандартный профиль чарта на hosted, измените три переменные в configMaps.save-backend-envs.data:

configMaps:
  save-backend-envs:
    data:
      DATABASE_DRIVER: "sqlite"
      DATABASE_SQLITE_PATH: "./data/repository_manager.db"
      STORAGE_TYPE: "filesystem"

ConfigMap save-backend-envs подключен к backend, worker, scheduler и auth, поэтому дополнительные ConfigMap создавать не требуется. Остальные параметры из поставляемого values.yaml сохраните без изменений.

Компоненты worker и scheduler требуют PostgreSQL и не поддерживают работу с SQLite. В hosted-инсталляции обязательно отключите оба deployment:

deployments:
  worker:
    enabled: false
  scheduler:
    enabled: false

Постоянное хранение данных

Для hosted-установки нужны три отдельных постоянных тома:

  • db-data — база SQLite backend;
  • auth-data — база SQLite auth;
  • storage — файловое хранилище артефактов.

Подключите PVC к deployments через volumes и volumeMounts. Для auth также задайте пустое значение initContainers, чтобы удалить унаследованный init-контейнер wait-for-postgres:

deployments:
  save:
    containers:
      save:
        volumeMounts:
          - name: db-data
            mountPath: /app/data
          - name: storage
            mountPath: /app/storage
    volumes:
      - name: db-data
        type: pvc
      - name: storage
        type: pvc

  auth:
    initContainers:
    containers:
      auth:
        volumeMounts:
          - name: auth-data
            mountPath: /app/data
    volumes:
      - name: auth-data
        type: pvc

Backend и auth используют одинаковое значение DATABASE_SQLITE_PATH, но отдельные PVC, поэтому каждый сервис хранит собственную базу в своем каталоге /app/data. Значение STORAGE_ROOT_PATH по умолчанию — ./storage, что соответствует точке монтирования /app/storage при рабочем каталоге /app.

При использовании Dynamic Volume Provisioning укажите StorageClass для каждого PVC. Соответствующие PV будут созданы автоматически:

pvcs:
  db-data:
    accessModes:
      - ReadWriteOnce
    storageClassName: "default"
    size: 5Gi
  auth-data:
    accessModes:
      - ReadWriteOnce
    storageClassName: "default"
    size: 1Gi
  storage:
    accessModes:
      - ReadWriteOnce
    storageClassName: "default"
    size: 10Gi

Размеры томов и storageClassName необходимо подобрать с учетом нагрузки и конфигурации кластера.

Также можно использовать заранее созданные PV любого поддерживаемого Kubernetes типа. В этом случае создайте PV самостоятельно или опишите их в секции pvs, а в каждом PVC задайте пустой storageClassName и соответствующий volumeName, например:

pvs:
  db-data:
    accessModes:
      - ReadWriteMany
    size: 5Gi
    storageClassName: ""
    mountOptions:
      - nfsvers=4.2
    nfs:
      server: nfs.example.com
      path: /exports/codescoring-save/db-data

pvcs:
  db-data:
    accessModes:
      - ReadWriteMany
    storageClassName: ""
    volumeName: codescoring-save-db-data
    size: 5Gi

В примере для Helm-релиза codescoring-save чарт создает PV codescoring-save-db-data из секции pvs.db-data, а PVC явно привязывается к нему через volumeName. Замените адрес NFS-сервера и путь экспорта значениями своей инфраструктуры.

Аналогично создайте и привяжите тома auth-data и storage. Конкретный источник тома может быть NFS, CSI, локальным диском или другим хранилищем; параметры зависят от инфраструктуры кластера.

Опциональный Redis

Redis не обязателен для hosted-установки. Чтобы запустить Save без Redis, выключите его в конфигурации приложения и отключите связанные StatefulSet, Service и PVC:

configMaps:
  save-backend-envs:
    data:
      REDIS_ENABLED: "false"

statefulSets:
  save-redis:
    enabled: false

services:
  redis:
    enabled: false

pvcs:
  save-redis:
    enabled: false

Если Redis используется, сохраните REDIS_ENABLED: "true", оставьте его StatefulSet, Service и PVC включенными.

SQLite рассчитана на работу одной реплики. Не увеличивайте deploymentsGeneral.replicas и отключите автоматическое масштабирование backend и worker:

deploymentsGeneral:
  replicas: 1

hpas:
  save:
    enabled: false
  worker:
    enabled: false

После переключения приложение не использует PostgreSQL. Чтобы не создавать неиспользуемые ресурсы, можно дополнительно отключить StatefulSet и PVC:

statefulSets:
  save-postgresql:
    enabled: false

pvcs:
  save-postgresql:
    enabled: false
Важно

SQLite и файловое хранилище подходят только для односерверной установки. Каталоги с базами SQLite и артефактами должны находиться на сохраняемом диске k3s и регулярно копироваться. Не используйте этот профиль для многорепличного развертывания.

Ingress

По умолчанию Ingress выключен. Чтобы открыть веб-интерфейс и API, включите его и замените доменное имя:

ingresses:
  ingress:
    enabled: true
    ingressClassName: nginx
    hosts:
      - hostname: save.example.com
        paths:
          - path: /
            serviceName: frontend
            servicePort: 8081
    tls:
      - hosts:
          - save.example.com
        secretName: save-tls

configMaps:
  save-frontend-envs:
    data:
      NGINX_HOST: "save.example.com"
      NGINX_PORT: "8081"

Если TLS завершается на внешнем балансировщике, настройте tls и аннотации Ingress в соответствии с инфраструктурой кластера.

Чтобы через Ingress проходили большие файлы (слои Docker, архивы, пакеты), снимите ограничение на размер запроса и увеличьте таймауты до 10 минут — столько Save ждёт один запрос. Пример для ingress-nginx:

ingresses:
  ingress:
    annotations:
      nginx.ingress.kubernetes.io/proxy-body-size: "0"
      nginx.ingress.kubernetes.io/proxy-request-buffering: "off"
      nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
      nginx.ingress.kubernetes.io/proxy-send-timeout: "600"

Без этих настроек ingress-nginx по умолчанию отклоняет запросы больше 1 МБ с ошибкой 413 Request Entity Too Large.

HTTPRoute (Gateway API)

Если в кластере используется Kubernetes Gateway API, настройте маршрут к frontend через секцию httpRoutes. Ресурс Gateway, на который ссылается маршрут, должен существовать до установки CodeScoring.Save.

httpRoutesGeneral: {}
httpRoutes:
  save:
    gatewayName: codescoring-gateway
    gatewayNamespace: gateway-system
    gatewaySectionName: https
    gatewayKind: Gateway
    gatewayGroup: gateway.networking.k8s.io
    hostnames:
      - "save.example.com"
    rules:
      - matches:
          - path:
              type: PathPrefix
              value: /
        backendRefs:
          - name: codescoring-save-frontend
            port: 8081

configMaps:
  save-frontend-envs:
    data:
      NGINX_HOST: "save.example.com"
      NGINX_PORT: "8081"

Значения gatewayName, gatewayNamespace, gatewaySectionName и hostnames должны соответствовать Gateway и DNS-имени в вашем кластере.

Важно

Значение backendRefs.name формируется как {helm-release-name}-frontend. Например, для команды helm install codescoring-save ... необходимо указать name: codescoring-save-frontend.

OSA Proxy

OSA Proxy отключена по умолчанию. Для ее включения необходимо выставить поле osa-proxy.enabled в значение true. В существующем блоке osa-proxy.config.content замените значение codescoring.url на адрес инсталляции CodeScoring. Токен передайте через Secret osa-proxy:

osa-proxy:
  enabled: true
  secret:
    create: true
    stringData:
      CODESCORING_TOKEN: <CODESCORING_TOKEN>

Если проверка компонентов через OSA Proxy не требуется, отключите зависимость:

osa-proxy:
  enabled: false

osa-proxy.config.content содержит полную конфигурацию сервиса. При ее изменении сохраните остальные секции из поставляемого values.yaml.

Ограничения ресурсов

В поставляемом values.yaml ресурсы контейнеров не ограничены. Для продуктивной установки задайте requests и limits для каждого компонента по результатам нагрузочного тестирования:

deployments:
  save:
    containers:
      save:
        resources:
          requests:
            cpu: 500m
            memory: 1Gi
          limits:
            cpu: "2"
            memory: 4Gi
  worker:
    containers:
      worker:
        resources:
          requests:
            cpu: 500m
            memory: 1Gi
          limits:
            cpu: "2"
            memory: 4Gi

Аналогично настройте deployments.scheduler, deployments.auth, deployments.save-frontend, statefulSets.save-postgresql и statefulSets.save-redis. Для корректной работы HPA у масштабируемых контейнеров должны быть заданы CPU requests.

External Secrets

Чарт может получать секреты из внешнего хранилища через External Secrets Operator. В кластере должны быть заранее установлены оператор и SecretStore или ClusterSecretStore.

Включите нужный ресурс в секции vaults:

vaults:
  save-secrets-external:
    apiVersion: external-secrets.io/v1
    enabled: true
    store:
      name: vault-backend
      kind: ClusterSecretStore
    path: save-secrets

Затем подключите создаваемый Secret к deployments:

deploymentsGeneral:
  envConfigmaps:
    - save-backend-envs
  envSecrets:
    - save-secrets-external

Для встроенной PostgreSQL аналогично настройте vaults.postgresql-secrets-external и подключите Secret в statefulSets.save-postgresql.envSecrets.

Установка

Из каталога распакованного чарта выполните:

helm install codescoring-save . \
  --namespace codescoring-save \
  --values values.yaml \
  --atomic

Для обновления существующей инсталляции используйте ту же версию настроенного values.yaml:

helm upgrade codescoring-save . \
  --namespace codescoring-save \
  --values values.yaml \
  --atomic

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

Проверьте состояние ресурсов:

kubectl get pods -n codescoring-save
kubectl get statefulset,pvc -n codescoring-save
kubectl get service,ingress -n codescoring-save

Все Pod должны перейти в состояние Running, а их контейнеры — быть готовы. Для диагностики используйте логи компонентов:

kubectl logs -n codescoring-save -l app=backend --tail=100
kubectl logs -n codescoring-save -l app=worker --tail=100
kubectl logs -n codescoring-save -l app=scheduler --tail=100
kubectl logs -n codescoring-save -l app=auth --tail=100
kubectl logs -n codescoring-save -l app=frontend --tail=100

Проверить probe-эндпоинты worker/scheduler можно вручную (через port-forward на HEALTH_PORT, по умолчанию 8082):

kubectl -n codescoring-save port-forward deploy/codescoring-save-worker 18082:8082
curl -f http://127.0.0.1:18082/health/startup
curl -f http://127.0.0.1:18082/health/ready
curl -f http://127.0.0.1:18082/health/live

После установки откройте адрес, указанный в Ingress, и введите ключ активации. Затем войдите с паролем из AUTH_ADMIN_PASSWORD.

Ключ активации

Пока ключ активации не введён, Save отвечает 403 с сообщением No valid license на запросы к API и к репозиториям. Без ключа работают только вход в систему, проверка состояния, Swagger и страница ключа активации.

Ключ активации предоставляет вендор. Ввести его можно двумя способами.

В веб-интерфейсе.

  1. Откройте Settings -> Activation key.
  2. Нажмите Add new activation key в правом верхнем углу.
  3. Вставьте ключ в поле Enter new key here и нажмите Activate.

Новый ключ заменяет текущий. На странице Activation key видны состояние ключа (Status), дата выдачи (Issued at), срок действия (Expires in) и число артефактов (Artifacts).

Через API:

curl -sS -X POST https://save.example.com/api/v1/license \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ADMIN_JWT" \
  -d '{"license": "<ключ активации>"}'

В ответе — состояние ключа: is_valid, владелец (owner), даты issued_at и expires_at, оставшееся время expires_in (в миллисекундах) и пояснение message.

Проверить состояние ключа и счётчик артефактов:

curl -sS https://save.example.com/api/v1/license -H "Authorization: Bearer $ADMIN_JWT"
curl -sS https://save.example.com/api/v1/license/usage -H "Authorization: Bearer $ADMIN_JWT"
Несколько реплик backend без Redis

Каждый под запоминает результат проверки ключа активации до 2 часов. С Redis новый ключ сразу виден всем подам. Без Redis под, который уже запомнил, что ключа нет, может отвечать 403 до 2 часов — после ввода ключа перезапустите поды backend: kubectl rollout restart deployment -n codescoring-save.

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

После успешной установки:

  1. Создайте первый репозиторий.
  2. Настройте политики очистки.
  3. Создайте пользователей и назначьте роли.
Страница была полезна?