Add brand-master app

This commit is contained in:
dvirlabs 2026-05-05 06:28:19 +03:00
parent b34aafda4d
commit 6f6650078b
18 changed files with 1068 additions and 0 deletions

View File

@ -0,0 +1,21 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: brand-master
namespace: argocd
spec:
project: my-apps
source:
repoURL: ssh://git@gitea-ssh.dev-tools.svc.cluster.local:2222/dvirlabs/my-apps.git
targetRevision: HEAD
path: charts/brand-master-chart
helm:
valueFiles:
- ../../manifests/brand-master/values.yaml
destination:
server: https://kubernetes.default.svc
namespace: my-apps
syncPolicy:
automated:
prune: true
selfHeal: true

View File

@ -0,0 +1,13 @@
apiVersion: v2
name: brand-master
description: A Helm chart for Brand Master - E-commerce Fashion & Shoe Store
type: application
version: 1.0.0
appVersion: "1.0.0"
keywords:
- brand-master
- ecommerce
- fashion
- shoes
maintainers:
- name: dvir

View File

@ -0,0 +1,158 @@
# Brand Master Helm Chart
This Helm chart deploys the Brand Master e-commerce application on Kubernetes.
## Components
- **Frontend**: React-based UI served by Nginx
- **Backend**: FastAPI application
- **Database**: PostgreSQL 16
- **Storage**: 15GB PVC for product images
## Prerequisites
- Kubernetes 1.19+
- Helm 3.0+
- cert-manager (for TLS certificates)
- Storage class configured (nfs-client by default)
## Installation
### 1. Update values.yaml
Edit `values.yaml` and configure:
- Image repositories (if using private registry)
- Domain names for ingress
- JWT secret key (IMPORTANT!)
- Database credentials
- Storage class name
### 2. Install the chart
```bash
# Install in the my-apps namespace
helm install brand-master ./brand-master-chart -n my-apps --create-namespace
# Or with custom values
helm install brand-master ./brand-master-chart -n my-apps \
--set backend.jwtSecretKey=your-super-secret-key \
--set postgres.password=secure-password
```
### 3. Upgrade the chart
```bash
helm upgrade brand-master ./brand-master-chart -n my-apps
```
### 4. Uninstall
```bash
helm uninstall brand-master -n my-apps
```
## Configuration
### Key Configuration Options
| Parameter | Description | Default |
|-----------|-------------|---------|
| `backend.image.repository` | Backend Docker image | `harbor.dvirlabs.com/my-apps/brand-master-backend` |
| `backend.image.tag` | Backend image tag | `latest` |
| `backend.jwtSecretKey` | JWT secret for authentication | `your-secret-key-change-this-in-production` |
| `backend.persistence.enabled` | Enable persistent storage for images | `true` |
| `backend.persistence.size` | Size of uploads PVC | `15Gi` |
| `frontend.image.repository` | Frontend Docker image | `harbor.dvirlabs.com/my-apps/brand-master-frontend` |
| `frontend.image.tag` | Frontend image tag | `latest` |
| `postgres.user` | PostgreSQL username | `brand_master_user` |
| `postgres.password` | PostgreSQL password | `brand_master_password` |
| `postgres.database` | PostgreSQL database name | `brand_master_db` |
| `postgres.persistence.size` | Size of database PVC | `10Gi` |
## Building Docker Images
### Backend
```bash
cd backend
docker build -t harbor.dvirlabs.com/my-apps/brand-master-backend:latest .
docker push harbor.dvirlabs.com/my-apps/brand-master-backend:latest
```
### Frontend
```bash
cd frontend
docker build -t harbor.dvirlabs.com/my-apps/brand-master-frontend:latest \
--build-arg VITE_API_URL=https://api-brand-master.dvirlabs.com .
docker push harbor.dvirlabs.com/my-apps/brand-master-frontend:latest
```
## Storage
The chart creates two PVCs:
1. **Database PVC**: 10GB for PostgreSQL data
2. **Uploads PVC**: 15GB for product images at `/app/uploads`
Both use the `nfs-client` storage class by default. Update this in `values.yaml` if needed.
## Ingress
The chart creates two ingress resources:
- **Frontend**: `brand-master.dvirlabs.com`
- **Backend API**: `api-brand-master.dvirlabs.com`
TLS is enabled by default using Let's Encrypt via cert-manager.
## Troubleshooting
### Check pod status
```bash
kubectl get pods -n my-apps
```
### View logs
```bash
# Backend logs
kubectl logs -n my-apps -l app.kubernetes.io/component=backend
# Frontend logs
kubectl logs -n my-apps -l app.kubernetes.io/component=frontend
# Database logs
kubectl logs -n my-apps -l app.kubernetes.io/component=database
```
### Access services locally
```bash
# Frontend
kubectl port-forward -n my-apps svc/brand-master-frontend 8080:80
# Backend
kubectl port-forward -n my-apps svc/brand-master-backend 8000:8000
# Database
kubectl port-forward -n my-apps svc/brand-master-db 5432:5432
```
### Check PVC status
```bash
kubectl get pvc -n my-apps
```
## Security Notes
1. **Change the JWT secret** in production
2. **Update database credentials**
3. **Use strong passwords**
4. **Configure proper CORS settings**
5. **Review and adjust resource limits**
6. **Enable network policies** if needed
7. **Use image pull secrets** for private registries
## Support
For issues or questions, refer to the main repository documentation.

