Add invy app

This commit is contained in:
dvirlabs 2025-12-29 20:43:56 +02:00
parent fe3dd1e208
commit 3306c7c680
19 changed files with 1050 additions and 0 deletions

21
argocd-apps/invy.yaml Normal file
View File

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

View File

@ -0,0 +1,12 @@
apiVersion: v2
name: invy
description: A Helm chart for Invy - Wedding Guest List Management Application
type: application
version: 1.0.0
appVersion: "1.0.0"
keywords:
- invy
- wedding
- guest-management
maintainers:
- name: dvir

183
charts/invy-chart/README.md Normal file
View File

@ -0,0 +1,183 @@
# Invy Helm Chart
This Helm chart deploys the Invy wedding guest list management application on Kubernetes.
## Prerequisites
- Kubernetes 1.19+
- Helm 3.0+
- Persistent Volume provisioner support in the underlying infrastructure (for PostgreSQL)
- Ingress controller (Traefik recommended)
- Cert-manager (for TLS certificates)
## Components
This chart deploys the following components:
- **Frontend**: React + Vite application (Nginx)
- **Backend**: FastAPI application
- **Database**: PostgreSQL 16
## Installation
### Add the chart repository (if applicable)
```bash
helm repo add invy https://your-helm-repo.com
helm repo update
```
### Install the chart
```bash
# Install with default values
helm install invy ./invy-chart -n my-apps --create-namespace
# Install with custom values
helm install invy ./invy-chart -n my-apps --create-namespace -f custom-values.yaml
```
## Configuration
The following table lists the configurable parameters and their default values.
### Global Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| `global.namespace` | Namespace for all resources | `my-apps` |
| `global.imagePullSecrets` | Image pull secrets | `[]` |
### Backend Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| `backend.image.repository` | Backend image repository | `harbor.dvirlabs.com/my-apps/invy-backend` |
| `backend.image.tag` | Backend image tag | `latest` |
| `backend.replicaCount` | Number of backend replicas | `1` |
| `backend.service.port` | Backend service port | `8000` |
| `backend.ingress.enabled` | Enable backend ingress | `true` |
| `backend.ingress.hosts[0].host` | Backend ingress hostname | `api-invy.dvirlabs.com` |
### Frontend Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| `frontend.image.repository` | Frontend image repository | `harbor.dvirlabs.com/my-apps/invy-frontend` |
| `frontend.image.tag` | Frontend image tag | `latest` |
| `frontend.replicaCount` | Number of frontend replicas | `1` |
| `frontend.service.port` | Frontend service port | `80` |
| `frontend.env.VITE_API_URL` | Backend API URL | `https://api-invy.dvirlabs.com` |
| `frontend.ingress.enabled` | Enable frontend ingress | `true` |
| `frontend.ingress.hosts[0].host` | Frontend ingress hostname | `invy.dvirlabs.com` |
### PostgreSQL Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| `postgres.user` | PostgreSQL user | `invy_user` |
| `postgres.password` | PostgreSQL password | `invy_password` |
| `postgres.database` | PostgreSQL database name | `invy_db` |
| `postgres.persistence.enabled` | Enable persistence | `true` |
| `postgres.persistence.size` | Persistent volume size | `10Gi` |
| `postgres.persistence.storageClass` | Storage class | `nfs-client` |
## Building and Pushing Images
### Backend Image
```bash
cd backend
docker build -t harbor.dvirlabs.com/my-apps/invy-backend:latest .
docker push harbor.dvirlabs.com/my-apps/invy-backend:latest
```
### Frontend Image
```bash
cd frontend
docker build --build-arg VITE_API_URL=https://api-invy.dvirlabs.com -t harbor.dvirlabs.com/my-apps/invy-frontend:latest .
docker push harbor.dvirlabs.com/my-apps/invy-frontend:latest
```
## Upgrading
```bash
helm upgrade invy ./invy-chart -n my-apps
```
## Uninstalling
```bash
helm uninstall invy -n my-apps
```
## Customization
Create a `custom-values.yaml` file to override default values:
```yaml
backend:
image:
tag: "v1.0.0"
ingress:
hosts:
- host: api.mycompany.com
paths:
- path: /
pathType: Prefix
frontend:
image:
tag: "v1.0.0"
env:
VITE_API_URL: "https://api.mycompany.com"
ingress:
hosts:
- host: invy.mycompany.com
paths:
- path: /
pathType: Prefix
postgres:
password: "your-secure-password"
persistence:
storageClass: "your-storage-class"
```
Then install with:
```bash
helm install invy ./invy-chart -n my-apps -f custom-values.yaml
```
## Troubleshooting
### Check pod status
```bash
kubectl get pods -n my-apps
```
### View pod 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 the database
```bash
kubectl exec -it -n my-apps invy-db-0 -- psql -U invy_user -d invy_db
```
## Support
For issues and feature requests, please open an issue in the repository.

