Merge branch 'feature/DEVOPS-117' into 'main'

DEVOPS-117: чарт on-premise 3.0 — Nanabush Player, секреты в Secret, валидация values

See merge request hrbox-public/helm-chart!7
This commit is contained in:
2026-09-05 13:11:13 +00:00
35 changed files with 2722 additions and 1118 deletions
+11 -9
View File
@@ -1,19 +1,21 @@
apiVersion: v2 apiVersion: v2
name: hrbox name: hrbox
description: Simplified HRBox application Helm chart description: HRBox — HR-платформа для on-premise установки
type: application type: application
# Версия самого чарта. Увеличивается при каждом изменении чарта version: 3.0.0
version: 2.0.0 appVersion: "3.1.0"
# Версия приложения, которое деплоится. Не обязательно увеличивать при изменении чарта
appVersion: "3.0.0"
# Ключевые слова для поиска
keywords: keywords:
- hrbox - hrbox
- hr - hr
- application - lms
- kedo
- on-premise
# Домашняя страница проекта
home: https://hrbox.io home: https://hrbox.io
annotations:
hrbox.io/components: >-
web, worker, conductor, chatbox, goworker, kedoca, geonames,
file-processor, nanabush-player, dragonfly, nats
+26
View File
@@ -0,0 +1,26 @@
{{- if not .Values.secrets.existingSecret }}
---
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: {{ include "hrbox.secretName" . | quote }}
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "app") | nindent 4 }}
stringData:
cookie-validation-key: {{ .Values.secrets.cookieValidationKey | quote }}
encryption-key: {{ .Values.secrets.encryptionKey | quote }}
services-internal-secret: {{ .Values.secrets.servicesInternalSecret | quote }}
postgres-password: {{ .Values.app.postgres.password | quote }}
s3-key: {{ .Values.app.s3.key | quote }}
s3-secret: {{ .Values.app.s3.secret | quote }}
smtp-password: {{ .Values.app.smtp.password | quote }}
hub-token: {{ .Values.app.hub.token | quote }}
chatbox-wrapping-key: {{ .Values.app.chatbox.wrappingKey | quote }}
livekit-api-secret: {{ .Values.app.livekit.apiSecret | quote }}
yandex-client-password: {{ .Values.app.yandex.clientPassword | quote }}
yandex-ai-api-key: {{ .Values.app.ai.yandex.apiKey | quote }}
google-client-secret: {{ .Values.app.integrations.google.clientSecret | quote }}
slack-client-secret: {{ .Values.app.slack.clientSecret | quote }}
slack-verification-token: {{ .Values.app.slack.verificationToken | quote }}
{{- end }}
@@ -0,0 +1,17 @@
{{- $cfg := .Values.app.nanabushPlayer.deployment }}
{{- if and $cfg.enabled $cfg.existingSecret.create }}
---
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: {{ include "nanabushPlayer.secretName" . | quote }}
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "nanabush-player") | nindent 4 }}
stringData:
{{ required "Нужно имя ключа ticketHs256 в секрете Nanabush Player" $cfg.existingSecret.keys.ticketHs256 }}: {{ .Values.app.nanabushPlayer.keys.ticketHs256 | quote }}
{{ required "Нужно имя ключа sessionHs256 в секрете Nanabush Player" $cfg.existingSecret.keys.sessionHs256 }}: {{ .Values.app.nanabushPlayer.keys.sessionHs256 | quote }}
{{- with $cfg.existingSecret.keys.ticketKeys }}
{{ . }}: {{ $.Values.app.nanabushPlayer.keys.ticketKeys | quote }}
{{- end }}
{{- end }}
+132
View File
@@ -0,0 +1,132 @@
{{- if .Values.app.image }}
{{- fail "app.image переехал в image.hrbox (см. CHANGELOG, миграция 2.x -> 3.0)" }}
{{- end }}
{{- if .Values.app.chatbox.image }}
{{- fail "app.chatbox.image переехал в image.chatbox" }}
{{- end }}
{{- if .Values.app.goworker.image }}
{{- fail "app.goworker.image переехал в image.goworker" }}
{{- end }}
{{- if .Values.app.kedoca.image }}
{{- fail "app.kedoca.image переехал в image.kedoca" }}
{{- end }}
{{- if .Values.app.file_processor }}
{{- fail "app.file_processor переименован в app.fileProcessor, а образ переехал в image.fileProcessor" }}
{{- end }}
{{- if .Values.app.custom_policy }}
{{- fail "app.custom_policy переименован в app.customPolicy" }}
{{- end }}
{{- if .Values.app.replicas.websocket }}
{{- fail "app.replicas.websocket переименован в app.replicas.chatbox ещё в версии 2.0" }}
{{- end }}
{{- if .Values.resources.websocket }}
{{- fail "resources.websocket переименован в resources.chatbox ещё в версии 2.0" }}
{{- end }}
{{- if .Values.nats.image }}
{{- fail "nats.image переехал в image.nats" }}
{{- end }}
{{- if not .Values.ingress.host }}
{{- fail "Заполните ingress.host — домен, по которому открывается HRBox" }}
{{- end }}
{{- if not .Values.app.defaultTenantHostname }}
{{- fail "Заполните app.defaultTenantHostname (обычно совпадает с ingress.host)" }}
{{- end }}
{{- if not .Values.app.postgres.password }}
{{- fail "Заполните app.postgres.password" }}
{{- end }}
{{- if not .Values.app.s3.key }}
{{- fail "Заполните app.s3.key — без хранилища файлов HRBox не работает" }}
{{- end }}
{{- if not .Values.app.s3.secret }}
{{- fail "Заполните app.s3.secret" }}
{{- end }}
{{- if not .Values.app.hub.token }}
{{- fail "Заполните app.hub.token — токен выдают сотрудники HRBox" }}
{{- end }}
{{- if not .Values.secrets.existingSecret }}
{{- if not .Values.secrets.cookieValidationKey }}
{{- fail "Заполните secrets.cookieValidationKey (openssl rand -hex 16)" }}
{{- end }}
{{- if not .Values.secrets.encryptionKey }}
{{- fail "Заполните secrets.encryptionKey (openssl rand -base64 48). Потеря ключа делает зашифрованные данные нечитаемыми" }}
{{- end }}
{{- if not .Values.secrets.servicesInternalSecret }}
{{- fail "Заполните secrets.servicesInternalSecret (openssl rand -base64 48)" }}
{{- end }}
{{- if not .Values.app.chatbox.wrappingKey }}
{{- fail "Заполните app.chatbox.wrappingKey (openssl rand -hex 16)" }}
{{- end }}
{{- end }}
{{- if .Values.ingress.tls.enabled }}
{{- if not .Values.ingress.tls.secretName }}
{{- fail "При ingress.tls.enabled нужен ingress.tls.secretName с TLS-сертификатом" }}
{{- end }}
{{- end }}
{{- if and (not .Values.dragonfly.enabled) (not .Values.app.redis.host) }}
{{- fail "dragonfly.enabled: false требует app.redis.host — иначе приложение обратится к сервису, которого нет в релизе" }}
{{- end }}
{{- if and (not .Values.nats.enabled) (not .Values.app.nats.url) }}
{{- fail "nats.enabled: false требует app.nats.url — иначе приложение обратится к брокеру, которого нет в релизе" }}
{{- end }}
{{- if and .Values.nats.enabled .Values.nats.cluster.enabled }}
{{- if ne (.Values.nats.replicas | int) (.Values.nats.cluster.replicas | int) }}
{{- fail (printf "nats.replicas (%d) и nats.cluster.replicas (%d) должны совпадать: иначе часть нод не войдёт в кластер, а реплики JetStream-стримов будут посчитаны неверно" (.Values.nats.replicas | int) (.Values.nats.cluster.replicas | int)) }}
{{- end }}
{{- end }}
{{- $player := .Values.app.nanabushPlayer }}
{{- if and $player.enabled (not $player.deployment.enabled) }}
{{- fail "app.nanabushPlayer.enabled требует deployment.enabled: HRBox нельзя переключить на плеер, которого нет в кластере" }}
{{- end }}
{{- if and $player.enabled (not $player.ingress.enabled) }}
{{- fail "app.nanabushPlayer.enabled требует ingress.enabled: иначе HRBox выдаст ссылку на недоступный адрес" }}
{{- end }}
{{- if and $player.ingress.enabled (not $player.deployment.enabled) }}
{{- fail "app.nanabushPlayer.ingress.enabled требует deployment.enabled: маршрут вёл бы в несуществующий Service" }}
{{- end }}
{{- if and $player.ingress.enabled (not .Values.ingress.enabled) }}
{{- fail "Путь плеера публикуется на основном Ingress, поэтому нужен ingress.enabled: true" }}
{{- end }}
{{- if $player.deployment.enabled }}
{{- $basePath := $player.basePath | default "/nanabush-player" }}
{{- if eq (trimSuffix "/" $basePath) "" }}
{{- fail "app.nanabushPlayer.basePath не может быть корнем: корень домена занят самим HRBox" }}
{{- end }}
{{- if not (hasPrefix "/" $basePath) }}
{{- fail "app.nanabushPlayer.basePath должен начинаться со слэша, например /nanabush-player" }}
{{- end }}
{{- if not (include "hrbox.imageTag" .Values.image.nanabushPlayer) }}
{{- fail "image.nanabushPlayer должен содержать явный тег версии, например nanabush-player:1.0.11 — из него выводится версия плеера в launch-тикете" }}
{{- end }}
{{- if not $player.deployment.binaryCapabilities.basePath }}
{{- fail "On-premise монтирует плеер под путём, поэтому нужен образ с поддержкой base path. Проверьте сборку и верните deployment.binaryCapabilities.basePath: true" }}
{{- end }}
{{- if not $player.deployment.existingSecret.name }}
{{- fail "Заполните app.nanabushPlayer.deployment.existingSecret.name" }}
{{- end }}
{{- if $player.deployment.existingSecret.create }}
{{- if not $player.keys.ticketHs256 }}
{{- fail "Заполните app.nanabushPlayer.keys.ticketHs256 (openssl rand -base64 48)" }}
{{- end }}
{{- if not $player.keys.sessionHs256 }}
{{- fail "Заполните app.nanabushPlayer.keys.sessionHs256 (openssl rand -base64 48)" }}
{{- end }}
{{- if eq $player.keys.ticketHs256 $player.keys.sessionHs256 }}
{{- fail "app.nanabushPlayer.keys.ticketHs256 и sessionHs256 должны отличаться: это ключи разных контуров" }}
{{- end }}
{{- if and $player.deployment.existingSecret.keys.ticketKeys (not $player.keys.ticketKeys) }}
{{- fail "Указано имя ключа ticketKeys в секрете, но само кольцо app.nanabushPlayer.keys.ticketKeys пустое" }}
{{- end }}
{{- end }}
{{- if and $player.deployment.redis.urlFromExistingSecret $player.deployment.existingSecret.create }}
{{- fail "redis.urlFromExistingSecret: true требует existingSecret.create: false — Secret, создаваемый чартом, не содержит URL Redis" }}
{{- end }}
{{- if $player.deployment.metrics.enabled }}
{{- if eq ($player.deployment.metrics.port | int) ($player.service.port | int) }}
{{- fail "Порт метрик плеера должен отличаться от публичного порта сервиса, иначе метрики окажутся доступны содержимому курсов" }}
{{- end }}
{{- end }}
{{- end }}
+10 -6
View File
@@ -1,11 +1,14 @@
{{- if .Values.nats.enabled }}
{{- $name := include "hrbox.component" (dict "ctx" . "name" "nats") -}}
--- ---
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: {{ .Chart.Name }}-nats-config name: {{ printf "%s-config" $name }}
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "nats") | nindent 4 }}
data: data:
nats.conf: | nats.conf: |
# PID file shared with configuration reloader.
pid_file: "/var/run/nats/nats.pid" pid_file: "/var/run/nats/nats.pid"
############### ###############
@@ -42,17 +45,18 @@ data:
################################### ###################################
cluster { cluster {
port: 6222 port: 6222
name: {{ .Chart.Name }}-nats-cluster name: {{ printf "%s-cluster" $name }}
routes = [ routes = [
{{- range $i := until (int .Values.nats.cluster.replicas) }} {{- range $i := until (int .Values.nats.cluster.replicas) }}
nats://{{ $.Chart.Name }}-nats-{{ $i }}.{{ $.Chart.Name }}-nats.{{ $.Release.Namespace }}.svc.cluster.local:6222, nats://{{ $name }}-{{ $i }}.{{ $name }}.{{ $.Release.Namespace }}.svc.{{ $.Values.cluster.domain }}:6222,
{{- end }} {{- end }}
] ]
cluster_advertise: $CLUSTER_ADVERTISE cluster_advertise: $CLUSTER_ADVERTISE
connect_retries: 120 connect_retries: 120
} }
{{- end }} {{- end }}
lame_duck_duration: 120s lame_duck_duration: {{ .Values.nats.terminationGracePeriodSeconds }}s
{{- end }}
+38
View File
@@ -0,0 +1,38 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: assetlinks
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "web") | nindent 4 }}
data:
assetlinks.json: |
[
{{- range $i, $app := .Values.app.mobileApps.android }}
{{- if $i }},{{ end }}
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": {{ $app.packageName | quote }},
"sha256_cert_fingerprints": {{ toJson $app.sha256CertFingerprints }}
}
}
{{- end }}
]
apple-app-site-association: |
{
"applinks": {
"details": [
{
"appIDs": {{ toJson .Values.app.mobileApps.apple.appIds }},
"components": [
{
"/": "/*"
}
]
}
]
}
}
+141 -70
View File
@@ -3,83 +3,83 @@ apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: web-configuration name: web-configuration
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "web") | nindent 4 }}
data: data:
nginx.conf: | nginx.conf: |
user www-data; user www-data;
worker_processes 6; worker_processes 6;
pid /run/nginx.pid; pid /run/nginx.pid;
events { events {
worker_connections 10000; worker_connections 10000;
use epoll; use epoll;
multi_accept on; multi_accept on;
} }
http { http {
set_real_ip_from 10.0.0.0/8; set_real_ip_from 10.0.0.0/8;
## ##
# Basic Settings # Basic Settings
## ##
sendfile on; sendfile on;
tcp_nopush on; tcp_nopush on;
tcp_nodelay on; tcp_nodelay on;
keepalive_timeout 0; keepalive_timeout 0;
types_hash_max_size 2048; types_hash_max_size 2048;
server_tokens off; server_tokens off;
limit_conn_zone $binary_remote_addr zone=addr:10m; limit_conn_zone $binary_remote_addr zone=addr:10m;
server_names_hash_bucket_size 64; server_names_hash_bucket_size 64;
server_name_in_redirect off; server_name_in_redirect off;
fastcgi_buffer_size 256k; fastcgi_buffer_size 256k;
fastcgi_buffers 4 256k; fastcgi_buffers 4 256k;
client_body_buffer_size 1024k; client_body_buffer_size 1024k;
client_max_body_size 20m; client_max_body_size 20m;
client_header_buffer_size 1024k; client_header_buffer_size 1024k;
large_client_header_buffers 16 1024k; large_client_header_buffers 16 1024k;
default_type application/octet-stream;
default_type application/octet-stream; include /etc/nginx/mime.types;
include /etc/nginx/mime.types;
##
## # SSL Settings
# SSL Settings ##
##
ssl_protocols TLSv1.2 TLSv1.3;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m; ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m; ssl_session_timeout 10m;
## ##
# Logging Settings # Logging Settings
## ##
access_log /var/log/nginx/access.log; access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log; error_log /var/log/nginx/error.log;
rewrite_log on;
##
## # Gzip Settings
# Gzip Settings ##
##
gzip on;
gzip on; gzip_disable "msie6";
gzip_disable "msie6"; gzip_vary on;
gzip_vary on; gzip_proxied any;
gzip_proxied any; gzip_comp_level 6;
gzip_comp_level 6; gzip_buffers 16 8k;
gzip_buffers 16 8k; gzip_http_version 1.1;
gzip_http_version 1.1; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
## # Virtual Host Configs
# Virtual Host Configs ##
##
server { server {
listen 80 default; listen 80 default;
server_name _ ; server_name _ ;
@@ -96,7 +96,73 @@ data:
location ~ /\.(git) { location ~ /\.(git) {
deny all; deny all;
} }
location = /healthz {
access_log off;
return 200 "ok\n";
}
location = /health-check {
fastcgi_pass 127.0.0.1:9000;
fastcgi_connect_timeout 1s;
fastcgi_read_timeout 3s;
fastcgi_send_timeout 1s;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_param SCRIPT_NAME /index.php;
fastcgi_param PATH_INFO /health-check;
}
location = /api/v1/integration/commit {
client_max_body_size 500m;
fastcgi_request_buffering off;
fastcgi_pass localhost:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_param SCRIPT_NAME /index.php;
include fastcgi_params;
fastcgi_read_timeout 300s;
fastcgi_send_timeout 300s;
fastcgi_connect_timeout 60s;
}
location /.well-known/assetlinks.json {
default_type "application/json";
alias /var/www/assetlinks/assetlinks.json;
}
location /.well-known/apple-app-site-association {
default_type "application/json";
alias /var/www/assetlinks/apple-app-site-association;
}
location = /frontend/sw.js {
add_header Service-Worker-Allowed /;
add_header Cache-Control "no-cache, must-revalidate, public";
expires off;
try_files $uri $uri/ /index.php?$args;
access_log off;
}
location ^~ /ai/ {
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
add_header X-XSS-Protection "1; mode=block";
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header Permissions-Policy "browsing-topics=()" always;
fastcgi_pass localhost:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_param SCRIPT_NAME /index.php;
include fastcgi_params;
fastcgi_read_timeout 300s;
fastcgi_connect_timeout 60s;
fastcgi_send_timeout 60s;
}
location / { location / {
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
@@ -105,38 +171,43 @@ data:
add_header X-Content-Type-Options "nosniff"; add_header X-Content-Type-Options "nosniff";
add_header Permissions-Policy "browsing-topics=()" always; add_header Permissions-Policy "browsing-topics=()" always;
# Redirect everything that isn't a real file to index.php
try_files $uri $uri/ /index.php?$args; try_files $uri $uri/ /index.php?$args;
# uncomment to avoid processing of calls to non-existing static files by Yii
#location ~* \.(js|css|png|jpg|gif|ico|pdf|mov|fla|zip|rar)$ {
location ~* \.(js|css|png|jpg|gif|ico)$ { location ~* \.(js|css|png|jpg|gif|ico)$ {
expires 30d; expires 30d;
add_header Vary Accept-Encoding; add_header Vary Accept-Encoding;
add_header Pragma "public"; add_header Pragma "public";
add_header Cache-Control "public, must-revalidate, proxy-revalidate"; add_header Cache-Control "public, must-revalidate, proxy-revalidate";
access_log off; access_log off;
tcp_nodelay off; tcp_nodelay off;
try_files $uri $uri/ /index.php?$args; try_files $uri $uri/ /index.php?$args;
open_file_cache max=3000 inactive=120s; open_file_cache max=3000 inactive=120s;
open_file_cache_valid 45s; open_file_cache_valid 45s;
open_file_cache_min_uses 2; open_file_cache_min_uses 2;
open_file_cache_errors off; open_file_cache_errors off;
} }
#error_page 404 /404.html; location ~* \.(woff|woff2|ttf|otf|eot)$ {
expires 30d;
add_header Vary Accept-Encoding;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
access_log off;
try_files $uri $uri/ /index.php?$args;
}
} }
location ~ \.php$ { location ~ \.php$ {
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
add_header X-XSS-Protection "1; mode=block"; add_header X-XSS-Protection "1; mode=block";
add_header X-Frame-Options "SAMEORIGIN"; add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff"; add_header X-Content-Type-Options "nosniff";
fastcgi_split_path_info ^(.+?\.php)(/.*)$; fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f $document_root$fastcgi_script_name) { if (!-f $document_root$fastcgi_script_name) {
return 404; return 404;
@@ -151,4 +222,4 @@ data:
fastcgi_send_timeout 60s; fastcgi_send_timeout 60s;
} }
} }
} }
+34
View File
@@ -0,0 +1,34 @@
{{- if .Values.app.tracing.enabled }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: otel-config
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "web") | nindent 4 }}
data:
config.yml: |
receivers:
otlp:
protocols:
grpc:
endpoint: "0.0.0.0:4317"
http:
endpoint: "0.0.0.0:4318"
processors:
batch:
exporters:
otlp:
endpoint: {{ required "При app.tracing.enabled нужен app.tracing.tempoUrl — адрес приёмника трейсов" .Values.app.tracing.tempoUrl | quote }}
tls:
insecure: true
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp]
{{- end }}
+5 -3
View File
@@ -3,10 +3,12 @@ apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: job-scripts name: job-scripts
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "jobs") | nindent 4 }}
data: data:
wait.sh: | wait.sh: |
until pg_isready -h $POSTGRES_VHOST -p $POSTGRES_PORT -U $POSTGRES_USER until pg_isready -h "$POSTGRES_VHOST" -p "$POSTGRES_PORT" -U "$POSTGRES_USER"
do do
echo "Waiting for postgres" echo "Waiting for postgres"
sleep 2; sleep 2
done done
+37 -22
View File
@@ -1,46 +1,61 @@
{{- if .Values.dragonfly.enabled }} {{- if .Values.dragonfly.enabled }}
{{- $name := include "hrbox.component" (dict "ctx" . "name" "dragonfly") -}}
--- ---
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: {{ .Chart.Name }}-dragonfly name: {{ $name }}
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "dragonfly") | nindent 4 }}
spec: spec:
revisionHistoryLimit: 3 revisionHistoryLimit: 3
strategy: strategy:
type: Recreate type: Recreate
selector: selector:
matchLabels: matchLabels:
component: {{ .Chart.Name }}-dragonfly component: {{ $name }}
template: template:
metadata: metadata:
labels: labels:
component: {{ .Chart.Name }}-dragonfly component: {{ $name }}
app: dragonfly
spec: spec:
imagePullSecrets: {{- include "hrbox.imagePullSecrets" . | nindent 6 }}
- name: regsecret
containers: containers:
- name: dragonfly - name: dragonfly
image: cr.yandex/crpnn6fi85p3dauha6nc/dragonflydb:1.15.1 image: {{ .Values.image.dragonfly | quote }}
{{- if .Values.dragonfly.maxmemory }} imagePullPolicy: {{ .Values.image.pullPolicy }}
args: {{- with .Values.dragonfly.maxmemory }}
- --maxmemory={{ .Values.dragonfly.maxmemory }} args:
{{- end }} - --maxmemory={{ . }}
ports: {{- end }}
- name: dragonfly ports:
containerPort: 6379 - name: dragonfly
livenessProbe: containerPort: 6379
tcpSocket: {{- include "hrbox.resources" (dict "ctx" . "component" "dragonfly") | indent 10 }}
port: 6379 readinessProbe:
initialDelaySeconds: 30 tcpSocket:
port: 6379
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 6379
initialDelaySeconds: 30
periodSeconds: 10
--- ---
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: {{ .Chart.Name }}-dragonfly name: {{ $name }}
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "dragonfly") | nindent 4 }}
spec: spec:
clusterIP: None clusterIP: None
selector: selector:
component: {{ .Chart.Name }}-dragonfly component: {{ $name }}
ports: ports:
- port: 6379 - name: dragonfly
{{- end }} port: 6379
{{- end }}
+60 -59
View File
@@ -1,18 +1,19 @@
{{- if .Values.nats.enabled }}
{{- $name := include "hrbox.component" (dict "ctx" . "name" "nats") -}}
--- ---
apiVersion: apps/v1 apiVersion: apps/v1
kind: StatefulSet kind: StatefulSet
metadata: metadata:
name: {{ .Chart.Name }}-nats name: {{ $name }}
labels: labels:
app.kubernetes.io/name: nats {{- include "hrbox.labels" (dict "ctx" . "name" "nats") | nindent 4 }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec: spec:
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: nats app.kubernetes.io/name: nats
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
replicas: {{ .Values.nats.replicas }} replicas: {{ .Values.nats.replicas }}
serviceName: {{ .Chart.Name }}-nats serviceName: {{ $name }}
template: template:
metadata: metadata:
labels: labels:
@@ -22,50 +23,50 @@ spec:
volumes: volumes:
- name: config-volume - name: config-volume
configMap: configMap:
name: {{ .Chart.Name }}-nats-config name: {{ printf "%s-config" $name }}
- name: pid - name: pid
emptyDir: {} emptyDir: {}
shareProcessNamespace: true shareProcessNamespace: true
terminationGracePeriodSeconds: {{ .Values.nats.terminationGracePeriodSeconds }} terminationGracePeriodSeconds: {{ .Values.nats.terminationGracePeriodSeconds }}
imagePullSecrets: {{- include "hrbox.imagePullSecrets" . | nindent 6 }}
- name: regsecret
containers: containers:
- name: nats - name: nats
image: {{ .Values.nats.image }} image: {{ .Values.image.nats | quote }}
imagePullPolicy: IfNotPresent imagePullPolicy: {{ .Values.image.pullPolicy }}
ports: ports:
- containerPort: 4222 - containerPort: 4222
name: client name: client
- containerPort: 6222 - containerPort: 6222
name: cluster name: cluster
- containerPort: 8222 - containerPort: 8222
name: monitor name: monitor
- containerPort: 7777 - containerPort: 7777
name: metrics name: metrics
command: command:
- "nats-server" - "nats-server"
- "--config" - "--config"
- "/etc/nats-config/nats.conf" - "/etc/nats-config/nats.conf"
env: env:
- name: POD_NAME - name: POD_NAME
valueFrom: valueFrom:
fieldRef: fieldRef:
fieldPath: metadata.name fieldPath: metadata.name
- name: SERVER_NAME - name: SERVER_NAME
value: $(POD_NAME) value: $(POD_NAME)
- name: POD_NAMESPACE - name: POD_NAMESPACE
valueFrom: valueFrom:
fieldRef: fieldRef:
fieldPath: metadata.namespace fieldPath: metadata.namespace
- name: CLUSTER_ADVERTISE - name: CLUSTER_ADVERTISE
value: $(POD_NAME).{{ .Chart.Name }}-nats.$(POD_NAMESPACE).{{ .Values.cluster.domain | default "cluster.local" }} value: $(POD_NAME).{{ $name }}.$(POD_NAMESPACE).svc.{{ .Values.cluster.domain }}
{{- include "hrbox.resources" (dict "ctx" . "component" "nats") | indent 10 }}
volumeMounts: volumeMounts:
- name: config-volume - name: config-volume
mountPath: /etc/nats-config mountPath: /etc/nats-config
- name: pid - name: pid
mountPath: /var/run/nats mountPath: /var/run/nats
{{- if .Values.nats.jetstream.fileStorage.enabled }} {{- if .Values.nats.jetstream.fileStorage.enabled }}
- name: {{ .Chart.Name }}-nats-js-pvc - name: {{ printf "%s-js-pvc" $name }}
mountPath: {{ .Values.nats.jetstream.fileStorage.storageDirectory }} mountPath: {{ .Values.nats.jetstream.fileStorage.storageDirectory }}
{{- end }} {{- end }}
livenessProbe: livenessProbe:
@@ -84,20 +85,20 @@ spec:
preStop: preStop:
exec: exec:
command: command:
- "/bin/sh" - "/bin/sh"
- "-c" - "-c"
- "nats-server -sl=ldm=/var/run/nats/nats.pid && /bin/sleep 120" - "nats-server -sl=ldm=/var/run/nats/nats.pid && /bin/sleep {{ .Values.nats.terminationGracePeriodSeconds }}"
{{- if .Values.nats.reloader.enabled }} {{- if .Values.nats.reloader.enabled }}
- name: reloader - name: reloader
image: natsio/nats-server-config-reloader:0.6.2 image: {{ .Values.image.natsConfigReloader | quote }}
imagePullPolicy: IfNotPresent imagePullPolicy: {{ .Values.image.pullPolicy }}
command: command:
- "nats-server-config-reloader" - "nats-server-config-reloader"
- "-pid" - "-pid"
- "/var/run/nats/nats.pid" - "/var/run/nats/nats.pid"
- "-config" - "-config"
- "/etc/nats-config/nats.conf" - "/etc/nats-config/nats.conf"
volumeMounts: volumeMounts:
- name: config-volume - name: config-volume
mountPath: /etc/nats-config mountPath: /etc/nats-config
@@ -108,15 +109,15 @@ spec:
{{- if .Values.nats.jetstream.fileStorage.enabled }} {{- if .Values.nats.jetstream.fileStorage.enabled }}
volumeClaimTemplates: volumeClaimTemplates:
- metadata: - metadata:
name: {{ .Chart.Name }}-nats-js-pvc name: {{ printf "%s-js-pvc" $name }}
spec: spec:
accessModes: accessModes:
- ReadWriteOnce - ReadWriteOnce
resources: resources:
requests: requests:
storage: {{ .Values.nats.jetstream.fileStorage.size }} storage: {{ .Values.nats.jetstream.fileStorage.size }}
{{- if .Values.nats.jetstream.fileStorage.storageClassName }} {{- with .Values.nats.jetstream.fileStorage.storageClassName }}
storageClassName: {{ .Values.nats.jetstream.fileStorage.storageClassName }} storageClassName: {{ . | quote }}
{{- end }} {{- end }}
{{- end }} {{- end }}
@@ -124,21 +125,21 @@ spec:
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: {{ .Chart.Name }}-nats name: {{ $name }}
labels: labels:
app.kubernetes.io/name: nats {{- include "hrbox.labels" (dict "ctx" . "name" "nats") | nindent 4 }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec: spec:
clusterIP: None
selector: selector:
app.kubernetes.io/name: nats app.kubernetes.io/name: nats
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
clusterIP: None
ports: ports:
- name: client - name: client
port: 4222 port: 4222
- name: cluster - name: cluster
port: 6222 port: 6222
- name: monitor - name: monitor
port: 8222 port: 8222
- name: metrics - name: metrics
port: 7777 port: 7777
{{- end }}
+15
View File
@@ -0,0 +1,15 @@
{{- $replicas := .Values.app.replicas.web | int }}
{{- if gt $replicas 1 }}
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: {{ include "hrbox.component" (dict "ctx" . "name" "web") }}-pdb
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "web") | nindent 4 }}
spec:
minAvailable: 75%
selector:
matchLabels:
{{- include "hrbox.selectorLabels" (dict "ctx" . "name" "web") | nindent 6 }}
{{- end }}
+88 -21
View File
@@ -1,48 +1,59 @@
{{- $name := include "hrbox.component" (dict "ctx" . "name" "web") -}}
--- ---
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: {{ .Chart.Name }}-web name: {{ $name }}
labels: labels:
app: web {{- include "hrbox.labels" (dict "ctx" . "name" "web") | nindent 4 }}
spec: spec:
minReadySeconds: 5 minReadySeconds: 5
strategy: strategy:
type: RollingUpdate type: RollingUpdate
rollingUpdate: rollingUpdate:
maxSurge: 1 maxSurge: 1
maxUnavailable: 1 maxUnavailable: 0
replicas: {{ .Values.app.replicas.web }} replicas: {{ .Values.app.replicas.web }}
selector: selector:
matchLabels: matchLabels:
service: {{ .Chart.Name }}-web {{- include "hrbox.selectorLabels" (dict "ctx" . "name" "web") | nindent 6 }}
template: template:
metadata: metadata:
labels: labels:
service: {{ .Chart.Name }}-web {{- include "hrbox.selectorLabels" (dict "ctx" . "name" "web") | nindent 8 }}
app: web
annotations: annotations:
prometheus.io/scrape: 'true' prometheus.io/scrape: 'true'
prometheus.io/port: '9253' prometheus.io/port: '9253'
checksum/nginx-config: {{ include (print $.Template.BasePath "/01-nginx-configmap.yaml") . | sha256sum }}
checksum/app-secret: {{ include (print $.Template.BasePath "/00-app-secret.yaml") . | sha256sum }}
spec: spec:
imagePullSecrets: terminationGracePeriodSeconds: 30
- name: regsecret {{- include "hrbox.imagePullSecrets" . | nindent 6 }}
containers: containers:
- name: fpm - name: fpm
image: {{ .Values.app.image }} image: {{ .Values.image.hrbox | quote }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: ["/usr/local/sbin/php-fpm", "-c", "/usr/local/etc/php-fpm"] command: ["/usr/local/sbin/php-fpm", "-c", "/usr/local/etc/php-fpm"]
ports: ports:
- name: fpm - name: fpm
containerPort: 9000 containerPort: 9000
env: env:
{{- include "envs_all" . | indent 12 }} {{- include "envs_all" . | indent 12 }}
{{- include "app_resources" . | indent 10 }} {{- include "envs_nanabush_player_signing" . | indent 12 }}
- name: VIDEO_CONVERTER_ENABLED
value: {{ .Values.app.videoConverter.enabled | quote }}
{{- if .Values.app.tracing.enabled }}
{{- include "envs_tracing" . | indent 12 }}
{{- end }}
{{- include "hrbox.resources" (dict "ctx" . "component" "app") | indent 10 }}
lifecycle: lifecycle:
preStop: preStop:
exec: exec:
command: command:
- sh - sh
- '-c' - '-c'
- sleep 5 && kill -SIGQUIT 1 - sleep 15 && kill -SIGQUIT 1
readinessProbe: readinessProbe:
tcpSocket: tcpSocket:
port: 9000 port: 9000
@@ -53,48 +64,104 @@ spec:
port: 9000 port: 9000
initialDelaySeconds: 5 initialDelaySeconds: 5
periodSeconds: 10 periodSeconds: 10
- name: nginx - name: nginx
image: {{ .Values.app.image }} image: {{ .Values.image.hrbox | quote }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: ["/usr/sbin/nginx", "-g", "daemon off;"] command: ["/usr/sbin/nginx", "-g", "daemon off;"]
ports: ports:
- name: http - name: http
containerPort: 80 containerPort: 80
env: env:
{{- include "envs_all" . | indent 12 }} {{- include "envs_all" . | indent 12 }}
{{- include "nginx_resources" . | indent 10}} {{- include "hrbox.resources" (dict "ctx" . "component" "nginx") | indent 10 }}
lifecycle: lifecycle:
preStop: preStop:
exec: exec:
command: command:
- sh - sh
- '-c' - '-c'
- sleep 5 && /usr/sbin/nginx -s quit - sleep 15 && /usr/sbin/nginx -s quit
livenessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 10
failureThreshold: 5
readinessProbe:
httpGet:
path: /health-check
port: 80
initialDelaySeconds: 15
periodSeconds: 5
timeoutSeconds: 10
failureThreshold: 3
volumeMounts: volumeMounts:
- name: configs - name: configs
mountPath: /etc/nginx/nginx.conf mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf subPath: nginx.conf
- name: phpfpm-exporter - name: assetlinks
image: cr.yandex/crpnn6fi85p3dauha6nc/php-fpm_exporter:latest mountPath: /var/www/assetlinks/assetlinks.json
subPath: assetlinks.json
- name: assetlinks
mountPath: /var/www/assetlinks/apple-app-site-association
subPath: apple-app-site-association
{{- if .Values.app.tracing.enabled }}
- name: otel-collector
image: {{ .Values.image.otelCollector | quote }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
args: ["--config=/etc/otel-config/otel-collector-config.yaml"]
ports: ports:
- containerPort: 9253 - containerPort: 4317
name: otlp-grpc
- containerPort: 4318
name: otlp-http
volumeMounts:
- name: otel-config
mountPath: /etc/otel-config/otel-collector-config.yaml
subPath: config.yml
{{- end }}
- name: phpfpm-exporter
image: {{ .Values.image.phpFpmExporter | quote }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: 9253
name: metrics
env: env:
- name: PHP_FPM_SCRAPE_URI - name: PHP_FPM_SCRAPE_URI
value: "tcp://127.0.0.1:9000/hrbox-fpm-status" value: "tcp://127.0.0.1:9000/hrbox-fpm-status"
volumes: volumes:
- name: configs - name: configs
configMap: configMap:
name: web-configuration name: web-configuration
defaultMode: 420 defaultMode: 420
- name: assetlinks
configMap:
name: assetlinks
defaultMode: 420
{{- if .Values.app.tracing.enabled }}
- name: otel-config
configMap:
name: otel-config
defaultMode: 420
{{- end }}
--- ---
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: {{ .Chart.Name }}-web name: {{ $name }}
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "web") | nindent 4 }}
spec: spec:
selector: selector:
service: {{ .Chart.Name }}-web {{- include "hrbox.selectorLabels" (dict "ctx" . "name" "web") | nindent 4 }}
ports: ports:
- name: http - name: http
port: 80 port: 80
protocol: TCP protocol: TCP
+57
View File
@@ -0,0 +1,57 @@
{{- $name := include "hrbox.component" (dict "ctx" . "name" "chatbox") -}}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ $name }}
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "chatbox") | nindent 4 }}
spec:
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
replicas: {{ .Values.app.replicas.chatbox }}
selector:
matchLabels:
{{- include "hrbox.selectorLabels" (dict "ctx" . "name" "chatbox") | nindent 6 }}
template:
metadata:
labels:
{{- include "hrbox.selectorLabels" (dict "ctx" . "name" "chatbox") | nindent 8 }}
app: chatbox
annotations:
prometheus.io/scrape: 'true'
prometheus.io/port: '9797'
prometheus.io/path: "/info"
checksum/app-secret: {{ include (print $.Template.BasePath "/00-app-secret.yaml") . | sha256sum }}
spec:
{{- include "hrbox.imagePullSecrets" . | nindent 6 }}
containers:
- name: chatbox
image: {{ .Values.image.chatbox | quote }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 9797
env:
{{- include "envs_all" . | indent 12 }}
{{- include "hrbox.resources" (dict "ctx" . "component" "chatbox") | indent 10 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ $name }}
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "chatbox") | nindent 4 }}
spec:
selector:
{{- include "hrbox.selectorLabels" (dict "ctx" . "name" "chatbox") | nindent 4 }}
ports:
- name: http
port: 80
targetPort: 9797
protocol: TCP
-51
View File
@@ -1,51 +0,0 @@
---
# Chatbox (WebSocket server) - обеспечивает real-time функционал
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Chart.Name }}-chatbox
labels:
app: chatbox
spec:
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
replicas: {{ .Values.app.replicas.chatbox }}
selector:
matchLabels:
service: {{ .Chart.Name }}-chatbox
template:
metadata:
labels:
service: {{ .Chart.Name }}-chatbox
annotations:
prometheus.io/scrape: 'true'
prometheus.io/port: '9797'
prometheus.io/path: "/info"
spec:
imagePullSecrets:
- name: regsecret
containers:
- name: chatbox
image: {{ .Values.app.chatbox.image }}
imagePullPolicy: Always
env:
{{- include "envs_all" . | indent 12 }}
{{- include "chatbox_resources" . | indent 10 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Chart.Name }}-chatbox
spec:
selector:
service: {{ .Chart.Name }}-chatbox
ports:
- name: http
port: 80
targetPort: 9797
protocol: TCP
+14 -9
View File
@@ -1,10 +1,11 @@
{{- $name := include "hrbox.component" (dict "ctx" . "name" "worker") -}}
--- ---
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: {{ .Chart.Name }}-worker name: {{ $name }}
labels: labels:
app: worker {{- include "hrbox.labels" (dict "ctx" . "name" "worker") | nindent 4 }}
spec: spec:
minReadySeconds: 5 minReadySeconds: 5
strategy: strategy:
@@ -12,22 +13,26 @@ spec:
replicas: {{ .Values.app.replicas.worker }} replicas: {{ .Values.app.replicas.worker }}
selector: selector:
matchLabels: matchLabels:
service: {{ .Chart.Name }}-worker {{- include "hrbox.selectorLabels" (dict "ctx" . "name" "worker") | nindent 6 }}
template: template:
metadata: metadata:
labels: labels:
service: {{ .Chart.Name }}-worker {{- include "hrbox.selectorLabels" (dict "ctx" . "name" "worker") | nindent 8 }}
app: worker
annotations: annotations:
prometheus.io/scrape: 'true' prometheus.io/scrape: 'true'
prometheus.io/port: '9253' prometheus.io/port: '9253'
checksum/app-secret: {{ include (print $.Template.BasePath "/00-app-secret.yaml") . | sha256sum }}
spec: spec:
imagePullSecrets: {{- include "hrbox.imagePullSecrets" . | nindent 6 }}
- name: regsecret
containers: containers:
- name: worker - name: worker
image: {{ .Values.app.image }} image: {{ .Values.image.hrbox | quote }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: ["hrbox-worker"] command: ["hrbox-worker"]
env: env:
{{- include "envs_all" . | indent 12 }} {{- include "envs_all" . | indent 12 }}
{{- include "worker_resources" . | indent 10}} - name: VIDEO_CONVERTER_ENABLED
terminationGracePeriodSeconds: 600 value: {{ .Values.app.videoConverter.enabled | quote }}
{{- include "hrbox.resources" (dict "ctx" . "component" "worker") | indent 10 }}
terminationGracePeriodSeconds: 600
+51 -19
View File
@@ -1,40 +1,72 @@
{{- $name := include "hrbox.component" (dict "ctx" . "name" "conductor") -}}
--- ---
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: {{ .Chart.Name }}-conductor name: {{ $name }}
labels: labels:
app: conductor {{- include "hrbox.labels" (dict "ctx" . "name" "conductor") | nindent 4 }}
spec: spec:
replicas: 1 replicas: 1
strategy: strategy:
type: Recreate type: Recreate
selector: selector:
matchLabels: matchLabels:
service: {{ .Chart.Name }}-conductor {{- include "hrbox.selectorLabels" (dict "ctx" . "name" "conductor") | nindent 6 }}
template: template:
metadata: metadata:
labels: labels:
service: {{ .Chart.Name }}-conductor {{- include "hrbox.selectorLabels" (dict "ctx" . "name" "conductor") | nindent 8 }}
app: conductor
annotations:
prometheus.io/scrape: 'true'
prometheus.io/port: '8080'
prometheus.io/path: '/metrics'
checksum/app-secret: {{ include (print $.Template.BasePath "/00-app-secret.yaml") . | sha256sum }}
spec: spec:
affinity: affinity:
podAntiAffinity: podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution: preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100 - weight: 100
podAffinityTerm: podAffinityTerm:
labelSelector: labelSelector:
matchExpressions: matchExpressions:
- key: app - key: app
operator: In operator: In
values: values:
- conductor - conductor
topologyKey: kubernetes.io/hostname topologyKey: kubernetes.io/hostname
imagePullSecrets: {{- include "hrbox.imagePullSecrets" . | nindent 6 }}
- name: regsecret
containers: containers:
- name: conductor - name: conductor
{{- include "conductor_resources" . | indent 10 }} image: {{ .Values.image.conductor | quote }}
image: cr.yandex/crphnph9c2s776j32sjd/hrbox-conductor:2.2.0 imagePullPolicy: {{ .Values.image.pullPolicy }}
imagePullPolicy: IfNotPresent ports:
- name: http
containerPort: 8080
env: env:
{{- include "envs_all" . | indent 12 }} {{- include "envs_all" . | indent 12 }}
{{- include "hrbox.resources" (dict "ctx" . "component" "conductor") | indent 10 }}
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 30
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 30
timeoutSeconds: 5
failureThreshold: 3
lifecycle:
preStop:
exec:
command:
- /bin/sh
- -c
- "sleep 5"
@@ -0,0 +1,49 @@
{{- if .Values.app.videoConverter.enabled }}
{{- $name := include "hrbox.component" (dict "ctx" . "name" "file-processor-video") -}}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ $name }}
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "file-processor-video") | nindent 4 }}
spec:
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
replicas: {{ .Values.app.replicas.fileProcessorVideo }}
selector:
matchLabels:
{{- include "hrbox.selectorLabels" (dict "ctx" . "name" "file-processor-video") | nindent 6 }}
template:
metadata:
labels:
{{- include "hrbox.selectorLabels" (dict "ctx" . "name" "file-processor-video") | nindent 8 }}
app: file-processor
annotations:
checksum/app-secret: {{ include (print $.Template.BasePath "/00-app-secret.yaml") . | sha256sum }}
spec:
{{- with .Values.app.videoConverter.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.app.videoConverter.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- include "hrbox.imagePullSecrets" . | nindent 6 }}
containers:
- name: file-processor
image: {{ .Values.image.fileProcessor | quote }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
{{- include "envs_all" . | indent 12 }}
- name: VIDEO_CONVERTER_ENABLED
value: "true"
- name: IMAGE_RESIZE_MAX_PARALLEL
value: {{ .Values.app.fileProcessor.imageResizeMaxParallel | quote }}
{{- include "hrbox.resources" (dict "ctx" . "component" "fileProcessorVideo") | indent 10 }}
{{- end }}
+13 -10
View File
@@ -1,11 +1,11 @@
{{- $name := include "hrbox.component" (dict "ctx" . "name" "file-processor") -}}
--- ---
{{ $name := printf "%s-file-processor" (.Chart.Name) }}
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: {{ $name }} name: {{ $name }}
labels: labels:
app: file-processor {{- include "hrbox.labels" (dict "ctx" . "name" "file-processor") | nindent 4 }}
spec: spec:
minReadySeconds: 5 minReadySeconds: 5
strategy: strategy:
@@ -13,22 +13,25 @@ spec:
rollingUpdate: rollingUpdate:
maxSurge: 1 maxSurge: 1
maxUnavailable: 1 maxUnavailable: 1
replicas: {{ .Values.app.file_processor.replicas }} replicas: {{ .Values.app.replicas.fileProcessor }}
selector: selector:
matchLabels: matchLabels:
service: {{ $name }} {{- include "hrbox.selectorLabels" (dict "ctx" . "name" "file-processor") | nindent 6 }}
template: template:
metadata: metadata:
labels: labels:
service: {{ $name }} {{- include "hrbox.selectorLabels" (dict "ctx" . "name" "file-processor") | nindent 8 }}
app: file-processor
annotations:
checksum/app-secret: {{ include (print $.Template.BasePath "/00-app-secret.yaml") . | sha256sum }}
spec: spec:
imagePullSecrets: {{- include "hrbox.imagePullSecrets" . | nindent 6 }}
- name: regsecret
containers: containers:
- name: file-processor - name: file-processor
image: {{ .Values.app.file_processor.image }} image: {{ .Values.image.fileProcessor | quote }}
imagePullPolicy: Always imagePullPolicy: {{ .Values.image.pullPolicy }}
env: env:
{{- include "envs_all" . | indent 12 }} {{- include "envs_all" . | indent 12 }}
- name: VIDEO_CONVERTER_ENABLED - name: VIDEO_CONVERTER_ENABLED
value: "false" value: "false"
{{- include "hrbox.resources" (dict "ctx" . "component" "fileProcessor") | indent 10 }}
+57
View File
@@ -0,0 +1,57 @@
{{- $name := include "hrbox.component" (dict "ctx" . "name" "geonames") -}}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ $name }}
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "geonames") | nindent 4 }}
spec:
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
replicas: {{ .Values.app.replicas.geonames }}
selector:
matchLabels:
{{- include "hrbox.selectorLabels" (dict "ctx" . "name" "geonames") | nindent 6 }}
template:
metadata:
labels:
{{- include "hrbox.selectorLabels" (dict "ctx" . "name" "geonames") | nindent 8 }}
app: geonames
annotations:
prometheus.io/scrape: 'true'
prometheus.io/port: '9797'
prometheus.io/path: "/info"
checksum/app-secret: {{ include (print $.Template.BasePath "/00-app-secret.yaml") . | sha256sum }}
spec:
{{- include "hrbox.imagePullSecrets" . | nindent 6 }}
containers:
- name: geonames
image: {{ .Values.image.geonames | quote }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 8181
env:
{{- include "envs_all" . | indent 12 }}
{{- include "hrbox.resources" (dict "ctx" . "component" "geonames") | indent 10 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ $name }}
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "geonames") | nindent 4 }}
spec:
selector:
{{- include "hrbox.selectorLabels" (dict "ctx" . "name" "geonames") | nindent 4 }}
ports:
- name: http
port: 8181
targetPort: 8181
protocol: TCP
-50
View File
@@ -1,50 +0,0 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Chart.Name }}-geonames
labels:
app: geonames
spec:
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
replicas: {{ .Values.app.replicas.geonames }}
selector:
matchLabels:
service: {{ .Chart.Name }}-geonames
template:
metadata:
labels:
service: {{ .Chart.Name }}-geonames
annotations:
prometheus.io/scrape: 'true'
prometheus.io/port: '9797'
prometheus.io/path: "/info"
spec:
imagePullSecrets:
- name: regsecret
containers:
- name: geonames
{{- include "geonames_resources" . | indent 10}}
image: cr.yandex/crphnph9c2s776j32sjd/hrbox-geonames:3.1
imagePullPolicy: Always
env:
{{- include "envs_all" . | indent 12 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Chart.Name }}-geonames
spec:
selector:
service: {{ .Chart.Name }}-geonames
ports:
- name: http
port: 8181
targetPort: 8181
protocol: TCP
+20 -12
View File
@@ -1,10 +1,11 @@
{{- $name := include "hrbox.component" (dict "ctx" . "name" "goworker") -}}
--- ---
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: {{ .Chart.Name }}-goworker name: {{ $name }}
labels: labels:
app: goworker {{- include "hrbox.labels" (dict "ctx" . "name" "goworker") | nindent 4 }}
spec: spec:
minReadySeconds: 5 minReadySeconds: 5
strategy: strategy:
@@ -12,39 +13,46 @@ spec:
rollingUpdate: rollingUpdate:
maxSurge: 1 maxSurge: 1
maxUnavailable: 1 maxUnavailable: 1
replicas: {{ .Values.app.goworker.replicas }} replicas: {{ .Values.app.replicas.goworker }}
selector: selector:
matchLabels: matchLabels:
service: {{ .Chart.Name }}-goworker {{- include "hrbox.selectorLabels" (dict "ctx" . "name" "goworker") | nindent 6 }}
template: template:
metadata: metadata:
labels: labels:
service: {{ .Chart.Name }}-goworker {{- include "hrbox.selectorLabels" (dict "ctx" . "name" "goworker") | nindent 8 }}
app: goworker
annotations:
checksum/app-secret: {{ include (print $.Template.BasePath "/00-app-secret.yaml") . | sha256sum }}
spec: spec:
imagePullSecrets: {{- include "hrbox.imagePullSecrets" . | nindent 6 }}
- name: regsecret
containers: containers:
- name: goworker - name: goworker
image: {{ .Values.image.goworker | quote }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
stdin: true stdin: true
tty: true tty: true
image: {{ .Values.app.goworker.image }} ports:
imagePullPolicy: Always - name: http
containerPort: 8686
env: env:
{{- include "envs_all" . | indent 12 }} {{- include "envs_all" . | indent 12 }}
{{- include "goworker_resources" . | indent 10 }} {{- include "hrbox.resources" (dict "ctx" . "component" "goworker") | indent 10 }}
--- ---
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: {{ .Chart.Name }}-goworker name: {{ $name }}
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "goworker") | nindent 4 }}
annotations: annotations:
prometheus.io/scrape: "true" prometheus.io/scrape: "true"
prometheus.io/port: "8686" prometheus.io/port: "8686"
prometheus.io/path: "/metrics" prometheus.io/path: "/metrics"
spec: spec:
selector: selector:
service: {{ .Chart.Name }}-goworker {{- include "hrbox.selectorLabels" (dict "ctx" . "name" "goworker") | nindent 4 }}
ports: ports:
- name: http - name: http
port: 8686 port: 8686
+33 -17
View File
@@ -1,10 +1,11 @@
{{- $name := include "hrbox.component" (dict "ctx" . "name" "kedoca") -}}
--- ---
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: {{ .Chart.Name }}-kedoca name: {{ $name }}
labels: labels:
app: kedoca {{- include "hrbox.labels" (dict "ctx" . "name" "kedoca") | nindent 4 }}
spec: spec:
minReadySeconds: 5 minReadySeconds: 5
strategy: strategy:
@@ -12,27 +13,42 @@ spec:
rollingUpdate: rollingUpdate:
maxSurge: 1 maxSurge: 1
maxUnavailable: 1 maxUnavailable: 1
replicas: {{ .Values.app.kedoca.replicas }} replicas: {{ .Values.app.replicas.kedoca }}
selector: selector:
matchLabels: matchLabels:
service: {{ .Chart.Name }}-kedoca {{- include "hrbox.selectorLabels" (dict "ctx" . "name" "kedoca") | nindent 6 }}
template: template:
metadata: metadata:
labels: labels:
service: {{ .Chart.Name }}-kedoca {{- include "hrbox.selectorLabels" (dict "ctx" . "name" "kedoca") | nindent 8 }}
app: kedoca
annotations:
checksum/app-secret: {{ include (print $.Template.BasePath "/00-app-secret.yaml") . | sha256sum }}
spec: spec:
imagePullSecrets: affinity:
- name: regsecret podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- kedoca
topologyKey: kubernetes.io/hostname
{{- include "hrbox.imagePullSecrets" . | nindent 6 }}
containers: containers:
- name: kedoca - name: kedoca
image: {{ .Values.app.kedoca.image }} image: {{ .Values.image.kedoca | quote }}
imagePullPolicy: Always imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 8558
env: env:
{{- include "envs_all" . | indent 12 }} {{- include "envs_all" . | indent 12 }}
{{- include "envs_kedoca" . | indent 12 }} {{- include "envs_kedoca" . | indent 12 }}
ports: {{- include "hrbox.resources" (dict "ctx" . "component" "kedoca") | indent 10 }}
- containerPort: 8558
{{- include "kedoca_resources" . | indent 10 }}
{{- if .Values.app.kedoca.secretName }} {{- if .Values.app.kedoca.secretName }}
volumeMounts: volumeMounts:
- name: ca-cert - name: ca-cert
@@ -42,22 +58,22 @@ spec:
volumes: volumes:
- name: ca-cert - name: ca-cert
secret: secret:
secretName: {{ .Values.app.kedoca.secretName }} secretName: {{ .Values.app.kedoca.secretName | quote }}
{{- end }} {{- end }}
--- ---
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: {{ .Chart.Name }}-kedoca name: {{ $name }}
labels: labels:
app: kedoca {{- include "hrbox.labels" (dict "ctx" . "name" "kedoca") | nindent 4 }}
spec: spec:
type: ClusterIP
selector: selector:
service: {{ .Chart.Name }}-kedoca {{- include "hrbox.selectorLabels" (dict "ctx" . "name" "kedoca") | nindent 4 }}
ports: ports:
- name: http - name: http
port: 8558 port: 8558
targetPort: 8558 targetPort: 8558
protocol: TCP protocol: TCP
type: ClusterIP
+203
View File
@@ -0,0 +1,203 @@
{{- $cfg := .Values.app.nanabushPlayer.deployment }}
{{- if $cfg.enabled }}
{{- $name := include "nanabushPlayer.serviceName" . -}}
{{- $secretName := include "nanabushPlayer.secretName" . -}}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ $name }}
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "nanabush-player") | nindent 4 }}
spec:
replicas: {{ $cfg.replicas }}
revisionHistoryLimit: 3
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
service: {{ $name }}
template:
metadata:
labels:
service: {{ $name }}
app: nanabush-player
{{- if $cfg.metrics.enabled }}
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: {{ $cfg.metrics.port | quote }}
prometheus.io/path: "/metrics"
{{- end }}
spec:
automountServiceAccountToken: false
terminationGracePeriodSeconds: {{ $cfg.terminationGracePeriodSeconds }}
{{- include "hrbox.imagePullSecrets" . | nindent 6 }}
securityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
seccompProfile:
type: RuntimeDefault
containers:
- name: player
image: {{ .Values.image.nanabushPlayer | quote }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
ports:
- name: http
containerPort: {{ .Values.app.nanabushPlayer.service.port }}
protocol: TCP
{{- if $cfg.metrics.enabled }}
- name: metrics
containerPort: {{ $cfg.metrics.port }}
protocol: TCP
{{- end }}
env:
- name: PLAYER_HTTP_ADDR
value: {{ printf ":%d" (.Values.app.nanabushPlayer.service.port | int) | quote }}
- name: PLAYER_METRICS_ADDR
{{- if $cfg.metrics.enabled }}
value: {{ printf ":%d" ($cfg.metrics.port | int) | quote }}
{{- else }}
value: "off"
{{- end }}
- name: PLAYER_BASE_PATH
value: {{ include "nanabushPlayer.basePath" . | quote }}
- name: PLAYER_AUDIENCE
value: {{ include "nanabushPlayer.publicOrigin" . | quote }}
- name: PLAYER_ALLOWED_ISSUERS
value: {{ include "nanabushPlayer.issuer" . | quote }}
- name: PLAYER_HS256_SECRET
valueFrom:
secretKeyRef:
name: {{ $secretName | quote }}
key: {{ required "Нужно имя ключа ticketHs256 в секрете Nanabush Player" $cfg.existingSecret.keys.ticketHs256 | quote }}
{{- with $cfg.existingSecret.keys.ticketKeys }}
- name: PLAYER_TICKET_KEYS
valueFrom:
secretKeyRef:
name: {{ $secretName | quote }}
key: {{ . | quote }}
{{- with $cfg.ticket.keylessAcceptedUntil }}
- name: PLAYER_TICKET_KEYLESS_UNTIL
value: {{ . | quote }}
{{- end }}
{{- end }}
- name: PLAYER_SESSION_SECRET
valueFrom:
secretKeyRef:
name: {{ $secretName | quote }}
key: {{ required "Нужно имя ключа sessionHs256 в секрете Nanabush Player" $cfg.existingSecret.keys.sessionHs256 | quote }}
- name: PLAYER_SESSION_ISSUER
value: {{ include "nanabushPlayer.publicOrigin" . | quote }}
- name: PLAYER_SESSION_TTL
value: {{ $cfg.ticket.sessionTtl | quote }}
- name: PLAYER_MAX_TICKET_LIFETIME
value: {{ $cfg.ticket.maxLifetime | quote }}
- name: REDIS_URL
{{- if $cfg.redis.urlFromExistingSecret }}
valueFrom:
secretKeyRef:
name: {{ $secretName | quote }}
key: {{ required "Нужно имя ключа redisUrl, когда redis.urlFromExistingSecret: true" $cfg.existingSecret.keys.redisUrl | quote }}
{{- else }}
value: {{ include "nanabushPlayer.redisUrl" . | quote }}
{{- end }}
- name: PLAYER_REDIS_KEY_PREFIX
value: {{ include "nanabushPlayer.redisKeyPrefix" . | quote }}
- name: PLAYER_PACKAGE_FETCH_SCHEMES
value: {{ $cfg.backchannel.schemes | quote }}
- name: PLAYER_PACKAGE_FETCH_ALLOWLIST
value: {{ include "nanabushPlayer.backchannelHost" . | quote }}
- name: PLAYER_PACKAGE_FETCH_ALLOW_PRIVATE_IPS
value: {{ $cfg.backchannel.allowPrivateIps | quote }}
- name: PLAYER_PACKAGE_FETCH_MAX_BYTES
value: {{ $cfg.backchannel.packageFetchMaxBytes | quote }}
- name: PLAYER_PACKAGE_CONTENT_MAX_BYTES
value: {{ $cfg.backchannel.packageContentMaxBytes | quote }}
- name: PLAYER_PACKAGE_FETCH_TIMEOUT
value: {{ $cfg.backchannel.packageFetchTimeout | quote }}
- name: PLAYER_PACKAGE_STREAM_TIMEOUT
value: {{ $cfg.backchannel.packageStreamTimeout | quote }}
- name: PLAYER_REPORT_ENDPOINT_SCHEMES
value: {{ $cfg.backchannel.schemes | quote }}
- name: PLAYER_REPORT_ENDPOINT_ALLOWLIST
value: {{ include "nanabushPlayer.backchannelHost" . | quote }}
- name: PLAYER_REPORT_ENDPOINT_ALLOW_PRIVATE_IPS
value: {{ $cfg.backchannel.allowPrivateIps | quote }}
- name: PLAYER_REPORT_ENDPOINT_TIMEOUT
value: {{ $cfg.backchannel.reportTimeout | quote }}
- name: PLAYER_FORWARDER_QUEUE_SIZE
value: {{ $cfg.forwarder.queueSize | quote }}
- name: PLAYER_FORWARDER_WORKERS
value: {{ $cfg.forwarder.workers | quote }}
- name: PLAYER_FORWARDER_MAX_ATTEMPTS
value: {{ $cfg.forwarder.maxAttempts | quote }}
- name: PLAYER_FORWARDER_INITIAL_BACKOFF
value: {{ $cfg.forwarder.initialBackoff | quote }}
- name: PLAYER_FORWARDER_MAX_BACKOFF
value: {{ $cfg.forwarder.maxBackoff | quote }}
- name: PLAYER_FORWARDER_PER_ATTEMPT_TIMEOUT
value: {{ $cfg.forwarder.perAttemptTimeout | quote }}
- name: PLAYER_FORWARDER_DEAD_LETTER_SIZE
value: {{ $cfg.forwarder.deadLetterSize | quote }}
- name: PLAYER_FORWARDER_CLAIM_IDLE
value: {{ $cfg.forwarder.claimIdle | quote }}
- name: PLAYER_FORWARDER_POLL_INTERVAL
value: {{ $cfg.forwarder.pollInterval | quote }}
- name: PLAYER_FORWARDER_RATE_LIMIT_EVENTS_PER_MINUTE
value: {{ $cfg.forwarder.rateLimitEventsPerMinute | quote }}
- name: PLAYER_FORWARDER_RATE_LIMIT_BATCHES_PER_MINUTE
value: {{ $cfg.forwarder.rateLimitBatchesPerMinute | quote }}
- name: PLAYER_FORWARDER_RATE_LIMIT_PAYLOAD_BYTES_PER_MINUTE
value: {{ $cfg.forwarder.rateLimitPayloadBytesPerMinute | quote }}
- name: LOG_LEVEL
value: {{ $cfg.log.level | quote }}
- name: LOG_FORMAT
value: {{ $cfg.log.format | quote }}
- name: PLAYER_DEV_HMR
value: "false"
readinessProbe:
httpGet:
path: {{ $cfg.probes.readiness.path }}
port: http
initialDelaySeconds: {{ $cfg.probes.readiness.initialDelaySeconds }}
periodSeconds: {{ $cfg.probes.readiness.periodSeconds }}
timeoutSeconds: {{ $cfg.probes.readiness.timeoutSeconds }}
failureThreshold: {{ $cfg.probes.readiness.failureThreshold }}
livenessProbe:
httpGet:
path: {{ $cfg.probes.liveness.path }}
port: http
initialDelaySeconds: {{ $cfg.probes.liveness.initialDelaySeconds }}
periodSeconds: {{ $cfg.probes.liveness.periodSeconds }}
timeoutSeconds: {{ $cfg.probes.liveness.timeoutSeconds }}
failureThreshold: {{ $cfg.probes.liveness.failureThreshold }}
{{- include "hrbox.resources" (dict "ctx" . "component" "nanabushPlayer") | indent 10 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ $name }}
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "nanabush-player") | nindent 4 }}
spec:
type: ClusterIP
selector:
service: {{ $name }}
ports:
- name: http
port: {{ .Values.app.nanabushPlayer.service.port }}
targetPort: http
protocol: TCP
{{- end }}
+26 -8
View File
@@ -1,35 +1,52 @@
{{- if .Values.ingress.enabled }}
{{- $player := .Values.app.nanabushPlayer -}}
--- ---
apiVersion: networking.k8s.io/v1 apiVersion: networking.k8s.io/v1
kind: Ingress kind: Ingress
metadata: metadata:
name: {{ .Chart.Name }}-ingress name: {{ include "hrbox.component" (dict "ctx" . "name" "ingress") }}
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "web") | nindent 4 }}
annotations: annotations:
kubernetes.io/ingress.class: {{ .Values.ingress.className }} kubernetes.io/ingress.class: {{ .Values.ingress.className | quote }}
nginx.org/websocket-services: {{ .Chart.Name }}-chatbox nginx.org/websocket-services: {{ include "hrbox.component" (dict "ctx" . "name" "chatbox") | quote }}
nginx.ingress.kubernetes.io/proxy-body-size: "10m" nginx.ingress.kubernetes.io/proxy-body-size: {{ .Values.ingress.maxBodySize | quote }}
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600" nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600" nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/configuration-snippet: | nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header X-Forwarded-For "$remote_addr, $server_addr"; proxy_set_header X-Forwarded-For "$remote_addr, $server_addr";
proxy_set_header X-Forwarded-Port $pass_port; proxy_set_header X-Forwarded-Port $pass_port;
proxy_set_header X-Forwarded-Proto $pass_access_scheme; proxy_set_header X-Forwarded-Proto $pass_access_scheme;
{{- with .Values.ingress.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec: spec:
ingressClassName: {{ .Values.ingress.className | quote }}
rules: rules:
- host: {{ .Values.ingress.host | quote }} # something.example.com - host: {{ .Values.ingress.host | quote }}
http: http:
paths: paths:
{{- if and $player.ingress.enabled $player.deployment.enabled }}
- path: {{ include "nanabushPlayer.basePath" . | quote }}
pathType: Prefix
backend:
service:
name: {{ include "nanabushPlayer.serviceName" . }}
port:
number: {{ $player.service.port }}
{{- end }}
- path: /chatbox/ - path: /chatbox/
pathType: Prefix pathType: Prefix
backend: backend:
service: service:
name: {{ .Chart.Name }}-chatbox name: {{ include "hrbox.component" (dict "ctx" . "name" "chatbox") }}
port: port:
number: 80 number: 80
- path: / - path: /
pathType: Prefix pathType: Prefix
backend: backend:
service: service:
name: {{ .Chart.Name }}-web name: {{ include "hrbox.component" (dict "ctx" . "name" "web") }}
port: port:
number: 80 number: 80
{{- if .Values.ingress.tls.enabled }} {{- if .Values.ingress.tls.enabled }}
@@ -37,4 +54,5 @@ spec:
- hosts: - hosts:
- {{ .Values.ingress.host | quote }} - {{ .Values.ingress.host | quote }}
secretName: {{ .Values.ingress.tls.secretName | quote }} secretName: {{ .Values.ingress.tls.secretName | quote }}
{{- end }} {{- end }}
{{- end }}
+17 -11
View File
@@ -2,20 +2,28 @@
apiVersion: batch/v1 apiVersion: batch/v1
kind: Job kind: Job
metadata: metadata:
name: {{ .Chart.Name }}-migrate name: {{ include "hrbox.component" (dict "ctx" . "name" "migrate") }}-{{ .Release.Revision }}
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "jobs") | nindent 4 }}
annotations: annotations:
"helm.sh/hook": post-install,post-upgrade "helm.sh/hook": post-install,post-upgrade
"helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation "helm.sh/hook-delete-policy": before-hook-creation
"helm.sh/hook-weight": "10" "helm.sh/hook-weight": "10"
spec: spec:
ttlSecondsAfterFinished: 100 ttlSecondsAfterFinished: 3600
backoffLimit: 6
template: template:
metadata:
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "jobs") | nindent 8 }}
spec: spec:
imagePullSecrets: restartPolicy: OnFailure
- name: regsecret terminationGracePeriodSeconds: 5
{{- include "hrbox.imagePullSecrets" . | nindent 6 }}
initContainers: initContainers:
- name: wait-postgres - name: wait-postgres
image: postgres:14-alpine image: {{ .Values.image.postgresClient | quote }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: command:
- bash - bash
- /wait.sh - /wait.sh
@@ -27,16 +35,14 @@ spec:
{{- include "envs_all" . | indent 12 }} {{- include "envs_all" . | indent 12 }}
containers: containers:
- name: run-migrations - name: run-migrations
image: {{ .Values.app.image }} image: {{ .Values.image.hrbox | quote }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: ["php", "yii", "migrate", "--interactive=0"] command: ["php", "yii", "migrate", "--interactive=0"]
env: env:
{{- include "envs_all" . | indent 12 }} {{- include "envs_all" . | indent 12 }}
{{- include "jobs_resources" . | indent 10 }} {{- include "hrbox.resources" (dict "ctx" . "component" "jobs") | indent 10 }}
volumes: volumes:
- name: configs - name: configs
configMap: configMap:
name: job-scripts name: job-scripts
defaultMode: 420 defaultMode: 420
restartPolicy: OnFailure
terminationGracePeriodSeconds: 5
backoffLimit: 6
-24
View File
@@ -1,24 +0,0 @@
---
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .Chart.Name }}-update-cluster
annotations:
"helm.sh/hook": post-install,post-upgrade
"helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation
"helm.sh/hook-weight": "20"
spec:
template:
spec:
imagePullSecrets:
- name: regsecret
containers:
- name: run-update
image: {{ .Values.app.image }}
command: [ "php", "yii", "util/update-cluster" ]
env:
{{- include "envs_all" . | indent 12 }}
{{- include "jobs_resources" . | indent 10 }}
restartPolicy: OnFailure
terminationGracePeriodSeconds: 5
backoffLimit: 6
@@ -0,0 +1,30 @@
---
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "hrbox.component" (dict "ctx" . "name" "update-cluster") }}-{{ .Release.Revision }}
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "jobs") | nindent 4 }}
annotations:
"helm.sh/hook": post-install,post-upgrade
"helm.sh/hook-delete-policy": before-hook-creation
"helm.sh/hook-weight": "20"
spec:
ttlSecondsAfterFinished: 3600
backoffLimit: 6
template:
metadata:
labels:
{{- include "hrbox.labels" (dict "ctx" . "name" "jobs") | nindent 8 }}
spec:
restartPolicy: OnFailure
terminationGracePeriodSeconds: 5
{{- include "hrbox.imagePullSecrets" . | nindent 6 }}
containers:
- name: run-update
image: {{ .Values.image.hrbox | quote }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: ["php", "yii", "util/update-cluster"]
env:
{{- include "envs_all" . | indent 12 }}
{{- include "hrbox.resources" (dict "ctx" . "component" "jobs") | indent 10 }}
+72
View File
@@ -0,0 +1,72 @@
HRBox {{ .Chart.AppVersion }} — релиз «{{ .Release.Name }}» в namespace «{{ .Release.Namespace }}».
Адрес: http{{ if .Values.ingress.tls.enabled }}s{{ end }}://{{ .Values.ingress.host }}
Что происходит прямо сейчас
---------------------------
1. Поднимаются поды приложения и сервисов.
2. Джоба {{ include "hrbox.component" (dict "ctx" . "name" "migrate") }}-{{ .Release.Revision }} накатывает миграции базы.
3. Джоба {{ include "hrbox.component" (dict "ctx" . "name" "update-cluster") }}-{{ .Release.Revision }} обновляет данные кластера.
Дождитесь завершения миграций:
kubectl -n {{ .Release.Namespace }} wait --for=condition=complete --timeout=30m \
job/{{ include "hrbox.component" (dict "ctx" . "name" "migrate") }}-{{ .Release.Revision }}
Проверка состояния
------------------
kubectl -n {{ .Release.Namespace }} get pods
kubectl -n {{ .Release.Namespace }} logs -l app=web -c fpm --tail=100
{{ if .Release.IsInstall -}}
Первый запуск: создайте администратора
--------------------------------------
kubectl -n {{ .Release.Namespace }} exec -it \
deploy/{{ include "hrbox.component" (dict "ctx" . "name" "worker") }} -- \
php yii user/create-admin admin@example.com --tenant-id=1
{{ end -}}
{{- if .Values.app.nanabushPlayer.deployment.enabled }}
Nanabush Player
---------------
Смонтирован на {{ include "nanabushPlayer.publicOrigin" . }}{{ include "nanabushPlayer.basePath" . }}
Версия: {{ include "nanabushPlayer.version" . }}
Проверить, что плеер отвечает сам, а не HRBox через общий маршрут
(настоящий плеер возвращает JSON, HTML означает, что запрос ушёл в HRBox):
kubectl -n {{ .Release.Namespace }} exec deploy/{{ include "hrbox.component" (dict "ctx" . "name" "worker") }} -- \
curl -s http://{{ include "nanabushPlayer.serviceName" . }}:{{ .Values.app.nanabushPlayer.service.port }}{{ .Values.app.nanabushPlayer.deployment.probes.readiness.path }}
Служебные пути (/healthz, /readyz, метрики) живут в корне и не зависят от
basePath; под basePath публикуются /start, статика и API плеера.
{{- if not .Values.app.nanabushPlayer.enabled }}
ВНИМАНИЕ: плеер развёрнут, но выключен для пользователей
(app.nanabushPlayer.enabled: false). Учебные материалы открываются старым
проигрывателем.
{{- end }}
{{- else }}
Nanabush Player выключен (app.nanabushPlayer.deployment.enabled: false).
Учебные материалы открываются старым проигрывателем.
{{- end }}
{{ if not .Values.dragonfly.enabled -}}
Dragonfly выключен — проверьте, что app.redis указывает на внешний Redis:
{{ include "hrbox.redisHost" . }}:{{ .Values.app.redis.port }}
{{ end -}}
{{- if not .Values.nats.enabled }}
NATS выключен — проверьте, что app.nats.url указывает на внешний брокер:
{{ include "hrbox.natsUrl" . }}
{{ end -}}
{{- if eq .Values.app.debug "1" }}
ВНИМАНИЕ: включён режим отладки (app.debug: "1"). Для production верните "0".
{{- end }}
{{- if not .Values.ingress.tls.enabled }}
ВНИМАНИЕ: TLS выключен (ingress.tls.enabled: false). Приложение отдаёт
cookie сессий по открытому HTTP.
{{- end }}
+217 -159
View File
@@ -1,61 +1,50 @@
{{- define "envs_all" }} {{- define "envs_all" }}
# Основные настройки приложения # Приложение
- name: INSTANCE_NAME - name: INSTANCE_NAME
value: {{ .Values.app.instanceName | quote }} value: {{ .Values.app.instanceName | quote }}
- name: DEFAULT_TENANT_HOSTNAME - name: DEFAULT_TENANT_HOSTNAME
value: {{ .Values.app.defaultTenantHostname | quote }} value: {{ .Values.app.defaultTenantHostname | quote }}
- name: APP_ENV - name: APP_ENV
value: "prod" value: "prod"
- name: APP_PORT
value: "80"
- name: YII_DEBUG - name: YII_DEBUG
value: {{ .Values.app.debug | quote }} value: {{ .Values.app.debug | quote }}
- name: YII_TRACE_LEVEL - name: YII_TRACE_LEVEL
value: "0" value: "0"
- name: APP_COOKIE_VALIDATION_KEY
value: {{ .Values.secrets.cookieValidationKey | quote }}
- name: APP_ENCRYPTION_KEY
value: {{ .Values.secrets.encryptionKey | quote }}
- name: APP_PORT
value: "80"
- name: AUTH_HOST - name: AUTH_HOST
value: {{ .Values.app.authHost | quote }} 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 - name: LAUNCHPAD_TOPICS
value: {{ .Values.app.launchpad.topics | quote }} value: {{ .Values.app.launchpad.topics | quote }}
- name: SMS_SENDER_NAME - name: SMS_SENDER_NAME
value: "HRBOX" value: {{ .Values.app.sms.senderName | quote }}
- name: ENABLE_FRONTEND - name: IFRAME_FULL_ACCESS
value: {{ .Values.app.front2 | quote }} value: {{ .Values.app.security.iframeFullAccess | quote }}
{{- if .Values.app.custom_policy }} - 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 - name: ALLOW_CUSTOM_POLICY_URLS
value: {{ .Values.app.custom_policy.enabled | default false | quote }} value: {{ .Values.app.customPolicy.enabled | quote }}
{{- if .Values.app.custom_policy.enabled }} {{- if .Values.app.customPolicy.enabled }}
- name: CUSTOM_PRIVACY_POLICY_URL - name: CUSTOM_PRIVACY_POLICY_URL
value: {{ .Values.app.custom_policy.privacy_url | default "https://hrbox.io/policy" | quote }} value: {{ .Values.app.customPolicy.privacyUrl | default "https://hrbox.io/policy" | quote }}
- name: CUSTOM_TERMS_URL - name: CUSTOM_TERMS_URL
value: {{ .Values.app.custom_policy.terms_url | default "https://hrbox.io/terms" | quote }} value: {{ .Values.app.customPolicy.termsUrl | default "https://hrbox.io/terms" | quote }}
{{- end }}
{{- else }} {{- else }}
- name: ALLOW_CUSTOM_POLICY_URLS - name: CUSTOM_PRIVACY_POLICY_URL
value: "false" value: ""
{{- end }} - name: CUSTOM_TERMS_URL
value: ""
# NATS
- name: BROKER
value: "nats"
- name: NATS_URL
value: {{ .Values.app.nats.url | quote }}
# Sentry (опционально)
{{- if .Values.app.sentry.dsn }}
- name: SENTRY_DSN
value: {{ .Values.app.sentry.dsn | quote }}
- name: SENTRY_DSN_LAUNCHPAD
value: {{ .Values.app.sentry.dsn | quote }}
- name: SENTRY_DSN_CONDUCTOR
value: {{ .Values.app.sentry.dsn | quote }}
- name: SENTRY_ENVIRONMENT
value: {{ .Values.app.sentry.environment | quote }}
- name: SENTRY_RELEASE
value: {{ .Values.app.image | quote }}
{{- end }} {{- end }}
# PostgreSQL # PostgreSQL
@@ -67,74 +56,35 @@
value: {{ .Values.app.postgres.database | quote }} value: {{ .Values.app.postgres.database | quote }}
- name: POSTGRES_USER - name: POSTGRES_USER
value: {{ .Values.app.postgres.user | quote }} value: {{ .Values.app.postgres.user | quote }}
- name: POSTGRES_PASSWORD
value: {{ .Values.app.postgres.password | quote }}
- name: POSTGRES_CITUS - name: POSTGRES_CITUS
value: {{ .Values.app.postgres.citus | quote }} value: {{ .Values.app.postgres.citus | quote }}
{{- include "hrbox.secretEnv" (dict "ctx" . "env" "POSTGRES_PASSWORD" "key" "postgres-password") | nindent 0 }}
# Redis # Redis / Dragonfly
- name: REDIS_HOST - name: REDIS_HOST
value: {{ .Values.app.redis.host | quote }} value: {{ include "hrbox.redisHost" . | quote }}
- name: REDIS_PORT - name: REDIS_PORT
value: {{ .Values.app.redis.port | quote }} value: {{ .Values.app.redis.port | quote }}
- name: REDIS_CONNECTION - name: REDIS_CONNECTION
value: {{ printf "tcp://%s:%s" .Values.app.redis.host .Values.app.redis.port | quote }} value: {{ printf "tcp://%s:%s" (include "hrbox.redisHost" .) (.Values.app.redis.port | toString) | quote }}
# Yandex API (опционально) # NATS
{{- if .Values.app.yandex.clientId }} - name: BROKER
- name: YANDEX_CLIENT_ID value: "nats"
value: {{ .Values.app.yandex.clientId | quote }} - name: NATS_URL
- name: YANDEX_CLIENT_PASSWORD value: {{ include "hrbox.natsUrl" . | quote }}
value: {{ .Values.app.yandex.clientPassword | quote }} - name: NATS_STREAM_REPLICAS
{{- if and .Values.nats.enabled .Values.nats.cluster.enabled }}
value: {{ .Values.nats.cluster.replicas | quote }}
{{- else }}
value: "1"
{{- end }} {{- end }}
# Slack (опционально)
{{- if .Values.app.slack.clientId }}
- name: SLACK_APP_CLIENT_ID
value: {{ .Values.app.slack.clientId | quote }}
- name: SLACK_APP_CLIENT_SECRET
value: {{ .Values.app.slack.clientSecret | quote }}
- name: SLACK_APP_VERIFICATION_TOKEN
value: {{ .Values.app.slack.verificationToken | quote }}
{{- end }}
# Email
- name: SENDER_ENV
value: "PROD"
- name: SENDER_DEV_EMAIL
value: ""
- name: SENDGRID_API_KEY
value: ""
# SMTP
- name: SMTP_USERNAME
value: {{ .Values.app.smtp.user | quote }}
- name: SMTP_PASSWORD
value: {{ .Values.app.smtp.password | quote }}
- name: SMTP_HOST
value: {{ .Values.app.smtp.host | quote }}
- name: SMTP_PORT
value: {{ .Values.app.smtp.port | 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 }}
# S3 # S3
- name: S3_ENDPOINT - name: S3_ENDPOINT
value: {{ .Values.app.s3.endpoint | quote }} value: {{ .Values.app.s3.endpoint | quote }}
- name: S3_BUCKET - name: S3_BUCKET
value: {{ .Values.app.s3.bucket | quote }} value: {{ .Values.app.s3.bucket | quote }}
- name: S3_KEY
value: {{ .Values.app.s3.key | quote }}
- name: S3_SECRET
value: {{ .Values.app.s3.secret | quote }}
- name: S3_PREFIX - name: S3_PREFIX
value: {{ .Values.app.s3.prefix | quote }} value: {{ .Values.app.s3.prefix | quote }}
- name: S3_REGION - name: S3_REGION
@@ -145,38 +95,118 @@
value: {{ .Values.app.s3.pathStyle | quote }} value: {{ .Values.app.s3.pathStyle | quote }}
- name: S3_MULTIPART - name: S3_MULTIPART
value: {{ .Values.app.s3.multipart | quote }} 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 }}
# Hub # Почта
- name: HUB_URL - name: SENDER_ENV
value: {{ .Values.app.hub.url | quote }} value: "PROD"
- name: HUB_TOKEN - name: SENDER_DEV_EMAIL
value: {{ .Values.app.hub.token | quote }} 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 }}
# Geonames # Внутренние сервисы
- name: GEONAMES_URL - name: GEONAMES_URL
value: {{ .Values.app.geonames.url | quote }} 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 - name: CONDUCTOR_TOPIC_CONDUCTOR
value: "conductor" value: "conductor"
- name: CONDUCTOR_TOPIC_LAUNCHER - name: CONDUCTOR_TOPIC_LAUNCHER
value: "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 - name: GOOGLE_CLIENT_ID
value: "692956564858-ccapt35khk7tmadl17b3879ht2cropp6.apps.googleusercontent.com" value: {{ .Values.app.integrations.google.clientId | quote }}
- name: GOOGLE_CLIENT_SECRET {{- include "hrbox.secretEnv" (dict "ctx" . "env" "GOOGLE_CLIENT_SECRET" "key" "google-client-secret") | nindent 0 }}
value: "nW4pl4YsVWAR371gMRStW9qg" - name: YANDEX_CLIENT_ID
- name: SINGLE_TENANT value: {{ .Values.app.yandex.clientId | quote }}
value: "0" {{- include "hrbox.secretEnv" (dict "ctx" . "env" "YANDEX_CLIENT_PASSWORD" "key" "yandex-client-password") | nindent 0 }}
- name: FORCE_HTTPS - name: SLACK_APP_CLIENT_ID
value: "true" 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 - name: GLAGOL_PARTNER_ID
value: "ab230ee1-6946-43b9-8kfa-447beb8348b0" value: {{ .Values.app.integrations.glagol.partnerId | quote }}
- name: GLAGOL_API_URL - name: GLAGOL_API_URL
value: "https://api.glagol.online/glagol-api" value: {{ .Values.app.integrations.glagol.apiUrl | quote }}
- name: LDAPTLS_REQCERT
value: "never" # Sentry
- name: IFRAME_FULL_ACCESS - name: SENTRY_DSN
value: {{ .Values.app.security.iframeFullAccess | default "false" | quote }} 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 - name: POD_NAME
@@ -195,56 +225,67 @@
valueFrom: valueFrom:
fieldRef: fieldRef:
fieldPath: spec.nodeName fieldPath: spec.nodeName
# AI (опционально)
{{- if .Values.app.ai.yandex.folderId }}
- name: YANDEX_CLOUD_AI_FOLDER_ID
value: {{ .Values.app.ai.yandex.folderId | quote }}
- name: YANDEX_CLOUD_AI_API_KEY
value: {{ .Values.app.ai.yandex.apiKey | quote }}
{{- end }} {{- end }}
# Integration Services {{- define "envs_nanabush_player" -}}
- name: GOWORKER_URL {{- $player := .Values.app.nanabushPlayer }}
value: {{ .Values.app.goworker.url | quote }} - name: NANABUSH_PLAYER_ENABLED
{{- if .Values.app.goworker.sentryDsn }} value: {{ $player.enabled | quote }}
- name: GOWORKER_SENTRY_DSN {{- if $player.deployment.enabled }}
value: {{ .Values.app.goworker.sentryDsn | quote }} - 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 }} {{- end }}
- name: GOWORKER_PUSH_MIN_INTERVAL - name: NANABUSH_PLAYER_LEGACY_FALLBACK
value: {{ .Values.app.goworker.pushMinInterval | quote }} value: {{ $player.rollout.legacyFallback | quote }}
- name: NANABUSH_PLAYER_ALLOWED_CONTENT_TYPES
- name: KEDOCA_URL value: {{ join "," $player.rollout.allowedContentTypes | quote }}
value: {{ .Values.app.kedoca.url | quote }} - name: NANABUSH_PLAYER_ALLOWED_TENANTS
- name: TSP_URL value: {{ join "," $player.rollout.allowedTenants | quote }}
value: "http://qs.cryptopro.ru/tsp/tsp.srf" - name: NANABUSH_PLAYER_ROLLOUT_PERCENT
value: {{ $player.rollout.percent | quote }}
# Internal Services
- name: SERVICES_INTERNAL_SECRET
value: {{ .Values.secrets.servicesInternalSecret | default "QrrH84K2dG5JfoYxi4ZNPyg5p2LEj6rN69z5tIQYkfY6SJZ8GDXOcRjTNnefbOx5" | quote }}
# Document Converter
- name: PYTHONUNBUFFERED
value: "1"
- name: DOCCONV_MAX_PARALLEL_TASKS
value: "1"
# AI Features
- name: AI_DOCS_INDEX_ENABLED
value: "true"
- name: AI_SEMANTIC_INDEX_ENABLED
value: "true"
- name: AI_SEMANTIC_INDEX_USE_BATCH
value: "true"
# Chatbox
{{- if .Values.app.chatbox.sentryDsn }}
- name: CHATBOX_SENTRY_DSN
value: {{ .Values.app.chatbox.sentryDsn | quote }}
{{- end }} {{- end }}
- name: CHATBOX_WRAPPING_KEY {{- end -}}
value: {{ .Values.app.chatbox.wrappingKey | quote }}
{{- 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 }}
- name: NANABUSH_PLAYER_TICKET_KEYS
valueFrom:
secretKeyRef:
name: {{ include "nanabushPlayer.secretName" $ | quote }}
key: {{ . | quote }}
{{- end }} {{- end }}
{{- end }}
{{- end -}}
{{- define "envs_kedoca" }} {{- define "envs_kedoca" }}
- name: ROOT_CA_PASS - name: ROOT_CA_PASS
@@ -255,4 +296,21 @@
value: {{ .Values.app.kedoca.algorithm | quote }} value: {{ .Values.app.kedoca.algorithm | quote }}
- name: KEDO_PKEYOPT - name: KEDO_PKEYOPT
value: {{ .Values.app.kedoca.pkeyopt | quote }} value: {{ .Values.app.kedoca.pkeyopt | quote }}
{{- end }} {{- end }}
{{- 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 }}
+114 -94
View File
@@ -1,110 +1,130 @@
{{/* {{- define "hrbox.name" -}}
Expand the name of the chart. {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
*/}}
{{- define "nats.name" -}}
{{- default .Chart.Name .Values.nats.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}} {{- end -}}
{{- define "hrbox.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- define "nats.fullname" -}} {{- define "hrbox.component" -}}
{{- if .Values.nats.fullnameOverride -}} {{- printf "%s-%s" (include "hrbox.name" .ctx) .name | trunc 63 | trimSuffix "-" -}}
{{- .Values.nats.fullnameOverride | trunc 63 | trimSuffix "-" -}} {{- end -}}
{{- define "hrbox.selectorLabels" -}}
service: {{ include "hrbox.component" (dict "ctx" .ctx "name" .name) }}
{{- end -}}
{{- define "hrbox.labels" -}}
app: {{ .name }}
app.kubernetes.io/name: {{ include "hrbox.name" .ctx }}
app.kubernetes.io/component: {{ .name }}
app.kubernetes.io/instance: {{ .ctx.Release.Name }}
app.kubernetes.io/managed-by: {{ .ctx.Release.Service }}
app.kubernetes.io/version: {{ .ctx.Chart.AppVersion | quote }}
helm.sh/chart: {{ include "hrbox.chart" .ctx }}
{{- end -}}
{{- define "hrbox.imagePullSecrets" -}}
{{- if .Values.imagePullSecrets }}
imagePullSecrets:
{{- range .Values.imagePullSecrets }}
- name: {{ .name | quote }}
{{- end }}
{{- end }}
{{- end -}}
{{- define "hrbox.imageTag" -}}
{{- $lastSegment := splitList "/" . | last -}}
{{- if contains ":" $lastSegment -}}
{{- splitList ":" $lastSegment | last -}}
{{- end -}}
{{- end -}}
{{- define "hrbox.geonamesUrl" -}}
{{- .Values.app.geonames.url | default (printf "http://%s:8181" (include "hrbox.component" (dict "ctx" . "name" "geonames"))) -}}
{{- end -}}
{{- define "hrbox.goworkerUrl" -}}
{{- .Values.app.goworker.url | default (printf "http://%s:8686" (include "hrbox.component" (dict "ctx" . "name" "goworker"))) -}}
{{- end -}}
{{- define "hrbox.kedocaUrl" -}}
{{- .Values.app.kedoca.url | default (printf "http://%s:8558" (include "hrbox.component" (dict "ctx" . "name" "kedoca"))) -}}
{{- end -}}
{{- define "hrbox.redisHost" -}}
{{- .Values.app.redis.host | default (include "hrbox.component" (dict "ctx" . "name" "dragonfly")) -}}
{{- end -}}
{{- define "hrbox.natsUrl" -}}
{{- .Values.app.nats.url | default (printf "nats://%s:4222" (include "hrbox.component" (dict "ctx" . "name" "nats"))) -}}
{{- end -}}
{{- define "hrbox.secretName" -}}
{{- if .Values.secrets.existingSecret -}}
{{- .Values.secrets.existingSecret -}}
{{- else -}} {{- else -}}
{{- $name := default .Chart.Name .Values.nats.nameOverride -}} {{- include "hrbox.component" (dict "ctx" . "name" "secrets") -}}
{{- if contains $name .Release.Name -}} {{- end -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}} {{- end -}}
{{- define "hrbox.secretEnv" -}}
- name: {{ .env }}
valueFrom:
secretKeyRef:
name: {{ include "hrbox.secretName" .ctx | quote }}
key: {{ .key | quote }}
{{- end -}}
{{- define "nanabushPlayer.host" -}}
{{- required "Для Nanabush Player нужен непустой ingress.host" .Values.ingress.host -}}
{{- end -}}
{{- define "nanabushPlayer.publicOrigin" -}}
{{- printf "https://%s" (include "nanabushPlayer.host" .) -}}
{{- end -}}
{{- define "nanabushPlayer.basePath" -}}
{{- $path := .Values.app.nanabushPlayer.basePath | default "/nanabush-player" -}}
{{- $path | trimSuffix "/" -}}
{{- end -}}
{{- define "nanabushPlayer.issuer" -}}
{{- if .Values.app.nanabushPlayer.issuer -}}
{{- .Values.app.nanabushPlayer.issuer -}}
{{- else -}} {{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} {{- printf "https://%s/lms/player" (include "nanabushPlayer.host" .) -}}
{{- end -}} {{- end -}}
{{- end -}} {{- end -}}
{{- define "nanabushPlayer.serviceName" -}}
{{- .Values.app.nanabushPlayer.service.name | default (include "hrbox.component" (dict "ctx" . "name" "nanabush-player")) -}}
{{- end -}} {{- end -}}
{{- define "nats.chart" -}} {{- define "nanabushPlayer.backchannelHost" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- .Values.app.nanabushPlayer.deployment.backchannel.host | default (include "hrbox.component" (dict "ctx" . "name" "web")) -}}
{{- end }}
{{/*
Common labels
*/}}
{{- define "nats.labels" -}}
app.kubernetes.io/name: nats
app.kubernetes.io/instance: {{ .Release.Name }}
helm.sh/chart: {{ include "nats.chart" . }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "nats.selectorLabels" -}}
app.kubernetes.io/name: nats
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Return the proper NATS image name
*/}}
{{- define "nats.clusterAdvertise" -}}
{{- printf "$(POD_NAME).%s.$(POD_NAMESPACE).svc.%s" (include "nats.fullname" . ) $.Values.nats.k8sClusterDomain }}
{{- end }}
{{/*
Return the NATS cluster routes.
*/}}
{{- define "nats.clusterRoutes" -}}
{{- $name := (include "nats.fullname" . ) -}}
{{- range $i, $e := until (.Values.nats.cluster.replicas | int) -}}
{{- printf "nats://%s-%d.%s.%s.svc.%s:6222," $name $i $name $.Release.Namespace $.Values.nats.k8sClusterDomain -}}
{{- end -}} {{- end -}}
{{- end }}
{{- define "nats.extraRoutes" -}} {{- define "nanabushPlayer.internalOrigin" -}}
{{- range $i, $url := .Values.nats.cluster.extraRoutes -}} {{- printf "http://%s" (include "nanabushPlayer.backchannelHost" .) -}}
{{- printf "%s," $url -}}
{{- end -}} {{- end -}}
{{- end }}
{{- define "nats.tlsConfig" -}} {{- define "nanabushPlayer.version" -}}
tls { {{- $tag := include "hrbox.imageTag" .Values.image.nanabushPlayer -}}
{{- if .cert }} {{- if not $tag -}}
cert_file: {{ .secretPath }}/{{ .secret.name }}/{{ .cert }} {{- fail "image.nanabushPlayer должен содержать явный тег версии, например nanabush-player:1.0.11" -}}
{{- end }} {{- end -}}
{{- if .key }} {{- $tag -}}
key_file: {{ .secretPath }}/{{ .secret.name }}/{{ .key }} {{- end -}}
{{- end }}
{{- if .ca }}
ca_file: {{ .secretPath }}/{{ .secret.name }}/{{ .ca }}
{{- end }}
{{- if .insecure }}
insecure: {{ .insecure }}
{{- end }}
{{- if .verify }}
verify: {{ .verify }}
{{- end }}
{{- if .verifyAndMap }}
verify_and_map: {{ .verifyAndMap }}
{{- end }}
{{- if .curvePreferences }}
curve_preferences: {{ .curvePreferences }}
{{- end }}
{{- if .timeout }}
timeout: {{ .timeout }}
{{- end }}
}
{{- end }}
{{- define "nanabushPlayer.secretName" -}}
{{- required "app.nanabushPlayer.deployment.existingSecret.name обязателен, когда Player включён" .Values.app.nanabushPlayer.deployment.existingSecret.name -}}
{{- end -}}
{{/* {{- define "nanabushPlayer.redisUrl" -}}
Renders a value that contains template. {{- printf "redis://%s:%s/%d" (include "hrbox.redisHost" .) (.Values.app.redis.port | toString) (.Values.app.nanabushPlayer.deployment.redis.database | int) -}}
Usage: {{- end -}}
{{ include "tplvalues.render" ( dict "value" .Values.nats.path.to.the.Value "context" $) }}
*/}} {{- define "nanabushPlayer.redisKeyPrefix" -}}
{{- define "tplvalues.render" -}} {{- printf "hrbox:%s:%s" .Release.Namespace .Values.app.nanabushPlayer.deployment.redis.keyPrefixSuffix -}}
{{- if typeIs "string" .value }}
{{- tpl .value .context }}
{{- else }}
{{- tpl (.value | toYaml) .context }}
{{- end }}
{{- end -}} {{- end -}}
+24 -113
View File
@@ -1,119 +1,30 @@
{{- define "app_resources" }} {{- define "hrbox.resources" -}}
{{- $r := index .ctx.Values.resources .component -}}
{{- if $r }}
resources: resources:
{{- with $r.requests }}
requests: requests:
memory: {{ .Values.resources.app.requests.memory | quote }} {{- with .cpu }}
cpu: {{ .Values.resources.app.requests.cpu | quote }} cpu: {{ . | quote }}
ephemeral-storage: {{ .Values.resources.app.requests.ephemeralStorage | quote }} {{- end }}
limits: {{- with .memory }}
memory: {{ .Values.resources.app.limits.memory | quote }} memory: {{ . | quote }}
cpu: {{ .Values.resources.app.limits.cpu | quote }} {{- end }}
ephemeral-storage: {{ .Values.resources.app.limits.ephemeralStorage | quote }} {{- with .ephemeralStorage }}
ephemeral-storage: {{ . | quote }}
{{- end }}
{{- end }} {{- end }}
{{- with $r.limits }}
{{- define "nginx_resources" }}
resources:
requests:
memory: {{ .Values.resources.nginx.requests.memory | quote }}
cpu: {{ .Values.resources.nginx.requests.cpu | quote }}
ephemeral-storage: {{ .Values.resources.nginx.requests.ephemeralStorage | quote }}
limits: limits:
memory: {{ .Values.resources.nginx.limits.memory | quote }} {{- with .cpu }}
cpu: {{ .Values.resources.nginx.limits.cpu | quote }} cpu: {{ . | quote }}
ephemeral-storage: {{ .Values.resources.nginx.limits.ephemeralStorage | quote }} {{- end }}
{{- with .memory }}
memory: {{ . | quote }}
{{- end }}
{{- with .ephemeralStorage }}
ephemeral-storage: {{ . | quote }}
{{- end }}
{{- end }} {{- end }}
{{- define "worker_resources" }}
resources:
requests:
memory: {{ .Values.resources.worker.requests.memory | quote }}
cpu: {{ .Values.resources.worker.requests.cpu | quote }}
ephemeral-storage: {{ .Values.resources.worker.requests.ephemeralStorage | quote }}
limits:
memory: {{ .Values.resources.worker.limits.memory | quote }}
cpu: {{ .Values.resources.worker.limits.cpu | quote }}
ephemeral-storage: {{ .Values.resources.worker.limits.ephemeralStorage | quote }}
{{- end }} {{- end }}
{{- end -}}
{{- define "websocket_resources" }}
resources:
requests:
memory: {{ .Values.resources.websocket.requests.memory | quote }}
cpu: {{ .Values.resources.websocket.requests.cpu | quote }}
ephemeral-storage: {{ .Values.resources.websocket.requests.ephemeralStorage | quote }}
limits:
memory: {{ .Values.resources.websocket.limits.memory | quote }}
cpu: {{ .Values.resources.websocket.limits.cpu | quote }}
ephemeral-storage: {{ .Values.resources.websocket.limits.ephemeralStorage | quote }}
{{- end }}
{{- define "geonames_resources" }}
resources:
requests:
memory: {{ .Values.resources.geonames.requests.memory | quote }}
cpu: {{ .Values.resources.geonames.requests.cpu | quote }}
ephemeral-storage: {{ .Values.resources.geonames.requests.ephemeralStorage | quote }}
limits:
memory: {{ .Values.resources.geonames.limits.memory | quote }}
cpu: {{ .Values.resources.geonames.limits.cpu | quote }}
ephemeral-storage: {{ .Values.resources.geonames.limits.ephemeralStorage | quote }}
{{- end }}
{{- define "conductor_resources" }}
resources:
requests:
memory: {{ .Values.resources.conductor.requests.memory | quote }}
cpu: {{ .Values.resources.conductor.requests.cpu | quote }}
ephemeral-storage: {{ .Values.resources.conductor.requests.ephemeralStorage | quote }}
limits:
memory: {{ .Values.resources.conductor.limits.memory | quote }}
cpu: {{ .Values.resources.conductor.limits.cpu | quote }}
ephemeral-storage: {{ .Values.resources.conductor.limits.ephemeralStorage | quote }}
{{- end }}
{{- define "jobs_resources" }}
resources:
requests:
memory: {{ .Values.resources.jobs.requests.memory | quote }}
cpu: {{ .Values.resources.jobs.requests.cpu | quote }}
ephemeral-storage: {{ .Values.resources.jobs.requests.ephemeralStorage | quote }}
limits:
memory: {{ .Values.resources.jobs.limits.memory | quote }}
cpu: {{ .Values.resources.jobs.limits.cpu | quote }}
ephemeral-storage: {{ .Values.resources.jobs.limits.ephemeralStorage | quote }}
{{- end }}
{{- define "goworker_resources" }}
resources:
requests:
memory: {{ .Values.resources.goworker.requests.memory | quote }}
cpu: {{ .Values.resources.goworker.requests.cpu | quote }}
ephemeral-storage: {{ .Values.resources.goworker.requests.ephemeralStorage | quote }}
limits:
memory: {{ .Values.resources.goworker.limits.memory | quote }}
cpu: {{ .Values.resources.goworker.limits.cpu | quote }}
ephemeral-storage: {{ .Values.resources.goworker.limits.ephemeralStorage | quote }}
{{- end }}
{{- define "kedoca_resources" }}
resources:
requests:
memory: {{ .Values.resources.kedoca.requests.memory | quote }}
cpu: {{ .Values.resources.kedoca.requests.cpu | quote }}
ephemeral-storage: {{ .Values.resources.kedoca.requests.ephemeralStorage | quote }}
limits:
memory: {{ .Values.resources.kedoca.limits.memory | quote }}
cpu: {{ .Values.resources.kedoca.limits.cpu | quote }}
ephemeral-storage: {{ .Values.resources.kedoca.limits.ephemeralStorage | quote }}
{{- end }}
{{- define "chatbox_resources" }}
resources:
requests:
memory: {{ .Values.resources.chatbox.requests.memory | quote }}
cpu: {{ .Values.resources.chatbox.requests.cpu | quote }}
ephemeral-storage: {{ .Values.resources.chatbox.requests.ephemeralStorage | quote }}
limits:
memory: {{ .Values.resources.chatbox.limits.memory | quote }}
cpu: {{ .Values.resources.chatbox.limits.cpu | quote }}
ephemeral-storage: {{ .Values.resources.chatbox.limits.ephemeralStorage | quote }}
{{- end }}
+545 -308
View File
File diff suppressed because it is too large Load Diff
+262
View File
@@ -5,6 +5,267 @@ All notable changes to the HRBox Helm chart will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [3.0.0] - 2026-09-02
Чарт подтянут к тому, как HRBox работает в облаке: добавлен плеер учебных
материалов, пароли и ключи уехали в Secret, повторяющиеся куски шаблонов
заменены одним хелпером, а неполная конфигурация теперь останавливает
установку с понятным сообщением.
### Added
#### Nanabush Player
Плеер учебных материалов: SCORM 1.2 и 2004, cmi5, xAPI, нативные курсы,
тесты и эссе.
- `09-nanabush-player.yaml` — Deployment и Service, образ `nanabush-player:1.0.11`
- `00-nanabush-player-secret.yaml` — ключи launch-тикета и сессии
- маршрут `/nanabush-player` на общем Ingress
- настройки `app.nanabushPlayer`, ресурсы `resources.nanabushPlayer`
- переменные `NANABUSH_PLAYER_*` в HRBox и `PLAYER_*` в самом плеере
В on-premise выделенного поддомена нет, поэтому плеер стоит на основном
домене по пути. Отсюда два ограничения, они описаны в README: cookie HRBox
доступны содержимому курсов, и нужны синхронизированные часы — тикет живёт
5 минут.
Для быстрого отката оставлены три переключателя: `enabled`,
`ingress.enabled`, `deployment.enabled`. Маршрут без пода или включённый
плеер без маршрута чарт не пропустит.
#### Проверка конфигурации
- `00-validate.yaml` — объектов не создаёт, но останавливает установку, если
не заполнены обязательные значения, остались ключи из версии 2.x или
нарушены требования плеера. Сообщения на русском, с указанием, что править.
#### Secret приложения
- `00-app-secret.yaml` — один Secret со всеми паролями и ключами. Поды
читают его через `secretKeyRef`, поэтому `kubectl get deploy -o yaml`
больше не показывает пароль базы и ключ шифрования.
- `secrets.existingSecret` — можно подставить Secret, созданный вне чарта.
#### Новые компоненты
- `09-file-processor-video.yaml` — отдельные поды для конвертации видео,
со своими ресурсами, `nodeSelector` и `tolerations`
(`app.videoConverter.enabled`, по умолчанию выключено)
- `02-web-pdb.yaml` — PodDisruptionBudget для `web`, создаётся от двух реплик
- `01-otel-configmap.yaml` и коллектор OpenTelemetry рядом с `web`
(`app.tracing.enabled`)
- `01-nginx-assetlinks.yaml` — привязка мобильных приложений к домену
(`app.mobileApps`)
- `templates/NOTES.txt` — что делать после установки, с готовыми командами
#### Новые переменные окружения
- `NATS_STREAM_REPLICAS` — число реплик стримов JetStream по размеру кластера
- `TELEGRAM_API_URL`, `AUTH_GOOGLE_ENABLED`
- `LIVEKIT_URL`, `LIVEKIT_API_KEY`, `LIVEKIT_API_SECRET` — видеозвонки
- `APP_INTERNAL_URL` — внутренний адрес HRBox для конвертера
- `VIDEO_CONVERTER_ENABLED` — отдельно для каждого пула
- `SENDER_ENV`, `IMAGE_RESIZE_MAX_PARALLEL`, `OTEL_*`
### Changed
#### values.yaml
- все образы собраны в блок `image`: сменить версию сервиса — это правка
одной строки
- `imagePullSecrets` вынесен в настройки, `regsecret` больше не зашит
в шаблоны
- ключи приведены к camelCase: `file_processor` → `fileProcessor`,
`custom_policy` → `customPolicy`
- в `resources` добавлены `fileProcessor`, `fileProcessorVideo`,
`nanabushPlayer`, `dragonfly`, `nats`
- адреса внутренних сервисов (`app.geonames.url`, `app.goworker.url`,
`app.kedoca.url`, `app.redis.host`, `app.nats.url`) по умолчанию пустые
и собираются из имён, которые создаёт сам чарт. Раньше это были строки
`hrbox-*`, зашитые в шаблоны: при `nameOverride` они молча переставали
работать. Заданное значение по-прежнему используется как есть, поэтому
старые values работают без правок. Выключить `dragonfly` или `nats`,
не указав внешний адрес, теперь нельзя.
#### Шаблоны
- `_resources.tpl`: девять почти одинаковых define заменены одним
`hrbox.resources`, незаполненные поля не рендерятся
- `_helpers.tpl`: удалено около сотни строк неиспользуемого кода (хелперы
`nats.*`, которые ссылались на несуществующий `nats.k8sClusterDomain`);
добавлены `hrbox.component`, `hrbox.labels`, `hrbox.selectorLabels`,
`hrbox.secretEnv` и хелперы плеера
- у всех объектов появились стандартные лейблы `app.kubernetes.io/*`;
лейбл `app` остался, привычный `kubectl get pods -l app=worker` работает
- селекторы Deployment не менялись, обновление 2.x → 3.0 не пересоздаёт
объекты
- аннотации `checksum/*` перезапускают поды при изменении конфигурации
nginx или Secret приложения
- образы, порты и таймауты вынесены из шаблонов в values.yaml
#### nginx
Набор `location` синхронизирован с облачным:
- `/healthz` и `/health-check` — на них настроены пробы пода `web`
(раньше проверялся только TCP-порт)
- `/api/v1/integration/commit` — потоковая загрузка оргструктуры из 1С
без буферизации, лимит 500 МБ
- `/ai/` — увеличенные таймауты
- `/.well-known/assetlinks.json` и `/.well-known/apple-app-site-association`
- `/frontend/sw.js` — правильные заголовки service worker
- кеширование шрифтов
- убраны TLSv1 и TLSv1.1
#### Версии образов
| Компонент | Было | Стало |
|---|---|---|
| chatbox | 3.0 | 5.18 |
| goworker | 2.7 | 3.21.2 |
| kedoca | 0.8 | 1.0.6 |
| geonames | 3.1 | 3.3 |
| file-processor | 1.0 | 1.4.6 |
| nanabush-player | — | 1.0.11 |
#### Джобы
- в имени появился номер ревизии релиза: в `kubectl get jobs` видно, какой
выкат запускал миграции, а повторный `upgrade` не спотыкается о старый
объект
- `ttlSecondsAfterFinished` — час у обеих джоб (было 100 секунд у миграций
и ничего у обновления кластера), логи упавшей джобы успевают дожить до
того, как их посмотрят
#### Переименования файлов
- `03-websocket.yaml` → `03-chatbox.yaml` (внутри был chatbox с версии 2.0)
- `09-geonames.yml` → `09-geonames.yaml`
- `99-update-cluser-job.yaml` → `99-update-cluster-job.yaml`
### Fixed
- **Общий секрет у всех установок.** У `SERVICES_INTERNAL_SECRET` было
значение по умолчанию, зашитое в чарт: все, кто его не заполнил, работали
на одном и том же секрете межсервисной аутентификации. Теперь значение
обязательное.
- **`cluster.domain` не использовался.** Маршруты кластера NATS были зашиты
на `cluster.local`, хотя параметр в values был и применялся в соседней
переменной. На кластере с другим доменом ноды не находили друг друга.
- **`CLUSTER_ADVERTISE` без сегмента `svc`.** Имя не резолвилось, ноды NATS
сообщали соседям недостижимый адрес.
- **Разные значения реплик NATS.** `nats.replicas` и `nats.cluster.replicas`
задавались независимо, при расхождении часть нод не входила в кластер.
Теперь чарт требует, чтобы они совпадали.
- **Пробы `web` не проверяли приложение.** Проверялся TCP-порт 9000, поэтому
под с неработающим PHP считался готовым. Теперь readiness ходит
в `/health-check` через FPM.
- Пароли и ключи больше не видны в спеках Deployment.
- У части сервисов `imagePullPolicy` был `Always` на фиксированных тегах —
лишние обращения к реестру при каждом рестарте пода.
### Removed
- у `secrets` больше нет значений по умолчанию: с пустыми ключами установка
останавливается, а не запускается на предсказуемых секретах
- удалены неиспользуемые хелперы `nats.name`, `nats.fullname`, `nats.chart`,
`nats.labels`, `nats.selectorLabels`, `nats.clusterAdvertise`,
`nats.clusterRoutes`, `nats.extraRoutes`, `nats.tlsConfig`,
`tplvalues.render`
- `SENDGRID_API_KEY` — в on-premise не используется
### Migration Guide
#### Переход с 2.x на 3.0
Все переехавшие ключи чарт узнаёт и пишет, куда именно они переехали,
поэтому проще всего запустить `helm template` и править по сообщениям.
**Шаг 1. Перенесите образы в блок `image`**
```yaml
# было
app:
image: "cr.yandex/.../hrbox:latest"
chatbox:
image: "cr.yandex/.../hrbox-chatbox:3.0"
goworker:
image: "cr.yandex/.../hrbox-goworker:2.7"
kedoca:
image: "cr.yandex/.../hrbox-kedoca:0.8"
file_processor:
image: "cr.yandex/.../hrbox-file-processor:1.0"
replicas: 1
# стало
image:
hrbox: "cr.yandex/.../hrbox:latest"
chatbox: "cr.yandex/.../hrbox-chatbox:5.18"
goworker: "cr.yandex/.../hrbox-goworker:3.21.2"
kedoca: "cr.yandex/.../hrbox-kedoca:1.0.6"
fileProcessor: "cr.yandex/.../hrbox-file-processor:1.4.6"
app:
replicas:
fileProcessor: 1
```
**Шаг 2. Переименуйте ключи**
| Было | Стало |
|---|---|
| `app.file_processor` | `app.fileProcessor` |
| `app.custom_policy` | `app.customPolicy` |
| `app.custom_policy.privacy_url` | `app.customPolicy.privacyUrl` |
| `app.custom_policy.terms_url` | `app.customPolicy.termsUrl` |
| `app.goworker.replicas` | `app.replicas.goworker` |
| `app.kedoca.replicas` | `app.replicas.kedoca` |
| `app.goworker.sentryDsn` | `app.sentry.goworkerDsn` |
| `app.chatbox.sentryDsn` | `app.sentry.chatboxDsn` |
| `nats.image` | `image.nats` |
**Шаг 3. Сгенерируйте ключи плеера**
```bash
openssl rand -base64 48 # app.nanabushPlayer.keys.ticketHs256
openssl rand -base64 48 # app.nanabushPlayer.keys.sessionHs256
```
Ключи должны быть разными.
**Шаг 4. Проверьте `secrets.servicesInternalSecret`**
Если поле было пустым, установка работала на общем значении по умолчанию.
Сгенерируйте своё: `openssl rand -base64 48`. После обновления перезапустятся
все сервисы, которые ходят друг к другу, — это нормально.
**Шаг 5. Проверьте рендер и обновитесь**
```bash
helm template hrbox .helm -f values.yaml > /dev/null
helm upgrade hrbox .helm -n hrbox -f values.yaml
```
**Шаг 6. Включите плеер**
Порядок включения и проверки — в README, раздел «Nanabush Player».
#### Breaking Changes
1. **Ключи `values.yaml` переехали.** Установка останавливается с подсказкой,
молча ничего не игнорируется.
2. **`secrets.*` стали обязательными.** Без них установка не пройдёт.
3. **Появился Nanabush Player.** Это дополнительный под, Service, Secret и
маршрут, учтите ресурсы кластера. Плееру нужно синхронизированное время
на нодах.
4. **Пробы `web` стали строже.** Под, где PHP-FPM не отвечает по HTTP, теперь
не проходит readiness. Если приложение отдаёт `/health-check` иначе,
проверьте это до обновления.
5. **В `app.replicas` добавились** `goworker`, `kedoca`, `fileProcessor`,
`fileProcessorVideo`; поля `replicas` внутри самих сервисов удалены.
---
## [2.0.0] - 2026-01-30 ## [2.0.0] - 2026-01-30
Масштабная актуализация чарта на основе продового окружения hrbox. Синхронизированы версии компонентов, добавлены новые микросервисы, обновлены переменные окружения. Масштабная актуализация чарта на основе продового окружения hrbox. Синхронизированы версии компонентов, добавлены новые микросервисы, обновлены переменные окружения.
@@ -227,5 +488,6 @@ kubectl get pods -n hrbox -l app=websocket # Должно быть пусто
--- ---
[3.0.0]: #300---2026-09-02
[2.0.0]: #200---2026-01-30 [2.0.0]: #200---2026-01-30
[1.2.0]: #120---previous-version [1.2.0]: #120---previous-version
+304 -43
View File
@@ -1,14 +1,47 @@
# HRBox Helm Chart # HRBox Helm Chart
Helm-чарт для развертывания приложения HRBox в Kubernetes. Чарт для установки HRBox в свой Kubernetes-кластер.
Сам чарт лежит в [`.helm`](.helm), настройки — в [`.helm/values.yaml`](.helm/values.yaml).
Каждый параметр там подписан, ниже — только то, что нужно сделать руками.
--- ---
## Быстрый старт ## Что разворачивается
### 1. Создайте секрет для доступа к Docker-реестру | Компонент | Что делает | Порт |
|---|---|---|
| `web` | PHP-FPM и nginx: веб-интерфейс и API | 80 |
| `worker` | фоновые задачи: файлы, почта, отчёты | — |
| `conductor` | задачи по расписанию, всегда 1 под | 8080 |
| `chatbox` | вебсокеты чата и уведомлений | 80 → 9797 |
| `nanabush-player` | плеер курсов: SCORM, cmi5, xAPI, нативные материалы | 8094 |
| `goworker` | мессенджеры, пуши, синхронизация оргструктуры с 1С | 8686 |
| `kedoca` | электронная подпись: КЭДО, МЧД | 8558 |
| `geonames` | справочник городов, стран, часовых поясов | 8181 |
| `file-processor` | конвертация документов и изображений | — |
| `file-processor-video` | конвертация видео, по умолчанию выключен | — |
| `dragonfly` | Redis-совместимый кеш и сессии | 6379 |
| `nats` | брокер сообщений JetStream | 4222 |
Для скачивания приватного Docker-образа создайте Kubernetes Secret с помощью предоставленного JSON-ключа: Публичных маршрутов три, и все на одном домене: `/` — приложение,
`/chatbox/` — вебсокеты, `/nanabush-player` — плеер курсов.
## Что нужно подготовить
- Kubernetes 1.21+ и ingress-контроллер (nginx или traefik);
- PostgreSQL 14+ (с Citus, если планируется шардирование);
- S3-совместимое хранилище: AWS S3, MinIO, Yandex Object Storage, VK Cloud;
- SMTP-сервер;
- доступ к реестру образов HRBox и токен HRBox Hub — выдают сотрудники HRBox.
Базу и S3 чарт не разворачивает: эти хранилища содержат постоянные данные и должны быть развёрнуты вручную.
---
## Установка
### 1. Доступ к реестру образов
```bash ```bash
kubectl create secret docker-registry regsecret \ kubectl create secret docker-registry regsecret \
@@ -18,57 +51,285 @@ kubectl create secret docker-registry regsecret \
--docker-email=not@used.com --docker-email=not@used.com
``` ```
### 2. Создайте TLS-секрет с сертификатом для домена ### 2. TLS-сертификат
```bash ```bash
kubectl create secret tls hrbox-tls --cert=cert.pem --key=key.pem kubectl create secret tls hrbox-tls --cert=cert.pem --key=key.pem
``` ```
### 3. Сгенерируйте секретные ключи приложения Либо выпустите сертификат через cert-manager и укажите его Secret
в `ingress.tls.secretName`.
Для обеспечения безопасности необходимо сгенерировать и указать в `values.yaml` следующие ключи: ### 3. Ключи
- **cookieValidationKey** — 32 байта в hex (например: `openssl rand -hex 16`)
- **encryptionKey** — 64 байта в base64 (например: `openssl rand -base64 48`)
- **servicesInternalSecret** — 64 байта в base64 (например: `openssl rand -base64 48`)
- **chatbox.wrappingKey** — 32 символа в hex (например: `openssl rand -hex 16`)
Эти ключи используются для защиты cookie, шифрования данных, межсервисной коммуникации и шифрования чатов.
### 4. Заполните обязательные параметры в `values.yaml`
Обязательно укажите в конфигурации:
- Параметры подключения к базе данных PostgreSQL (`app.postgres.host`, `port`, `database`, `user`, `password`).
- Настройки S3-совместимого хранилища (`app.s3.endpoint`, `bucket`, `key`, `secret`).
- SMTP-настройки для отправки почты (`app.smtp.host`, `port`, `user`, `password`, `from`, `fromHost`).
- Домен для приложения (`app.defaultTenantHostname`) и Ingress (`ingress.host`).
- Имя TLS-секрета для HTTPS (`ingress.tls.secretName`), созданного на шаге 2.
- Ключ для hrbox hub (предоставляется сотрудниками hrbox)
Прочие настройки и пример `values.yml` с подробным описанием ключей вы можете найти [тут](.helm/values.yaml)
### 5. Установите или обновите Helm-релиз
```bash ```bash
helm upgrade --install hrbox . -f values.yaml # secrets.cookieValidationKey и app.chatbox.wrappingKey
openssl rand -hex 16
# secrets.encryptionKey, secrets.servicesInternalSecret,
# app.nanabushPlayer.keys.ticketHs256, app.nanabushPlayer.keys.sessionHs256
openssl rand -base64 48
``` ```
### 6. Дождитесь завершения миграций `secrets.encryptionKey` шифруют пароли, в случае его утери придётся заново задавать пароли в настройках интеграций.
Job `hrbox-migrate-xxxxx` должна завершиться Ключи плеера `ticketHs256` и `sessionHs256` должны быть разными, одинаковые чарт не примет.
### 7. При первом развертывании - создайте суперпользователя ### 4. Заполните `values.yaml`
Минимум:
```yaml
ingress:
host: "hrbox.company.com"
tls:
secretName: "hrbox-tls"
app:
defaultTenantHostname: "hrbox.company.com"
postgres:
host: "postgresql"
database: "hrbox"
user: "hrbox"
password: "..."
s3:
endpoint: "https://storage.company.com"
bucket: "hrbox"
key: "..."
secret: "..."
smtp:
host: "smtp.company.com"
user: "noreply@company.com"
password: "..."
from: "noreply@company.com"
fromHost: "company.com"
hub:
token: "..."
chatbox:
wrappingKey: "..."
nanabushPlayer:
keys:
ticketHs256: "..."
sessionHs256: "..."
secrets:
cookieValidationKey: "..."
encryptionKey: "..."
servicesInternalSecret: "..."
```
У остальных параметров есть рабочие значения по умолчанию.
Проверить конфигурацию, ничего не устанавливая:
```bash ```bash
kubectl get pods helm template hrbox .helm -f values.yaml > /dev/null
NAME READY STATUS RESTARTS AGE
...
hrbox-worker-7898b77b85-5ppwm 1/1 Running 0 53s
hrbox-worker-7898b77b85-9fnkc 1/1 Running 0 53s
kubectl exec -it hrbox-worker-7898b77b85-5ppwm bash
php yii user/create-admin youremail@hrbox.io --tenant-id=1
``` ```
Если чего-то не хватает, команда остановится и напишет, что заполнить.
### 5. Установка
```bash
helm upgrade --install hrbox .helm -n hrbox --create-namespace -f values.yaml
```
### 6. Дождитесь миграций
```bash
kubectl -n hrbox wait --for=condition=complete --timeout=30m job -l app=jobs
```
### 7. Создайте администратора
```bash
kubectl -n hrbox exec -it deploy/hrbox-worker -- \
php yii user/create-admin admin@company.com --tenant-id=1
```
---
## Секреты
Пароли и ключи из `values.yaml` чарт кладёт в один Secret `hrbox-secrets`,
поды читают их оттуда. В спеке Deployment паролей нет.
Если секретами управляет внешний инструмент, создайте Secret сами и укажите
имя в `secrets.existingSecret`. Ключи должны называться так:
| Ключ | Что кладут |
|---|---|
| `cookie-validation-key` | `secrets.cookieValidationKey` |
| `encryption-key` | `secrets.encryptionKey` |
| `services-internal-secret` | `secrets.servicesInternalSecret` |
| `postgres-password` | `app.postgres.password` |
| `s3-key` | `app.s3.key` |
| `s3-secret` | `app.s3.secret` |
| `smtp-password` | `app.smtp.password` |
| `hub-token` | `app.hub.token` |
| `chatbox-wrapping-key` | `app.chatbox.wrappingKey` |
| `livekit-api-secret` | `app.livekit.apiSecret` |
| `yandex-client-password` | `app.yandex.clientPassword` |
| `yandex-ai-api-key` | `app.ai.yandex.apiKey` |
| `google-client-secret` | `app.integrations.google.clientSecret` |
| `slack-client-secret` | `app.slack.clientSecret` |
| `slack-verification-token` | `app.slack.verificationToken` |
Ключи плеера лежат в отдельном Secret `hrbox-nanabush-player`, за него
отвечает `app.nanabushPlayer.deployment.existingSecret`.
---
## Nanabush Player
Плеер учебных материалов: SCORM 1.2 и 2004, cmi5, xAPI, нативные курсы,
тесты и эссе.
В облаке HRBox плеер стоит на отдельном поддомене. В on-premise поддомена
нет, поэтому плеер живёт на основном домене по пути `/nanabush-player`.
Из этого следуют две вещи:
- **Cookie общие.** Плеер и HRBox на одном домене, поэтому cookie сессии
HRBox уходят и в запросы к содержимому курсов, включая сторонние
SCORM-пакеты. Если такая изоляция нужна, запросите у HRBox схему
с отдельным поддоменом.
- **Часы должны быть синхронны.** Launch-тикет живёт 5 минут, у сессии
допуск 2 минуты. Настройте NTP на нодах и сервере базы. Если это
невозможно, выключите плеер: `app.nanabushPlayer.enabled: false`.
Порядок первого включения:
1. Убедитесь, что миграции применились: плееру нужны свои таблицы.
2. Дождитесь, пока **все** поды `web` перейдут на новую версию. Пока часть
подов старая, при `rollout.percent > 0` по одному назначению может
открыться вторая попытка.
3. Проверьте, что отвечает именно плеер, а не HRBox через общий маршрут:
```bash
kubectl -n hrbox exec deploy/hrbox-worker -- \
curl -s http://hrbox-nanabush-player:8094/readyz
```
Плеер вернёт JSON. HTML означает, что запрос ушёл в HRBox.
4. Откройте `https://<домен>/nanabush-player/start` и проверьте статику
и API плеера по этому пути.
`/healthz`, `/readyz` и метрики отвечают в корне и от `basePath` не зависят.
Порт метрик наружу не публикуется.
Быстро выключить плеер можно тремя переключателями:
```yaml
app:
nanabushPlayer:
enabled: false # пользователи вернутся на старый проигрыватель
ingress:
enabled: false # маршрут снимается
deployment:
enabled: false # под останавливается
```
Выключать нужно сверху вниз: чарт не даст оставить маршрут без пода
или включённый плеер без маршрута.
Подробности контракта — `docs/nanabush-player-deployment.md` в репозитории HRBox.
---
## Эксплуатация
### Обновление
```bash
helm upgrade hrbox .helm -n hrbox -f values.yaml
```
Миграции и обновление кластера запускаются сами как хуки `post-upgrade`,
строго по очереди. В имени джобы есть номер ревизии релиза, поэтому
в `kubectl get jobs` видно, к какому выкату она относится.
### Масштабирование
```yaml
app:
replicas:
web: 4 # по числу одновременных пользователей
worker: 3 # по объёму фоновых задач
chatbox: 4 # по числу открытых вкладок
```
`conductor` всегда в одном экземпляре: два планировщика запустят каждую
задачу дважды.
Для `web` от двух реплик создаётся PodDisruptionBudget (`minAvailable: 75%`),
чтобы вывод ноды из обслуживания не уронил приложение целиком.
### Конвертация видео
Выключена по умолчанию, потому что требует заметно больше ресурсов, чем
остальная обработка файлов. Включение:
```yaml
app:
videoConverter:
enabled: true
nodeSelector:
role: converter-dedicated
tolerations:
- key: dedicated
operator: Equal
value: video-converter
effect: NoSchedule
```
### Трассировка
```yaml
app:
tracing:
enabled: true
tempoUrl: "http://tempo.monitoring:4317"
```
Рядом с `web` появится коллектор OpenTelemetry, PHP начнёт слать трейсы.
### Внешние Redis и NATS
```yaml
dragonfly:
enabled: false
nats:
enabled: false
app:
redis:
host: "redis.company.local"
nats:
url: "nats://n1:4222,nats://n2:4222,nats://n3:4222"
```
### Диагностика
```bash
kubectl -n hrbox get pods
kubectl -n hrbox logs -l app=web -c fpm --tail=200
kubectl -n hrbox logs -l app=worker --tail=200
kubectl -n hrbox logs -l app=nanabush-player --tail=200
kubectl -n hrbox get jobs
```
| Что видно | Куда смотреть |
|---|---|
| Поды `web` не готовы | пробы `/healthz` и `/health-check`, логи контейнера `fpm` |
| Джоба миграций висит | init-контейнер `wait-postgres`: доступность базы и права |
| Курс не открывается | логи `nanabush-player`, совпадают ли `ingress.host` и `app.defaultTenantHostname` |
| Не приходят уведомления | логи `goworker`, очереди NATS, `app.launchpad.topics` |
| Пользователей разлогинивает | перезапуски `dragonfly`: сессии хранятся в памяти |
---
## Обновление с версии 2.x
Часть ключей `values.yaml` переехала. Старые имена чарт узнаёт и
останавливает установку с подсказкой, поэтому ничего не потеряется.
Список изменений и порядок перехода — в [CHANGELOG.md](CHANGELOG.md).