View File

@ -0,0 +1,48 @@
1. Get the application URL by running these commands:
{{- if .Values.frontend.ingress.enabled }}
{{- range $host := .Values.frontend.ingress.hosts }}
{{- range .paths }}
Frontend: http{{ if $.Values.frontend.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.backend.ingress.enabled }}
{{- range $host := .Values.backend.ingress.hosts }}
{{- range .paths }}
Backend API: http{{ if $.Values.backend.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
{{- end }}
{{- end }}
{{- end }}
2. Database Connection:
Host: {{ include "brand-master.fullname" . }}-db
Port: {{ .Values.postgres.port }}
Database: {{ .Values.postgres.database }}
User: {{ .Values.postgres.user }}
3. Product Images Storage:
{{- if .Values.backend.persistence.enabled }}
PVC: {{ include "brand-master.fullname" . }}-uploads-pvc
Size: {{ .Values.backend.persistence.size }}
Mount Path: {{ .Values.backend.persistence.mountPath }}
{{- else }}
Warning: Persistence is disabled. Product images will be lost on pod restart!
{{- end }}
4. IMPORTANT Security Notes:
- Change the JWT secret key in values.yaml before deploying to production
- Update the database password in values.yaml
- Configure your domain names in the ingress sections
- Ensure cert-manager is installed for TLS certificates
5. To access the application locally without ingress:
kubectl port-forward svc/{{ include "brand-master.fullname" . }}-frontend 8080:80
kubectl port-forward svc/{{ include "brand-master.fullname" . }}-backend 8000:8000
6. To check pod status:
kubectl get pods -l app.kubernetes.io/instance={{ .Release.Name }}
7. To view logs:
kubectl logs -l app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=backend
kubectl logs -l app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=frontend

View File

@ -0,0 +1,60 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "brand-master.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "brand-master.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "brand-master.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "brand-master.labels" -}}
helm.sh/chart: {{ include "brand-master.chart" . }}
{{ include "brand-master.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "brand-master.selectorLabels" -}}
app.kubernetes.io/name: {{ include "brand-master.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "brand-master.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "brand-master.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,106 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "brand-master.fullname" . }}-backend
labels:
{{- include "brand-master.labels" . | nindent 4 }}
app.kubernetes.io/component: backend
spec:
replicas: {{ .Values.backend.replicaCount }}
selector:
matchLabels:
{{- include "brand-master.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: backend
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "brand-master.selectorLabels" . | nindent 8 }}
app.kubernetes.io/component: backend
spec:
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "brand-master.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
initContainers:
- name: wait-for-postgres
image: harbor.dvirlabs.com/dockerhub/busybox:1.35
command: ['sh', '-c', 'until nc -z {{ include "brand-master.fullname" . }}-db-headless {{ .Values.postgres.port | default 5432 }}; do echo waiting for postgres; sleep 2; done;']
containers:
- name: backend
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.backend.image.repository }}:{{ .Values.backend.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.backend.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.backend.service.targetPort }}
protocol: TCP
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: {{ include "brand-master.fullname" . }}-secrets
key: database-url
- name: SECRET_KEY
valueFrom:
secretKeyRef:
name: {{ include "brand-master.fullname" . }}-secrets
key: jwt-secret-key
- name: ALGORITHM
valueFrom:
secretKeyRef:
name: {{ include "brand-master.fullname" . }}-secrets
key: jwt-algorithm
- name: ACCESS_TOKEN_EXPIRE_MINUTES
valueFrom:
secretKeyRef:
name: {{ include "brand-master.fullname" . }}-secrets
key: jwt-expire-minutes
{{- range $key, $value := .Values.backend.env }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
volumeMounts:
{{- if .Values.backend.persistence.enabled }}
- name: uploads
mountPath: {{ .Values.backend.persistence.mountPath }}
{{- end }}
livenessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 10
periodSeconds: 5
resources:
{{- toYaml .Values.backend.resources | nindent 12 }}
volumes:
{{- if .Values.backend.persistence.enabled }}
- name: uploads
persistentVolumeClaim:
claimName: {{ include "brand-master.fullname" . }}-uploads-pvc
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}

View File

@ -0,0 +1,42 @@
{{- if .Values.backend.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "brand-master.fullname" . }}-backend
labels:
{{- include "brand-master.labels" . | nindent 4 }}
app.kubernetes.io/component: backend
{{- with .Values.backend.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.backend.ingress.className }}
ingressClassName: {{ .Values.backend.ingress.className }}
{{- end }}
{{- if .Values.backend.ingress.tls }}
tls:
{{- range .Values.backend.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.backend.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "brand-master.fullname" $ }}-backend
port:
number: {{ $.Values.backend.service.port }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,18 @@
{{- if .Values.backend.persistence.enabled }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "brand-master.fullname" . }}-uploads-pvc
labels:
{{- include "brand-master.labels" . | nindent 4 }}
app.kubernetes.io/component: backend
spec:
accessModes:
- {{ .Values.backend.persistence.accessMode }}
{{- if .Values.backend.persistence.storageClass }}
storageClassName: {{ .Values.backend.persistence.storageClass }}
{{- end }}
resources:
requests:
storage: {{ .Values.backend.persistence.size }}
{{- end }}

View File

@ -0,0 +1,17 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "brand-master.fullname" . }}-backend
labels:
{{- include "brand-master.labels" . | nindent 4 }}
app.kubernetes.io/component: backend
spec:
type: {{ .Values.backend.service.type }}
ports:
- port: {{ .Values.backend.service.port }}
targetPort: {{ .Values.backend.service.targetPort }}
protocol: TCP
name: http
selector:
{{- include "brand-master.selectorLabels" . | nindent 4 }}
app.kubernetes.io/component: backend

View File

@ -0,0 +1,36 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "brand-master.fullname" . }}-db
labels:
{{- include "brand-master.labels" . | nindent 4 }}
app.kubernetes.io/component: database
spec:
type: {{ .Values.postgres.service.type }}
ports:
- port: {{ .Values.postgres.service.port }}
targetPort: {{ .Values.postgres.service.targetPort }}
protocol: TCP
name: postgres
selector:
{{- include "brand-master.selectorLabels" . | nindent 4 }}
app.kubernetes.io/component: database
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "brand-master.fullname" . }}-db-headless
labels:
{{- include "brand-master.labels" . | nindent 4 }}
app.kubernetes.io/component: database
spec:
type: ClusterIP
clusterIP: None
ports:
- port: {{ .Values.postgres.service.port }}
targetPort: {{ .Values.postgres.service.targetPort }}
protocol: TCP
name: postgres
selector:
{{- include "brand-master.selectorLabels" . | nindent 4 }}
app.kubernetes.io/component: database