View File

@ -0,0 +1,38 @@
Thank you for installing {{ .Chart.Name }}!
Your release is named {{ .Release.Name }}.
To learn more about the release, try:
$ helm status {{ .Release.Name }}
$ helm get all {{ .Release.Name }}
{{- if .Values.frontend.ingress.enabled }}
Application URLs:
{{- range .Values.frontend.ingress.hosts }}
Frontend: https://{{ .host }}
{{- end }}
{{- range .Values.backend.ingress.hosts }}
Backend API: https://{{ .host }}
{{- end }}
{{- else }}
To access your application:
1. Get the frontend URL:
export POD_NAME=$(kubectl get pods --namespace {{ .Values.global.namespace }} -l "app.kubernetes.io/name={{ include "invy.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=frontend" -o jsonpath="{.items[0].metadata.name}")
kubectl --namespace {{ .Values.global.namespace }} port-forward $POD_NAME 8080:80
echo "Visit http://127.0.0.1:8080 to use your application"
2. Get the backend URL:
export POD_NAME=$(kubectl get pods --namespace {{ .Values.global.namespace }} -l "app.kubernetes.io/name={{ include "invy.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=backend" -o jsonpath="{.items[0].metadata.name}")
kubectl --namespace {{ .Values.global.namespace }} port-forward $POD_NAME 8000:8000
echo "Visit http://127.0.0.1:8000 to access the API"
{{- end }}
Database connection:
Host: {{ include "invy.fullname" . }}-db
Port: {{ .Values.postgres.port }}
Database: {{ .Values.postgres.database }}
User: {{ .Values.postgres.user }}

View File

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

View File

@ -0,0 +1,80 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "invy.fullname" . }}-backend
labels:
{{- include "invy.labels" . | nindent 4 }}
app.kubernetes.io/component: backend
spec:
replicas: {{ .Values.backend.replicaCount }}
selector:
matchLabels:
{{- include "invy.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: backend
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "invy.selectorLabels" . | nindent 8 }}
app.kubernetes.io/component: backend
spec:
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "invy.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
initContainers:
- name: wait-for-postgres
image: busybox:1.35
command: ['sh', '-c', 'until nc -z {{ include "invy.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 "invy.fullname" . }}-secrets
key: database-url
{{- range $key, $value := .Values.backend.env }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- 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 }}
{{- 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 "invy.fullname" . }}-backend
labels:
{{- include "invy.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 "invy.fullname" $ }}-backend
port:
number: {{ $.Values.backend.service.port }}
{{- end }}
{{- end }}
{{- end }}

View File

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

View File

@ -0,0 +1,41 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "invy.fullname" . }}-db-schema
labels:
{{- include "invy.labels" . | nindent 4 }}
app.kubernetes.io/component: database
data:
init.sql: |
-- Wedding Guest List Database Schema
CREATE TABLE IF NOT EXISTS guests (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
phone VARCHAR(50),
email VARCHAR(255),
rsvp_status VARCHAR(50) DEFAULT 'pending',
meal_preference VARCHAR(100),
plus_one BOOLEAN DEFAULT FALSE,
plus_one_name VARCHAR(255),
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Create index for faster searches
CREATE INDEX IF NOT EXISTS idx_guests_name ON guests(name);
CREATE INDEX IF NOT EXISTS idx_guests_email ON guests(email);
CREATE INDEX IF NOT EXISTS idx_guests_rsvp_status ON guests(rsvp_status);
-- Create trigger to update updated_at timestamp
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ language 'plpgsql';
CREATE TRIGGER update_guests_updated_at BEFORE UPDATE ON guests
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

View File

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

View File

@ -0,0 +1,90 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ include "invy.fullname" . }}-db
labels:
{{- include "invy.labels" . | nindent 4 }}
app.kubernetes.io/component: database
spec:
serviceName: {{ include "invy.fullname" . }}-db-headless
replicas: 1
selector:
matchLabels:
{{- include "invy.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: database
template:
metadata:
labels:
{{- include "invy.selectorLabels" . | nindent 8 }}
app.kubernetes.io/component: database
spec:
containers:
- name: postgres
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 "invy.fullname" . }}-secrets
key: postgres-user
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "invy.fullname" . }}-secrets
key: postgres-password
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
name: {{ include "invy.fullname" . }}-secrets
key: postgres-database
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
- name: init-script
mountPath: /docker-entrypoint-initdb.d
resources:
{{- toYaml .Values.postgres.resources | nindent 12 }}
livenessProbe:
exec:
command:
- pg_isready
- -U
- $(POSTGRES_USER)
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
exec:
command:
- pg_isready
- -U
- $(POSTGRES_USER)
initialDelaySeconds: 5
periodSeconds: 5
volumes:
- name: init-script
configMap:
name: {{ include "invy.fullname" . }}-db-schema
{{- if .Values.postgres.persistence.enabled }}
volumeClaimTemplates:
- metadata:
name: postgres-data
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 "invy.fullname" . }}-frontend
labels:
{{- include "invy.labels" . | nindent 4 }}
app.kubernetes.io/component: frontend
spec:
replicas: {{ .Values.frontend.replicaCount }}
selector:
matchLabels:
{{- include "invy.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: frontend
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "invy.selectorLabels" . | nindent 8 }}
app.kubernetes.io/component: frontend
spec:
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "invy.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 "invy.fullname" . }}-frontend
labels:
{{- include "invy.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 "invy.fullname" $ }}-frontend
port:
number: {{ $.Values.frontend.service.port }}
{{- end }}
{{- end }}
{{- end }}

View File

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

View File

@ -0,0 +1,12 @@
apiVersion: v1
kind: Secret
metadata:
name: {{ include "invy.fullname" . }}-secrets
labels:
{{- include "invy.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 "invy.fullname" . }}-db:{{ .Values.postgres.port }}/{{ .Values.postgres.database }}"

View File

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

View File

@ -0,0 +1,136 @@
global:
namespace: my-apps
imagePullSecrets: []
# Backend configuration
backend:
name: backend
replicaCount: 1
image:
repository: harbor.dvirlabs.com/my-apps/invy-backend
pullPolicy: IfNotPresent
tag: "latest"
service:
type: ClusterIP
port: 8000
targetPort: 8000
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
env:
PYTHONUNBUFFERED: "1"
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-invy.dvirlabs.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: api-invy-tls
hosts:
- api-invy.dvirlabs.com
# Frontend configuration
frontend:
name: frontend
replicaCount: 1
image:
repository: harbor.dvirlabs.com/my-apps/invy-frontend
pullPolicy: IfNotPresent
tag: "latest"
service:
type: ClusterIP
port: 80
targetPort: 80
env:
VITE_API_URL: "https://api-invy.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: invy.dvirlabs.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: invy-tls
hosts:
- invy.dvirlabs.com
# PostgreSQL configuration
postgres:
name: db
image:
repository: postgres
tag: "16-alpine"
pullPolicy: IfNotPresent
user: invy_user
password: invy_password
database: invy_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
# Ingress configuration
ingress:
enabled: false # Individual frontend/backend ingress resources handle routing instead
className: "traefik"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: invy.dvirlabs.com
paths:
- path: /
pathType: Prefix
backend: frontend
tls:
- secretName: invy-tls
hosts:
- invy.dvirlabs.com

View File

@ -0,0 +1,2 @@
enabled: true
hostname: ipify.dvirlabs.com

136
manifests/invy/values.yaml Normal file
View File

@ -0,0 +1,136 @@
global:
namespace: my-apps
imagePullSecrets: []
# Backend configuration
backend:
name: backend
replicaCount: 1
image:
repository: harbor.dvirlabs.com/my-apps/invy-backend
pullPolicy: IfNotPresent
tag: "latest"
service:
type: ClusterIP
port: 8000
targetPort: 8000
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
env:
PYTHONUNBUFFERED: "1"
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-invy.dvirlabs.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: api-invy-tls
hosts:
- api-invy.dvirlabs.com
# Frontend configuration
frontend:
name: frontend
replicaCount: 1
image:
repository: harbor.dvirlabs.com/my-apps/invy-frontend
pullPolicy: IfNotPresent
tag: "latest"
service:
type: ClusterIP
port: 80
targetPort: 80
env:
VITE_API_URL: "https://api-invy.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: invy.dvirlabs.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: invy-tls
hosts:
- invy.dvirlabs.com
# PostgreSQL configuration
postgres:
name: db
image:
repository: postgres
tag: "16-alpine"
pullPolicy: IfNotPresent
user: invy_user
password: invy_password
database: invy_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
# Ingress configuration
ingress:
enabled: false # Individual frontend/backend ingress resources handle routing instead
className: "traefik"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: invy.dvirlabs.com
paths:
- path: /
pathType: Prefix
backend: frontend
tls:
- secretName: invy-tls
hosts:
- invy.dvirlabs.com