Files
hrbox-helm-chart/.helm/templates/_envs.tpl
T
gnome627andClaude Opus 5 efc506e5de DEVOPS-117: чарт on-premise 3.0 — Nanabush Player, секреты в Secret, валидация values
Актуализация чарта по продовому .helm из HRBOX.

Nanabush Player перенесён из прода и упрощён под one-release-топологию
on-premise: без карт env/ci_dc, но с сохранёнными инвариантами (audience =
https://<host>, basePath отдельно от aud, allowlist обратного канала только
на внутрикластерный web, метрики на непубликуемом порту). Выделенного
поддомена в on-premise нет, поэтому плеер монтируется на основной домен под
/nanabush-player. Три переключателя для аварийного отката сохранены.

Из прода также перенесены: пул конвертации видео, PodDisruptionBudget для
web, OpenTelemetry-сайдкар, assetlinks, набор location в nginx (/healthz,
/health-check, потоковый /api/v1/integration/commit, /ai/, sw.js, шрифты).
Версии образов подтянуты к продовым.

Приведение чарта в порядок: все образы в блоке image, imagePullSecrets в
настройках, девять одинаковых define ресурсов заменены одним хелпером,
удалено ~100 строк мёртвого кода в _helpers.tpl, пароли и ключи уехали в
Secret и читаются через secretKeyRef, добавлены 00-validate.yaml и NOTES.txt.

Исправлено в 2.x:
- SERVICES_INTERNAL_SECRET имел захардкоженное значение по умолчанию, то есть
  все установки, где его не заполнили, работали на одном секрете межсервисной
  аутентификации;
- cluster.domain игнорировался: маршруты кластера NATS были захардкожены на
  cluster.local;
- CLUSTER_ADVERTISE без сегмента svc — ноды NATS объявляли соседям
  недостижимый адрес;
- nats.replicas и nats.cluster.replicas задавались независимо, при
  расхождении часть нод не входила в кластер;
- пробы web проверяли только TCP-порт 9000, поэтому под с неработающим PHP
  считался готовым;
- внутренние URL были захардкожены строками hrbox-* и молча ломались при
  nameOverride.

Имена объектов и селекторы Deployment не менялись — обновление 2.x -> 3.0 не
пересоздаёт объекты. Переехавшие ключи values.yaml чарт распознаёт и
останавливает установку с подсказкой; порядок перехода — в CHANGELOG.md.

Проверено: helm lint чистый; отрендерены 4 конфигурации (дефолт, всё
включено, плеер и инфра выключены, nameOverride); структурная проверка
рендера без замечаний; 20 негативных сценариев срабатывают с ожидаемыми
сообщениями; реалистичный values.yaml из 2.x последовательно ловится всеми
шестью guard'ами.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 16:37:42 +06:00