View File

@ -0,0 +1,124 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ include "brand-master.fullname" . }}-db
labels:
{{- include "brand-master.labels" . | nindent 4 }}
app.kubernetes.io/component: database
spec:
serviceName: {{ include "brand-master.fullname" . }}-db-headless
replicas: 1
selector:
matchLabels:
{{- include "brand-master.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: database
template:
metadata:
labels:
{{- include "brand-master.selectorLabels" . | nindent 8 }}
app.kubernetes.io/component: database
spec:
securityContext:
fsGroup: 999
initContainers:
- name: fix-permissions
image: harbor.dvirlabs.com/dockerhub/busybox:latest
command:
- sh
- -c
- |
chown -R 999:999 /var/lib/postgresql/data || true
chmod 700 /var/lib/postgresql/data || true
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
securityContext:
runAsUser: 0
containers:
- name: postgres
securityContext:
runAsUser: 999
runAsNonRoot: true
image: "{{ .Values.postgres.image.repository }}:{{ .Values.postgres.image.tag }}"
imagePullPolicy: {{ .Values.postgres.image.pullPolicy }}
ports:
- name: postgres
containerPort: {{ .Values.postgres.port }}
protocol: TCP
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: {{ include "brand-master.fullname" . }}-secrets
key: postgres-user
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "brand-master.fullname" . }}-secrets
key: postgres-password
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
name: {{ include "brand-master.fullname" . }}-secrets
key: postgres-database
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
- name: postgres-run
mountPath: /var/run/postgresql
resources:
{{- toYaml .Values.postgres.resources | nindent 12 }}
startupProbe:
exec:
command:
- sh
- -c
- pg_isready -h 127.0.0.1 -p 5432 -U "$POSTGRES_USER" -d "$POSTGRES_DB"
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 30
livenessProbe:
exec:
command:
- sh
- -c
- pg_isready -h 127.0.0.1 -p 5432 -U "$POSTGRES_USER" -d "$POSTGRES_DB"
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
exec:
command:
- sh
- -c
- pg_isready -h 127.0.0.1 -p 5432 -U "$POSTGRES_USER" -d "$POSTGRES_DB"
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 3
volumes:
- name: postgres-run
emptyDir: {}
{{- if .Values.postgres.persistence.enabled }}
volumeClaimTemplates:
- metadata:
name: postgres-data
labels:
{{- include "brand-master.labels" . | nindent 8 }}
spec:
accessModes:
- {{ .Values.postgres.persistence.accessMode }}
{{- if .Values.postgres.persistence.storageClass }}
storageClassName: {{ .Values.postgres.persistence.storageClass }}
{{- end }}
resources:
requests:
storage: {{ .Values.postgres.persistence.size }}
{{- else }}
- name: postgres-data
emptyDir: {}
{{- end }}

