Add new infra architecture

This commit is contained in:
Urtzi Alfaro
2026-01-19 11:55:17 +01:00
parent 21d35ea92b
commit 35f164f0cd
311 changed files with 13241 additions and 3700 deletions

View File

@@ -0,0 +1,87 @@
apiVersion: batch/v1
kind: CronJob
metadata:
name: demo-session-cleanup
namespace: bakery-ia
labels:
app: demo-cleanup
component: maintenance
spec:
schedule: "0 * * * *" # Every hour
timeZone: "Europe/Madrid"
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
concurrencyPolicy: Forbid
jobTemplate:
metadata:
labels:
app: demo-cleanup
spec:
imagePullSecrets:
- name: dockerhub-creds
template:
metadata:
labels:
app: demo-cleanup
spec:
initContainers:
- name: wait-for-migrations
image: postgres:17-alpine
command: ["sh", "-c",
"echo 'Waiting for database to be ready...' && \
until pg_isready -h demo-session-db-service -p 5432; do sleep 2; done && \
echo 'Database ready, checking for demo_sessions table...' && \
MAX_ATTEMPTS=60 && \
ATTEMPT=1 && \
until psql -h demo-session-db-service -U demo_session_user -d demo_session_db -c 'SELECT 1 FROM demo_sessions LIMIT 1;' 2>/dev/null; do \
if [ $ATTEMPT -ge $MAX_ATTEMPTS ]; then \
echo 'ERROR: demo_sessions table not created after maximum attempts'; \
exit 1; \
fi; \
echo \"Waiting for demo_sessions table to be created by migrations... (attempt $ATTEMPT/$MAX_ATTEMPTS)\"; \
ATTEMPT=$((ATTEMPT + 1)); \
sleep 5; \
done && \
echo 'demo_sessions table is ready!'"]
env:
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: database-secrets
key: DEMO_SESSION_DB_PASSWORD
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"
containers:
- name: cleanup-trigger
image: curlimages/curl:latest
command:
- sh
- -c
- |
echo "Triggering demo session cleanup..."
response=$(curl -s -w "\n%{http_code}" -X POST http://demo-session-service:8000/api/v1/demo/operations/cleanup)
http_code=$(echo "$response" | tail -n 1)
body=$(echo "$response" | sed '$d')
echo "Response: $body"
echo "HTTP Status: $http_code"
if [ "$http_code" -ge 200 ] && [ "$http_code" -lt 300 ]; then
echo "Cleanup job enqueued successfully"
exit 0
else
echo "Failed to enqueue cleanup job"
exit 1
fi
resources:
requests:
memory: "32Mi"
cpu: "10m"
limits:
memory: "64Mi"
cpu: "50m"
restartPolicy: OnFailure
activeDeadlineSeconds: 30

View File

@@ -0,0 +1,77 @@
apiVersion: v1
kind: Service
metadata:
name: demo-session-db-service
namespace: bakery-ia
labels:
app: demo-session-db
component: database
spec:
type: ClusterIP
ports:
- port: 5432
targetPort: 5432
protocol: TCP
name: postgres
selector:
app: demo-session-db
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: demo-session-db
namespace: bakery-ia
labels:
app: demo-session-db
component: database
spec:
serviceName: demo-session-db-service
replicas: 1
selector:
matchLabels:
app: demo-session-db
template:
metadata:
labels:
app: demo-session-db
component: database
spec:
containers:
- name: postgres
image: postgres:17-alpine
ports:
- containerPort: 5432
name: postgres
env:
- name: POSTGRES_DB
value: "demo_session_db"
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: database-secrets
key: DEMO_SESSION_DB_USER
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: database-secrets
key: DEMO_SESSION_DB_PASSWORD
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
volumeClaimTemplates:
- metadata:
name: postgres-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 2Gi

View File

@@ -0,0 +1,125 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-cleanup-worker
namespace: bakery-ia
labels:
app: demo-cleanup-worker
component: background-jobs
service: demo-session
spec:
replicas: 2
selector:
matchLabels:
app: demo-cleanup-worker
template:
metadata:
labels:
app: demo-cleanup-worker
component: background-jobs
service: demo-session
spec:
imagePullSecrets:
- name: dockerhub-creds
initContainers:
- name: wait-for-migrations
image: postgres:17-alpine
command: ["sh", "-c",
"echo 'Waiting for database to be ready...' && \
until pg_isready -h demo-session-db-service -p 5432; do sleep 2; done && \
echo 'Database ready, checking for demo_sessions table...' && \
MAX_ATTEMPTS=60 && \
ATTEMPT=1 && \
until psql -h demo-session-db-service -U demo_session_user -d demo_session_db -c 'SELECT 1 FROM demo_sessions LIMIT 1;' 2>/dev/null; do \
if [ $ATTEMPT -ge $MAX_ATTEMPTS ]; then \
echo 'ERROR: demo_sessions table not created after maximum attempts'; \
exit 1; \
fi; \
echo \"Waiting for demo_sessions table to be created by migrations... (attempt $ATTEMPT/$MAX_ATTEMPTS)\"; \
ATTEMPT=$((ATTEMPT + 1)); \
sleep 5; \
done && \
echo 'demo_sessions table is ready!'"]
env:
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: database-secrets
key: DEMO_SESSION_DB_PASSWORD
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"
containers:
- name: worker
image: bakery/demo-session-service
imagePullPolicy: IfNotPresent
command:
- python
- -m
- app.jobs.cleanup_worker
env:
- name: DEMO_SESSION_DATABASE_URL
valueFrom:
secretKeyRef:
name: database-secrets
key: DEMO_SESSION_DATABASE_URL
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: redis-secrets
key: REDIS_PASSWORD
- name: REDIS_URL
value: "rediss://:$(REDIS_PASSWORD)@redis-service:6379/0?ssl_cert_reqs=none"
- name: LOG_LEVEL
value: "INFO"
- name: INVENTORY_SERVICE_URL
value: "http://inventory-service:8000"
- name: RECIPES_SERVICE_URL
value: "http://recipes-service:8000"
- name: SALES_SERVICE_URL
value: "http://sales-service:8000"
- name: ORDERS_SERVICE_URL
value: "http://orders-service:8000"
- name: PRODUCTION_SERVICE_URL
value: "http://production-service:8000"
- name: SUPPLIERS_SERVICE_URL
value: "http://suppliers-service:8000"
- name: POS_SERVICE_URL
value: "http://pos-service:8000"
- name: PROCUREMENT_SERVICE_URL
value: "http://procurement-service:8000"
- name: DISTRIBUTION_SERVICE_URL
value: "http://distribution-service:8000"
- name: FORECASTING_SERVICE_URL
value: "http://forecasting-service:8000"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
exec:
command:
- python
- -c
- "import sys; sys.exit(0)"
initialDelaySeconds: 30
periodSeconds: 60
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
exec:
command:
- python
- -c
- "import sys; sys.exit(0)"
initialDelaySeconds: 10
periodSeconds: 30
timeoutSeconds: 5
restartPolicy: Always

View File

@@ -0,0 +1,135 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-session-service
namespace: bakery-ia
labels:
app: demo-session-service
component: demo-session
spec:
replicas: 2
selector:
matchLabels:
app: demo-session-service
template:
metadata:
labels:
app: demo-session-service
component: demo-session
spec:
serviceAccountName: demo-session-sa
containers:
- name: demo-session-service
image: bakery/demo-session-service:latest
ports:
- containerPort: 8000
name: http
envFrom:
- configMapRef:
name: bakery-config
env:
- name: SERVICE_NAME
value: "demo-session-service"
- name: ALERT_PROCESSOR_SERVICE_URL
value: "http://alert-processor:8000"
- name: DEMO_SESSION_DATABASE_URL
valueFrom:
secretKeyRef:
name: database-secrets
key: DEMO_SESSION_DATABASE_URL
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: redis-secrets
key: REDIS_PASSWORD
- name: REDIS_URL
value: "rediss://:$(REDIS_PASSWORD)@redis-service:6379/0?ssl_cert_reqs=none"
- name: AUTH_SERVICE_URL
value: "http://auth-service:8000"
- name: TENANT_SERVICE_URL
value: "http://tenant-service:8000"
- name: INVENTORY_SERVICE_URL
value: "http://inventory-service:8000"
- name: RECIPES_SERVICE_URL
value: "http://recipes-service:8000"
- name: SALES_SERVICE_URL
value: "http://sales-service:8000"
- name: ORDERS_SERVICE_URL
value: "http://orders-service:8000"
- name: PRODUCTION_SERVICE_URL
value: "http://production-service:8000"
- name: SUPPLIERS_SERVICE_URL
value: "http://suppliers-service:8000"
- name: LOG_LEVEL
value: "INFO"
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
resources:
requests:
memory: "256Mi"
cpu: "200m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 30
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 10
periodSeconds: 10
startupProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 30
initContainers:
- name: wait-for-redis
image: busybox:1.36
command: ['sh', '-c', 'until nc -z redis-service 6379; do echo waiting for redis; sleep 2; done']
- name: wait-for-migrations
image: postgres:17-alpine
command: ["sh", "-c",
"echo 'Waiting for database to be ready...' && \
until pg_isready -h demo-session-db-service -p 5432; do sleep 2; done && \
echo 'Database ready, checking for demo_sessions table...' && \
MAX_ATTEMPTS=60 && \
ATTEMPT=1 && \
while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do \
if psql -h demo-session-db-service -U demo_session_user -d demo_session_db -c 'SELECT 1 FROM demo_sessions LIMIT 1;' 2>/dev/null; then \
break; \
fi; \
echo \"Waiting for demo_sessions table to be created by migrations... (attempt $ATTEMPT/$MAX_ATTEMPTS)\"; \
ATTEMPT=$((ATTEMPT + 1)); \
sleep 5; \
done && \
if [ $ATTEMPT -gt $MAX_ATTEMPTS ]; then \
echo 'ERROR: demo_sessions table not created after maximum attempts'; \
exit 1; \
fi && \
echo 'demo_sessions table is ready!' && \
echo 'Checking if table has required columns...' && \
psql -h demo-session-db-service -U demo_session_user -d demo_session_db -c '\\d demo_sessions' && \
echo 'Table structure verified!'"]
env:
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: database-secrets
key: DEMO_SESSION_DB_PASSWORD
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"

View File

@@ -0,0 +1,135 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-session-service
namespace: bakery-ia
labels:
app: demo-session-service
component: demo-session
spec:
replicas: 2
selector:
matchLabels:
app: demo-session-service
template:
metadata:
labels:
app: demo-session-service
component: demo-session
spec:
serviceAccountName: demo-session-sa
containers:
- name: demo-session-service
image: bakery/demo-session-service:latest
ports:
- containerPort: 8000
name: http
envFrom:
- configMapRef:
name: bakery-config
env:
- name: SERVICE_NAME
value: "demo-session-service"
- name: ALERT_PROCESSOR_SERVICE_URL
value: "http://alert-processor:8000"
- name: DEMO_SESSION_DATABASE_URL
valueFrom:
secretKeyRef:
name: database-secrets
key: DEMO_SESSION_DATABASE_URL
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: redis-secrets
key: REDIS_PASSWORD
- name: REDIS_URL
value: "rediss://:$(REDIS_PASSWORD)@redis-service:6379/0?ssl_cert_reqs=none"
- name: AUTH_SERVICE_URL
value: "http://auth-service:8000"
- name: TENANT_SERVICE_URL
value: "http://tenant-service:8000"
- name: INVENTORY_SERVICE_URL
value: "http://inventory-service:8000"
- name: RECIPES_SERVICE_URL
value: "http://recipes-service:8000"
- name: SALES_SERVICE_URL
value: "http://sales-service:8000"
- name: ORDERS_SERVICE_URL
value: "http://orders-service:8000"
- name: PRODUCTION_SERVICE_URL
value: "http://production-service:8000"
- name: SUPPLIERS_SERVICE_URL
value: "http://suppliers-service:8000"
- name: LOG_LEVEL
value: "INFO"
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
resources:
requests:
memory: "256Mi"
cpu: "200m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 30
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 10
periodSeconds: 10
startupProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 30
initContainers:
- name: wait-for-redis
image: busybox:1.36
command: ['sh', '-c', 'until nc -z redis-service 6379; do echo waiting for redis; sleep 2; done']
- name: wait-for-migrations
image: localhost:5000/postgres_17-alpine
command: ["sh", "-c",
"echo 'Waiting for database to be ready...' && \
until pg_isready -h demo-session-db-service -p 5432; do sleep 2; done && \
echo 'Database ready, checking for demo_sessions table...' && \
MAX_ATTEMPTS=60 && \
ATTEMPT=1 && \
while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do \
if psql -h demo-session-db-service -U demo_session_user -d demo_session_db -c 'SELECT 1 FROM demo_sessions LIMIT 1;' 2>/dev/null; then \
break; \
fi; \
echo \"Waiting for demo_sessions table to be created by migrations... (attempt $ATTEMPT/$MAX_ATTEMPTS)\"; \
ATTEMPT=$((ATTEMPT + 1)); \
sleep 5; \
done && \
if [ $ATTEMPT -gt $MAX_ATTEMPTS ]; then \
echo 'ERROR: demo_sessions table not created after maximum attempts'; \
exit 1; \
fi && \
echo 'demo_sessions table is ready!' && \
echo 'Checking if table has required columns...' && \
psql -h demo-session-db-service -U demo_session_user -d demo_session_db -c '\\d demo_sessions' && \
echo 'Table structure verified!'"]
env:
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: database-secrets
key: DEMO_SESSION_DB_PASSWORD
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"

View File

@@ -0,0 +1,32 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: demo-seed-sa
namespace: bakery-ia
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: demo-seed-role
namespace: bakery-ia
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: demo-seed-rolebinding
namespace: bakery-ia
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: demo-seed-role
subjects:
- kind: ServiceAccount
name: demo-seed-sa
namespace: bakery-ia

View File

@@ -0,0 +1,56 @@
apiVersion: batch/v1
kind: Job
metadata:
name: demo-session-migration
namespace: bakery-ia
labels:
app.kubernetes.io/name: demo-session-migration
app.kubernetes.io/component: migration
app.kubernetes.io/part-of: bakery-ia
spec:
backoffLimit: 3
template:
metadata:
labels:
app.kubernetes.io/name: demo-session-migration
app.kubernetes.io/component: migration
spec:
imagePullSecrets:
- name: dockerhub-creds
initContainers:
- name: wait-for-db
image: postgres:17-alpine
command: ["sh", "-c", "until pg_isready -h demo-session-db-service -p 5432; do sleep 2; done"]
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"
containers:
- name: migrate
image: bakery/demo-session-service
command: ["python", "/app/shared/scripts/run_migrations.py", "demo_session"]
env:
- name: DEMO_SESSION_DATABASE_URL
valueFrom:
secretKeyRef:
name: database-secrets
key: DEMO_SESSION_DATABASE_URL
- name: DB_FORCE_RECREATE
valueFrom:
configMapKeyRef:
name: bakery-config
key: DB_FORCE_RECREATE
optional: true
- name: LOG_LEVEL
value: "INFO"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
restartPolicy: OnFailure

View File

@@ -0,0 +1,35 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: demo-session-sa
namespace: bakery-ia
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: demo-session-job-creator
namespace: bakery-ia
rules:
- apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["create", "get", "list", "watch", "delete"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: demo-session-job-creator-binding
namespace: bakery-ia
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: demo-session-job-creator
subjects:
- kind: ServiceAccount
name: demo-session-sa
namespace: bakery-ia

View File

@@ -0,0 +1,17 @@
apiVersion: v1
kind: Service
metadata:
name: demo-session-service
namespace: bakery-ia
labels:
app: demo-session-service
component: demo-session
spec:
type: ClusterIP
ports:
- port: 8000
targetPort: 8000
protocol: TCP
name: http
selector:
app: demo-session-service