feat: billing — usage tracking per SQS operation in PostgreSQL
- New package app/billing: Init/RecordUsage/Close with auto-migrate - Integration in actionHandler: record tenant_id, operation, msg_count, msg_bytes - Helm chart: billing section in values.yaml, secret-billing.yaml, env vars in deployment - Optional: billing disabled by default (BILLING_PG_HOST not set = no-op) - Table: sqs_usage_records with index on (tenant_id, recorded_at)
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
# deployment.yaml — Deployment shared-sqs с RollingUpdate
|
||||
# Created: 2026-04-11
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: shared-sqs
|
||||
namespace: {{ .Values.namespace }}
|
||||
labels:
|
||||
{{- include "shared-sqs.labels" . | nindent 4 }}
|
||||
spec:
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
strategy:
|
||||
type: {{ .Values.strategy.type }}
|
||||
{{- if eq .Values.strategy.type "RollingUpdate" }}
|
||||
rollingUpdate:
|
||||
maxSurge: {{ .Values.strategy.rollingUpdate.maxSurge }}
|
||||
maxUnavailable: {{ .Values.strategy.rollingUpdate.maxUnavailable }}
|
||||
{{- end }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "shared-sqs.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "shared-sqs.selectorLabels" . | nindent 8 }}
|
||||
spec:
|
||||
containers:
|
||||
- name: shared-sqs
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
ports:
|
||||
- containerPort: {{ .Values.service.port }}
|
||||
name: http
|
||||
env:
|
||||
- name: SHARED_SQS_ADMIN_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: shared-sqs-admin
|
||||
key: token
|
||||
- name: SHARED_SQS_SEED_DEMO
|
||||
value: {{ .Values.seedDemo | quote }}
|
||||
- name: REDIS_ADDR
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: shared-sqs-redis
|
||||
key: addr
|
||||
- name: REDIS_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: shared-sqs-redis
|
||||
key: user
|
||||
- name: REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: shared-sqs-redis
|
||||
key: password
|
||||
- name: NUBES_ENDPOINT
|
||||
value: {{ .Values.nubesEndpoint | quote }}
|
||||
{{- if .Values.billing.enabled }}
|
||||
- name: BILLING_PG_HOST
|
||||
value: {{ .Values.billing.postgres.host | quote }}
|
||||
- name: BILLING_PG_PORT
|
||||
value: {{ .Values.billing.postgres.port | quote }}
|
||||
- name: BILLING_PG_DATABASE
|
||||
value: {{ .Values.billing.postgres.database | quote }}
|
||||
- name: BILLING_PG_USER
|
||||
value: {{ .Values.billing.postgres.user | quote }}
|
||||
- name: BILLING_PG_SSLMODE
|
||||
value: {{ .Values.billing.postgres.sslmode | quote }}
|
||||
- name: BILLING_PG_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
{{- if .Values.billing.postgres.existingSecret }}
|
||||
name: {{ .Values.billing.postgres.existingSecret }}
|
||||
{{- else }}
|
||||
name: shared-sqs-billing-pg
|
||||
{{- end }}
|
||||
key: {{ .Values.billing.postgres.secretKey | default "password" }}
|
||||
{{- end }}
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 10 }}
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: {{ .Values.probes.liveness.path }}
|
||||
port: {{ .Values.service.port }}
|
||||
initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }}
|
||||
periodSeconds: {{ .Values.probes.liveness.periodSeconds }}
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: {{ .Values.probes.readiness.path }}
|
||||
port: {{ .Values.service.port }}
|
||||
initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }}
|
||||
periodSeconds: {{ .Values.probes.readiness.periodSeconds }}
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,15 @@
|
||||
# secret-billing.yaml — Secret с PostgreSQL credentials для billing
|
||||
# Создаётся только если billing.enabled=true и existingSecret не указан
|
||||
# Created: 2026-04-12
|
||||
{{- if and .Values.billing.enabled (not .Values.billing.postgres.existingSecret) }}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: shared-sqs-billing-pg
|
||||
namespace: {{ .Values.namespace }}
|
||||
labels:
|
||||
{{- include "shared-sqs.labels" . | nindent 4 }}
|
||||
type: Opaque
|
||||
stringData:
|
||||
password: {{ required "billing.postgres.password is required when billing is enabled" .Values.billing.postgres.password | quote }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,97 @@
|
||||
# values.yaml — параметры деплоя shared-sqs
|
||||
# Created: 2026-04-11
|
||||
# Updated: 2026-04-12 09:57 MSK — image tag v0.1.22 для demo UI showcase mode
|
||||
# Все значения — переменные, меняются при деплое через --set или -f override.yaml
|
||||
|
||||
# -- Namespace для деплоя
|
||||
namespace: shared-sqs
|
||||
|
||||
# -- Количество реплик
|
||||
replicaCount: 1
|
||||
|
||||
# -- Образ приложения
|
||||
image:
|
||||
repository: naeel/shared-sqs
|
||||
tag: "v0.1.22"
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
# -- imagePullSecrets (имя Secret'а с credentials к registry)
|
||||
imagePullSecrets:
|
||||
- name: sless-registry-auth
|
||||
|
||||
# -- Redis: эндпоинт, credentials
|
||||
# addr — полный host:port (можно internal K8s DNS или внешний IP)
|
||||
redis:
|
||||
addr: "rfrm-redisk8s.54467f74-67f5-4ca7-9b4a-bdd50e8c23d6.svc:6379"
|
||||
user: "default"
|
||||
password: "quiY2oovugaiChiejah9"
|
||||
|
||||
# -- Admin токен для /admin/* API
|
||||
admin:
|
||||
token: "sqs-admin-7a7d8bd0c060a75c198d48680f34077a"
|
||||
|
||||
# -- Seed demo tenant при старте
|
||||
seedDemo: true
|
||||
|
||||
# -- Nubes API endpoint
|
||||
nubesEndpoint: "https://deck-api-test.ngcloud.ru/api/v1"
|
||||
|
||||
# -- Ресурсы контейнера
|
||||
resources:
|
||||
requests:
|
||||
memory: "64Mi"
|
||||
cpu: "50m"
|
||||
limits:
|
||||
memory: "256Mi"
|
||||
cpu: "500m"
|
||||
|
||||
# -- Service
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 4100
|
||||
|
||||
# -- Ingress
|
||||
ingress:
|
||||
enabled: true
|
||||
className: nginx
|
||||
host: qu.kube5s.ru
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
|
||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "30"
|
||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "30"
|
||||
tls:
|
||||
enabled: true
|
||||
secretName: shared-sqs-tls
|
||||
|
||||
# -- Probes
|
||||
probes:
|
||||
liveness:
|
||||
path: /health
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
readiness:
|
||||
path: /health
|
||||
initialDelaySeconds: 3
|
||||
periodSeconds: 5
|
||||
|
||||
# -- Strategy
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
|
||||
# -- Billing: PostgreSQL для учёта использования SQS-операций.
|
||||
# Если enabled=false — billing отключён, сервис работает без PostgreSQL.
|
||||
billing:
|
||||
enabled: false
|
||||
postgres:
|
||||
host: ""
|
||||
port: "5432"
|
||||
database: "sqsdb"
|
||||
user: ""
|
||||
sslmode: "require"
|
||||
# Имя существующего K8s Secret с ключом "password"
|
||||
existingSecret: ""
|
||||
secretKey: "password"
|
||||
Reference in New Issue
Block a user