View File

@ -0,0 +1,73 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "brand-master.fullname" . }}-frontend
labels:
{{- include "brand-master.labels" . | nindent 4 }}
app.kubernetes.io/component: frontend
spec:
replicas: {{ .Values.frontend.replicaCount }}
selector:
matchLabels:
{{- include "brand-master.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: frontend
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "brand-master.selectorLabels" . | nindent 8 }}
app.kubernetes.io/component: frontend
spec:
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "brand-master.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: frontend
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.frontend.image.repository }}:{{ .Values.frontend.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.frontend.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.frontend.service.targetPort }}
protocol: TCP
{{- if .Values.frontend.env }}
env:
{{- range $key, $value := .Values.frontend.env }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
{{- end }}
livenessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 10
periodSeconds: 5
resources:
{{- toYaml .Values.frontend.resources | nindent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}

View File

@ -0,0 +1,42 @@
{{- if .Values.frontend.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "brand-master.fullname" . }}-frontend
labels:
{{- include "brand-master.labels" . | nindent 4 }}
app.kubernetes.io/component: frontend
{{- with .Values.frontend.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.frontend.ingress.className }}
ingressClassName: {{ .Values.frontend.ingress.className }}
{{- end }}
{{- if .Values.frontend.ingress.tls }}
tls:
{{- range .Values.frontend.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.frontend.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "brand-master.fullname" $ }}-frontend
port:
number: {{ $.Values.frontend.service.port }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,17 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "brand-master.fullname" . }}-frontend
labels:
{{- include "brand-master.labels" . | nindent 4 }}
app.kubernetes.io/component: frontend
spec:
type: {{ .Values.frontend.service.type }}
ports:
- port: {{ .Values.frontend.service.port }}
targetPort: {{ .Values.frontend.service.targetPort }}
protocol: TCP
name: http
selector:
{{- include "brand-master.selectorLabels" . | nindent 4 }}
app.kubernetes.io/component: frontend

View File

@ -0,0 +1,15 @@
apiVersion: v1
kind: Secret
metadata:
name: {{ include "brand-master.fullname" . }}-secrets
labels:
{{- include "brand-master.labels" . | nindent 4 }}
type: Opaque
stringData:
postgres-user: {{ .Values.postgres.user | quote }}
postgres-password: {{ .Values.postgres.password | quote }}
postgres-database: {{ .Values.postgres.database | quote }}
database-url: "postgresql://{{ .Values.postgres.user }}:{{ .Values.postgres.password }}@{{ include "brand-master.fullname" . }}-db:{{ .Values.postgres.port }}/{{ .Values.postgres.database }}"
jwt-secret-key: {{ .Values.backend.jwtSecretKey | quote }}
jwt-algorithm: {{ .Values.backend.jwtAlgorithm | quote }}
jwt-expire-minutes: {{ .Values.backend.jwtExpireMinutes | quote }}

View File

@ -0,0 +1,12 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "brand-master.serviceAccountName" . }}
labels:
{{- include "brand-master.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,165 @@
global:
namespace: my-apps
imagePullSecrets: []
# Backend configuration
backend:
name: backend
replicaCount: 1
image:
repository: harbor.dvirlabs.com/my-apps/brand-master-backend
pullPolicy: IfNotPresent
tag: "latest"
service:
type: ClusterIP
port: 8000
targetPort: 8000
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 1000m
memory: 1Gi
env:
PYTHONUNBUFFERED: "1"
BACKEND_URL: "https://api-brand-master.dvirlabs.com"
FRONTEND_URL: "https://brand-master.dvirlabs.com"
# JWT Secret Key (IMPORTANT: Change this in production!)
jwtSecretKey: "your-secret-key-change-this-in-production"
jwtAlgorithm: "HS256"
jwtExpireMinutes: "30"
# Persistent storage for product images
persistence:
enabled: true
storageClass: "nfs-client"
accessMode: ReadWriteOnce
size: 15Gi
mountPath: /app/uploads
ingress:
enabled: true
className: "traefik"
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: api-brand-master.dvirlabs.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: api-brand-master-tls
hosts:
- api-brand-master.dvirlabs.com
# Frontend configuration
frontend:
name: frontend
replicaCount: 1
image:
repository: harbor.dvirlabs.com/my-apps/brand-master-frontend
pullPolicy: IfNotPresent
tag: "latest"
service:
type: ClusterIP
port: 80
targetPort: 80
env:
VITE_API_URL: "https://api-brand-master.dvirlabs.com"
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 256Mi
ingress:
enabled: true
className: "traefik"
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: brand-master.dvirlabs.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: brand-master-tls
hosts:
- brand-master.dvirlabs.com
# PostgreSQL configuration
postgres:
name: db
image:
repository: harbor.dvirlabs.com/dockerhub/postgres
tag: "16-alpine"
pullPolicy: IfNotPresent
user: brand_master_user
password: brand_master_password
database: brand_master_db
port: 5432
service:
type: ClusterIP
port: 5432
targetPort: 5432
persistence:
enabled: true
accessMode: ReadWriteOnce
storageClass: "nfs-client"
size: 10Gi
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 1000m
memory: 1Gi
# Service Account
serviceAccount:
create: true
annotations: {}
name: ""
# Pod annotations
podAnnotations: {}
# Pod security context
podSecurityContext: {}
# fsGroup: 2000
# Container security context
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
# Node selector
nodeSelector: {}
# Tolerations
tolerations: []
# Affinity
affinity: {}

View File

@ -0,0 +1,101 @@
nameOverride: ""
fullnameOverride: ""
commonLabels: {}
commonAnnotations: {}
imagePullSecrets:
- name: harbor-regcred
backend:
image:
repository: harbor.dvirlabs.com/my-apps/brand-master-backend
tag: latest
pullPolicy: IfNotPresent
replicas: 1
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 200m
memory: 256Mi
env:
- name: PYTHONUNBUFFERED
value: "1"
- name: BACKEND_URL
value: "https://api-brand-master.dvirlabs.com"
- name: FRONTEND_URL
value: "https://brand-master.dvirlabs.com"
- name: JWT_SECRET_KEY
value: "your-secret-key-change-this-in-production"
- name: JWT_ALGORITHM
value: "HS256"
- name: JWT_EXPIRE_MINUTES
value: "30"
persistence:
enabled: true
storageClass: "nfs-client"
size: 15Gi
mountPath: /app/uploads
service:
type: ClusterIP
port: 8000
healthCheck:
path: /health
initialDelaySeconds: 10
periodSeconds: 30
ingress:
enabled: true
className: "traefik"
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: api-brand-master.dvirlabs.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: api-brand-master-tls
hosts:
- api-brand-master.dvirlabs.com
frontend:
image:
repository: harbor.dvirlabs.com/my-apps/brand-master-frontend
tag: latest
pullPolicy: IfNotPresent
replicas: 1
resources:
limits:
cpu: 200m
memory: 256Mi
requests:
cpu: 50m
memory: 64Mi
env:
- name: VITE_API_URL
value: "https://api-brand-master.dvirlabs.com"
service:
type: ClusterIP
port: 80
healthCheck:
path: /
initialDelaySeconds: 5
periodSeconds: 30
ingress:
enabled: true
className: "traefik"
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: brand-master.dvirlabs.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: brand-master-tls
hosts:
- brand-master.dvirlabs.com