348 lines
14 KiB
Smarty
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{{/*
============================================================================
Переменные окружения HRBox
============================================================================
envs_all включается во все контейнеры, которым нужен конфиг приложения:
web, worker, conductor, chatbox, goworker, kedoca, file-processor, geonames
и джобы миграций. Один общий блок проще расходящихся наборов, и именно так
устроено продовое окружение.
Чувствительные значения приходят через secretKeyRef из секрета приложения
(00-app-secret.yaml), а не открытым текстом в спеке пода.
*/}}
{{- define "envs_all" }}
# --- Приложение -----------------------------------------------------------
- name: INSTANCE_NAME
value: {{ .Values.app.instanceName | quote }}
- name: DEFAULT_TENANT_HOSTNAME
value: {{ .Values.app.defaultTenantHostname | quote }}
- name: APP_ENV
value: "prod"
- name: APP_PORT
value: "80"
- name: YII_DEBUG
value: {{ .Values.app.debug | quote }}
- name: YII_TRACE_LEVEL
value: "0"
- name: AUTH_HOST
value: {{ .Values.app.authHost | quote }}
- name: SINGLE_TENANT
value: {{ .Values.app.singleTenant | quote }}
- name: FORCE_HTTPS
value: {{ .Values.app.forceHttps | quote }}
- name: ENABLE_FRONTEND
value: {{ .Values.app.front2 | quote }}
- name: LAUNCHPAD_TOPICS
value: {{ .Values.app.launchpad.topics | quote }}
- name: SMS_SENDER_NAME
value: {{ .Values.app.sms.senderName | quote }}
- name: IFRAME_FULL_ACCESS
value: {{ .Values.app.security.iframeFullAccess | quote }}
- name: LDAPTLS_REQCERT
value: "never"
{{- include "hrbox.secretEnv" (dict "ctx" . "env" "APP_COOKIE_VALIDATION_KEY" "key" "cookie-validation-key") | nindent 0 }}
{{- include "hrbox.secretEnv" (dict "ctx" . "env" "APP_ENCRYPTION_KEY" "key" "encryption-key") | nindent 0 }}
{{- include "hrbox.secretEnv" (dict "ctx" . "env" "SERVICES_INTERNAL_SECRET" "key" "services-internal-secret") | nindent 0 }}
# --- Своя политика конфиденциальности -------------------------------------
- name: ALLOW_CUSTOM_POLICY_URLS
value: {{ .Values.app.customPolicy.enabled | quote }}
{{- if .Values.app.customPolicy.enabled }}
- name: CUSTOM_PRIVACY_POLICY_URL
value: {{ .Values.app.customPolicy.privacyUrl | default "https://hrbox.io/policy" | quote }}
- name: CUSTOM_TERMS_URL
value: {{ .Values.app.customPolicy.termsUrl | default "https://hrbox.io/terms" | quote }}
{{- else }}
- name: CUSTOM_PRIVACY_POLICY_URL
value: ""
- name: CUSTOM_TERMS_URL
value: ""
{{- end }}
# --- PostgreSQL -----------------------------------------------------------
- name: POSTGRES_VHOST
value: {{ .Values.app.postgres.host | quote }}
- name: POSTGRES_PORT
value: {{ .Values.app.postgres.port | quote }}
- name: POSTGRES_DB
value: {{ .Values.app.postgres.database | quote }}
- name: POSTGRES_USER
value: {{ .Values.app.postgres.user | quote }}
- name: POSTGRES_CITUS
value: {{ .Values.app.postgres.citus | quote }}
{{- include "hrbox.secretEnv" (dict "ctx" . "env" "POSTGRES_PASSWORD" "key" "postgres-password") | nindent 0 }}
# --- Redis / Dragonfly ----------------------------------------------------
- name: REDIS_HOST
value: {{ include "hrbox.redisHost" . | quote }}
- name: REDIS_PORT
value: {{ .Values.app.redis.port | quote }}
- name: REDIS_CONNECTION
value: {{ printf "tcp://%s:%s" (include "hrbox.redisHost" .) (.Values.app.redis.port | toString) | quote }}
# --- NATS -----------------------------------------------------------------
- name: BROKER
value: "nats"
- name: NATS_URL
value: {{ include "hrbox.natsUrl" . | quote }}
# Число реплик JetStream-стримов должно совпадать с размером кластера NATS,
# иначе стрим создаётся в одном экземпляре и теряется вместе со своей нодой.
- name: NATS_STREAM_REPLICAS
{{- if and .Values.nats.enabled .Values.nats.cluster.enabled }}
value: {{ .Values.nats.cluster.replicas | quote }}
{{- else }}
value: "1"
{{- end }}
# --- S3 -------------------------------------------------------------------
- name: S3_ENDPOINT
value: {{ .Values.app.s3.endpoint | quote }}
- name: S3_BUCKET
value: {{ .Values.app.s3.bucket | quote }}
- name: S3_PREFIX
value: {{ .Values.app.s3.prefix | quote }}
- name: S3_REGION
value: {{ .Values.app.s3.region | quote }}
- name: S3_VERSION
value: {{ .Values.app.s3.version | quote }}
- name: S3_PATH_STYLE
value: {{ .Values.app.s3.pathStyle | quote }}
- name: S3_MULTIPART
value: {{ .Values.app.s3.multipart | quote }}
{{- include "hrbox.secretEnv" (dict "ctx" . "env" "S3_KEY" "key" "s3-key") | nindent 0 }}
{{- include "hrbox.secretEnv" (dict "ctx" . "env" "S3_SECRET" "key" "s3-secret") | nindent 0 }}
# --- Почта ----------------------------------------------------------------
- name: SENDER_ENV
value: "PROD"
- name: SENDER_DEV_EMAIL
value: ""
- name: SMTP_HOST
value: {{ .Values.app.smtp.host | quote }}
- name: SMTP_PORT
value: {{ .Values.app.smtp.port | quote }}
- name: SMTP_USERNAME
value: {{ .Values.app.smtp.user | quote }}
- name: SMTP_FROM
value: {{ .Values.app.smtp.from | quote }}
- name: SMTP_FROM_HOST
value: {{ .Values.app.smtp.fromHost | quote }}
- name: SMTP_SECURITY_TYPE
value: {{ .Values.app.smtp.securityType | quote }}
- name: SMTP_SSL_ALLOW_SELF_SIGNED
value: {{ .Values.app.smtp.sslAllowSelfSigned | quote }}
- name: SMTP_SSL_VERIFY_PEER
value: {{ .Values.app.smtp.sslVerifyPeer | quote }}
{{- include "hrbox.secretEnv" (dict "ctx" . "env" "SMTP_PASSWORD" "key" "smtp-password") | nindent 0 }}
# --- Внутренние сервисы ---------------------------------------------------
- name: GEONAMES_URL
value: {{ include "hrbox.geonamesUrl" . | quote }}
- name: GOWORKER_URL
value: {{ include "hrbox.goworkerUrl" . | quote }}
- name: GOWORKER_PUSH_MIN_INTERVAL
value: {{ .Values.app.goworker.pushMinInterval | quote }}
- name: GOWORKER_SENTRY_DSN
value: {{ .Values.app.sentry.goworkerDsn | quote }}
- name: KEDOCA_URL
value: {{ include "hrbox.kedocaUrl" . | quote }}
- name: TSP_URL
value: {{ .Values.app.kedoca.tspUrl | quote }}
- name: APP_INTERNAL_URL
value: {{ .Values.app.videoConverter.internalUrl | default (printf "http://%s" (include "hrbox.component" (dict "ctx" . "name" "web"))) | quote }}
- name: CONDUCTOR_TOPIC_CONDUCTOR
value: "conductor"
- name: CONDUCTOR_TOPIC_LAUNCHER
value: "launcher"
- name: PYTHONUNBUFFERED
value: "1"
- name: DOCCONV_MAX_PARALLEL_TASKS
value: {{ .Values.app.fileProcessor.docconvMaxParallelTasks | quote }}
# --- HRBox Hub ------------------------------------------------------------
- name: HUB_URL
value: {{ .Values.app.hub.url | quote }}
{{- include "hrbox.secretEnv" (dict "ctx" . "env" "HUB_TOKEN" "key" "hub-token") | nindent 0 }}
# --- Nanabush Player ------------------------------------------------------
{{- include "envs_nanabush_player" . }}
# --- Чат ------------------------------------------------------------------
- name: CHATBOX_SENTRY_DSN
value: {{ .Values.app.sentry.chatboxDsn | quote }}
{{- include "hrbox.secretEnv" (dict "ctx" . "env" "CHATBOX_WRAPPING_KEY" "key" "chatbox-wrapping-key") | nindent 0 }}
# --- Видеозвонки (LiveKit) ------------------------------------------------
- name: LIVEKIT_URL
value: {{ .Values.app.livekit.url | quote }}
- name: LIVEKIT_API_KEY
value: {{ .Values.app.livekit.apiKey | quote }}
{{- include "hrbox.secretEnv" (dict "ctx" . "env" "LIVEKIT_API_SECRET" "key" "livekit-api-secret") | nindent 0 }}
# --- AI -------------------------------------------------------------------
- name: AI_DOCS_INDEX_ENABLED
value: {{ .Values.app.ai.docsIndexEnabled | quote }}
- name: AI_SEMANTIC_INDEX_ENABLED
value: {{ .Values.app.ai.semanticIndexEnabled | quote }}
- name: AI_SEMANTIC_INDEX_USE_BATCH
value: {{ .Values.app.ai.semanticIndexUseBatch | quote }}
- name: YANDEX_CLOUD_AI_FOLDER_ID
value: {{ .Values.app.ai.yandex.folderId | quote }}
{{- include "hrbox.secretEnv" (dict "ctx" . "env" "YANDEX_CLOUD_AI_API_KEY" "key" "yandex-ai-api-key") | nindent 0 }}
# --- Внешние интеграции ---------------------------------------------------
- name: TELEGRAM_API_URL
value: {{ .Values.app.integrations.telegram.apiUrl | quote }}
- name: AUTH_GOOGLE_ENABLED
value: {{ .Values.app.integrations.google.enabled | quote }}
- name: GOOGLE_CLIENT_ID
value: {{ .Values.app.integrations.google.clientId | quote }}
{{- include "hrbox.secretEnv" (dict "ctx" . "env" "GOOGLE_CLIENT_SECRET" "key" "google-client-secret") | nindent 0 }}
- name: YANDEX_CLIENT_ID
value: {{ .Values.app.yandex.clientId | quote }}
{{- include "hrbox.secretEnv" (dict "ctx" . "env" "YANDEX_CLIENT_PASSWORD" "key" "yandex-client-password") | nindent 0 }}
- name: SLACK_APP_CLIENT_ID
value: {{ .Values.app.slack.clientId | quote }}
{{- include "hrbox.secretEnv" (dict "ctx" . "env" "SLACK_APP_CLIENT_SECRET" "key" "slack-client-secret") | nindent 0 }}
{{- include "hrbox.secretEnv" (dict "ctx" . "env" "SLACK_APP_VERIFICATION_TOKEN" "key" "slack-verification-token") | nindent 0 }}
- name: GLAGOL_PARTNER_ID
value: {{ .Values.app.integrations.glagol.partnerId | quote }}
- name: GLAGOL_API_URL
value: {{ .Values.app.integrations.glagol.apiUrl | quote }}
# --- Sentry ---------------------------------------------------------------
- name: SENTRY_DSN
value: {{ .Values.app.sentry.dsn | quote }}
- name: SENTRY_DSN_LAUNCHPAD
value: {{ .Values.app.sentry.launchpadDsn | default .Values.app.sentry.dsn | quote }}
- name: SENTRY_DSN_CONDUCTOR
value: {{ .Values.app.sentry.conductorDsn | default .Values.app.sentry.dsn | quote }}
- name: SENTRY_ENVIRONMENT
value: {{ .Values.app.sentry.environment | quote }}
- name: SENTRY_RELEASE
value: {{ .Values.image.hrbox | quote }}
# --- Метаданные пода ------------------------------------------------------
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
{{- end }}
{{/*
Настройки Nanabush Player на стороне HRBox.
NANABUSH_PLAYER_AUDIENCE и NANABUSH_PLAYER_PUBLIC_ORIGIN всегда равны:
audience тикета — это origin браузера без пути, а путь монтирования едет
отдельной переменной NANABUSH_PLAYER_BASE_PATH.
*/}}
{{- define "envs_nanabush_player" -}}
{{- $player := .Values.app.nanabushPlayer }}
- name: NANABUSH_PLAYER_ENABLED
value: {{ $player.enabled | quote }}
{{- if $player.deployment.enabled }}
- name: NANABUSH_PLAYER_PUBLIC_ORIGIN
value: {{ include "nanabushPlayer.publicOrigin" . | quote }}
- name: NANABUSH_PLAYER_AUDIENCE
value: {{ include "nanabushPlayer.publicOrigin" . | quote }}
- name: NANABUSH_PLAYER_BASE_PATH
value: {{ include "nanabushPlayer.basePath" . | quote }}
- name: NANABUSH_PLAYER_INTERNAL_ORIGIN
value: {{ include "nanabushPlayer.internalOrigin" . | quote }}
- name: NANABUSH_PLAYER_ISSUER
value: {{ include "nanabushPlayer.issuer" . | quote }}
- name: NANABUSH_PLAYER_CONTRACT_VERSION
value: {{ $player.contractVersion | quote }}
- name: NANABUSH_PLAYER_PLAYER_VERSION
value: {{ include "nanabushPlayer.version" . | quote }}
- name: NANABUSH_PLAYER_TICKET_TTL_SECONDS
value: {{ $player.deployment.ticket.ttlSeconds | quote }}
- name: NANABUSH_PLAYER_SESSION_TTL_SECONDS
value: {{ $player.deployment.ticket.credentialTtlSeconds | quote }}
- name: NANABUSH_PLAYER_PACKAGE_CONTENT_MAX_BYTES
value: {{ $player.deployment.backchannel.packageContentMaxBytes | quote }}
- name: NANABUSH_PLAYER_SCORM_PACKAGE_MAX_BYTES
value: {{ $player.deployment.backchannel.scormPackageMaxBytes | quote }}
{{- with $player.deployment.backchannel.scormPackageMaxFiles }}
- name: NANABUSH_PLAYER_SCORM_PACKAGE_MAX_FILES
value: {{ . | quote }}
{{- end }}
- name: NANABUSH_PLAYER_LEGACY_FALLBACK
value: {{ $player.rollout.legacyFallback | quote }}
- name: NANABUSH_PLAYER_ALLOWED_CONTENT_TYPES
value: {{ join "," $player.rollout.allowedContentTypes | quote }}
- name: NANABUSH_PLAYER_ALLOWED_TENANTS
value: {{ join "," $player.rollout.allowedTenants | quote }}
- name: NANABUSH_PLAYER_ROLLOUT_PERCENT
value: {{ $player.rollout.percent | quote }}
{{- end }}
{{- end -}}
{{/*
Ключ подписи launch-тикета. Живёт только в PHP-контейнерах, которые выпускают
тикеты: nginx и вспомогательным контейнерам он не нужен.
*/}}
{{- define "envs_nanabush_player_signing" -}}
{{- $cfg := .Values.app.nanabushPlayer.deployment }}
{{- if $cfg.enabled }}
- name: NANABUSH_PLAYER_HS256_SECRET
valueFrom:
secretKeyRef:
name: {{ include "nanabushPlayer.secretName" . | quote }}
key: {{ required "Нужно имя ключа ticketHs256 в секрете Nanabush Player" $cfg.existingSecret.keys.ticketHs256 | quote }}
{{- with $cfg.existingSecret.keys.ticketKeys }}
# Кольцо ключей launch-тикета: HRBox подписывает первым ключом, Player
# принимает все. Тот же ключ секрета читает и сам Player, поэтому ротация —
# это одно значение на обе стороны.
- name: NANABUSH_PLAYER_TICKET_KEYS
valueFrom:
secretKeyRef:
name: {{ include "nanabushPlayer.secretName" $ | quote }}
key: {{ . | quote }}
{{- end }}
{{- end }}
{{- end -}}
{{/* Криптографические настройки сервиса электронной подписи. */}}
{{- define "envs_kedoca" }}
- name: ROOT_CA_PASS
value: {{ .Values.app.kedoca.rootCaPass | quote }}
- name: KEDO_ENGINE
value: {{ .Values.app.kedoca.engine | quote }}
- name: KEDO_ALGORITHM
value: {{ .Values.app.kedoca.algorithm | quote }}
- name: KEDO_PKEYOPT
value: {{ .Values.app.kedoca.pkeyopt | quote }}
{{- end }}
{{/* OpenTelemetry — только когда app.tracing.enabled. */}}
{{- define "envs_tracing" }}
- name: OTEL_PHP_AUTOLOAD_ENABLED
value: "true"
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: {{ .Values.app.tracing.exporterUrl | quote }}
- name: OTEL_SERVICE_NAME
value: "hrbox-app"
- name: OTEL_TRACES_EXPORTER
value: "otlp"
- name: OTEL_EXPORTER_OTLP_PROTOCOL
value: "http/protobuf"
- name: OTEL_PROPAGATORS
value: "baggage,tracecontext"
- name: OTEL_LOG_LEVEL
value: "info"
{{- end }}