first commit

This commit is contained in:
David 2025-08-03 02:44:38 +02:00
commit dc9da64778
7 changed files with 660 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

145
k8s/backend.yaml Normal file
View File

@ -0,0 +1,145 @@
apiVersion: v1
kind: Secret
metadata:
name: backend-secret
namespace: xpeditis
type: Opaque
data:
# Base64 encoded JWT secret
JWT_SECRET: eHBlZGl0aXMtcHJvZC1zZWNyZXQta2V5LWNoYW5nZS1pbi1wcm9kdWN0aW9u
---
apiVersion: v1
kind: ConfigMap
metadata:
name: backend-config
namespace: xpeditis
data:
SPRING_PROFILES_ACTIVE: "prod"
SPRING_DATASOURCE_URL: "jdbc:postgresql://postgres-service:5432/xpeditis_prod"
CORS_ALLOWED_ORIGINS: "https://xpeditis.fr,https://www.xpeditis.fr"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace: xpeditis
labels:
app: backend
spec:
replicas: 2
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: ghcr.io/your-username/xpeditis/backend:latest
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
valueFrom:
configMapKeyRef:
name: backend-config
key: SPRING_PROFILES_ACTIVE
- name: SPRING_DATASOURCE_URL
valueFrom:
configMapKeyRef:
name: backend-config
key: SPRING_DATASOURCE_URL
- name: SPRING_DATASOURCE_USERNAME
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_USER
- name: SPRING_DATASOURCE_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_PASSWORD
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: backend-secret
key: JWT_SECRET
- name: CORS_ALLOWED_ORIGINS
valueFrom:
configMapKeyRef:
name: backend-config
key: CORS_ALLOWED_ORIGINS
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
livenessProbe:
httpGet:
path: /api/actuator/health
port: 8080
initialDelaySeconds: 60
periodSeconds: 30
timeoutSeconds: 10
readinessProbe:
httpGet:
path: /api/actuator/health/readiness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
volumeMounts:
- name: logs-volume
mountPath: /app/logs
volumes:
- name: logs-volume
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: backend-service
namespace: xpeditis
labels:
app: backend
spec:
selector:
app: backend
ports:
- port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: backend-hpa
namespace: xpeditis
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: backend
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

78
k8s/frontend.yaml Normal file
View File

@ -0,0 +1,78 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: xpeditis
labels:
app: frontend
spec:
replicas: 2
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: ghcr.io/your-username/xpeditis/frontend:latest
ports:
- containerPort: 80
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 30
periodSeconds: 30
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: frontend-service
namespace: xpeditis
labels:
app: frontend
spec:
selector:
app: frontend
ports:
- port: 80
targetPort: 80
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: frontend-hpa
namespace: xpeditis
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: frontend
minReplicas: 2
maxReplicas: 5
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70

73
k8s/ingress.yaml Normal file
View File

@ -0,0 +1,73 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: xpeditis-ingress
namespace: xpeditis
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/rate-limit: "100"
nginx.ingress.kubernetes.io/rate-limit-window: "1m"
spec:
tls:
- hosts:
- xpeditis.fr
- www.xpeditis.fr
- api.xpeditis.fr
secretName: xpeditis-tls
rules:
# Frontend principal
- host: xpeditis.fr
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
# Redirection www vers domaine principal
- host: www.xpeditis.fr
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
# API Backend
- host: api.xpeditis.fr
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: backend-service
port:
number: 8080
---
# Certificat SSL automatique avec cert-manager
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@xpeditis.fr
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx

7
k8s/namespace.yaml Normal file
View File

@ -0,0 +1,7 @@
apiVersion: v1
kind: Namespace
metadata:
name: xpeditis
labels:
name: xpeditis
environment: production

115
k8s/postgres.yaml Normal file
View File

@ -0,0 +1,115 @@
apiVersion: v1
kind: Secret
metadata:
name: postgres-secret
namespace: xpeditis
type: Opaque
data:
# Base64 encoded values
POSTGRES_DB: eHBlZGl0aXNfcHJvZA== # xpeditis_prod
POSTGRES_USER: eHBlZGl0aXNfdXNlcg== # xpeditis_user
POSTGRES_PASSWORD: eHBlZGl0aXNfcGFzc3dvcmQ= # xpeditis_password
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
namespace: xpeditis
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: standard
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
namespace: xpeditis
labels:
app: postgres
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15-alpine
ports:
- containerPort: 5432
env:
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_DB
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_USER
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_PASSWORD
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
exec:
command:
- pg_isready
- -U
- xpeditis_user
- -d
- xpeditis_prod
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
exec:
command:
- pg_isready
- -U
- xpeditis_user
- -d
- xpeditis_prod
initialDelaySeconds: 5
periodSeconds: 5
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: postgres-pvc
---
apiVersion: v1
kind: Service
metadata:
name: postgres-service
namespace: xpeditis
labels:
app: postgres
spec:
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432
type: ClusterIP

242
scripts/deploy.sh Executable file
View File

