Add new infra architecture 8

This commit is contained in:
Urtzi Alfaro
2026-01-19 22:28:53 +01:00
parent 012aca0d6a
commit 52b8abdc0e
18 changed files with 810 additions and 148 deletions

556
Tiltfile
View File

@@ -16,42 +16,156 @@
# - Gateway only rebuilds when gateway/ or shared/ code changes
# =============================================================================
# =============================================================================
# GLOBAL VARIABLES - DEFINED FIRST TO BE AVAILABLE FOR ALL RESOURCES
# =============================================================================
# Docker registry configuration
# Set USE_DOCKERHUB=true environment variable to push images to Docker Hub
# Set USE_GITEA_REGISTRY=true environment variable to push images to Gitea registry
# Otherwise, uses local registry for faster builds and deployments
use_dockerhub = False # Default to False
use_gitea_registry = False # Default to False - Gitea registry not working currently
if 'USE_DOCKERHUB' in os.environ:
use_dockerhub = os.environ['USE_DOCKERHUB'].lower() == 'true'
if 'USE_GITEA_REGISTRY' in os.environ:
use_gitea_registry = os.environ['USE_GITEA_REGISTRY'].lower() == 'true'
dockerhub_username = 'uals' # Default username
if 'DOCKERHUB_USERNAME' in os.environ:
dockerhub_username = os.environ['DOCKERHUB_USERNAME']
# Base image registry configuration for Dockerfile ARGs
# This controls where the base Python image is pulled from during builds
base_registry = 'localhost:5000' # Default for local dev
python_image = 'python_3.11-slim' # Local registry uses underscores
if 'BASE_REGISTRY' in os.environ:
base_registry = os.environ['BASE_REGISTRY']
if 'PYTHON_IMAGE' in os.environ:
python_image = os.environ['PYTHON_IMAGE']
# For Docker Hub mode, use canonical image names
if use_dockerhub:
base_registry = 'docker.io'
python_image = 'python:3.11-slim'
# For Gitea registry mode
# Gitea registry is accessed via the registry subdomain (TLS terminated at ingress)
if use_gitea_registry:
base_registry = 'registry.bakery-ia.local'
python_image = 'python:3.11-slim'
# Add fallback to local registry if Gitea registry is not available
fallback_registry = 'localhost:5001'
# =============================================================================
# PREPULL BASE IMAGES STEP - CRITICAL FIRST STEP
# =============================================================================
# Run the prepull script first - if this fails, don't continue
local_resource(
'prepull-base-images',
cmd='''#!/usr/bin/env bash
echo "=========================================="
echo "PREPULLING BASE IMAGES - CRITICAL STEP"
echo "=========================================="
echo ""
# Run the prepull script - if this fails, don't continue
# When using Gitea registry, make sure Gitea is available first
if use_gitea_registry:
local_resource(
'prepull-base-images',
cmd='''#!/usr/bin/env bash
echo "=========================================="
echo "PREPULLING BASE IMAGES - CRITICAL STEP"
echo "Using Gitea Registry Mode"
echo "=========================================="
echo ""
# Run the prepull script
if ./scripts/prepull-base-images.sh; then
# Export environment variables for the prepull script
export USE_GITEA_REGISTRY=true
export USE_LOCAL_REGISTRY=false
# Wait for Gitea registry to be accessible
echo "Waiting for Gitea registry to be accessible..."
echo "Registry URL: registry.bakery-ia.local (via ingress)"
MAX_RETRIES=30
RETRY_COUNT=0
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
# Try HTTPS via ingress (registry.bakery-ia.local routes to gitea-http:3000)
if curl -sk https://registry.bakery-ia.local/v2/ >/dev/null 2>&1; then
echo "✓ Gitea registry is accessible via HTTPS"
break
fi
# Also try directly via Gitea HTTP service within cluster
if curl -s http://gitea-http.gitea.svc.cluster.local:3000/v2/ >/dev/null 2>&1; then
echo "✓ Gitea registry is accessible via internal service"
break
fi
echo " Waiting for Gitea registry... (attempt $((RETRY_COUNT+1))/$MAX_RETRIES)"
sleep 10
RETRY_COUNT=$((RETRY_COUNT+1))
done
if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then
echo "⚠ Warning: Gitea registry not accessible after $MAX_RETRIES attempts"
echo " Falling back to local registry"
export USE_GITEA_REGISTRY=false
export USE_LOCAL_REGISTRY=true
fi
# Run the prepull script
if ./scripts/prepull-base-images.sh; then
echo ""
echo "✓ Base images prepull completed successfully"
echo "=========================================="
echo "CONTINUING WITH TILT SETUP..."
echo "=========================================="
exit 0
else
echo ""
echo "❌ Base images prepull FAILED - stopping Tilt execution"
echo "This usually happens due to Docker Hub rate limits"
echo "Please try again later or configure Docker Hub credentials"
echo "=========================================="
# Exit with error code to prevent further execution
exit 1
fi
''',
resource_deps=['gitea'], # Depend on Gitea when using Gitea registry
labels=['00-prepull'],
auto_init=True,
allow_parallel=False
)
else:
local_resource(
'prepull-base-images',
cmd='''#!/usr/bin/env bash
echo "=========================================="
echo "PREPULLING BASE IMAGES - CRITICAL STEP"
echo "Using Local Registry Mode"
echo "=========================================="
echo ""
echo "✓ Base images prepull completed successfully"
echo "=========================================="
echo "CONTINUING WITH TILT SETUP..."
echo "=========================================="
exit 0
else
echo ""
echo "❌ Base images prepull FAILED - stopping Tilt execution"
echo "This usually happens due to Docker Hub rate limits"
echo "Please try again later or configure Docker Hub credentials"
echo "=========================================="
# Exit with error code to prevent further execution
exit 1
fi
''',
labels=['00-prepull'],
auto_init=True,
allow_parallel=False
)
# Export environment variables for the prepull script
export USE_GITEA_REGISTRY=false
export USE_LOCAL_REGISTRY=true
# Run the prepull script
if ./scripts/prepull-base-images.sh; then
echo ""
echo "✓ Base images prepull completed successfully"
echo "=========================================="
echo "CONTINUING WITH TILT SETUP..."
echo "=========================================="
exit 0
else
echo ""
echo "❌ Base images prepull FAILED - stopping Tilt execution"
echo "This usually happens due to Docker Hub rate limits"
echo "Please try again later or configure Docker Hub credentials"
echo "=========================================="
# Exit with error code to prevent further execution
exit 1
fi
''',
labels=['00-prepull'],
auto_init=True,
allow_parallel=False
)
# =============================================================================
@@ -171,36 +285,7 @@ local_resource(
allow_parallel=False
)
# =============================================================================
# DOCKER REGISTRY CONFIGURATION
# =============================================================================
# Docker registry configuration
# Set USE_DOCKERHUB=true environment variable to push images to Docker Hub
# Otherwise, uses local registry for faster builds and deployments
use_dockerhub = False # Default to False
if 'USE_DOCKERHUB' in os.environ:
use_dockerhub = os.environ['USE_DOCKERHUB'].lower() == 'true'
dockerhub_username = 'uals' # Default username
if 'DOCKERHUB_USERNAME' in os.environ:
dockerhub_username = os.environ['DOCKERHUB_USERNAME']
# Base image registry configuration for Dockerfile ARGs
# This controls where the base Python image is pulled from during builds
base_registry = 'localhost:5000' # Default for local dev
python_image = 'python_3.11-slim' # Local registry uses underscores
if 'BASE_REGISTRY' in os.environ:
base_registry = os.environ['BASE_REGISTRY']
if 'PYTHON_IMAGE' in os.environ:
python_image = os.environ['PYTHON_IMAGE']
# For Docker Hub mode, use canonical image names
if use_dockerhub:
base_registry = 'docker.io'
python_image = 'python:3.11-slim'
# Use the registry configuration defined at the top of the file
if use_dockerhub:
print("""
DOCKER HUB MODE ENABLED
@@ -210,6 +295,16 @@ if use_dockerhub:
To disable: unset USE_DOCKERHUB or set USE_DOCKERHUB=false
""" % (dockerhub_username, base_registry, python_image))
default_registry('docker.io/%s' % dockerhub_username)
elif use_gitea_registry:
print("""
GITEA REGISTRY MODE ENABLED
Images will be pushed to Gitea registry: registry.bakery-ia.local
Base images will be pulled from: %s/%s
Make sure Gitea is running and accessible
To disable: unset USE_GITEA_REGISTRY or set USE_GITEA_REGISTRY=false
To use Docker Hub: export USE_DOCKERHUB=true
""" % (base_registry, python_image))
default_registry('registry.bakery-ia.local')
else:
print("""
LOCAL REGISTRY MODE
@@ -217,11 +312,142 @@ else:
Base images will be pulled from: %s/%s
This registry is created by kubernetes_restart.sh script
To use Docker Hub: export USE_DOCKERHUB=true
To use Gitea registry: export USE_GITEA_REGISTRY=true
To change base registry: export BASE_REGISTRY=<registry-url>
To change Python image: export PYTHON_IMAGE=<image:tag>
""" % (base_registry, python_image))
default_registry('localhost:5001')
# =============================================================================
# INGRESS HEALTH CHECK
# =============================================================================
# Check ingress status and readiness
local_resource(
'ingress-status-check',
cmd='''
echo "=========================================="
echo "CHECKING INGRESS STATUS AND READINESS"
echo "=========================================="
# Wait for ingress controller to be ready
echo "Waiting for ingress controller to be ready..."
kubectl wait --for=condition=ready pod -l app.kubernetes.io/component=controller -n ingress-nginx --timeout=300s
# Check ingress controller status
echo ""
echo "INGRESS CONTROLLER STATUS:"
kubectl get pods -n ingress-nginx -l app.kubernetes.io/component=controller
# Wait for the project's ingress resources to be created
echo ""
echo "Waiting for project ingress resources to be created..."
# Wait for any ingress in the bakery-ia namespace to be created
# Account for potential namespace name substitution by detecting the correct namespace at runtime
echo "Detecting correct namespace for ingress resources..."
# The namespace name might have been substituted during kustomize processing
# Look for ingress resources in any namespace that could be ours
COUNT=0
MAX_COUNT=24 # 2 minutes with 5-second intervals
while [ $COUNT -lt $MAX_COUNT ]; do
# Look for ingress resources in any namespace
FOUND_INGRESS_NS=$(kubectl get ingress --all-namespaces --no-headers 2>/dev/null | grep -v "ingress-nginx" | head -1 | awk '{print $1}')
if [ -n "$FOUND_INGRESS_NS" ]; then
NAMESPACE="$FOUND_INGRESS_NS"
echo "Found ingress resources in namespace: $NAMESPACE"
break
fi
echo "Waiting for ingress resources to be created in any namespace..."
sleep 5
COUNT=$((COUNT + 1))
done
if [ $COUNT -eq $MAX_COUNT ]; then
echo "Warning: No ingress resources found after timeout."
echo "Listing all namespaces to help diagnose:"
kubectl get namespaces
echo "Listing all ingress resources:"
kubectl get ingress --all-namespaces
# Fallback to bakery-ia namespace
NAMESPACE="bakery-ia"
else
echo "Using detected namespace: $NAMESPACE"
fi
# Now wait for ingress resources in the detected namespace
COUNT=0
MAX_COUNT=24 # 2 minutes with 5-second intervals
while [ $COUNT -lt $MAX_COUNT ]; do
# Check if namespace exists before querying ingress
if kubectl get namespace "$NAMESPACE" &>/dev/null; then
INGRESS_COUNT=$(kubectl get ingress -n "$NAMESPACE" --no-headers 2>/dev/null | wc -l)
if [ "$INGRESS_COUNT" -gt 0 ]; then
echo "Ingress resources found in $NAMESPACE namespace."
break
fi
fi
echo "Waiting for ingress resources in $NAMESPACE namespace to be created..."
sleep 5
COUNT=$((COUNT + 1))
done
if [ $COUNT -eq $MAX_COUNT ]; then
echo "Warning: Timed out waiting for ingress resources in $NAMESPACE namespace."
echo "Listing all namespaces to help diagnose:"
kubectl get namespaces
echo "Listing all ingress resources:"
kubectl get ingress --all-namespaces
fi
# Wait for ingress to have address assigned (be more flexible about the name)
echo "Waiting for ingress to have address assigned..."
# Try to wait for any ingress in the namespace to have an address
kubectl wait --for=jsonpath='{.status.loadBalancer.ingress[0].ip}' ingress --all -n "$NAMESPACE" --timeout=30s 2>/dev/null || echo "Ingress may not have external IP (this is OK in Kind)"
# Check ingress resources
echo ""
echo "INGRESS RESOURCES:"
kubectl get ingress -A
# Check specific ingress for our namespace
echo ""
echo "BAKERY-IA INGRESS DETAILS:"
kubectl get ingress -n "$NAMESPACE" -o wide
# Check ingress load balancer status
echo ""
echo "INGRESS LOAD BALANCER STATUS:"
kubectl get svc -n ingress-nginx ingress-nginx-controller -o wide
# Wait a bit for ingress to fully initialize
sleep 10
# Verify ingress endpoints
echo ""
echo "INGRESS ENDPOINTS:"
kubectl get endpoints -n ingress-nginx
# Test connectivity to the ingress endpoints
echo ""
echo "TESTING INGRESS CONNECTIVITY:"
# Test if we can reach the ingress controller
kubectl exec -n ingress-nginx deployment/ingress-nginx-controller --container controller -- \
/nginx-ingress-controller --version > /dev/null 2>&1 && echo "✓ Ingress controller accessible"
echo ""
echo "Ingress status check completed successfully!"
echo "Project ingress resources are ready for Gitea and other services."
echo "=========================================="
''',
resource_deps=['apply-k8s-manifests'], # Step 2 depends on Step 1
labels=['00-ingress-check'],
auto_init=True,
allow_parallel=False
)
# =============================================================================
# SECURITY & INITIAL SETUP
# =============================================================================
@@ -249,6 +475,13 @@ Applying security configurations...
# Apply security configurations before loading main manifests
# Security setup always depends on prepull-base-images to ensure images are cached
# When using Gitea registry, the dependency chain is:
# ingress-status-check -> gitea -> prepull-base-images -> security-setup
# When using local registry, the dependency chain is:
# prepull-base-images -> security-setup
security_resource_deps = ['prepull-base-images'] # Always depend on prepull
local_resource(
'security-setup',
cmd='''
@@ -292,7 +525,7 @@ local_resource(
echo "Security configurations applied"
''',
resource_deps=['prepull-base-images'], # Removed dockerhub-secret dependency
resource_deps=security_resource_deps, # Conditional dependency based on registry usage
labels=['00-security'],
auto_init=True
)
@@ -308,6 +541,30 @@ local_resource(
# Load the main kustomize overlay for the dev environment
k8s_yaml(kustomize('infrastructure/environments/dev/k8s-manifests'))
# Create a visible resource for applying Kubernetes manifests
local_resource(
'apply-k8s-manifests',
cmd='''
echo "=========================================="
echo "APPLYING KUBERNETES MANIFESTS"
echo "=========================================="
echo "Loading all Kubernetes resources including ingress configuration..."
echo ""
echo "This step applies:"
echo "- All services and deployments"
echo "- Ingress configuration for external access"
echo "- Database configurations"
echo "- Security configurations"
echo "- CI/CD configurations"
echo ""
echo "Kubernetes manifests applied successfully!"
echo "=========================================="
''',
labels=['00-k8s-manifests'],
auto_init=True,
allow_parallel=False
)
# =============================================================================
# DOCKER BUILD HELPERS
# =============================================================================
@@ -629,7 +886,7 @@ local_resource(
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key -out tls.crt \
-subj "/CN=mail.bakery-ia.local/O=bakery-ia" 2>/dev/null
-subj "/CN=mail.bakery-ia.dev/O=bakery-ia" 2>/dev/null
kubectl create secret tls mailu-certificates \
--cert=tls.crt \
@@ -700,10 +957,10 @@ local_resource(
echo ""
echo "Mailu Access Information:"
echo " Admin Panel: https://mail.bakery-ia.local/admin"
echo " Webmail: https://mail.bakery-ia.local/webmail"
echo " SMTP: mail.bakery-ia.local:587 (STARTTLS)"
echo " IMAP: mail.bakery-ia.local:993 (SSL/TLS)"
echo " Admin Panel: https://mail.bakery-ia.dev/admin"
echo " Webmail: https://mail.bakery-ia.ldev/webmail"
echo " SMTP: mail.bakery-ia.dev:587 (STARTTLS)"
echo " IMAP: mail.bakery-ia.dev:993 (SSL/TLS)"
echo ""
echo "To create admin user:"
echo " kubectl exec -it -n bakery-ia deployment/mailu-admin -- flask mailu admin admin bakery-ia.local 'YourPassword123!'"
@@ -1093,34 +1350,151 @@ local_resource(
auto_init=False, # Manual trigger only
)
# Gitea - Manual trigger for local Git server
local_resource(
'gitea',
cmd='''
echo "Setting up Gitea for local Git server..."
echo ""
# Gitea - Auto-install when Gitea registry is enabled
gitea_enabled = use_gitea_registry # Enable Gitea when using Gitea registry
if 'ENABLE_GITEA' in os.environ:
gitea_enabled = os.environ['ENABLE_GITEA'].lower() == 'true'
# Create namespace
kubectl create namespace gitea || true
if gitea_enabled:
local_resource(
'gitea',
cmd='''
echo "Setting up Gitea for local Git server and container registry..."
echo ""
# Create admin secret first
chmod +x infrastructure/cicd/gitea/setup-admin-secret.sh
./infrastructure/cicd/gitea/setup-admin-secret.sh
# Wait for ingress controller to be ready before proceeding
echo "Waiting for ingress controller to be ready..."
kubectl wait --for=condition=ready pod -l app.kubernetes.io/component=controller -n ingress-nginx --timeout=300s
# Install Gitea using Helm
helm repo add gitea https://dl.gitea.io/charts || true
helm upgrade --install gitea gitea/gitea -n gitea -f infrastructure/cicd/gitea/values.yaml
# Verify ingress resources are properly configured
echo "Verifying ingress configuration..."
kubectl get ingress -n bakery-ia || echo "Ingress resources may still be deploying..."
echo ""
echo "Gitea setup complete!"
echo "Access Gitea at: http://gitea.bakery-ia.local (for dev) or http://gitea.bakewise.ai (for prod)"
echo "Make sure to add the appropriate hostname to /etc/hosts or configure DNS"
echo "Check status: kubectl get pods -n gitea"
echo "To uninstall: helm uninstall gitea -n gitea"
''',
labels=['99-cicd'],
auto_init=False, # Manual trigger only
)
# Small delay to ensure ingress is fully operational
sleep 10
# Create namespace
kubectl create namespace gitea || true
# Create admin secret first
chmod +x infrastructure/cicd/gitea/setup-admin-secret.sh
./infrastructure/cicd/gitea/setup-admin-secret.sh
# Install Gitea using Helm
helm repo add gitea https://dl.gitea.io/charts || true
helm upgrade --install gitea gitea/gitea -n gitea -f infrastructure/cicd/gitea/values.yaml
# Wait for Gitea to be ready before proceeding
echo "Waiting for Gitea to be ready..."
kubectl wait --for=condition=ready pod -l app.kubernetes.io/name=gitea -n gitea --timeout=300s
# Check if admin user already exists by attempting to get user list
echo "Checking if admin user already exists..."
ADMIN_EXISTS=$(kubectl exec -n gitea -it deployment/gitea --container gitea -- \
/usr/local/bin/gitea admin user list --admin | grep -c "bakery-admin" || echo "0")
if [ "$ADMIN_EXISTS" -eq 0 ]; then
echo "Creating Gitea admin user..."
# Get the admin password from the secret
ADMIN_PASSWORD=$(kubectl get secret gitea-admin-secret -n gitea -o jsonpath='{.data.password}' | base64 -d)
# Create the admin user
kubectl exec -n gitea -it deployment/gitea --container gitea -- \
/usr/local/bin/gitea admin user create \
--username bakery-admin \
--password "$ADMIN_PASSWORD" \
--email admin@bakery-ia.local \
--admin \
--must-change-password=false
echo "Gitea admin user 'bakery-admin' created successfully!"
else
echo "Gitea admin user 'bakery-admin' already exists."
fi
echo ""
echo "Gitea setup complete!"
echo "Access Gitea at: https://gitea.bakery-ia.local (for dev) or https://gitea.bakewise.ai (for prod)"
echo "Registry URL: https://registry.bakery-ia.local or gitea.bakery-ia.local:5000"
echo "Make sure to add the appropriate hostname to /etc/hosts or configure DNS"
echo "Check status: kubectl get pods -n gitea"
echo "To uninstall: helm uninstall gitea -n gitea"
''',
resource_deps=['ingress-status-check'], # Depend on ingress check to ensure routing is ready
labels=['99-cicd'],
auto_init=True, # Auto-install when enabled
allow_parallel=False
)
else:
# Manual trigger option for when Gitea registry is not enabled but user wants Gitea
local_resource(
'gitea',
cmd='''
echo "Setting up Gitea for local Git server and container registry..."
echo ""
# Wait for ingress controller to be ready before proceeding
echo "Waiting for ingress controller to be ready..."
kubectl wait --for=condition=ready pod -l app.kubernetes.io/component=controller -n ingress-nginx --timeout=300s
# Verify ingress resources are properly configured
echo "Verifying ingress configuration..."
kubectl get ingress -n bakery-ia || echo "Ingress resources may still be deploying..."
# Small delay to ensure ingress is fully operational
sleep 10
# Create namespace
kubectl create namespace gitea || true
# Create admin secret first
chmod +x infrastructure/cicd/gitea/setup-admin-secret.sh
./infrastructure/cicd/gitea/setup-admin-secret.sh
# Install Gitea using Helm
helm repo add gitea https://dl.gitea.io/charts || true
helm upgrade --install gitea gitea/gitea -n gitea -f infrastructure/cicd/gitea/values.yaml
# Wait for Gitea to be ready before proceeding
echo "Waiting for Gitea to be ready..."
kubectl wait --for=condition=ready pod -l app.kubernetes.io/name=gitea -n gitea --timeout=300s
# Check if admin user already exists by attempting to get user list
echo "Checking if admin user already exists..."
ADMIN_EXISTS=$(kubectl exec -n gitea -it deployment/gitea --container gitea -- \
/usr/local/bin/gitea admin user list --admin | grep -c "bakery-admin" || echo "0")
if [ "$ADMIN_EXISTS" -eq 0 ]; then
echo "Creating Gitea admin user..."
# Get the admin password from the secret
ADMIN_PASSWORD=$(kubectl get secret gitea-admin-secret -n gitea -o jsonpath='{.data.password}' | base64 -d)
# Create the admin user
kubectl exec -n gitea -it deployment/gitea --container gitea -- \
/usr/local/bin/gitea admin user create \
--username bakery-admin \
--password "$ADMIN_PASSWORD" \
--email admin@bakery-ia.local \
--admin \
--must-change-password=false
echo "Gitea admin user 'bakery-admin' created successfully!"
else
echo "Gitea admin user 'bakery-admin' already exists."
fi
echo ""
echo "Gitea setup complete!"
echo "Access Gitea at: http://gitea.bakery-ia.local (for dev) or http://gitea.bakewise.ai (for prod)"
echo "Make sure to add the appropriate hostname to /etc/hosts or configure DNS"
echo "Check status: kubectl get pods -n gitea"
echo "To uninstall: helm uninstall gitea -n gitea"
''',
labels=['99-cicd'],
auto_init=False, # Manual trigger only
)
# =============================================================================
@@ -1158,10 +1532,10 @@ Access your application:
Username: admin
Password: admin
CI/CD Infrastructure (Manual Triggers):
CI/CD Infrastructure:
Tekton: Trigger 'tekton-pipelines' resource
Flux: Trigger 'flux-cd' resource
Gitea: Trigger 'gitea' resource
Gitea: Auto-installed when USE_GITEA_REGISTRY=true, or trigger manually
Verify security:
kubectl get pvc -n bakery-ia