Fix frontend API connectivity: switch to nginx, add runtime env injection, update chart ports
This commit is contained in:
parent
88ec0585a7
commit
5c8481304f
@ -1,7 +1,8 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
TEMPLATE="/etc/env/env.js.template"
|
||||
# Template is in dist (copied by Dockerfile builder stage)
|
||||
TEMPLATE="/usr/share/nginx/html/env.js.template"
|
||||
TARGET="/usr/share/nginx/html/env.js"
|
||||
|
||||
if [ -f "$TEMPLATE" ]; then
|
||||
@ -16,8 +17,16 @@ window.__ENV__ = {
|
||||
EOF
|
||||
echo "✓ env.js generated at $TARGET"
|
||||
else
|
||||
echo "No env.js.template found at $TEMPLATE, skipping generation"
|
||||
echo "Warning: env.js.template not found at $TEMPLATE, creating default env.js"
|
||||
# Fallback: create env.js with default value
|
||||
: ${API_BASE:=/api}
|
||||
cat > "$TARGET" <<EOF
|
||||
window.__ENV__ = {
|
||||
API_BASE: "${API_BASE}"
|
||||
};
|
||||
EOF
|
||||
echo "✓ Default env.js created at $TARGET"
|
||||
fi
|
||||
|
||||
# Ensure ownership/permissions are OK
|
||||
# Ensure ownership/permissions are OK for nginx
|
||||
chown -R nginx:nginx /usr/share/nginx/html || true
|
||||
|
||||
@ -15,18 +15,25 @@ COPY . .
|
||||
# Build the application
|
||||
RUN npm run build
|
||||
|
||||
# Production stage
|
||||
FROM node:22-alpine
|
||||
# Copy env template to dist so it's available in production
|
||||
COPY public/env.js.template dist/env.js.template
|
||||
|
||||
WORKDIR /app
|
||||
# Production stage - use nginx to serve static files and proxy API calls
|
||||
FROM nginx:alpine
|
||||
|
||||
# Install a simple HTTP server to serve the built app
|
||||
RUN npm install -g serve
|
||||
# Copy nginx config
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
|
||||
# Copy built app from builder stage
|
||||
COPY --from=builder /app/dist ./dist
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
|
||||
EXPOSE 3000
|
||||
# Copy entrypoint script to nginx entrypoint.d directory
|
||||
# This will run before nginx starts and generate env.js from template
|
||||
COPY 10-generate-env.sh /docker-entrypoint.d/10-generate-env.sh
|
||||
|
||||
# Serve the built app
|
||||
CMD ["serve", "-s", "dist", "-l", "3000"]
|
||||
# Ensure entrypoint script is executable
|
||||
RUN chmod +x /docker-entrypoint.d/10-generate-env.sh
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
# nginx will start automatically; our script in /docker-entrypoint.d runs first
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>frontend</title>
|
||||
<!-- Load environment variables before app starts -->
|
||||
<script src="/env.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
96
manifests/my-recipes/values.yaml
Normal file
96
manifests/my-recipes/values.yaml
Normal file
@ -0,0 +1,96 @@
|
||||
global:
|
||||
namespace: my-apps
|
||||
imagePullSecrets: []
|
||||
# Backend configuration
|
||||
backend:
|
||||
name: backend
|
||||
replicaCount: 1
|
||||
image:
|
||||
repository: harbor.dvirlabs.com/my-apps/my-recipes-backend
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "master-895786b"
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 8000
|
||||
targetPort: 8000
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
env:
|
||||
PYTHONUNBUFFERED: "1"
|
||||
tag: master-895786b
|
||||
# Frontend configuration
|
||||
frontend:
|
||||
name: frontend
|
||||
replicaCount: 1
|
||||
image:
|
||||
repository: harbor.dvirlabs.com/my-apps/my-recipes-frontend
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "master-895786b"
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 80
|
||||
targetPort: 80
|
||||
env:
|
||||
API_BASE: "https://my-recipes.dvirlabs.com/api"
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
tag: master-bd31ffb
|
||||
# PostgreSQL configuration
|
||||
postgres:
|
||||
name: db
|
||||
image:
|
||||
repository: postgres
|
||||
tag: "16"
|
||||
pullPolicy: IfNotPresent
|
||||
user: recipes_user
|
||||
password: recipes_password # POC only – later use Secret/ExternalSecret
|
||||
database: recipes_db
|
||||
port: 5432
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 5432
|
||||
targetPort: 5432
|
||||
persistence:
|
||||
enabled: true
|
||||
accessMode: ReadWriteOnce
|
||||
storageClass: "nfs-client"
|
||||
size: 8Gi
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
cpu: 1000m
|
||||
memory: 1Gi
|
||||
# Ingress (top-level, maps frontend/backend paths)
|
||||
ingress:
|
||||
enabled: true
|
||||
className: "nginx"
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||
nginx.ingress.kubernetes.io/rewrite-target: "/$2"
|
||||
nginx.ingress.kubernetes.io/use-regex: "true"
|
||||
hosts:
|
||||
- host: my-recipes.dvirlabs.com
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend: frontend
|
||||
# use a regex to capture and rewrite /api/... to /... on the backend
|
||||
- path: /api(/|$)(.*)
|
||||
pathType: ImplementationSpecific
|
||||
backend: backend
|
||||
tls:
|
||||
- secretName: recipes-tls
|
||||
hosts:
|
||||
- my-recipes.dvirlabs.com
|
||||
47
manifests/navix/values.yaml
Normal file
47
manifests/navix/values.yaml
Normal file
@ -0,0 +1,47 @@
|
||||
frontend:
|
||||
image:
|
||||
repository: harbor.dvirlabs.com/my-apps/navix-frontend
|
||||
pullPolicy: IfNotPresent
|
||||
tag: master-e56328b
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 80
|
||||
ingress:
|
||||
enabled: true
|
||||
className: traefik
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||
hosts:
|
||||
- host: navix.dvirlabs.com
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
env:
|
||||
API_BASE: "https://api-navix.dvirlabs.com/api"
|
||||
MINIO_ENDPOINT: "s3.dvirlabs.com"
|
||||
MINIO_BUCKET: "navix-icons"
|
||||
backend:
|
||||
image:
|
||||
repository: harbor.dvirlabs.com/my-apps/navix-backend
|
||||
pullPolicy: IfNotPresent
|
||||
tag: master-62a2769
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 8000
|
||||
env:
|
||||
MINIO_ACCESS_KEY: "your-access-key"
|
||||
MINIO_SECRET_KEY: "your-secret-key"
|
||||
MINIO_ENDPOINT: "s3.dvirlabs.com"
|
||||
MINIO_BUCKET: "navix-icons"
|
||||
ingress:
|
||||
enabled: true
|
||||
className: traefik
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||
hosts:
|
||||
- host: api-navix.dvirlabs.com
|
||||
paths:
|
||||
- path: /api
|
||||
pathType: Prefix
|
||||
14
my-recipes-chart/Chart.yaml
Normal file
14
my-recipes-chart/Chart.yaml
Normal file
@ -0,0 +1,14 @@
|
||||
apiVersion: v2
|
||||
name: my-recipes
|
||||
description: Complete recipe management application with PostgreSQL, FastAPI backend, and React frontend
|
||||
type: application
|
||||
version: 1.0.0
|
||||
appVersion: "1.0.0"
|
||||
keywords:
|
||||
- recipes
|
||||
- fastapi
|
||||
- react
|
||||
- postgresql
|
||||
maintainers:
|
||||
- name: Development Team
|
||||
|
||||
69
my-recipes-chart/templates/backend-deployment.yaml
Normal file
69
my-recipes-chart/templates/backend-deployment.yaml
Normal file
@ -0,0 +1,69 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-{{ .Values.backend.name }}
|
||||
namespace: {{ .Values.global.namespace }}
|
||||
labels:
|
||||
app: {{ .Release.Name }}-{{ .Values.backend.name }}
|
||||
component: backend
|
||||
spec:
|
||||
replicas: {{ .Values.backend.replicaCount }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ .Release.Name }}-{{ .Values.backend.name }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ .Release.Name }}-{{ .Values.backend.name }}
|
||||
component: backend
|
||||
spec:
|
||||
containers:
|
||||
- name: {{ .Values.backend.name }}
|
||||
image: "{{ .Values.backend.image.repository }}:{{ .Values.backend.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.backend.image.pullPolicy }}
|
||||
ports:
|
||||
- containerPort: {{ .Values.backend.service.targetPort }}
|
||||
name: http
|
||||
protocol: TCP
|
||||
env:
|
||||
{{- if .Values.backend.env }}
|
||||
{{- range $key, $value := .Values.backend.env }}
|
||||
- name: {{ $key }}
|
||||
value: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ .Release.Name }}-db-credentials
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /docs
|
||||
port: http
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 30
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /docs
|
||||
port: http
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /docs
|
||||
port: http
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 2
|
||||
resources:
|
||||
requests:
|
||||
cpu: {{ .Values.backend.resources.requests.cpu }}
|
||||
memory: {{ .Values.backend.resources.requests.memory }}
|
||||
limits:
|
||||
cpu: {{ .Values.backend.resources.limits.cpu }}
|
||||
memory: {{ .Values.backend.resources.limits.memory }}
|
||||
|
||||
17
my-recipes-chart/templates/backend-service.yaml
Normal file
17
my-recipes-chart/templates/backend-service.yaml
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-{{ .Values.backend.name }}
|
||||
namespace: {{ .Values.global.namespace }}
|
||||
labels:
|
||||
app: {{ .Release.Name }}-{{ .Values.backend.name }}
|
||||
component: backend
|
||||
spec:
|
||||
type: {{ .Values.backend.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.backend.service.port }}
|
||||
targetPort: {{ .Values.backend.service.targetPort }}
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: {{ .Release.Name }}-{{ .Values.backend.name }}
|
||||
@ -11,7 +11,6 @@ data:
|
||||
name TEXT NOT NULL,
|
||||
meal_type TEXT NOT NULL,
|
||||
time_minutes INTEGER NOT NULL,
|
||||
made_by TEXT,
|
||||
tags JSONB NOT NULL DEFAULT '[]',
|
||||
ingredients JSONB NOT NULL DEFAULT '[]',
|
||||
steps JSONB NOT NULL DEFAULT '[]',
|
||||
@ -24,9 +23,6 @@ data:
|
||||
CREATE INDEX IF NOT EXISTS idx_recipes_time_minutes
|
||||
ON recipes (time_minutes);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_recipes_made_by
|
||||
ON recipes (made_by);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_recipes_tags_jsonb
|
||||
ON recipes USING GIN (tags);
|
||||
|
||||
|
||||
13
my-recipes-chart/templates/db-secret.yaml
Normal file
13
my-recipes-chart/templates/db-secret.yaml
Normal file
@ -0,0 +1,13 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-db-credentials
|
||||
namespace: {{ .Values.global.namespace }}
|
||||
type: Opaque
|
||||
stringData:
|
||||
DB_HOST: {{ printf "%s-%s-headless.%s.svc.cluster.local" .Release.Name .Values.postgres.name .Values.global.namespace }}
|
||||
DB_PORT: "{{ .Values.postgres.port }}"
|
||||
DB_NAME: {{ .Values.postgres.database | quote }}
|
||||
DB_USER: {{ .Values.postgres.user | quote }}
|
||||
DB_PASSWORD: {{ .Values.postgres.password | quote }}
|
||||
|
||||
36
my-recipes-chart/templates/db-service.yaml
Normal file
36
my-recipes-chart/templates/db-service.yaml
Normal file
@ -0,0 +1,36 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-{{ .Values.postgres.name }}-headless
|
||||
namespace: {{ .Values.global.namespace }}
|
||||
labels:
|
||||
app: {{ .Release.Name }}-{{ .Values.postgres.name }}
|
||||
component: database
|
||||
spec:
|
||||
clusterIP: None
|
||||
selector:
|
||||
app: {{ .Release.Name }}-{{ .Values.postgres.name }}
|
||||
ports:
|
||||
- name: postgres
|
||||
port: {{ .Values.postgres.port }}
|
||||
targetPort: {{ .Values.postgres.port }}
|
||||
protocol: TCP
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-{{ .Values.postgres.name }}
|
||||
namespace: {{ .Values.global.namespace }}
|
||||
labels:
|
||||
app: {{ .Release.Name }}-{{ .Values.postgres.name }}
|
||||
component: database
|
||||
spec:
|
||||
type: {{ .Values.postgres.service.type }}
|
||||
selector:
|
||||
app: {{ .Release.Name }}-{{ .Values.postgres.name }}
|
||||
ports:
|
||||
- name: postgres
|
||||
port: {{ .Values.postgres.service.port }}
|
||||
targetPort: {{ .Values.postgres.port }}
|
||||
protocol: TCP
|
||||
|
||||
86
my-recipes-chart/templates/db-statefulset.yaml
Normal file
86
my-recipes-chart/templates/db-statefulset.yaml
Normal file
@ -0,0 +1,86 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-{{ .Values.postgres.name }}
|
||||
namespace: {{ .Values.global.namespace }}
|
||||
labels:
|
||||
app: {{ .Release.Name }}-{{ .Values.postgres.name }}
|
||||
component: database
|
||||
spec:
|
||||
serviceName: {{ .Release.Name }}-{{ .Values.postgres.name }}-headless
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ .Release.Name }}-{{ .Values.postgres.name }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ .Release.Name }}-{{ .Values.postgres.name }}
|
||||
component: database
|
||||
spec:
|
||||
containers:
|
||||
- name: postgres
|
||||
image: "{{ .Values.postgres.image.repository }}:{{ .Values.postgres.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.postgres.image.pullPolicy }}
|
||||
ports:
|
||||
- containerPort: {{ .Values.postgres.port }}
|
||||
name: postgres
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: POSTGRES_USER
|
||||
value: {{ .Values.postgres.user | quote }}
|
||||
- name: POSTGRES_PASSWORD
|
||||
value: {{ .Values.postgres.password | quote }}
|
||||
- name: POSTGRES_DB
|
||||
value: {{ .Values.postgres.database | quote }}
|
||||
- name: PGDATA
|
||||
value: /var/lib/postgresql/data/pgdata
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /var/lib/postgresql/data
|
||||
- name: init-sql
|
||||
mountPath: /docker-entrypoint-initdb.d
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- pg_isready -U {{ .Values.postgres.user }}
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- pg_isready -U {{ .Values.postgres.user }}
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 2
|
||||
resources:
|
||||
requests:
|
||||
cpu: {{ .Values.postgres.resources.requests.cpu }}
|
||||
memory: {{ .Values.postgres.resources.requests.memory }}
|
||||
limits:
|
||||
cpu: {{ .Values.postgres.resources.limits.cpu }}
|
||||
memory: {{ .Values.postgres.resources.limits.memory }}
|
||||
volumes:
|
||||
- name: init-sql
|
||||
configMap:
|
||||
name: {{ .Release.Name }}-db-schema
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: data
|
||||
spec:
|
||||
accessModes:
|
||||
- {{ .Values.postgres.persistence.accessMode }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.postgres.persistence.size }}
|
||||
{{- if .Values.postgres.persistence.storageClass }}
|
||||
storageClassName: {{ .Values.postgres.persistence.storageClass | quote }}
|
||||
{{- end }}
|
||||
|
||||
70
my-recipes-chart/templates/frontend-deployment.yaml
Normal file
70
my-recipes-chart/templates/frontend-deployment.yaml
Normal file
@ -0,0 +1,70 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-{{ .Values.frontend.name }}
|
||||
namespace: {{ .Values.global.namespace }}
|
||||
labels:
|
||||
app: {{ .Release.Name }}-{{ .Values.frontend.name }}
|
||||
component: frontend
|
||||
spec:
|
||||
replicas: {{ .Values.frontend.replicaCount }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ .Release.Name }}-{{ .Values.frontend.name }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ .Release.Name }}-{{ .Values.frontend.name }}
|
||||
component: frontend
|
||||
spec:
|
||||
containers:
|
||||
- name: {{ .Values.frontend.name }}
|
||||
image: "{{ .Values.frontend.image.repository }}:{{ .Values.frontend.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.frontend.image.pullPolicy }}
|
||||
ports:
|
||||
- containerPort: {{ .Values.frontend.service.targetPort }}
|
||||
name: http
|
||||
protocol: TCP
|
||||
{{- /* compute API_BASE: prefer frontend.env.API_BASE, else use first ingress host */}}
|
||||
{{- $apiBase := "" }}
|
||||
{{- if .Values.frontend.env.API_BASE }}
|
||||
{{- $apiBase = .Values.frontend.env.API_BASE }}
|
||||
{{- else if .Values.ingress.hosts }}
|
||||
{{- $firstHost := index .Values.ingress.hosts 0 }}
|
||||
{{- $apiBase = printf "https://%s/api" $firstHost.host }}
|
||||
{{- end }}
|
||||
env:
|
||||
- name: API_BASE
|
||||
value: {{ $apiBase | quote }}
|
||||
{{- /* include any other env vars provided in values.frontend.env (skip API_BASE to avoid duplicate) */}}
|
||||
{{- with .Values.frontend.env }}
|
||||
{{- range $key, $value := . }}
|
||||
{{- if ne $key "API_BASE" }}
|
||||
- name: {{ $key }}
|
||||
value: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 2
|
||||
resources:
|
||||
requests:
|
||||
cpu: {{ .Values.frontend.resources.requests.cpu }}
|
||||
memory: {{ .Values.frontend.resources.requests.memory }}
|
||||
limits:
|
||||
cpu: {{ .Values.frontend.resources.limits.cpu }}
|
||||
memory: {{ .Values.frontend.resources.limits.memory }}
|
||||
17
my-recipes-chart/templates/frontend-service.yaml
Normal file
17
my-recipes-chart/templates/frontend-service.yaml
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-{{ .Values.frontend.name }}
|
||||
namespace: {{ .Values.global.namespace }}
|
||||
labels:
|
||||
app: {{ .Release.Name }}-{{ .Values.frontend.name }}
|
||||
component: frontend
|
||||
spec:
|
||||
type: {{ .Values.frontend.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.frontend.service.port }}
|
||||
targetPort: {{ .Values.frontend.service.targetPort }}
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: {{ .Release.Name }}-{{ .Values.frontend.name }}
|
||||
48
my-recipes-chart/templates/ingress.yaml
Normal file
48
my-recipes-chart/templates/ingress.yaml
Normal file
@ -0,0 +1,48 @@
|
||||
{{- if .Values.ingress.enabled }}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ .Release.Name }}
|
||||
namespace: {{ .Values.global.namespace }}
|
||||
labels:
|
||||
app: {{ .Release.Name }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if .Values.ingress.className }}
|
||||
ingressClassName: {{ .Values.ingress.className }}
|
||||
{{- end }}
|
||||
{{- if .Values.ingress.tls }}
|
||||
tls:
|
||||
{{- range .Values.ingress.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- host: {{ .host | quote }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ .path }}
|
||||
pathType: {{ .pathType }}
|
||||
backend:
|
||||
service:
|
||||
{{- if eq .backend "frontend" }}
|
||||
name: {{ $.Release.Name }}-{{ $.Values.frontend.name }}
|
||||
port:
|
||||
number: {{ $.Values.frontend.service.port }}
|
||||
{{- else if eq .backend "backend" }}
|
||||
name: {{ $.Release.Name }}-{{ $.Values.backend.name }}
|
||||
port:
|
||||
number: {{ $.Values.backend.service.port }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
109
my-recipes-chart/values.yaml
Normal file
109
my-recipes-chart/values.yaml
Normal file
@ -0,0 +1,109 @@
|
||||
global:
|
||||
namespace: my-apps
|
||||
imagePullSecrets: []
|
||||
|
||||
# Backend configuration
|
||||
backend:
|
||||
name: backend
|
||||
replicaCount: 2
|
||||
image:
|
||||
repository: harbor.dvirlabs.com/my-apps/my-recipes-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"
|
||||
|
||||
# Frontend configuration
|
||||
frontend:
|
||||
name: frontend
|
||||
replicaCount: 2
|
||||
image:
|
||||
repository: harbor.dvirlabs.com/my-apps/my-recipes-frontend
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "latest"
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 80
|
||||
targetPort: 80
|
||||
|
||||
env:
|
||||
API_BASE: "https://my-recipes.dvirlabs.com/api"
|
||||
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
|
||||
# PostgreSQL configuration
|
||||
postgres:
|
||||
name: db
|
||||
image:
|
||||
repository: postgres
|
||||
tag: "16-alpine"
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
user: recipes_user
|
||||
password: recipes_password
|
||||
database: recipes_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: true
|
||||
className: "nginx"
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||
nginx.ingress.kubernetes.io/rewrite-target: "/$2"
|
||||
nginx.ingress.kubernetes.io/use-regex: "true"
|
||||
hosts:
|
||||
- host: my-recipes.dvirlabs.com
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend: frontend
|
||||
# use a regex to capture and rewrite /api/... to /... on the backend
|
||||
- path: /api(/|$)(.*)
|
||||
pathType: ImplementationSpecific
|
||||
backend: backend
|
||||
tls:
|
||||
- secretName: recipes-tls
|
||||
hosts:
|
||||
- my-recipes.dvirlabs.com
|
||||
|
||||
4
navix-chart/Chart.yaml
Normal file
4
navix-chart/Chart.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
apiVersion: v2
|
||||
name: navix
|
||||
version: 0.1.0
|
||||
description: A DevOps dashboard called Navix
|
||||
29
navix-chart/templates/backend-deployment.yaml
Normal file
29
navix-chart/templates/backend-deployment.yaml
Normal file
@ -0,0 +1,29 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: navix-backend
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: navix-backend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: navix-backend
|
||||
spec:
|
||||
containers:
|
||||
- name: backend
|
||||
image: "{{ .Values.backend.image.repository }}:{{ .Values.backend.tag }}"
|
||||
imagePullPolicy: {{ .Values.backend.image.pullPolicy }}
|
||||
ports:
|
||||
- containerPort: 8000
|
||||
env:
|
||||
- name: MINIO_ACCESS_KEY
|
||||
value: "{{ .Values.backend.env.MINIO_ACCESS_KEY }}"
|
||||
- name: MINIO_SECRET_KEY
|
||||
value: "{{ .Values.backend.env.MINIO_SECRET_KEY }}"
|
||||
- name: MINIO_ENDPOINT
|
||||
value: "{{ .Values.backend.env.MINIO_ENDPOINT }}"
|
||||
- name: MINIO_BUCKET
|
||||
value: "{{ .Values.backend.env.MINIO_BUCKET }}"
|
||||
11
navix-chart/templates/backend-service.yaml
Normal file
11
navix-chart/templates/backend-service.yaml
Normal file
@ -0,0 +1,11 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: navix-backend
|
||||
spec:
|
||||
type: {{ .Values.backend.service.type }}
|
||||
selector:
|
||||
app: navix-backend
|
||||
ports:
|
||||
- port: {{ .Values.backend.service.port }}
|
||||
targetPort: 8000
|
||||
27
navix-chart/templates/frontend-deployment.yaml
Normal file
27
navix-chart/templates/frontend-deployment.yaml
Normal file
@ -0,0 +1,27 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: navix-frontend
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: navix-frontend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: navix-frontend
|
||||
spec:
|
||||
containers:
|
||||
- name: frontend
|
||||
image: "{{ .Values.frontend.image.repository }}:{{ .Values.frontend.tag }}"
|
||||
imagePullPolicy: {{ .Values.frontend.image.pullPolicy }}
|
||||
ports:
|
||||
- containerPort: 80
|
||||
env:
|
||||
- name: API_BASE
|
||||
value: {{ .Values.frontend.env.API_BASE | quote }}
|
||||
- name: MINIO_ENDPOINT
|
||||
value: {{ .Values.frontend.env.MINIO_ENDPOINT | quote }}
|
||||
- name: MINIO_BUCKET
|
||||
value: {{ .Values.frontend.env.MINIO_BUCKET | quote }}
|
||||
11
navix-chart/templates/frontend-service.yaml
Normal file
11
navix-chart/templates/frontend-service.yaml
Normal file
@ -0,0 +1,11 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: navix-frontend
|
||||
spec:
|
||||
type: {{ .Values.frontend.service.type }}
|
||||
selector:
|
||||
app: navix-frontend
|
||||
ports:
|
||||
- port: {{ .Values.frontend.service.port }}
|
||||
targetPort: 80
|
||||
57
navix-chart/templates/ingress.yaml
Normal file
57
navix-chart/templates/ingress.yaml
Normal file
@ -0,0 +1,57 @@
|
||||
{{- if .Values.frontend.ingress.enabled }}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: navix-frontend
|
||||
annotations:
|
||||
{{- range $key, $value := .Values.frontend.ingress.annotations }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
spec:
|
||||
ingressClassName: {{ .Values.frontend.ingress.className }}
|
||||
rules:
|
||||
{{- range .Values.frontend.ingress.hosts }}
|
||||
- host: {{ .host }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ .path }}
|
||||
pathType: {{ .pathType }}
|
||||
backend:
|
||||
service:
|
||||
name: navix-frontend
|
||||
port:
|
||||
number: {{ $.Values.frontend.service.port }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
---
|
||||
|
||||
{{- if .Values.backend.ingress.enabled }}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: navix-backend
|
||||
annotations:
|
||||
{{- range $key, $value := .Values.backend.ingress.annotations }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
spec:
|
||||
ingressClassName: {{ .Values.backend.ingress.className }}
|
||||
rules:
|
||||
{{- range .Values.backend.ingress.hosts }}
|
||||
- host: {{ .host }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ .path }}
|
||||
pathType: {{ .pathType }}
|
||||
backend:
|
||||
service:
|
||||
name: navix-backend
|
||||
port:
|
||||
number: {{ $.Values.backend.service.port }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
48
navix-chart/values.yaml
Normal file
48
navix-chart/values.yaml
Normal file
@ -0,0 +1,48 @@
|
||||
frontend:
|
||||
image:
|
||||
repository: harbor.dvirlabs.com/my-apps/navix-front
|
||||
tag: latest
|
||||
pullPolicy: IfNotPresent
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 80
|
||||
ingress:
|
||||
enabled: true
|
||||
className: traefik
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||
hosts:
|
||||
- host: navix.dvirlabs.com
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
env:
|
||||
API_BASE: "https://navix.dvirlabs.com/api"
|
||||
MINIO_ENDPOINT: "s3.dvirlabs.com"
|
||||
MINIO_BUCKET: "navix-icons"
|
||||
|
||||
backend:
|
||||
image:
|
||||
repository: harbor.dvirlabs.com/my-apps/navix-back
|
||||
tag: latest
|
||||
pullPolicy: IfNotPresent
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 8000
|
||||
env:
|
||||
MINIO_ACCESS_KEY: "your-access-key"
|
||||
MINIO_SECRET_KEY: "your-secret-key"
|
||||
MINIO_ENDPOINT: "s3.dvirlabs.com"
|
||||
MINIO_BUCKET: "navix-icons"
|
||||
ingress:
|
||||
enabled: true
|
||||
className: traefik
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||
hosts:
|
||||
- host: navix.dvirlabs.com
|
||||
paths:
|
||||
- path: /api
|
||||
pathType: Prefix
|
||||
Loading…
x
Reference in New Issue
Block a user