@ -0,0 +1,242 @@
#!/bin/bash
# Script de déploiement Xpeditis
# Usage: ./deploy.sh [environment] [component]
# Environments: dev, staging, prod
# Components: all, backend, frontend, database
set -e
ENVIRONMENT=${1:-dev}
COMPONENT=${2:-all}
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
# Couleurs pour les logs
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Vérifier les prérequis
check_prerequisites() {
log_info "Vérification des prérequis..."
if ! command -v docker &> /dev/null; then
log_error "Docker n'est pas installé"
exit 1
fi
if ! command -v docker-compose &> /dev/null; then
log_error "Docker Compose n'est pas installé"
exit 1
fi
if [[ "$ENVIRONMENT" == "prod" ]] && ! command -v kubectl &> /dev/null; then
log_error "kubectl n'est pas installé (requis pour la production)"
exit 1
fi
log_success "Prérequis vérifiés"
}
# Déploiement en développement
deploy_dev() {
log_info "Déploiement en environnement de développement..."
cd "$PROJECT_ROOT"
case $COMPONENT in
"all")
docker-compose down
docker-compose up --build -d
;;
"backend")
docker-compose up --build -d backend
;;
"frontend")
docker-compose up --build -d frontend
;;
"database")
docker-compose up -d postgres
;;
*)
log_error "Composant inconnu: $COMPONENT"
exit 1
;;
esac
log_success "Déploiement dev terminé"
log_info "Frontend: http://localhost:3000"
log_info "Backend: http://localhost:8080"
log_info "Base de données: localhost:5432"
}
# Déploiement en staging
deploy_staging() {
log_info "Déploiement en environnement de staging..."
# Build et push des images
build_and_push_images "staging"
# Déploiement Kubernetes
kubectl apply -f "$PROJECT_ROOT/k8s/namespace.yaml"
kubectl apply -f "$PROJECT_ROOT/k8s/" -n xpeditis-staging
log_success "Déploiement staging terminé"
}
# Déploiement en production
deploy_prod() {
log_info "Déploiement en environnement de production..."
# Confirmation utilisateur
read -p "Êtes-vous sûr de vouloir déployer en production? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
log_info "Déploiement annulé"
exit 0
fi
# Build et push des images
build_and_push_images "prod"
# Déploiement Kubernetes
kubectl apply -f "$PROJECT_ROOT/k8s/namespace.yaml"
kubectl apply -f "$PROJECT_ROOT/k8s/" -n xpeditis
# Attendre que les pods soient prêts
kubectl wait --for=condition=ready pod -l app=backend -n xpeditis --timeout=300s
kubectl wait --for=condition=ready pod -l app=frontend -n xpeditis --timeout=300s
log_success "Déploiement production terminé"
log_info "Site web: https://xpeditis.fr"
log_info "API: https://api.xpeditis.fr"
}
# Build et push des images Docker
build_and_push_images() {
local env=$1
log_info "Build et push des images Docker pour $env..."
# Backend
if [[ "$COMPONENT" == "all" || "$COMPONENT" == "backend" ]]; then
log_info "Build de l'image backend..."
docker build -t "xpeditis/backend:$env" "$PROJECT_ROOT/backend"
docker tag "xpeditis/backend:$env" "ghcr.io/your-username/xpeditis/backend:$env"
docker push "ghcr.io/your-username/xpeditis/backend:$env"
fi
# Frontend
if [[ "$COMPONENT" == "all" || "$COMPONENT" == "frontend" ]]; then
log_info "Build de l'image frontend..."
docker build -t "xpeditis/frontend:$env" \
--build-arg VITE_API_URL="https://api.xpeditis.fr" \
--target production \
"$PROJECT_ROOT/frontend"
docker tag "xpeditis/frontend:$env" "ghcr.io/your-username/xpeditis/frontend:$env"
docker push "ghcr.io/your-username/xpeditis/frontend:$env"
fi
log_success "Images Docker buildées et pushées"
}
# Fonction de rollback
rollback() {
log_warning "Rollback en cours..."
if [[ "$ENVIRONMENT" == "dev" ]]; then
docker-compose down
docker-compose up -d
else
kubectl rollout undo deployment/backend -n xpeditis
kubectl rollout undo deployment/frontend -n xpeditis
fi
log_success "Rollback terminé"
}
# Afficher l'aide
show_help() {
echo "Usage: $0 [environment] [component]"
echo ""
echo "Environments:"
echo " dev - Environnement de développement (défaut)"
echo " staging - Environnement de staging"
echo " prod - Environnement de production"
echo ""
echo "Components:"
echo " all - Tous les composants (défaut)"
echo " backend - Backend Spring Boot uniquement"
echo " frontend - Frontend React uniquement"
echo " database - Base de données uniquement"
echo ""
echo "Options:"
echo " --rollback - Effectuer un rollback"
echo " --help - Afficher cette aide"
echo ""
echo "Exemples:"
echo " $0 # Déploiement dev complet"
echo " $0 prod all # Déploiement production complet"
echo " $0 staging backend # Déploiement staging backend uniquement"
echo " $0 --rollback # Rollback"
}
# Point d'entrée principal
main() {
case "${1:-}" in
"--help"|"-h")
show_help
exit 0
;;
"--rollback")
rollback
exit 0
;;
esac
log_info "Démarrage du déploiement Xpeditis"
log_info "Environnement: $ENVIRONMENT"
log_info "Composant: $COMPONENT"
check_prerequisites
case $ENVIRONMENT in
"dev")
deploy_dev
;;
"staging")
deploy_staging
;;
"prod")
deploy_prod
;;
*)
log_error "Environnement inconnu: $ENVIRONMENT"
show_help
exit 1
;;
esac
log_success "Déploiement terminé avec succès!"
}
# Exécuter le script principal
main "$@"