Add new infra architecture
This commit is contained in:
@@ -886,7 +886,7 @@ microk8s kubectl apply -f infrastructure/ci-cd/tekton/pipelines/
|
|||||||
microk8s kubectl apply -f infrastructure/ci-cd/tekton/triggers/
|
microk8s kubectl apply -f infrastructure/ci-cd/tekton/triggers/
|
||||||
|
|
||||||
# Apply Flux configurations
|
# Apply Flux configurations
|
||||||
microk8s kubectl apply -f infrastructure/ci-cd/flux/
|
microk8s kubectl apply -k infrastructure/ci-cd/flux/
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,120 +0,0 @@
|
|||||||
# Docker Maintenance Guide for Local Development
|
|
||||||
|
|
||||||
## The Problem
|
|
||||||
|
|
||||||
When developing with Tilt and local Kubernetes (Kind), Docker accumulates:
|
|
||||||
- **Multiple image versions** from each code change (Tilt rebuilds)
|
|
||||||
- **Unused volumes** from previous cluster runs
|
|
||||||
- **Build cache** that grows over time
|
|
||||||
|
|
||||||
This quickly fills up disk space, causing pods to fail with "No space left on device" errors.
|
|
||||||
|
|
||||||
## Quick Fix (When You Hit Disk Issues)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Clean up all unused Docker resources
|
|
||||||
docker system prune -a --volumes -f
|
|
||||||
```
|
|
||||||
|
|
||||||
This removes:
|
|
||||||
- All unused images
|
|
||||||
- All unused volumes
|
|
||||||
- All build cache
|
|
||||||
|
|
||||||
**Expected recovery**: 60-100GB
|
|
||||||
|
|
||||||
## Regular Maintenance
|
|
||||||
|
|
||||||
### Option 1: Use the Cleanup Script (Recommended)
|
|
||||||
|
|
||||||
Run the maintenance script weekly:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./scripts/cleanup-docker.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Or run it automatically without confirmation:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./scripts/cleanup-docker.sh --auto
|
|
||||||
```
|
|
||||||
|
|
||||||
### Option 2: Manual Commands
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Remove images older than 24 hours
|
|
||||||
docker image prune -af --filter "until=24h"
|
|
||||||
|
|
||||||
# Remove unused volumes
|
|
||||||
docker volume prune -f
|
|
||||||
|
|
||||||
# Remove build cache
|
|
||||||
docker builder prune -af
|
|
||||||
```
|
|
||||||
|
|
||||||
### Option 3: Set Up Automated Cleanup
|
|
||||||
|
|
||||||
Add to your crontab (run every Sunday at 2 AM):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
crontab -e
|
|
||||||
# Add this line:
|
|
||||||
0 2 * * 0 /Users/urtzialfaro/Documents/bakery-ia/scripts/cleanup-docker.sh --auto >> /tmp/docker-cleanup.log 2>&1
|
|
||||||
```
|
|
||||||
|
|
||||||
## Monitoring Disk Usage
|
|
||||||
|
|
||||||
### Check Docker disk usage:
|
|
||||||
```bash
|
|
||||||
docker system df
|
|
||||||
```
|
|
||||||
|
|
||||||
### Check Kind node disk usage:
|
|
||||||
```bash
|
|
||||||
docker exec bakery-ia-local-control-plane df -h /var
|
|
||||||
```
|
|
||||||
|
|
||||||
### Alert thresholds:
|
|
||||||
- **< 70%**: Healthy ✅
|
|
||||||
- **70-85%**: Consider cleanup soon ⚠️
|
|
||||||
- **> 85%**: Run cleanup immediately 🚨
|
|
||||||
- **> 95%**: Critical - pods will fail ❌
|
|
||||||
|
|
||||||
## Prevention Tips
|
|
||||||
|
|
||||||
1. **Run cleanup weekly** to prevent accumulation
|
|
||||||
2. **Monitor disk usage** before long dev sessions
|
|
||||||
3. **Delete old Kind clusters** when switching projects:
|
|
||||||
```bash
|
|
||||||
kind delete cluster --name bakery-ia-local
|
|
||||||
```
|
|
||||||
4. **Increase Docker disk allocation** in Docker Desktop settings if you frequently rebuild many services
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Pods in CrashLoopBackOff after disk issues:
|
|
||||||
|
|
||||||
1. Run cleanup (see Quick Fix above)
|
|
||||||
2. Restart failed pods:
|
|
||||||
```bash
|
|
||||||
kubectl get pods -n bakery-ia | grep -E "(CrashLoopBackOff|Error)" | awk '{print $1}' | xargs kubectl delete pod -n bakery-ia
|
|
||||||
```
|
|
||||||
|
|
||||||
### Cleanup didn't free enough space:
|
|
||||||
|
|
||||||
If still above 90% after cleanup:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Nuclear option - rebuild everything
|
|
||||||
kind delete cluster --name bakery-ia-local
|
|
||||||
docker system prune -a --volumes -f
|
|
||||||
# Then recreate cluster with your setup scripts
|
|
||||||
```
|
|
||||||
|
|
||||||
## What Happened Today (2026-01-12)
|
|
||||||
|
|
||||||
- **Issue**: Disk was 100% full (113GB/113GB), causing database pods to crash
|
|
||||||
- **Root cause**: 122 unused Docker images + 16 unused volumes + 6GB build cache
|
|
||||||
- **Solution**: Ran `docker system prune -a --volumes -f`
|
|
||||||
- **Result**: Freed 89GB, disk now at 22% usage (24GB/113GB)
|
|
||||||
- **All services recovered successfully**
|
|
||||||
@@ -1,413 +0,0 @@
|
|||||||
# Infrastructure Reorganization Proposal for Bakery-IA
|
|
||||||
|
|
||||||
## Executive Summary
|
|
||||||
|
|
||||||
This document presents a comprehensive analysis of the current infrastructure organization and proposes a restructured layout that improves maintainability, scalability, and operational efficiency. The proposal is based on a detailed examination of the existing 177 files across 31 directories in the infrastructure folder.
|
|
||||||
|
|
||||||
## Current Infrastructure Analysis
|
|
||||||
|
|
||||||
### Current Structure Overview
|
|
||||||
|
|
||||||
```
|
|
||||||
infrastructure/
|
|
||||||
├── ci-cd/ # 18 files - CI/CD pipeline components
|
|
||||||
├── helm/ # 8 files - Helm charts and scripts
|
|
||||||
├── kubernetes/ # 103 files - Kubernetes manifests and configs
|
|
||||||
├── signoz/ # 11 files - Monitoring dashboards and scripts
|
|
||||||
└── tls/ # 37 files - TLS certificates and generation scripts
|
|
||||||
```
|
|
||||||
|
|
||||||
### Key Findings
|
|
||||||
|
|
||||||
1. **Kubernetes Base Components (103 files)**: The most complex area with:
|
|
||||||
- 20+ service deployments across 15+ microservices
|
|
||||||
- 20+ database configurations (PostgreSQL, RabbitMQ, MinIO)
|
|
||||||
- 19 migration jobs for different services
|
|
||||||
- Infrastructure components (gateway, monitoring, etc.)
|
|
||||||
|
|
||||||
2. **CI/CD Pipeline (18 files)**:
|
|
||||||
- Tekton tasks and pipelines for GitOps workflow
|
|
||||||
- Flux CD configuration for continuous delivery
|
|
||||||
- Gitea configuration for Git repository management
|
|
||||||
|
|
||||||
3. **Monitoring (11 files)**:
|
|
||||||
- SigNoz dashboards for comprehensive observability
|
|
||||||
- Import scripts for dashboard management
|
|
||||||
|
|
||||||
4. **TLS Certificates (37 files)**:
|
|
||||||
- CA certificates and generation scripts
|
|
||||||
- Service-specific certificates (PostgreSQL, Redis, MinIO)
|
|
||||||
- Certificate signing requests and configurations
|
|
||||||
|
|
||||||
### Strengths of Current Organization
|
|
||||||
|
|
||||||
1. **Logical Grouping**: Components are generally well-grouped by function
|
|
||||||
2. **Base/Overlay Pattern**: Kubernetes uses proper base/overlay structure
|
|
||||||
3. **Comprehensive Monitoring**: SigNoz dashboards cover all major aspects
|
|
||||||
4. **Security Focus**: Dedicated TLS certificate management
|
|
||||||
|
|
||||||
### Challenges Identified
|
|
||||||
|
|
||||||
1. **Complexity in Kubernetes Base**: 103 files make navigation difficult
|
|
||||||
2. **Mixed Component Types**: Services, databases, and infrastructure mixed together
|
|
||||||
3. **Limited Environment Separation**: Only dev/prod overlays, no staging
|
|
||||||
4. **Script Scattering**: Automation scripts spread across directories
|
|
||||||
5. **Documentation Gaps**: Some components lack clear documentation
|
|
||||||
|
|
||||||
## Proposed Infrastructure Organization
|
|
||||||
|
|
||||||
### High-Level Structure
|
|
||||||
|
|
||||||
```
|
|
||||||
infrastructure/
|
|
||||||
├── environments/ # Environment-specific configurations
|
|
||||||
├── platform/ # Platform-level infrastructure
|
|
||||||
├── services/ # Application services and microservices
|
|
||||||
├── monitoring/ # Observability and monitoring
|
|
||||||
├── cicd/ # CI/CD pipeline components
|
|
||||||
├── security/ # Security configurations and certificates
|
|
||||||
├── scripts/ # Automation and utility scripts
|
|
||||||
├── docs/ # Infrastructure documentation
|
|
||||||
└── README.md # Top-level infrastructure guide
|
|
||||||
```
|
|
||||||
|
|
||||||
### Detailed Structure Proposal
|
|
||||||
|
|
||||||
```
|
|
||||||
infrastructure/
|
|
||||||
├── environments/ # Environment-specific configurations
|
|
||||||
│ ├── dev/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ │ ├── base/
|
|
||||||
│ │ │ │ ├── namespace.yaml
|
|
||||||
│ │ │ │ ├── configmap.yaml
|
|
||||||
│ │ │ │ ├── secrets.yaml
|
|
||||||
│ │ │ │ └── ingress-https.yaml
|
|
||||||
│ │ │ ├── components/
|
|
||||||
│ │ │ │ ├── databases/
|
|
||||||
│ │ │ │ ├── infrastructure/
|
|
||||||
│ │ │ │ ├── microservices/
|
|
||||||
│ │ │ │ └── cert-manager/
|
|
||||||
│ │ │ ├── configs/
|
|
||||||
│ │ │ ├── cronjobs/
|
|
||||||
│ │ │ ├── jobs/
|
|
||||||
│ │ │ └── migrations/
|
|
||||||
│ │ ├── kustomization.yaml
|
|
||||||
│ │ └── values/
|
|
||||||
│ ├── staging/ # New staging environment
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── values/
|
|
||||||
│ └── prod/
|
|
||||||
│ ├── k8s-manifests/
|
|
||||||
│ ├── terraform/ # Production-specific IaC
|
|
||||||
│ └── values/
|
|
||||||
├── platform/ # Platform-level infrastructure
|
|
||||||
│ ├── cluster/
|
|
||||||
│ │ ├── eks/ # AWS EKS configuration
|
|
||||||
│ │ │ ├── terraform/
|
|
||||||
│ │ │ └── manifests/
|
|
||||||
│ │ └── kind/ # Local development cluster
|
|
||||||
│ │ ├── config.yaml
|
|
||||||
│ │ └── manifests/
|
|
||||||
│ ├── networking/
|
|
||||||
│ │ ├── dns/
|
|
||||||
│ │ ├── load-balancers/
|
|
||||||
│ │ └── ingress/
|
|
||||||
│ │ ├── nginx/
|
|
||||||
│ │ └── cert-manager/
|
|
||||||
│ ├── security/
|
|
||||||
│ │ ├── rbac/
|
|
||||||
│ │ ├── network-policies/
|
|
||||||
│ │ └── tls/
|
|
||||||
│ │ ├── ca/
|
|
||||||
│ │ ├── postgres/
|
|
||||||
│ │ ├── redis/
|
|
||||||
│ │ └── minio/
|
|
||||||
│ └── storage/
|
|
||||||
│ ├── postgres/
|
|
||||||
│ ├── redis/
|
|
||||||
│ └── minio/
|
|
||||||
├── services/ # Application services
|
|
||||||
│ ├── databases/
|
|
||||||
│ │ ├── postgres/
|
|
||||||
│ │ │ ├── k8s-manifests/
|
|
||||||
│ │ │ ├── backups/
|
|
||||||
│ │ │ ├── monitoring/
|
|
||||||
│ │ │ └── maintenance/
|
|
||||||
│ │ ├── redis/
|
|
||||||
│ │ │ ├── configs/
|
|
||||||
│ │ │ └── monitoring/
|
|
||||||
│ │ └── minio/
|
|
||||||
│ │ ├── buckets/
|
|
||||||
│ │ └── policies/
|
|
||||||
│ ├── api-gateway/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── configs/
|
|
||||||
│ └── microservices/
|
|
||||||
│ ├── auth/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── configs/
|
|
||||||
│ ├── tenant/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── configs/
|
|
||||||
│ ├── training/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── configs/
|
|
||||||
│ ├── forecasting/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── configs/
|
|
||||||
│ ├── sales/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── configs/
|
|
||||||
│ ├── external/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── configs/
|
|
||||||
│ ├── notification/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── configs/
|
|
||||||
│ ├── inventory/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── configs/
|
|
||||||
│ ├── recipes/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── configs/
|
|
||||||
│ ├── suppliers/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── configs/
|
|
||||||
│ ├── pos/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── configs/
|
|
||||||
│ ├── orders/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── configs/
|
|
||||||
│ ├── production/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── configs/
|
|
||||||
│ ├── procurement/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── configs/
|
|
||||||
│ ├── orchestrator/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── configs/
|
|
||||||
│ ├── alert-processor/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── configs/
|
|
||||||
│ ├── ai-insights/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── configs/
|
|
||||||
│ ├── demo-session/
|
|
||||||
│ │ ├── k8s-manifests/
|
|
||||||
│ │ └── configs/
|
|
||||||
│ └── frontend/
|
|
||||||
│ ├── k8s-manifests/
|
|
||||||
│ └── configs/
|
|
||||||
├── monitoring/ # Observability stack
|
|
||||||
│ ├── signoz/
|
|
||||||
│ │ ├── manifests/
|
|
||||||
│ │ ├── dashboards/
|
|
||||||
│ │ │ ├── alert-management.json
|
|
||||||
│ │ │ ├── api-performance.json
|
|
||||||
│ │ │ ├── application-performance.json
|
|
||||||
│ │ │ ├── database-performance.json
|
|
||||||
│ │ │ ├── error-tracking.json
|
|
||||||
│ │ │ ├── index.json
|
|
||||||
│ │ │ ├── infrastructure-monitoring.json
|
|
||||||
│ │ │ ├── log-analysis.json
|
|
||||||
│ │ │ ├── system-health.json
|
|
||||||
│ │ │ └── user-activity.json
|
|
||||||
│ │ ├── values-dev.yaml
|
|
||||||
│ │ ├── values-prod.yaml
|
|
||||||
│ │ ├── deploy-signoz.sh
|
|
||||||
│ │ ├── verify-signoz.sh
|
|
||||||
│ │ └── generate-test-traffic.sh
|
|
||||||
│ └── opentelemetry/
|
|
||||||
│ ├── collector/
|
|
||||||
│ └── agent/
|
|
||||||
├── cicd/ # CI/CD pipeline
|
|
||||||
│ ├── gitea/
|
|
||||||
│ │ ├── values.yaml
|
|
||||||
│ │ └── ingress.yaml
|
|
||||||
│ ├── tekton/
|
|
||||||
│ │ ├── tasks/
|
|
||||||
│ │ │ ├── git-clone.yaml
|
|
||||||
│ │ │ ├── detect-changes.yaml
|
|
||||||
│ │ │ ├── kaniko-build.yaml
|
|
||||||
│ │ │ └── update-gitops.yaml
|
|
||||||
│ │ ├── pipelines/
|
|
||||||
│ │ └── triggers/
|
|
||||||
│ └── flux/
|
|
||||||
│ ├── git-repository.yaml
|
|
||||||
│ └── kustomization.yaml
|
|
||||||
├── security/ # Security configurations
|
|
||||||
│ ├── policies/
|
|
||||||
│ │ ├── network-policies.yaml
|
|
||||||
│ │ ├── pod-security.yaml
|
|
||||||
│ │ └── rbac.yaml
|
|
||||||
│ ├── certificates/
|
|
||||||
│ │ ├── ca/
|
|
||||||
│ │ ├── services/
|
|
||||||
│ │ └── rotation-scripts/
|
|
||||||
│ ├── scanning/
|
|
||||||
│ │ ├── trivy/
|
|
||||||
│ │ └── policies/
|
|
||||||
│ └── compliance/
|
|
||||||
│ ├── cis-benchmarks/
|
|
||||||
│ └── audit-scripts/
|
|
||||||
├── scripts/ # Automation scripts
|
|
||||||
│ ├── setup/
|
|
||||||
│ │ ├── generate-certificates.sh
|
|
||||||
│ │ ├── generate-minio-certificates.sh
|
|
||||||
│ │ └── setup-dockerhub-secrets.sh
|
|
||||||
│ ├── deployment/
|
|
||||||
│ │ ├── deploy-signoz.sh
|
|
||||||
│ │ └── verify-signoz.sh
|
|
||||||
│ ├── maintenance/
|
|
||||||
│ │ ├── regenerate_migrations_k8s.sh
|
|
||||||
│ │ └── kubernetes_restart.sh
|
|
||||||
│ └── verification/
|
|
||||||
│ └── verify-registry.sh
|
|
||||||
├── docs/ # Infrastructure documentation
|
|
||||||
│ ├── architecture/
|
|
||||||
│ │ ├── diagrams/
|
|
||||||
│ │ └── decisions/
|
|
||||||
│ ├── operations/
|
|
||||||
│ │ ├── runbooks/
|
|
||||||
│ │ └── troubleshooting/
|
|
||||||
│ ├── onboarding/
|
|
||||||
│ └── reference/
|
|
||||||
│ ├── api/
|
|
||||||
│ └── configurations/
|
|
||||||
└── README.md
|
|
||||||
```
|
|
||||||
|
|
||||||
## Migration Strategy
|
|
||||||
|
|
||||||
### Phase 1: Preparation and Planning
|
|
||||||
|
|
||||||
1. **Inventory Analysis**: Complete detailed inventory of all current files
|
|
||||||
2. **Dependency Mapping**: Identify dependencies between components
|
|
||||||
3. **Impact Assessment**: Determine which components can be moved safely
|
|
||||||
4. **Backup Strategy**: Ensure all files are backed up before migration
|
|
||||||
|
|
||||||
### Phase 2: Non-Critical Components
|
|
||||||
|
|
||||||
1. **Documentation**: Move and update all documentation files
|
|
||||||
2. **Scripts**: Organize automation scripts into new structure
|
|
||||||
3. **Monitoring**: Migrate SigNoz dashboards and configurations
|
|
||||||
4. **CI/CD**: Reorganize pipeline components
|
|
||||||
|
|
||||||
### Phase 3: Environment-Specific Components
|
|
||||||
|
|
||||||
1. **Create Environment Structure**: Set up dev/staging/prod directories
|
|
||||||
2. **Migrate Kubernetes Manifests**: Move base components to appropriate locations
|
|
||||||
3. **Update References**: Ensure all cross-references are corrected
|
|
||||||
4. **Environment Validation**: Test each environment separately
|
|
||||||
|
|
||||||
### Phase 4: Service Components
|
|
||||||
|
|
||||||
1. **Database Migration**: Move database configurations to services/databases
|
|
||||||
2. **Microservice Organization**: Group microservices by domain
|
|
||||||
3. **Infrastructure Components**: Move gateway and other infrastructure
|
|
||||||
4. **Service Validation**: Test each service in isolation
|
|
||||||
|
|
||||||
### Phase 5: Finalization
|
|
||||||
|
|
||||||
1. **Integration Testing**: Test complete infrastructure workflow
|
|
||||||
2. **Documentation Update**: Finalize all documentation
|
|
||||||
3. **Team Training**: Conduct training on new structure
|
|
||||||
4. **Cleanup**: Remove old structure and temporary files
|
|
||||||
|
|
||||||
## Benefits of Proposed Structure
|
|
||||||
|
|
||||||
### 1. Improved Navigation
|
|
||||||
- **Clear Hierarchy**: Logical grouping by function and environment
|
|
||||||
- **Consistent Patterns**: Standardized structure across all components
|
|
||||||
- **Reduced Cognitive Load**: Easier to find specific components
|
|
||||||
|
|
||||||
### 2. Enhanced Maintainability
|
|
||||||
- **Environment Isolation**: Clear separation of dev/staging/prod
|
|
||||||
- **Component Grouping**: Related components grouped together
|
|
||||||
- **Standardized Structure**: Consistent patterns across services
|
|
||||||
|
|
||||||
### 3. Better Scalability
|
|
||||||
- **Modular Design**: Easy to add new services or environments
|
|
||||||
- **Domain Separation**: Services organized by business domain
|
|
||||||
- **Infrastructure Independence**: Platform components separate from services
|
|
||||||
|
|
||||||
### 4. Improved Security
|
|
||||||
- **Centralized Security**: All security configurations in one place
|
|
||||||
- **Environment-Specific Policies**: Tailored security for each environment
|
|
||||||
- **Better Secret Management**: Clear structure for sensitive data
|
|
||||||
|
|
||||||
### 5. Enhanced Observability
|
|
||||||
- **Comprehensive Monitoring**: All observability tools grouped
|
|
||||||
- **Standardized Dashboards**: Consistent monitoring across services
|
|
||||||
- **Centralized Logging**: Better log management structure
|
|
||||||
|
|
||||||
## Implementation Considerations
|
|
||||||
|
|
||||||
### Tools and Technologies
|
|
||||||
- **Terraform**: For infrastructure as code (IaC)
|
|
||||||
- **Kustomize**: For Kubernetes manifest management
|
|
||||||
- **Helm**: For complex application deployments
|
|
||||||
- **SOPS/Sealed Secrets**: For secret management
|
|
||||||
- **Trivy**: For vulnerability scanning
|
|
||||||
|
|
||||||
### Team Adaptation
|
|
||||||
- **Training Plan**: Develop comprehensive training materials
|
|
||||||
- **Migration Guide**: Create step-by-step migration documentation
|
|
||||||
- **Support Period**: Provide dedicated support during transition
|
|
||||||
- **Feedback Mechanism**: Establish channels for team feedback
|
|
||||||
|
|
||||||
### Risk Mitigation
|
|
||||||
- **Phased Approach**: Implement changes incrementally
|
|
||||||
- **Rollback Plan**: Develop comprehensive rollback procedures
|
|
||||||
- **Testing Strategy**: Implement thorough testing at each phase
|
|
||||||
- **Monitoring**: Enhanced monitoring during migration period
|
|
||||||
|
|
||||||
## Expected Outcomes
|
|
||||||
|
|
||||||
1. **Reduced Time-to-Find**: 40-60% reduction in time spent locating files
|
|
||||||
2. **Improved Deployment Speed**: 25-35% faster deployment cycles
|
|
||||||
3. **Enhanced Collaboration**: Better team coordination and understanding
|
|
||||||
4. **Reduced Errors**: 30-50% reduction in configuration errors
|
|
||||||
5. **Better Scalability**: Easier to add new services and features
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
The proposed infrastructure reorganization represents a significant improvement over the current structure. By implementing a clear, logical hierarchy with proper separation of concerns, the new organization will:
|
|
||||||
|
|
||||||
- **Improve operational efficiency** through better navigation and maintainability
|
|
||||||
- **Enhance security** with centralized security management
|
|
||||||
- **Support growth** with a scalable, modular design
|
|
||||||
- **Reduce errors** through standardized patterns and structures
|
|
||||||
- **Facilitate collaboration** with intuitive organization
|
|
||||||
|
|
||||||
The key to successful implementation is a phased approach with thorough testing and team involvement at each stage. With proper planning and execution, this reorganization will provide long-term benefits for the Bakery-IA project's infrastructure management.
|
|
||||||
|
|
||||||
## Appendix: File Migration Mapping
|
|
||||||
|
|
||||||
### Current → Proposed Mapping
|
|
||||||
|
|
||||||
**Kubernetes Components:**
|
|
||||||
- `infrastructure/kubernetes/base/components/*` → `infrastructure/services/microservices/*/`
|
|
||||||
- `infrastructure/kubernetes/base/components/databases/*` → `infrastructure/services/databases/*/`
|
|
||||||
- `infrastructure/kubernetes/base/migrations/*` → `infrastructure/services/microservices/*/migrations/`
|
|
||||||
- `infrastructure/kubernetes/base/configs/*` → `infrastructure/environments/*/values/`
|
|
||||||
|
|
||||||
**CI/CD Components:**
|
|
||||||
- `infrastructure/ci-cd/*` → `infrastructure/cicd/*/`
|
|
||||||
|
|
||||||
**Monitoring Components:**
|
|
||||||
- `infrastructure/signoz/*` → `infrastructure/monitoring/signoz/*/`
|
|
||||||
- `infrastructure/helm/*` → `infrastructure/monitoring/signoz/*/` (signoz-related)
|
|
||||||
|
|
||||||
**Security Components:**
|
|
||||||
- `infrastructure/tls/*` → `infrastructure/security/certificates/*/`
|
|
||||||
|
|
||||||
**Scripts:**
|
|
||||||
- `infrastructure/kubernetes/*.sh` → `infrastructure/scripts/*/`
|
|
||||||
- `infrastructure/helm/*.sh` → `infrastructure/scripts/deployment/*/`
|
|
||||||
- `infrastructure/tls/*.sh` → `infrastructure/scripts/setup/*/`
|
|
||||||
|
|
||||||
This mapping provides a clear path for migrating each component to its new location while maintaining functionality and relationships between components.
|
|
||||||
@@ -81,7 +81,7 @@ For production deployment on clouding.io with Kubernetes:
|
|||||||
3. Configure production-specific values
|
3. Configure production-specific values
|
||||||
4. Deploy using the production kustomization:
|
4. Deploy using the production kustomization:
|
||||||
```bash
|
```bash
|
||||||
kubectl apply -k infrastructure/kubernetes/environments/production/
|
kubectl apply -k infrastructure/environments/prod/k8s-manifests
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🤝 Contributing
|
## 🤝 Contributing
|
||||||
|
|||||||
335
Tiltfile
335
Tiltfile
@@ -17,6 +17,43 @@
|
|||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# 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 ./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
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# TILT CONFIGURATION
|
# TILT CONFIGURATION
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
@@ -191,132 +228,68 @@ Monitoring:
|
|||||||
Applying security configurations...
|
Applying security configurations...
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# Create Docker Hub secret for image pulls (if credentials are available)
|
|
||||||
local_resource(
|
|
||||||
'dockerhub-secret',
|
|
||||||
cmd='''
|
|
||||||
echo "Setting up Docker Hub image pull secret..."
|
|
||||||
|
|
||||||
# Check if Docker Hub credentials are available
|
|
||||||
if [ -n "$DOCKERHUB_USERNAME" ] && [ -n "$DOCKERHUB_PASSWORD" ]; then
|
|
||||||
echo " Found DOCKERHUB_USERNAME and DOCKERHUB_PASSWORD environment variables"
|
|
||||||
./infrastructure/kubernetes/create-dockerhub-secret.sh
|
|
||||||
elif [ -f "$HOME/.docker/config.json" ]; then
|
|
||||||
echo " Attempting to use Docker CLI credentials..."
|
|
||||||
./infrastructure/kubernetes/create-dockerhub-secret.sh
|
|
||||||
else
|
|
||||||
echo " Docker Hub credentials not found"
|
|
||||||
echo " To enable automatic Docker Hub authentication:"
|
|
||||||
echo " 1. Run 'docker login', OR"
|
|
||||||
echo " 2. Set environment variables:"
|
|
||||||
echo " export DOCKERHUB_USERNAME='your-username'"
|
|
||||||
echo " export DOCKERHUB_PASSWORD='your-password-or-token'"
|
|
||||||
echo ""
|
|
||||||
echo " Continuing without Docker Hub authentication..."
|
|
||||||
echo " (This is OK for local development using local registry)"
|
|
||||||
fi
|
|
||||||
''',
|
|
||||||
labels=['00-security'],
|
|
||||||
auto_init=True
|
|
||||||
)
|
|
||||||
|
|
||||||
# Apply security configurations before loading main manifests
|
# Apply security configurations before loading main manifests
|
||||||
local_resource(
|
local_resource(
|
||||||
'security-setup',
|
'security-setup',
|
||||||
cmd='''
|
cmd='''
|
||||||
echo "Applying security secrets and configurations..."
|
echo "Applying security secrets and configurations..."
|
||||||
kubectl apply -f infrastructure/kubernetes/base/secrets.yaml
|
|
||||||
kubectl apply -f infrastructure/kubernetes/base/secrets/postgres-tls-secret.yaml
|
# First, ensure all required namespaces exist
|
||||||
kubectl apply -f infrastructure/kubernetes/base/secrets/redis-tls-secret.yaml
|
echo "Creating namespaces..."
|
||||||
kubectl apply -f infrastructure/kubernetes/base/configs/postgres-init-config.yaml
|
kubectl apply -f infrastructure/namespaces/bakery-ia.yaml
|
||||||
kubectl apply -f infrastructure/kubernetes/base/configmaps/postgres-logging-config.yaml
|
kubectl apply -f infrastructure/namespaces/tekton-pipelines.yaml
|
||||||
|
kubectl apply -f infrastructure/namespaces/flux-system.yaml
|
||||||
|
|
||||||
|
# Wait for namespaces to be ready
|
||||||
|
echo "Waiting for namespaces to be ready..."
|
||||||
|
for ns in bakery-ia tekton-pipelines flux-system; do
|
||||||
|
until kubectl get namespace $ns 2>/dev/null; do
|
||||||
|
echo "Waiting for namespace $ns to be created..."
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
echo "Namespace $ns is available"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Apply common secrets and configs
|
||||||
|
kubectl apply -f infrastructure/environments/common/configs/configmap.yaml
|
||||||
|
kubectl apply -f infrastructure/environments/common/configs/secrets.yaml
|
||||||
|
|
||||||
|
# Apply database secrets and configs
|
||||||
|
kubectl apply -f infrastructure/platform/storage/postgres/secrets/postgres-tls-secret.yaml
|
||||||
|
kubectl apply -f infrastructure/platform/storage/postgres/configs/postgres-init-config.yaml
|
||||||
|
kubectl apply -f infrastructure/platform/storage/postgres/configs/postgres-logging-config.yaml
|
||||||
|
|
||||||
|
# Apply Redis secrets
|
||||||
|
kubectl apply -f infrastructure/platform/storage/redis/secrets/redis-tls-secret.yaml
|
||||||
|
|
||||||
|
# Apply MinIO secrets and configs
|
||||||
|
kubectl apply -f infrastructure/platform/storage/minio/minio-secrets.yaml
|
||||||
|
kubectl apply -f infrastructure/platform/storage/minio/secrets/minio-tls-secret.yaml
|
||||||
|
|
||||||
|
# Apply Mail/SMTP secrets
|
||||||
|
kubectl apply -f infrastructure/platform/mail/mailu/mailu-secrets.yaml
|
||||||
|
|
||||||
|
# Apply CI/CD secrets
|
||||||
|
kubectl apply -f infrastructure/cicd/tekton/secrets/secrets.yaml
|
||||||
|
|
||||||
echo "Security configurations applied"
|
echo "Security configurations applied"
|
||||||
''',
|
''',
|
||||||
resource_deps=['dockerhub-secret'],
|
resource_deps=['prepull-base-images'], # Removed dockerhub-secret dependency
|
||||||
labels=['00-security'],
|
labels=['00-security'],
|
||||||
auto_init=True
|
auto_init=True
|
||||||
)
|
)
|
||||||
|
|
||||||
# Verify TLS certificates are mounted correctly
|
# Verify TLS certificates are mounted correctly
|
||||||
local_resource(
|
|
||||||
'verify-tls',
|
|
||||||
cmd='''
|
|
||||||
echo "Verifying TLS configuration..."
|
|
||||||
sleep 5 # Wait for pods to be ready
|
|
||||||
|
|
||||||
# Check if auth-db pod exists and has TLS certs
|
|
||||||
AUTH_POD=$(kubectl get pods -n bakery-ia -l app.kubernetes.io/name=auth-db -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || echo "")
|
|
||||||
|
|
||||||
if [ -n "$AUTH_POD" ]; then
|
|
||||||
echo " Checking PostgreSQL TLS certificates..."
|
|
||||||
kubectl exec -n bakery-ia "$AUTH_POD" -- ls -la /tls/ 2>/dev/null && \
|
|
||||||
echo " PostgreSQL TLS certificates mounted" || \
|
|
||||||
echo " PostgreSQL TLS certificates not found (pods may still be starting)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if redis pod exists and has TLS certs
|
|
||||||
REDIS_POD=$(kubectl get pods -n bakery-ia -l app.kubernetes.io/name=redis -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || echo "")
|
|
||||||
|
|
||||||
if [ -n "$REDIS_POD" ]; then
|
|
||||||
echo " Checking Redis TLS certificates..."
|
|
||||||
kubectl exec -n bakery-ia "$REDIS_POD" -- ls -la /tls/ 2>/dev/null && \
|
|
||||||
echo " Redis TLS certificates mounted" || \
|
|
||||||
echo " Redis TLS certificates not found (pods may still be starting)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "TLS verification complete"
|
|
||||||
''',
|
|
||||||
resource_deps=['auth-db', 'redis'],
|
|
||||||
auto_init=True,
|
|
||||||
labels=['00-security']
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify PVCs are bound
|
|
||||||
local_resource(
|
|
||||||
'verify-pvcs',
|
|
||||||
cmd='''
|
|
||||||
echo "Verifying PersistentVolumeClaims..."
|
|
||||||
kubectl get pvc -n bakery-ia | grep -E "NAME|db-pvc" || echo " PVCs not yet bound"
|
|
||||||
PVC_COUNT=$(kubectl get pvc -n bakery-ia -o json | jq '.items | length')
|
|
||||||
echo " Found $PVC_COUNT PVCs"
|
|
||||||
echo "PVC verification complete"
|
|
||||||
''',
|
|
||||||
resource_deps=['auth-db'],
|
|
||||||
auto_init=True,
|
|
||||||
labels=['00-security']
|
|
||||||
)
|
|
||||||
|
|
||||||
# Install and verify cert-manager
|
|
||||||
local_resource(
|
|
||||||
'cert-manager-install',
|
|
||||||
cmd='''
|
|
||||||
echo "Installing cert-manager..."
|
|
||||||
|
|
||||||
# Check if cert-manager CRDs already exist
|
|
||||||
if kubectl get crd certificates.cert-manager.io >/dev/null 2>&1; then
|
|
||||||
echo " cert-manager CRDs already installed"
|
|
||||||
else
|
|
||||||
echo " Installing cert-manager v1.13.2..."
|
|
||||||
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml
|
|
||||||
|
|
||||||
echo " Waiting for cert-manager to be ready..."
|
|
||||||
kubectl wait --for=condition=available --timeout=120s deployment/cert-manager -n cert-manager
|
|
||||||
kubectl wait --for=condition=available --timeout=120s deployment/cert-manager-webhook -n cert-manager
|
|
||||||
|
|
||||||
echo " cert-manager installed and ready"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "cert-manager verification complete"
|
|
||||||
''',
|
|
||||||
labels=['00-security'],
|
|
||||||
auto_init=True
|
|
||||||
)
|
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# LOAD KUBERNETES MANIFESTS
|
# LOAD KUBERNETES MANIFESTS
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
k8s_yaml(kustomize('infrastructure/kubernetes/overlays/dev'))
|
# Load the main kustomize overlay for the dev environment
|
||||||
|
k8s_yaml(kustomize('infrastructure/environments/dev/k8s-manifests'))
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# DOCKER BUILD HELPERS
|
# DOCKER BUILD HELPERS
|
||||||
@@ -509,6 +482,9 @@ k8s_resource('nominatim', labels=['01-infrastructure'])
|
|||||||
k8s_resource('minio', resource_deps=['security-setup'], labels=['01-infrastructure'])
|
k8s_resource('minio', resource_deps=['security-setup'], labels=['01-infrastructure'])
|
||||||
k8s_resource('minio-bucket-init', resource_deps=['minio'], labels=['01-infrastructure'])
|
k8s_resource('minio-bucket-init', resource_deps=['minio'], labels=['01-infrastructure'])
|
||||||
|
|
||||||
|
# Mail Infrastructure (Mailu)
|
||||||
|
k8s_resource('mailu-front', resource_deps=['security-setup'], labels=['01-infrastructure'])
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# MONITORING RESOURCES - SigNoz (Unified Observability)
|
# MONITORING RESOURCES - SigNoz (Unified Observability)
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
@@ -520,15 +496,6 @@ local_resource(
|
|||||||
echo "Deploying SigNoz Monitoring Stack..."
|
echo "Deploying SigNoz Monitoring Stack..."
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Ensure Docker Hub secret exists in bakery-ia namespace
|
|
||||||
echo "Ensuring Docker Hub secret exists in bakery-ia namespace..."
|
|
||||||
if ! kubectl get secret dockerhub-creds -n bakery-ia &>/dev/null; then
|
|
||||||
echo " Docker Hub secret not found, attempting to create..."
|
|
||||||
./infrastructure/kubernetes/create-dockerhub-secret.sh || echo " Continuing without Docker Hub authentication..."
|
|
||||||
else
|
|
||||||
echo " Docker Hub secret exists"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if SigNoz is already deployed
|
# Check if SigNoz is already deployed
|
||||||
if helm list -n bakery-ia | grep -q signoz; then
|
if helm list -n bakery-ia | grep -q signoz; then
|
||||||
@@ -544,7 +511,7 @@ local_resource(
|
|||||||
# Install SigNoz with custom values in the bakery-ia namespace
|
# Install SigNoz with custom values in the bakery-ia namespace
|
||||||
helm upgrade --install signoz signoz/signoz \
|
helm upgrade --install signoz signoz/signoz \
|
||||||
-n bakery-ia \
|
-n bakery-ia \
|
||||||
-f infrastructure/helm/signoz-values-dev.yaml \
|
-f infrastructure/monitoring/signoz/signoz-values-dev.yaml \
|
||||||
--timeout 10m \
|
--timeout 10m \
|
||||||
--wait
|
--wait
|
||||||
|
|
||||||
@@ -568,43 +535,6 @@ local_resource(
|
|||||||
auto_init=False,
|
auto_init=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Track SigNoz pods in Tilt UI using workload tracking
|
|
||||||
# These will automatically discover pods once SigNoz is deployed
|
|
||||||
local_resource(
|
|
||||||
'signoz-status',
|
|
||||||
cmd='''
|
|
||||||
echo "SigNoz Status Check"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check pod status
|
|
||||||
echo "Current SigNoz pods:"
|
|
||||||
kubectl get pods -n bakery-ia -l app.kubernetes.io/instance=signoz -o wide 2>/dev/null || echo "No pods found"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "SigNoz Services:"
|
|
||||||
kubectl get svc -n bakery-ia -l app.kubernetes.io/instance=signoz 2>/dev/null || echo "No services found"
|
|
||||||
|
|
||||||
# Check if all pods are ready
|
|
||||||
TOTAL_PODS=$(kubectl get pods -n bakery-ia -l app.kubernetes.io/instance=signoz --no-headers 2>/dev/null | wc -l | tr -d ' ')
|
|
||||||
READY_PODS=$(kubectl get pods -n bakery-ia -l app.kubernetes.io/instance=signoz --field-selector=status.phase=Running --no-headers 2>/dev/null | wc -l | tr -d ' ')
|
|
||||||
|
|
||||||
if [ "$TOTAL_PODS" -gt 0 ]; then
|
|
||||||
echo ""
|
|
||||||
echo "Pod Status: $READY_PODS/$TOTAL_PODS ready"
|
|
||||||
|
|
||||||
if [ "$READY_PODS" -eq "$TOTAL_PODS" ]; then
|
|
||||||
echo "All SigNoz pods are running!"
|
|
||||||
echo ""
|
|
||||||
echo "Access SigNoz at: https://monitoring.bakery-ia.local"
|
|
||||||
echo "Credentials: admin / admin"
|
|
||||||
else
|
|
||||||
echo "Waiting for pods to become ready..."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
''',
|
|
||||||
labels=['05-monitoring'],
|
|
||||||
auto_init=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Optional exporters (in monitoring namespace) - DISABLED since using SigNoz
|
# Optional exporters (in monitoring namespace) - DISABLED since using SigNoz
|
||||||
# k8s_resource('node-exporter', labels=['05-monitoring'])
|
# k8s_resource('node-exporter', labels=['05-monitoring'])
|
||||||
@@ -774,6 +704,98 @@ watch_settings(
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# CI/CD INFRASTRUCTURE - MANUAL TRIGGERS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Tekton Pipelines - Manual trigger for local development
|
||||||
|
local_resource(
|
||||||
|
'tekton-pipelines',
|
||||||
|
cmd='''
|
||||||
|
echo "Setting up Tekton Pipelines for CI/CD..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if Tekton CRDs are already installed
|
||||||
|
if kubectl get crd pipelines.tekton.dev >/dev/null 2>&1; then
|
||||||
|
echo " Tekton CRDs already installed"
|
||||||
|
else
|
||||||
|
echo " Installing Tekton v0.57.0..."
|
||||||
|
kubectl apply -f https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml
|
||||||
|
|
||||||
|
echo " Waiting for Tekton to be ready..."
|
||||||
|
kubectl wait --for=condition=available --timeout=180s deployment/tekton-pipelines-controller -n tekton-pipelines
|
||||||
|
kubectl wait --for=condition=available --timeout=180s deployment/tekton-pipelines-webhook -n tekton-pipelines
|
||||||
|
|
||||||
|
echo " Tekton installed and ready"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Applying Tekton configurations..."
|
||||||
|
kubectl apply -f infrastructure/cicd/tekton/kustomization.yaml
|
||||||
|
kubectl apply -f infrastructure/cicd/tekton/rbac/
|
||||||
|
kubectl apply -f infrastructure/cicd/tekton/tasks/
|
||||||
|
kubectl apply -f infrastructure/cicd/tekton/pipelines/
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Tekton setup complete!"
|
||||||
|
echo "To check status: kubectl get pods -n tekton-pipelines"
|
||||||
|
''',
|
||||||
|
labels=['99-cicd'],
|
||||||
|
auto_init=False, # Manual trigger only
|
||||||
|
)
|
||||||
|
|
||||||
|
# Flux CD - Manual trigger for GitOps
|
||||||
|
local_resource(
|
||||||
|
'flux-cd',
|
||||||
|
cmd='''
|
||||||
|
echo "Setting up Flux CD for GitOps..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if Flux CRDs are already installed
|
||||||
|
if kubectl get crd gitrepositories.source.toolkit.fluxcd.io >/dev/null 2>&1; then
|
||||||
|
echo " Flux CRDs already installed"
|
||||||
|
else
|
||||||
|
echo " Installing Flux v2.2.3..."
|
||||||
|
curl -sL https://fluxcd.io/install.sh | sudo bash
|
||||||
|
flux install --version=latest
|
||||||
|
|
||||||
|
echo " Flux installed and ready"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Applying Flux configurations..."
|
||||||
|
kubectl apply -f infrastructure/cicd/flux/
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Flux setup complete!"
|
||||||
|
echo "To check status: flux check"
|
||||||
|
''',
|
||||||
|
labels=['99-cicd'],
|
||||||
|
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 ""
|
||||||
|
|
||||||
|
# Apply Gitea configurations
|
||||||
|
kubectl create namespace gitea || true
|
||||||
|
kubectl apply -f infrastructure/cicd/gitea/
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Gitea setup complete!"
|
||||||
|
echo "Access Gitea at: http://gitea.local (add to /etc/hosts)"
|
||||||
|
echo "Default credentials: admin/admin123 (change after first login)"
|
||||||
|
echo "To check status: kubectl get pods -n gitea"
|
||||||
|
''',
|
||||||
|
labels=['99-cicd'],
|
||||||
|
auto_init=False, # Manual trigger only
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# STARTUP SUMMARY
|
# STARTUP SUMMARY
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
@@ -804,11 +826,16 @@ Access your application:
|
|||||||
|
|
||||||
SigNoz (Unified Observability):
|
SigNoz (Unified Observability):
|
||||||
Deploy via Tilt: Trigger 'signoz-deployment' resource
|
Deploy via Tilt: Trigger 'signoz-deployment' resource
|
||||||
Manual deploy: ./infrastructure/helm/deploy-signoz.sh dev
|
Manual deploy: ./infrastructure/monitoring/signoz/deploy-signoz.sh dev
|
||||||
Access (if deployed): https://monitoring.bakery-ia.local
|
Access (if deployed): https://monitoring.bakery-ia.local
|
||||||
Username: admin
|
Username: admin
|
||||||
Password: admin
|
Password: admin
|
||||||
|
|
||||||
|
CI/CD Infrastructure (Manual Triggers):
|
||||||
|
Tekton: Trigger 'tekton-pipelines' resource
|
||||||
|
Flux: Trigger 'flux-cd' resource
|
||||||
|
Gitea: Trigger 'gitea' resource
|
||||||
|
|
||||||
Verify security:
|
Verify security:
|
||||||
kubectl get pvc -n bakery-ia
|
kubectl get pvc -n bakery-ia
|
||||||
kubectl get secrets -n bakery-ia | grep tls
|
kubectl get secrets -n bakery-ia | grep tls
|
||||||
|
|||||||
@@ -685,7 +685,7 @@ kubectl scale deployment auth-service -n bakery-ia --replicas=2
|
|||||||
# 2. Install MicroK8s (follow pilot launch guide)
|
# 2. Install MicroK8s (follow pilot launch guide)
|
||||||
# 3. Copy latest backup to new VPS
|
# 3. Copy latest backup to new VPS
|
||||||
# 4. Deploy infrastructure and databases
|
# 4. Deploy infrastructure and databases
|
||||||
kubectl apply -k infrastructure/kubernetes/overlays/prod
|
kubectl apply -k infrastructure/environments/prod/k8s-manifests
|
||||||
|
|
||||||
# 5. Wait for databases to be ready
|
# 5. Wait for databases to be ready
|
||||||
kubectl wait --for=condition=ready pod -l app.kubernetes.io/component=database -n bakery-ia
|
kubectl wait --for=condition=ready pod -l app.kubernetes.io/component=database -n bakery-ia
|
||||||
@@ -699,7 +699,7 @@ for backup in /backups/latest/*.sql; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
# 7. Deploy services
|
# 7. Deploy services
|
||||||
kubectl apply -k infrastructure/kubernetes/overlays/prod
|
kubectl apply -k infrastructure/environments/prod/k8s-manifests
|
||||||
|
|
||||||
# 8. Update DNS to point to new VPS
|
# 8. Update DNS to point to new VPS
|
||||||
# 9. Verify all services healthy
|
# 9. Verify all services healthy
|
||||||
@@ -830,12 +830,12 @@ nproc
|
|||||||
kubectl scale deployment orders-service -n bakery-ia --replicas=5
|
kubectl scale deployment orders-service -n bakery-ia --replicas=5
|
||||||
|
|
||||||
# Or update in kustomization for persistence
|
# Or update in kustomization for persistence
|
||||||
# Edit: infrastructure/kubernetes/overlays/prod/kustomization.yaml
|
# Edit: infrastructure/environments/prod/k8s-manifests/kustomization.yaml
|
||||||
replicas:
|
replicas:
|
||||||
- name: orders-service
|
- name: orders-service
|
||||||
count: 5
|
count: 5
|
||||||
|
|
||||||
kubectl apply -k infrastructure/kubernetes/overlays/prod
|
kubectl apply -k infrastructure/environments/prod/k8s-manifests
|
||||||
```
|
```
|
||||||
|
|
||||||
### Auto-Scaling (HPA)
|
### Auto-Scaling (HPA)
|
||||||
@@ -976,7 +976,7 @@ resources:
|
|||||||
memory: "1Gi" # Increased from 512Mi
|
memory: "1Gi" # Increased from 512Mi
|
||||||
|
|
||||||
# 4. Redeploy
|
# 4. Redeploy
|
||||||
kubectl apply -k infrastructure/kubernetes/overlays/prod
|
kubectl apply -k infrastructure/environments/prod/k8s-manifests
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Incident: Certificate Expired
|
#### Incident: Certificate Expired
|
||||||
|
|||||||
@@ -324,12 +324,12 @@ log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '
|
|||||||
**Renewal Process:**
|
**Renewal Process:**
|
||||||
```bash
|
```bash
|
||||||
# 1. Regenerate certificates (90 days before expiry)
|
# 1. Regenerate certificates (90 days before expiry)
|
||||||
cd infrastructure/tls && ./generate-certificates.sh
|
cd infrastructure/security/certificates && ./generate-certificates.sh
|
||||||
|
|
||||||
# 2. Update Kubernetes secrets
|
# 2. Update Kubernetes secrets
|
||||||
kubectl delete secret postgres-tls redis-tls -n bakery-ia
|
kubectl delete secret postgres-tls redis-tls -n bakery-ia
|
||||||
kubectl apply -f infrastructure/kubernetes/base/secrets/postgres-tls-secret.yaml
|
kubectl apply -f infrastructure/environments/dev/k8s-manifests/base/secrets/postgres-tls-secret.yaml
|
||||||
kubectl apply -f infrastructure/kubernetes/base/secrets/redis-tls-secret.yaml
|
kubectl apply -f infrastructure/environments/dev/k8s-manifests/base/secrets/redis-tls-secret.yaml
|
||||||
|
|
||||||
# 3. Restart database pods (automatic)
|
# 3. Restart database pods (automatic)
|
||||||
kubectl rollout restart deployment -l app.kubernetes.io/component=database -n bakery-ia
|
kubectl rollout restart deployment -l app.kubernetes.io/component=database -n bakery-ia
|
||||||
@@ -351,7 +351,7 @@ kubectl rollout restart deployment -l app.kubernetes.io/component=database -n ba
|
|||||||
./scripts/update-k8s-secrets.sh
|
./scripts/update-k8s-secrets.sh
|
||||||
|
|
||||||
# 4. Apply secrets
|
# 4. Apply secrets
|
||||||
kubectl apply -f infrastructure/kubernetes/base/secrets.yaml
|
kubectl apply -f infrastructure/environments/common/configs/secrets.yaml
|
||||||
|
|
||||||
# 5. Restart databases and services
|
# 5. Restart databases and services
|
||||||
kubectl rollout restart deployment -n bakery-ia
|
kubectl rollout restart deployment -n bakery-ia
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
# Add this stage at the top of each service Dockerfile
|
# Add this stage at the top of each service Dockerfile
|
||||||
FROM python:3.11-slim AS shared
|
FROM localhost:5000/python_3.11-slim AS shared
|
||||||
WORKDIR /shared
|
WORKDIR /shared
|
||||||
COPY shared/ /shared/
|
COPY shared/ /shared/
|
||||||
|
|
||||||
# Then your main service stage
|
# Then your main service stage
|
||||||
FROM python:3.11-slim
|
FROM localhost:5000/python_3.11-slim
|
||||||
|
|
||||||
# Create non-root user for security
|
# Create non-root user for security
|
||||||
RUN groupadd -r appgroup && useradd -r -g appgroup appuser
|
RUN groupadd -r appgroup && useradd -r -g appgroup appuser
|
||||||
|
|||||||
119
infrastructure/NAMESPACES.md
Normal file
119
infrastructure/NAMESPACES.md
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
# Bakery-IA Namespace Management
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This document explains the namespace strategy for the Bakery-IA platform and how to properly manage namespaces during deployment.
|
||||||
|
|
||||||
|
## Namespace Architecture
|
||||||
|
|
||||||
|
The Bakery-IA platform uses the following namespaces:
|
||||||
|
|
||||||
|
### Core Namespaces
|
||||||
|
|
||||||
|
1. **`bakery-ia`** - Main application namespace
|
||||||
|
- Contains all microservices, databases, and application components
|
||||||
|
- Defined in: `infrastructure/namespaces/bakery-ia.yaml`
|
||||||
|
|
||||||
|
2. **`tekton-pipelines`** - CI/CD pipeline namespace
|
||||||
|
- Contains Tekton pipeline resources, tasks, and triggers
|
||||||
|
- Defined in: `infrastructure/namespaces/tekton-pipelines.yaml`
|
||||||
|
|
||||||
|
3. **`flux-system`** - GitOps namespace
|
||||||
|
- Contains Flux CD components for GitOps deployments
|
||||||
|
- Defined in: `infrastructure/namespaces/flux-system.yaml`
|
||||||
|
|
||||||
|
### Infrastructure Namespaces
|
||||||
|
|
||||||
|
Additional namespaces may be created for:
|
||||||
|
- Monitoring components
|
||||||
|
- Logging components
|
||||||
|
- Security components
|
||||||
|
|
||||||
|
## Deployment Order
|
||||||
|
|
||||||
|
**CRITICAL**: Namespaces must be created BEFORE any resources that depend on them.
|
||||||
|
|
||||||
|
### Correct Deployment Sequence
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Create namespaces first
|
||||||
|
kubectl apply -f infrastructure/namespaces/
|
||||||
|
|
||||||
|
# 2. Apply common configurations (depends on bakery-ia namespace)
|
||||||
|
kubectl apply -f infrastructure/environments/common/configs/
|
||||||
|
|
||||||
|
# 3. Apply platform components
|
||||||
|
kubectl apply -f infrastructure/platform/
|
||||||
|
|
||||||
|
# 4. Apply CI/CD components (depends on tekton-pipelines and flux-system)
|
||||||
|
kubectl apply -f infrastructure/cicd/
|
||||||
|
|
||||||
|
# 5. Apply monitoring components
|
||||||
|
kubectl apply -f infrastructure/monitoring/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Issues and Solutions
|
||||||
|
|
||||||
|
### Issue: "namespace not found" errors
|
||||||
|
|
||||||
|
**Symptoms**: Errors like:
|
||||||
|
```
|
||||||
|
Error from server (NotFound): error when creating "path/to/resource.yaml": namespaces "[namespace-name]" not found
|
||||||
|
```
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
|
||||||
|
1. **Ensure namespaces are created first** - Use the deployment script that applies namespaces before other resources
|
||||||
|
|
||||||
|
2. **Check for templating issues** - If you see names like `[redacted secret rabbitmq-secrets:RABBITMQ_USER]-ia`, there may be environment variable substitution happening incorrectly
|
||||||
|
|
||||||
|
3. **Verify namespace YAML files** - Ensure the namespace files exist and are properly formatted
|
||||||
|
|
||||||
|
### Issue: Resource conflicts across namespaces
|
||||||
|
|
||||||
|
**Solution**: Use proper namespace isolation and RBAC policies to prevent cross-namespace conflicts.
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Namespace Isolation**: Keep resources properly isolated by namespace
|
||||||
|
2. **RBAC**: Use namespace-specific RBAC roles and bindings
|
||||||
|
3. **Resource Quotas**: Apply resource quotas per namespace
|
||||||
|
4. **Network Policies**: Use network policies to control cross-namespace communication
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Verify namespaces exist
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get namespaces
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check namespace labels
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get namespace bakery-ia --show-labels
|
||||||
|
```
|
||||||
|
|
||||||
|
### View namespace events
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl describe namespace bakery-ia
|
||||||
|
```
|
||||||
|
|
||||||
|
## Migration from Old Structure
|
||||||
|
|
||||||
|
If you're migrating from the old structure where namespaces were scattered across different directories:
|
||||||
|
|
||||||
|
1. **Remove old namespace files** from:
|
||||||
|
- `infrastructure/environments/common/configs/namespace.yaml`
|
||||||
|
- `infrastructure/cicd/flux/namespace.yaml`
|
||||||
|
|
||||||
|
2. **Update kustomization files** to reference the centralized namespace files
|
||||||
|
|
||||||
|
3. **Use the new deployment script** that follows the correct order
|
||||||
|
|
||||||
|
## Future Enhancements
|
||||||
|
|
||||||
|
- Add namespace lifecycle management
|
||||||
|
- Implement namespace cleanup scripts
|
||||||
|
- Add namespace validation checks to CI/CD pipelines
|
||||||
57
infrastructure/README.md
Normal file
57
infrastructure/README.md
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
# Bakery-IA Infrastructure
|
||||||
|
|
||||||
|
This directory contains all infrastructure-as-code for the Bakery-IA project, organized according to best practices for maintainability and scalability.
|
||||||
|
|
||||||
|
## Directory Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
infrastructure/
|
||||||
|
├── environments/ # Environment-specific configurations
|
||||||
|
│ ├── dev/ # Development environment
|
||||||
|
│ │ ├── k8s-manifests/ # Kubernetes manifests for dev
|
||||||
|
│ │ └── values/ # Environment-specific values
|
||||||
|
│ ├── staging/ # Staging environment
|
||||||
|
│ │ ├── k8s-manifests/
|
||||||
|
│ │ └── values/
|
||||||
|
│ └── prod/ # Production environment
|
||||||
|
│ ├── k8s-manifests/
|
||||||
|
│ ├── terraform/ # Production-specific IaC
|
||||||
|
│ └── values/
|
||||||
|
├── platform/ # Platform-level infrastructure
|
||||||
|
│ ├── cluster/ # Cluster configuration (EKS, Kind)
|
||||||
|
│ ├── networking/ # Network configuration
|
||||||
|
│ ├── security/ # Security policies and TLS
|
||||||
|
│ └── storage/ # Storage configuration
|
||||||
|
├── services/ # Application services
|
||||||
|
│ ├── databases/ # Database configurations
|
||||||
|
│ ├── api-gateway/ # API gateway configuration
|
||||||
|
│ └── microservices/ # Individual microservice configs
|
||||||
|
├── monitoring/ # Observability stack
|
||||||
|
│ └── signoz/ # SigNoz configuration
|
||||||
|
├── cicd/ # CI/CD pipeline components
|
||||||
|
├── security/ # Security configurations
|
||||||
|
├── scripts/ # Automation scripts
|
||||||
|
└── docs/ # Infrastructure documentation
|
||||||
|
```
|
||||||
|
|
||||||
|
## Environments
|
||||||
|
|
||||||
|
Each environment (dev, staging, prod) has its own configuration with appropriate isolation and security settings.
|
||||||
|
|
||||||
|
## Services
|
||||||
|
|
||||||
|
Services are organized by business domain with clear separation between databases, microservices, and infrastructure components.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
1. **Local Development**: Use `tilt up` to start the development environment
|
||||||
|
2. **Deployment**: Use `skaffold run` to deploy to your target environment
|
||||||
|
3. **CI/CD**: Tekton pipelines manage automated deployments
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
Security configurations are centralized in the `security/` directory with:
|
||||||
|
- TLS certificates and rotation scripts
|
||||||
|
- Network policies
|
||||||
|
- RBAC configurations
|
||||||
|
- Compliance checks
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
# Flux Kustomization for Bakery-IA Production Deployment
|
|
||||||
# This resource tells Flux how to deploy the application
|
|
||||||
|
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
|
||||||
kind: Kustomization
|
|
||||||
metadata:
|
|
||||||
name: bakery-ia-prod
|
|
||||||
namespace: flux-system
|
|
||||||
spec:
|
|
||||||
interval: 5m
|
|
||||||
path: ./infrastructure/kubernetes/overlays/prod
|
|
||||||
prune: true
|
|
||||||
sourceRef:
|
|
||||||
kind: GitRepository
|
|
||||||
name: bakery-ia
|
|
||||||
targetNamespace: bakery-ia
|
|
||||||
timeout: 5m
|
|
||||||
retryInterval: 1m
|
|
||||||
healthChecks:
|
|
||||||
- apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
name: auth-service
|
|
||||||
namespace: bakery-ia
|
|
||||||
- apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
name: gateway
|
|
||||||
namespace: bakery-ia
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
# Gitea Ingress configuration for Bakery-IA CI/CD
|
|
||||||
# This provides external access to Gitea within the cluster
|
|
||||||
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
name: gitea-ingress
|
|
||||||
namespace: gitea
|
|
||||||
annotations:
|
|
||||||
nginx.ingress.kubernetes.io/rewrite-target: /
|
|
||||||
nginx.ingress.kubernetes.io/proxy-body-size: "0"
|
|
||||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
|
|
||||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
|
|
||||||
spec:
|
|
||||||
rules:
|
|
||||||
- host: gitea.bakery-ia.local
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- path: /
|
|
||||||
pathType: Prefix
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: gitea-http
|
|
||||||
port:
|
|
||||||
number: 3000
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
# Gitea Helm values configuration for Bakery-IA CI/CD
|
|
||||||
# This configuration sets up Gitea with registry support and appropriate storage
|
|
||||||
|
|
||||||
service:
|
|
||||||
type: ClusterIP
|
|
||||||
httpPort: 3000
|
|
||||||
sshPort: 2222
|
|
||||||
|
|
||||||
persistence:
|
|
||||||
enabled: true
|
|
||||||
size: 50Gi
|
|
||||||
storageClass: "microk8s-hostpath"
|
|
||||||
|
|
||||||
gitea:
|
|
||||||
config:
|
|
||||||
server:
|
|
||||||
DOMAIN: gitea.bakery-ia.local
|
|
||||||
SSH_DOMAIN: gitea.bakery-ia.local
|
|
||||||
ROOT_URL: http://gitea.bakery-ia.local
|
|
||||||
repository:
|
|
||||||
ENABLE_PUSH_CREATE_USER: true
|
|
||||||
ENABLE_PUSH_CREATE_ORG: true
|
|
||||||
registry:
|
|
||||||
ENABLED: true
|
|
||||||
|
|
||||||
postgresql:
|
|
||||||
enabled: true
|
|
||||||
persistence:
|
|
||||||
size: 20Gi
|
|
||||||
|
|
||||||
# Resource configuration for production environment
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpu: 1000m
|
|
||||||
memory: 1Gi
|
|
||||||
requests:
|
|
||||||
cpu: 500m
|
|
||||||
memory: 512Mi
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
# OpenTelemetry Collector for Bakery-IA CI/CD Monitoring
|
|
||||||
# This collects metrics and traces from Tekton pipelines
|
|
||||||
|
|
||||||
apiVersion: opentelemetry.io/v1alpha1
|
|
||||||
kind: OpenTelemetryCollector
|
|
||||||
metadata:
|
|
||||||
name: tekton-otel
|
|
||||||
namespace: tekton-pipelines
|
|
||||||
spec:
|
|
||||||
config: |
|
|
||||||
receivers:
|
|
||||||
otlp:
|
|
||||||
protocols:
|
|
||||||
grpc:
|
|
||||||
endpoint: 0.0.0.0:4317
|
|
||||||
http:
|
|
||||||
endpoint: 0.0.0.0:4318
|
|
||||||
prometheus:
|
|
||||||
config:
|
|
||||||
scrape_configs:
|
|
||||||
- job_name: 'tekton-pipelines'
|
|
||||||
scrape_interval: 30s
|
|
||||||
static_configs:
|
|
||||||
- targets: ['tekton-pipelines-controller.tekton-pipelines.svc.cluster.local:9090']
|
|
||||||
|
|
||||||
processors:
|
|
||||||
batch:
|
|
||||||
timeout: 5s
|
|
||||||
send_batch_size: 1000
|
|
||||||
memory_limiter:
|
|
||||||
check_interval: 2s
|
|
||||||
limit_percentage: 75
|
|
||||||
spike_limit_percentage: 20
|
|
||||||
|
|
||||||
exporters:
|
|
||||||
otlp:
|
|
||||||
endpoint: "signoz-otel-collector.monitoring.svc.cluster.local:4317"
|
|
||||||
tls:
|
|
||||||
insecure: true
|
|
||||||
retry_on_failure:
|
|
||||||
enabled: true
|
|
||||||
initial_interval: 5s
|
|
||||||
max_interval: 30s
|
|
||||||
max_elapsed_time: 300s
|
|
||||||
logging:
|
|
||||||
logLevel: debug
|
|
||||||
|
|
||||||
service:
|
|
||||||
pipelines:
|
|
||||||
traces:
|
|
||||||
receivers: [otlp]
|
|
||||||
processors: [memory_limiter, batch]
|
|
||||||
exporters: [otlp, logging]
|
|
||||||
metrics:
|
|
||||||
receivers: [otlp, prometheus]
|
|
||||||
processors: [memory_limiter, batch]
|
|
||||||
exporters: [otlp, logging]
|
|
||||||
telemetry:
|
|
||||||
logs:
|
|
||||||
level: "info"
|
|
||||||
encoding: "json"
|
|
||||||
|
|
||||||
mode: deployment
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpu: 500m
|
|
||||||
memory: 512Mi
|
|
||||||
requests:
|
|
||||||
cpu: 200m
|
|
||||||
memory: 256Mi
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
# Main CI Pipeline for Bakery-IA
|
|
||||||
# This pipeline orchestrates the build, test, and deploy process
|
|
||||||
|
|
||||||
apiVersion: tekton.dev/v1beta1
|
|
||||||
kind: Pipeline
|
|
||||||
metadata:
|
|
||||||
name: bakery-ia-ci
|
|
||||||
namespace: tekton-pipelines
|
|
||||||
spec:
|
|
||||||
workspaces:
|
|
||||||
- name: shared-workspace
|
|
||||||
- name: docker-credentials
|
|
||||||
params:
|
|
||||||
- name: git-url
|
|
||||||
type: string
|
|
||||||
description: Repository URL
|
|
||||||
- name: git-revision
|
|
||||||
type: string
|
|
||||||
description: Git revision/commit hash
|
|
||||||
- name: registry
|
|
||||||
type: string
|
|
||||||
description: Container registry URL
|
|
||||||
default: "gitea.bakery-ia.local:5000"
|
|
||||||
tasks:
|
|
||||||
- name: fetch-source
|
|
||||||
taskRef:
|
|
||||||
name: git-clone
|
|
||||||
workspaces:
|
|
||||||
- name: output
|
|
||||||
workspace: shared-workspace
|
|
||||||
params:
|
|
||||||
- name: url
|
|
||||||
value: $(params.git-url)
|
|
||||||
- name: revision
|
|
||||||
value: $(params.git-revision)
|
|
||||||
|
|
||||||
- name: detect-changes
|
|
||||||
runAfter: [fetch-source]
|
|
||||||
taskRef:
|
|
||||||
name: detect-changed-services
|
|
||||||
workspaces:
|
|
||||||
- name: source
|
|
||||||
workspace: shared-workspace
|
|
||||||
|
|
||||||
- name: build-and-push
|
|
||||||
runAfter: [detect-changes]
|
|
||||||
taskRef:
|
|
||||||
name: kaniko-build
|
|
||||||
when:
|
|
||||||
- input: "$(tasks.detect-changes.results.changed-services)"
|
|
||||||
operator: notin
|
|
||||||
values: ["none"]
|
|
||||||
workspaces:
|
|
||||||
- name: source
|
|
||||||
workspace: shared-workspace
|
|
||||||
- name: docker-credentials
|
|
||||||
workspace: docker-credentials
|
|
||||||
params:
|
|
||||||
- name: services
|
|
||||||
value: $(tasks.detect-changes.results.changed-services)
|
|
||||||
- name: registry
|
|
||||||
value: $(params.registry)
|
|
||||||
- name: git-revision
|
|
||||||
value: $(params.git-revision)
|
|
||||||
|
|
||||||
- name: update-gitops-manifests
|
|
||||||
runAfter: [build-and-push]
|
|
||||||
taskRef:
|
|
||||||
name: update-gitops
|
|
||||||
when:
|
|
||||||
- input: "$(tasks.detect-changes.results.changed-services)"
|
|
||||||
operator: notin
|
|
||||||
values: ["none"]
|
|
||||||
workspaces:
|
|
||||||
- name: source
|
|
||||||
workspace: shared-workspace
|
|
||||||
params:
|
|
||||||
- name: services
|
|
||||||
value: $(tasks.detect-changes.results.changed-services)
|
|
||||||
- name: registry
|
|
||||||
value: $(params.registry)
|
|
||||||
- name: git-revision
|
|
||||||
value: $(params.git-revision)
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
# Tekton Detect Changed Services Task for Bakery-IA CI/CD
|
|
||||||
# This task identifies which services have changed in the repository
|
|
||||||
|
|
||||||
apiVersion: tekton.dev/v1beta1
|
|
||||||
kind: Task
|
|
||||||
metadata:
|
|
||||||
name: detect-changed-services
|
|
||||||
namespace: tekton-pipelines
|
|
||||||
spec:
|
|
||||||
workspaces:
|
|
||||||
- name: source
|
|
||||||
results:
|
|
||||||
- name: changed-services
|
|
||||||
description: Comma-separated list of changed services
|
|
||||||
steps:
|
|
||||||
- name: detect
|
|
||||||
image: alpine/git
|
|
||||||
script: |
|
|
||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
cd $(workspaces.source.path)
|
|
||||||
|
|
||||||
echo "Detecting changed files..."
|
|
||||||
# Get list of changed files compared to previous commit
|
|
||||||
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD 2>/dev/null || git diff --name-only HEAD)
|
|
||||||
|
|
||||||
echo "Changed files: $CHANGED_FILES"
|
|
||||||
|
|
||||||
# Map files to services
|
|
||||||
CHANGED_SERVICES=()
|
|
||||||
for file in $CHANGED_FILES; do
|
|
||||||
if [[ $file == services/* ]]; then
|
|
||||||
SERVICE=$(echo $file | cut -d'/' -f2)
|
|
||||||
# Only add unique service names
|
|
||||||
if [[ ! " ${CHANGED_SERVICES[@]} " =~ " ${SERVICE} " ]]; then
|
|
||||||
CHANGED_SERVICES+=("$SERVICE")
|
|
||||||
fi
|
|
||||||
elif [[ $file == frontend/* ]]; then
|
|
||||||
CHANGED_SERVICES+=("frontend")
|
|
||||||
break
|
|
||||||
elif [[ $file == gateway/* ]]; then
|
|
||||||
CHANGED_SERVICES+=("gateway")
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# If no specific services changed, check for infrastructure changes
|
|
||||||
if [ ${#CHANGED_SERVICES[@]} -eq 0 ]; then
|
|
||||||
for file in $CHANGED_FILES; do
|
|
||||||
if [[ $file == infrastructure/* ]]; then
|
|
||||||
CHANGED_SERVICES+=("infrastructure")
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Output result
|
|
||||||
if [ ${#CHANGED_SERVICES[@]} -eq 0 ]; then
|
|
||||||
echo "No service changes detected"
|
|
||||||
echo "none" | tee $(results.changed-services.path)
|
|
||||||
else
|
|
||||||
echo "Detected changes in services: ${CHANGED_SERVICES[@]}"
|
|
||||||
echo $(printf "%s," "${CHANGED_SERVICES[@]}" | sed 's/,$//') | tee $(results.changed-services.path)
|
|
||||||
fi
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
# Tekton Git Clone Task for Bakery-IA CI/CD
|
|
||||||
# This task clones the source code repository
|
|
||||||
|
|
||||||
apiVersion: tekton.dev/v1beta1
|
|
||||||
kind: Task
|
|
||||||
metadata:
|
|
||||||
name: git-clone
|
|
||||||
namespace: tekton-pipelines
|
|
||||||
spec:
|
|
||||||
workspaces:
|
|
||||||
- name: output
|
|
||||||
params:
|
|
||||||
- name: url
|
|
||||||
type: string
|
|
||||||
description: Repository URL to clone
|
|
||||||
- name: revision
|
|
||||||
type: string
|
|
||||||
description: Git revision to checkout
|
|
||||||
default: "main"
|
|
||||||
steps:
|
|
||||||
- name: clone
|
|
||||||
image: alpine/git
|
|
||||||
script: |
|
|
||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
echo "Cloning repository: $(params.url)"
|
|
||||||
git clone $(params.url) $(workspaces.output.path)
|
|
||||||
cd $(workspaces.output.path)
|
|
||||||
echo "Checking out revision: $(params.revision)"
|
|
||||||
git checkout $(params.revision)
|
|
||||||
echo "Repository cloned successfully"
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
# Tekton Kaniko Build Task for Bakery-IA CI/CD
|
|
||||||
# This task builds and pushes container images using Kaniko
|
|
||||||
|
|
||||||
apiVersion: tekton.dev/v1beta1
|
|
||||||
kind: Task
|
|
||||||
metadata:
|
|
||||||
name: kaniko-build
|
|
||||||
namespace: tekton-pipelines
|
|
||||||
spec:
|
|
||||||
workspaces:
|
|
||||||
- name: source
|
|
||||||
- name: docker-credentials
|
|
||||||
params:
|
|
||||||
- name: services
|
|
||||||
type: string
|
|
||||||
description: Comma-separated list of services to build
|
|
||||||
- name: registry
|
|
||||||
type: string
|
|
||||||
description: Container registry URL
|
|
||||||
default: "gitea.bakery-ia.local:5000"
|
|
||||||
- name: git-revision
|
|
||||||
type: string
|
|
||||||
description: Git revision for image tag
|
|
||||||
default: "latest"
|
|
||||||
steps:
|
|
||||||
- name: build-and-push
|
|
||||||
image: gcr.io/kaniko-project/executor:v1.9.0
|
|
||||||
args:
|
|
||||||
- --dockerfile=$(workspaces.source.path)/services/$(params.services)/Dockerfile
|
|
||||||
- --context=$(workspaces.source.path)
|
|
||||||
- --destination=$(params.registry)/bakery/$(params.services):$(params.git-revision)
|
|
||||||
- --verbosity=info
|
|
||||||
volumeMounts:
|
|
||||||
- name: docker-config
|
|
||||||
mountPath: /kaniko/.docker
|
|
||||||
securityContext:
|
|
||||||
runAsUser: 0
|
|
||||||
volumes:
|
|
||||||
- name: docker-config
|
|
||||||
emptyDir: {}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
# Tekton Update GitOps Manifests Task for Bakery-IA CI/CD
|
|
||||||
# This task updates Kubernetes manifests with new image tags
|
|
||||||
|
|
||||||
apiVersion: tekton.dev/v1beta1
|
|
||||||
kind: Task
|
|
||||||
metadata:
|
|
||||||
name: update-gitops
|
|
||||||
namespace: tekton-pipelines
|
|
||||||
spec:
|
|
||||||
workspaces:
|
|
||||||
- name: source
|
|
||||||
params:
|
|
||||||
- name: services
|
|
||||||
type: string
|
|
||||||
description: Comma-separated list of services to update
|
|
||||||
- name: registry
|
|
||||||
type: string
|
|
||||||
description: Container registry URL
|
|
||||||
- name: git-revision
|
|
||||||
type: string
|
|
||||||
description: Git revision for image tag
|
|
||||||
steps:
|
|
||||||
- name: update-manifests
|
|
||||||
image: bitnami/kubectl
|
|
||||||
script: |
|
|
||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
cd $(workspaces.source.path)
|
|
||||||
|
|
||||||
echo "Updating GitOps manifests for services: $(params.services)"
|
|
||||||
|
|
||||||
# Split services by comma
|
|
||||||
IFS=',' read -ra SERVICES <<< "$(params.services)"
|
|
||||||
|
|
||||||
for service in "${SERVICES[@]}"; do
|
|
||||||
echo "Processing service: $service"
|
|
||||||
|
|
||||||
# Find and update Kubernetes manifests
|
|
||||||
if [ "$service" = "frontend" ]; then
|
|
||||||
# Update frontend deployment
|
|
||||||
if [ -f "infrastructure/kubernetes/overlays/prod/frontend-deployment.yaml" ]; then
|
|
||||||
sed -i "s|image:.*|image: $(params.registry)/bakery/frontend:$(params.git-revision)|g" \
|
|
||||||
"infrastructure/kubernetes/overlays/prod/frontend-deployment.yaml"
|
|
||||||
fi
|
|
||||||
elif [ "$service" = "gateway" ]; then
|
|
||||||
# Update gateway deployment
|
|
||||||
if [ -f "infrastructure/kubernetes/overlays/prod/gateway-deployment.yaml" ]; then
|
|
||||||
sed -i "s|image:.*|image: $(params.registry)/bakery/gateway:$(params.git-revision)|g" \
|
|
||||||
"infrastructure/kubernetes/overlays/prod/gateway-deployment.yaml"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# Update service deployment
|
|
||||||
DEPLOYMENT_FILE="infrastructure/kubernetes/overlays/prod/${service}-deployment.yaml"
|
|
||||||
if [ -f "$DEPLOYMENT_FILE" ]; then
|
|
||||||
sed -i "s|image:.*|image: $(params.registry)/bakery/${service}:$(params.git-revision)|g" \
|
|
||||||
"$DEPLOYMENT_FILE"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Commit changes
|
|
||||||
git config --global user.name "bakery-ia-ci"
|
|
||||||
git config --global user.email "ci@bakery-ia.local"
|
|
||||||
git add .
|
|
||||||
git commit -m "CI: Update image tags for $(params.services) to $(params.git-revision)"
|
|
||||||
git push origin HEAD
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# Tekton EventListener for Bakery-IA CI/CD
|
|
||||||
# This listener receives webhook events and triggers pipelines
|
|
||||||
|
|
||||||
apiVersion: triggers.tekton.dev/v1alpha1
|
|
||||||
kind: EventListener
|
|
||||||
metadata:
|
|
||||||
name: bakery-ia-listener
|
|
||||||
namespace: tekton-pipelines
|
|
||||||
spec:
|
|
||||||
serviceAccountName: tekton-triggers-sa
|
|
||||||
triggers:
|
|
||||||
- name: bakery-ia-gitea-trigger
|
|
||||||
bindings:
|
|
||||||
- ref: bakery-ia-trigger-binding
|
|
||||||
template:
|
|
||||||
ref: bakery-ia-trigger-template
|
|
||||||
interceptors:
|
|
||||||
- ref:
|
|
||||||
name: "gitlab"
|
|
||||||
params:
|
|
||||||
- name: "secretRef"
|
|
||||||
value:
|
|
||||||
secretName: gitea-webhook-secret
|
|
||||||
secretKey: secretToken
|
|
||||||
- name: "eventTypes"
|
|
||||||
value: ["push"]
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
# GitLab/Gitea Webhook Interceptor for Tekton Triggers
|
|
||||||
# This interceptor validates and processes Gitea webhook events
|
|
||||||
|
|
||||||
apiVersion: triggers.tekton.dev/v1alpha1
|
|
||||||
kind: ClusterInterceptor
|
|
||||||
metadata:
|
|
||||||
name: gitlab
|
|
||||||
spec:
|
|
||||||
clientConfig:
|
|
||||||
service:
|
|
||||||
name: tekton-triggers-core-interceptors
|
|
||||||
namespace: tekton-pipelines
|
|
||||||
path: "/v1/webhook/gitlab"
|
|
||||||
port: 8443
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
# Tekton TriggerBinding for Bakery-IA CI/CD
|
|
||||||
# This binding extracts parameters from Gitea webhook events
|
|
||||||
|
|
||||||
apiVersion: triggers.tekton.dev/v1alpha1
|
|
||||||
kind: TriggerBinding
|
|
||||||
metadata:
|
|
||||||
name: bakery-ia-trigger-binding
|
|
||||||
namespace: tekton-pipelines
|
|
||||||
spec:
|
|
||||||
params:
|
|
||||||
- name: git-repo-url
|
|
||||||
value: $(body.repository.clone_url)
|
|
||||||
- name: git-revision
|
|
||||||
value: $(body.head_commit.id)
|
|
||||||
- name: git-repo-name
|
|
||||||
value: $(body.repository.name)
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
# Tekton TriggerTemplate for Bakery-IA CI/CD
|
|
||||||
# This template defines how PipelineRuns are created when triggers fire
|
|
||||||
|
|
||||||
apiVersion: triggers.tekton.dev/v1alpha1
|
|
||||||
kind: TriggerTemplate
|
|
||||||
metadata:
|
|
||||||
name: bakery-ia-trigger-template
|
|
||||||
namespace: tekton-pipelines
|
|
||||||
spec:
|
|
||||||
params:
|
|
||||||
- name: git-repo-url
|
|
||||||
description: The git repository URL
|
|
||||||
- name: git-revision
|
|
||||||
description: The git revision/commit hash
|
|
||||||
- name: git-repo-name
|
|
||||||
description: The git repository name
|
|
||||||
default: "bakery-ia"
|
|
||||||
resourcetemplates:
|
|
||||||
- apiVersion: tekton.dev/v1beta1
|
|
||||||
kind: PipelineRun
|
|
||||||
metadata:
|
|
||||||
generateName: bakery-ia-ci-run-$(params.git-repo-name)-
|
|
||||||
spec:
|
|
||||||
pipelineRef:
|
|
||||||
name: bakery-ia-ci
|
|
||||||
workspaces:
|
|
||||||
- name: shared-workspace
|
|
||||||
volumeClaimTemplate:
|
|
||||||
spec:
|
|
||||||
accessModes: ["ReadWriteOnce"]
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
storage: 5Gi
|
|
||||||
- name: docker-credentials
|
|
||||||
secret:
|
|
||||||
secretName: gitea-registry-credentials
|
|
||||||
params:
|
|
||||||
- name: git-url
|
|
||||||
value: $(params.git-repo-url)
|
|
||||||
- name: git-revision
|
|
||||||
value: $(params.git-revision)
|
|
||||||
- name: registry
|
|
||||||
value: "gitea.bakery-ia.local:5000"
|
|
||||||
@@ -19,8 +19,7 @@ graph TD
|
|||||||
```
|
```
|
||||||
infrastructure/ci-cd/
|
infrastructure/ci-cd/
|
||||||
├── gitea/ # Gitea configuration (Git server + registry)
|
├── gitea/ # Gitea configuration (Git server + registry)
|
||||||
│ ├── values.yaml # Helm values for Gitea
|
│ └── values.yaml # Helm values for Gitea (ingress now in main config)
|
||||||
│ └── ingress.yaml # Ingress configuration
|
|
||||||
├── tekton/ # Tekton CI/CD pipeline configuration
|
├── tekton/ # Tekton CI/CD pipeline configuration
|
||||||
│ ├── tasks/ # Individual pipeline tasks
|
│ ├── tasks/ # Individual pipeline tasks
|
||||||
│ │ ├── git-clone.yaml
|
│ │ ├── git-clone.yaml
|
||||||
@@ -59,8 +58,8 @@ infrastructure/ci-cd/
|
|||||||
-n gitea \
|
-n gitea \
|
||||||
-f infrastructure/ci-cd/gitea/values.yaml
|
-f infrastructure/ci-cd/gitea/values.yaml
|
||||||
|
|
||||||
# Apply ingress
|
# Note: Gitea ingress is now included in the main ingress configuration
|
||||||
microk8s kubectl apply -f infrastructure/ci-cd/gitea/ingress.yaml
|
# No separate ingress needs to be applied
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Deploy Tekton**:
|
2. **Deploy Tekton**:
|
||||||
@@ -85,8 +84,8 @@ infrastructure/ci-cd/
|
|||||||
# Verify Flux installation
|
# Verify Flux installation
|
||||||
microk8s kubectl get pods -n flux-system
|
microk8s kubectl get pods -n flux-system
|
||||||
|
|
||||||
# Apply Flux configurations
|
# Apply Flux configurations using kustomize
|
||||||
microk8s kubectl apply -f infrastructure/ci-cd/flux/
|
microk8s kubectl apply -k infrastructure/ci-cd/flux/
|
||||||
```
|
```
|
||||||
|
|
||||||
### Phase 2: Configuration
|
### Phase 2: Configuration
|
||||||
76
infrastructure/cicd/flux/flux-kustomization.yaml
Normal file
76
infrastructure/cicd/flux/flux-kustomization.yaml
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
# Flux Kustomization for Bakery-IA Production Deployment
|
||||||
|
# This resource tells Flux how to deploy the application
|
||||||
|
#
|
||||||
|
# Prerequisites:
|
||||||
|
# 1. Flux CD must be installed: flux install
|
||||||
|
# 2. GitRepository 'bakery-ia' must be created and ready
|
||||||
|
# 3. Secret 'gitea-credentials' must exist in flux-system namespace
|
||||||
|
|
||||||
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
|
kind: Kustomization
|
||||||
|
metadata:
|
||||||
|
name: bakery-ia-prod
|
||||||
|
namespace: flux-system
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia
|
||||||
|
app.kubernetes.io/component: flux
|
||||||
|
spec:
|
||||||
|
# Wait for GitRepository to be ready before reconciling
|
||||||
|
dependsOn: []
|
||||||
|
interval: 5m
|
||||||
|
path: ./infrastructure/environments/prod
|
||||||
|
prune: true
|
||||||
|
sourceRef:
|
||||||
|
kind: GitRepository
|
||||||
|
name: bakery-ia
|
||||||
|
targetNamespace: bakery-ia
|
||||||
|
timeout: 10m
|
||||||
|
retryInterval: 1m
|
||||||
|
wait: true
|
||||||
|
# Health checks for critical services
|
||||||
|
healthChecks:
|
||||||
|
# Core Infrastructure
|
||||||
|
- apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: gateway
|
||||||
|
namespace: bakery-ia
|
||||||
|
# Authentication & Authorization
|
||||||
|
- apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: auth-service
|
||||||
|
namespace: bakery-ia
|
||||||
|
- apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: tenant-service
|
||||||
|
namespace: bakery-ia
|
||||||
|
# Core Business Services
|
||||||
|
- apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: inventory-service
|
||||||
|
namespace: bakery-ia
|
||||||
|
- apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: orders-service
|
||||||
|
namespace: bakery-ia
|
||||||
|
- apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: pos-service
|
||||||
|
namespace: bakery-ia
|
||||||
|
# Data Services
|
||||||
|
- apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: forecasting-service
|
||||||
|
namespace: bakery-ia
|
||||||
|
- apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: notification-service
|
||||||
|
namespace: bakery-ia
|
||||||
|
# Post-build variable substitution
|
||||||
|
postBuild:
|
||||||
|
substituteFrom:
|
||||||
|
- kind: ConfigMap
|
||||||
|
name: bakery-ia-config
|
||||||
|
optional: true
|
||||||
|
- kind: Secret
|
||||||
|
name: bakery-ia-secrets
|
||||||
|
optional: true
|
||||||
25
infrastructure/cicd/flux/kustomization.yaml
Normal file
25
infrastructure/cicd/flux/kustomization.yaml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Kustomize build configuration for Flux resources
|
||||||
|
# This file is used to build and apply the Flux resources
|
||||||
|
#
|
||||||
|
# IMPORTANT: Apply resources in this order:
|
||||||
|
# 1. Install Flux CD first: flux install
|
||||||
|
# 2. Apply this kustomization: kubectl apply -k infrastructure/cicd/flux/
|
||||||
|
#
|
||||||
|
# The GitRepository must be ready before the Flux Kustomization can reconcile.
|
||||||
|
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
# Resources to apply in order (namespace and secrets first, then sources, then kustomizations)
|
||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- git-repository.yaml
|
||||||
|
- flux-kustomization.yaml
|
||||||
|
|
||||||
|
# Common labels for all resources
|
||||||
|
commonLabels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: flux
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
|
||||||
|
# Note: Do NOT set namespace here as resources already have explicit namespaces
|
||||||
15
infrastructure/cicd/flux/namespace.yaml
Normal file
15
infrastructure/cicd/flux/namespace.yaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Flux System Namespace
|
||||||
|
# This namespace is required for Flux CD components
|
||||||
|
# It should be created before any Flux resources are applied
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: flux-system
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: flux
|
||||||
|
app.kubernetes.io/component: system
|
||||||
|
kubernetes.io/metadata.name: flux-system
|
||||||
|
pod-security.kubernetes.io/enforce: restricted
|
||||||
|
pod-security.kubernetes.io/audit: restricted
|
||||||
|
pod-security.kubernetes.io/warn: restricted
|
||||||
44
infrastructure/cicd/gitea/ingress.yaml.disabled
Normal file
44
infrastructure/cicd/gitea/ingress.yaml.disabled
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# Gitea Ingress Configuration
|
||||||
|
# Routes external traffic to Gitea service for web UI and Git HTTP access
|
||||||
|
#
|
||||||
|
# Prerequisites:
|
||||||
|
# - Gitea must be deployed in the 'gitea' namespace
|
||||||
|
# - Ingress controller must be installed (nginx, traefik, etc.)
|
||||||
|
# - For HTTPS: cert-manager with a ClusterIssuer named 'letsencrypt-prod' or 'local-ca-issuer'
|
||||||
|
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: gitea-ingress
|
||||||
|
namespace: gitea
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: gitea
|
||||||
|
app.kubernetes.io/component: ingress
|
||||||
|
app.kubernetes.io/part-of: bakery-ia-cicd
|
||||||
|
annotations:
|
||||||
|
# For nginx ingress controller
|
||||||
|
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
|
||||||
|
# For traefik ingress controller
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
|
||||||
|
# For TLS with cert-manager (uncomment for HTTPS)
|
||||||
|
# cert-manager.io/cluster-issuer: "local-ca-issuer"
|
||||||
|
spec:
|
||||||
|
ingressClassName: nginx
|
||||||
|
# Uncomment for HTTPS
|
||||||
|
# tls:
|
||||||
|
# - hosts:
|
||||||
|
# - gitea.bakery-ia.local
|
||||||
|
# secretName: gitea-tls
|
||||||
|
rules:
|
||||||
|
- host: gitea.bakery-ia.local
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: gitea-http
|
||||||
|
port:
|
||||||
|
number: 3000
|
||||||
48
infrastructure/cicd/gitea/setup-admin-secret.sh
Executable file
48
infrastructure/cicd/gitea/setup-admin-secret.sh
Executable file
@@ -0,0 +1,48 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Setup Gitea Admin Secret
|
||||||
|
#
|
||||||
|
# This script creates the Kubernetes secret required for Gitea admin credentials.
|
||||||
|
# Run this BEFORE installing Gitea with Helm.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./setup-admin-secret.sh [password]
|
||||||
|
#
|
||||||
|
# If password is not provided, a random one will be generated.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
KUBECTL="kubectl"
|
||||||
|
NAMESPACE="gitea"
|
||||||
|
|
||||||
|
# Check if running in microk8s
|
||||||
|
if command -v microk8s &> /dev/null; then
|
||||||
|
KUBECTL="microk8s kubectl"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get or generate password
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
ADMIN_PASSWORD="$1"
|
||||||
|
else
|
||||||
|
ADMIN_PASSWORD=$(openssl rand -base64 24 | tr -d '/+=' | head -c 20)
|
||||||
|
echo "Generated admin password: $ADMIN_PASSWORD"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create namespace if it doesn't exist
|
||||||
|
$KUBECTL create namespace "$NAMESPACE" --dry-run=client -o yaml | $KUBECTL apply -f -
|
||||||
|
|
||||||
|
# Create the secret
|
||||||
|
$KUBECTL create secret generic gitea-admin-secret \
|
||||||
|
--namespace "$NAMESPACE" \
|
||||||
|
--from-literal=username=bakery-admin \
|
||||||
|
--from-literal=password="$ADMIN_PASSWORD" \
|
||||||
|
--dry-run=client -o yaml | $KUBECTL apply -f -
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Gitea admin secret created successfully!"
|
||||||
|
echo ""
|
||||||
|
echo "Admin credentials:"
|
||||||
|
echo " Username: bakery-admin"
|
||||||
|
echo " Password: $ADMIN_PASSWORD"
|
||||||
|
echo ""
|
||||||
|
echo "Now install Gitea with:"
|
||||||
|
echo " helm install gitea gitea/gitea -n gitea -f infrastructure/cicd/gitea/values.yaml"
|
||||||
83
infrastructure/cicd/gitea/values.yaml
Normal file
83
infrastructure/cicd/gitea/values.yaml
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
# Gitea Helm values configuration for Bakery-IA CI/CD
|
||||||
|
# This configuration sets up Gitea with registry support and appropriate storage
|
||||||
|
#
|
||||||
|
# Installation:
|
||||||
|
# helm repo add gitea https://dl.gitea.io/charts
|
||||||
|
# kubectl create namespace gitea
|
||||||
|
# helm install gitea gitea/gitea -n gitea -f infrastructure/cicd/gitea/values.yaml
|
||||||
|
#
|
||||||
|
# NOTE: The namespace is determined by the -n flag during helm install, not in this file.
|
||||||
|
|
||||||
|
service:
|
||||||
|
http:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 3000
|
||||||
|
ssh:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 2222
|
||||||
|
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
size: 10Gi
|
||||||
|
# Use standard storage class (works with Kind's default provisioner)
|
||||||
|
# For microk8s: storageClass: "microk8s-hostpath"
|
||||||
|
# For Kind: leave empty or use "standard"
|
||||||
|
storageClass: ""
|
||||||
|
|
||||||
|
gitea:
|
||||||
|
admin:
|
||||||
|
username: bakery-admin
|
||||||
|
# IMPORTANT: Override this with --set gitea.admin.password=<secure-password>
|
||||||
|
# or use existingSecret
|
||||||
|
password: ""
|
||||||
|
email: admin@bakery-ia.local
|
||||||
|
existingSecret: gitea-admin-secret
|
||||||
|
config:
|
||||||
|
server:
|
||||||
|
DOMAIN: gitea.bakery-ia.local
|
||||||
|
SSH_DOMAIN: gitea.bakery-ia.local
|
||||||
|
# Use HTTP internally; TLS termination happens at ingress
|
||||||
|
ROOT_URL: http://gitea.bakery-ia.local
|
||||||
|
HTTP_PORT: 3000
|
||||||
|
# For external HTTPS access via ingress, set:
|
||||||
|
# ROOT_URL: https://gitea.bakery-ia.local
|
||||||
|
repository:
|
||||||
|
ENABLE_PUSH_CREATE_USER: true
|
||||||
|
ENABLE_PUSH_CREATE_ORG: true
|
||||||
|
packages:
|
||||||
|
ENABLED: true
|
||||||
|
webhook:
|
||||||
|
ALLOWED_HOST_LIST: "*"
|
||||||
|
# Allow internal cluster URLs for Tekton EventListener
|
||||||
|
SKIP_TLS_VERIFY: true
|
||||||
|
service:
|
||||||
|
DISABLE_REGISTRATION: false
|
||||||
|
REQUIRE_SIGNIN_VIEW: false
|
||||||
|
|
||||||
|
# Use embedded SQLite for simpler local development
|
||||||
|
# For production, enable postgresql
|
||||||
|
postgresql:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Use embedded in-memory cache for local dev
|
||||||
|
redis-cluster:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Resource configuration for local development
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
|
||||||
|
# Init containers timeout
|
||||||
|
initContainers:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 64Mi
|
||||||
10
infrastructure/cicd/kustomization.yaml
Normal file
10
infrastructure/cicd/kustomization.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- tekton/
|
||||||
|
- ../../namespaces/flux-system.yaml
|
||||||
|
|
||||||
|
# Gitea is managed via Helm, so we don't include it directly here
|
||||||
|
# The Gitea Helm chart is deployed separately and referenced in the ingress
|
||||||
|
# Flux configuration is a Flux Kustomization resource, not a kustomize config
|
||||||
222
infrastructure/cicd/tekton/cleanup/cleanup.yaml
Normal file
222
infrastructure/cicd/tekton/cleanup/cleanup.yaml
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
# Workspace and PipelineRun Cleanup for Bakery-IA CI/CD
|
||||||
|
# This CronJob cleans up old PipelineRuns and PVCs to prevent storage exhaustion
|
||||||
|
|
||||||
|
---
|
||||||
|
# ServiceAccount for cleanup job
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: tekton-cleanup-sa
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: cleanup
|
||||||
|
|
||||||
|
---
|
||||||
|
# ClusterRole for cleanup operations
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: tekton-cleanup-role
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: cleanup
|
||||||
|
rules:
|
||||||
|
- apiGroups: ["tekton.dev"]
|
||||||
|
resources: ["pipelineruns", "taskruns"]
|
||||||
|
verbs: ["get", "list", "delete"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["persistentvolumeclaims"]
|
||||||
|
verbs: ["get", "list", "delete"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["pods"]
|
||||||
|
verbs: ["get", "list", "delete"]
|
||||||
|
|
||||||
|
---
|
||||||
|
# ClusterRoleBinding for cleanup
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: tekton-cleanup-binding
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: cleanup
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: tekton-cleanup-sa
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: tekton-cleanup-role
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
|
---
|
||||||
|
# CronJob to clean up old PipelineRuns
|
||||||
|
apiVersion: batch/v1
|
||||||
|
kind: CronJob
|
||||||
|
metadata:
|
||||||
|
name: tekton-pipelinerun-cleanup
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: cleanup
|
||||||
|
spec:
|
||||||
|
# Run every 6 hours
|
||||||
|
schedule: "0 */6 * * *"
|
||||||
|
concurrencyPolicy: Forbid
|
||||||
|
successfulJobsHistoryLimit: 3
|
||||||
|
failedJobsHistoryLimit: 3
|
||||||
|
jobTemplate:
|
||||||
|
spec:
|
||||||
|
ttlSecondsAfterFinished: 3600
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: cleanup
|
||||||
|
spec:
|
||||||
|
serviceAccountName: tekton-cleanup-sa
|
||||||
|
restartPolicy: OnFailure
|
||||||
|
containers:
|
||||||
|
- name: cleanup
|
||||||
|
image: bitnami/kubectl:latest
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "============================================"
|
||||||
|
echo "Tekton Cleanup Job"
|
||||||
|
echo "Timestamp: $(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
||||||
|
echo "============================================"
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
NAMESPACE="tekton-pipelines"
|
||||||
|
MAX_AGE_HOURS=24
|
||||||
|
KEEP_RECENT=10
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Configuration:"
|
||||||
|
echo " Namespace: $NAMESPACE"
|
||||||
|
echo " Max Age: ${MAX_AGE_HOURS} hours"
|
||||||
|
echo " Keep Recent: $KEEP_RECENT"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Get current timestamp
|
||||||
|
CURRENT_TIME=$(date +%s)
|
||||||
|
|
||||||
|
# Clean up completed PipelineRuns older than MAX_AGE_HOURS
|
||||||
|
echo "Cleaning up old PipelineRuns..."
|
||||||
|
|
||||||
|
# Get all completed PipelineRuns
|
||||||
|
COMPLETED_RUNS=$(kubectl get pipelineruns -n "$NAMESPACE" \
|
||||||
|
--no-headers \
|
||||||
|
-o custom-columns=NAME:.metadata.name,STATUS:.status.conditions[0].reason,AGE:.metadata.creationTimestamp \
|
||||||
|
2>/dev/null | grep -E "Succeeded|Failed" || true)
|
||||||
|
|
||||||
|
DELETED_COUNT=0
|
||||||
|
|
||||||
|
echo "$COMPLETED_RUNS" | while read -r line; do
|
||||||
|
if [ -z "$line" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
RUN_NAME=$(echo "$line" | awk '{print $1}')
|
||||||
|
RUN_TIME=$(echo "$line" | awk '{print $3}')
|
||||||
|
|
||||||
|
if [ -z "$RUN_NAME" ] || [ -z "$RUN_TIME" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Convert timestamp to seconds
|
||||||
|
RUN_TIMESTAMP=$(date -d "$RUN_TIME" +%s 2>/dev/null || echo "0")
|
||||||
|
|
||||||
|
if [ "$RUN_TIMESTAMP" = "0" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Calculate age in hours
|
||||||
|
AGE_SECONDS=$((CURRENT_TIME - RUN_TIMESTAMP))
|
||||||
|
AGE_HOURS=$((AGE_SECONDS / 3600))
|
||||||
|
|
||||||
|
if [ "$AGE_HOURS" -gt "$MAX_AGE_HOURS" ]; then
|
||||||
|
echo "Deleting PipelineRun: $RUN_NAME (age: ${AGE_HOURS}h)"
|
||||||
|
kubectl delete pipelinerun "$RUN_NAME" -n "$NAMESPACE" --ignore-not-found=true
|
||||||
|
DELETED_COUNT=$((DELETED_COUNT + 1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Deleted $DELETED_COUNT old PipelineRuns"
|
||||||
|
|
||||||
|
# Clean up orphaned PVCs (PVCs without associated PipelineRuns)
|
||||||
|
echo ""
|
||||||
|
echo "Cleaning up orphaned PVCs..."
|
||||||
|
|
||||||
|
ORPHANED_PVCS=$(kubectl get pvc -n "$NAMESPACE" \
|
||||||
|
-l tekton.dev/pipelineRun \
|
||||||
|
--no-headers \
|
||||||
|
-o custom-columns=NAME:.metadata.name,PIPELINERUN:.metadata.labels.tekton\\.dev/pipelineRun \
|
||||||
|
2>/dev/null || true)
|
||||||
|
|
||||||
|
echo "$ORPHANED_PVCS" | while read -r line; do
|
||||||
|
if [ -z "$line" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
PVC_NAME=$(echo "$line" | awk '{print $1}')
|
||||||
|
PR_NAME=$(echo "$line" | awk '{print $2}')
|
||||||
|
|
||||||
|
if [ -z "$PVC_NAME" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if associated PipelineRun exists
|
||||||
|
if ! kubectl get pipelinerun "$PR_NAME" -n "$NAMESPACE" > /dev/null 2>&1; then
|
||||||
|
echo "Deleting orphaned PVC: $PVC_NAME (PipelineRun $PR_NAME not found)"
|
||||||
|
kubectl delete pvc "$PVC_NAME" -n "$NAMESPACE" --ignore-not-found=true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Clean up completed/failed pods older than 1 hour
|
||||||
|
echo ""
|
||||||
|
echo "Cleaning up old completed pods..."
|
||||||
|
|
||||||
|
kubectl delete pods -n "$NAMESPACE" \
|
||||||
|
--field-selector=status.phase=Succeeded \
|
||||||
|
--ignore-not-found=true 2>/dev/null || true
|
||||||
|
|
||||||
|
kubectl delete pods -n "$NAMESPACE" \
|
||||||
|
--field-selector=status.phase=Failed \
|
||||||
|
--ignore-not-found=true 2>/dev/null || true
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
echo "Cleanup complete"
|
||||||
|
echo "============================================"
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 256Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
|
||||||
|
---
|
||||||
|
# ConfigMap for cleanup configuration
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: cleanup-config
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: cleanup
|
||||||
|
data:
|
||||||
|
# Maximum age of completed PipelineRuns to keep (in hours)
|
||||||
|
MAX_AGE_HOURS: "24"
|
||||||
|
# Number of recent PipelineRuns to keep regardless of age
|
||||||
|
KEEP_RECENT: "10"
|
||||||
|
# Cleanup schedule (cron format)
|
||||||
|
CLEANUP_SCHEDULE: "0 */6 * * *"
|
||||||
5
infrastructure/cicd/tekton/cleanup/kustomization.yaml
Normal file
5
infrastructure/cicd/tekton/cleanup/kustomization.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- cleanup.yaml
|
||||||
5
infrastructure/cicd/tekton/configs/kustomization.yaml
Normal file
5
infrastructure/cicd/tekton/configs/kustomization.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- pipeline-config.yaml
|
||||||
41
infrastructure/cicd/tekton/configs/pipeline-config.yaml
Normal file
41
infrastructure/cicd/tekton/configs/pipeline-config.yaml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# CI/CD Pipeline Configuration for Bakery-IA
|
||||||
|
# This ConfigMap contains configurable values for the CI/CD pipeline
|
||||||
|
#
|
||||||
|
# IMPORTANT: When changing REGISTRY_URL, also update:
|
||||||
|
# - infrastructure/cicd/tekton/triggers/trigger-template.yaml (registry-url default)
|
||||||
|
# - infrastructure/cicd/tekton/secrets/secrets.yaml (registry credentials)
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: pipeline-config
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: config
|
||||||
|
data:
|
||||||
|
# Container Registry Configuration
|
||||||
|
# Change this to your actual registry URL
|
||||||
|
# Also update trigger-template.yaml and secrets when changing this!
|
||||||
|
REGISTRY_URL: "gitea.bakery-ia.local:5000"
|
||||||
|
|
||||||
|
# Git Configuration
|
||||||
|
GIT_BRANCH: "main"
|
||||||
|
GIT_USER_NAME: "bakery-ia-ci"
|
||||||
|
GIT_USER_EMAIL: "ci@bakery-ia.local"
|
||||||
|
|
||||||
|
# Build Configuration
|
||||||
|
BUILD_CACHE_TTL: "24h"
|
||||||
|
BUILD_VERBOSITY: "info"
|
||||||
|
|
||||||
|
# Test Configuration
|
||||||
|
SKIP_TESTS: "false"
|
||||||
|
SKIP_LINT: "false"
|
||||||
|
|
||||||
|
# Deployment Configuration
|
||||||
|
DEPLOY_NAMESPACE: "bakery-ia"
|
||||||
|
FLUX_NAMESPACE: "flux-system"
|
||||||
|
|
||||||
|
# Workspace Configuration
|
||||||
|
WORKSPACE_SIZE: "5Gi"
|
||||||
|
WORKSPACE_STORAGE_CLASS: "standard"
|
||||||
11
infrastructure/cicd/tekton/kustomization.yaml
Normal file
11
infrastructure/cicd/tekton/kustomization.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- rbac/
|
||||||
|
- secrets/
|
||||||
|
- configs/
|
||||||
|
- tasks/
|
||||||
|
- triggers/
|
||||||
|
- pipelines/
|
||||||
|
- cleanup/
|
||||||
149
infrastructure/cicd/tekton/pipelines/ci-pipeline.yaml
Normal file
149
infrastructure/cicd/tekton/pipelines/ci-pipeline.yaml
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
# Main CI Pipeline for Bakery-IA
|
||||||
|
# This pipeline orchestrates the build, test, and deploy process
|
||||||
|
# Includes: fetch -> detect changes -> test -> build -> update gitops
|
||||||
|
|
||||||
|
apiVersion: tekton.dev/v1beta1
|
||||||
|
kind: Pipeline
|
||||||
|
metadata:
|
||||||
|
name: bakery-ia-ci
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: pipeline
|
||||||
|
spec:
|
||||||
|
workspaces:
|
||||||
|
- name: shared-workspace
|
||||||
|
description: Shared workspace for source code
|
||||||
|
- name: docker-credentials
|
||||||
|
description: Docker registry credentials
|
||||||
|
- name: git-credentials
|
||||||
|
description: Git credentials for pushing GitOps updates
|
||||||
|
optional: true
|
||||||
|
params:
|
||||||
|
- name: git-url
|
||||||
|
type: string
|
||||||
|
description: Repository URL
|
||||||
|
- name: git-revision
|
||||||
|
type: string
|
||||||
|
description: Git revision/commit hash
|
||||||
|
- name: registry
|
||||||
|
type: string
|
||||||
|
description: Container registry URL
|
||||||
|
- name: git-branch
|
||||||
|
type: string
|
||||||
|
description: Target branch for GitOps updates
|
||||||
|
default: "main"
|
||||||
|
- name: skip-tests
|
||||||
|
type: string
|
||||||
|
description: Skip tests if "true"
|
||||||
|
default: "false"
|
||||||
|
- name: dry-run
|
||||||
|
type: string
|
||||||
|
description: Dry run mode - don't push changes
|
||||||
|
default: "false"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
# Stage 1: Fetch source code
|
||||||
|
- name: fetch-source
|
||||||
|
taskRef:
|
||||||
|
name: git-clone
|
||||||
|
workspaces:
|
||||||
|
- name: output
|
||||||
|
workspace: shared-workspace
|
||||||
|
params:
|
||||||
|
- name: url
|
||||||
|
value: $(params.git-url)
|
||||||
|
- name: revision
|
||||||
|
value: $(params.git-revision)
|
||||||
|
|
||||||
|
# Stage 2: Detect which services changed
|
||||||
|
- name: detect-changes
|
||||||
|
runAfter: [fetch-source]
|
||||||
|
taskRef:
|
||||||
|
name: detect-changed-services
|
||||||
|
workspaces:
|
||||||
|
- name: source
|
||||||
|
workspace: shared-workspace
|
||||||
|
|
||||||
|
# Stage 3: Run tests on changed services
|
||||||
|
- name: run-tests
|
||||||
|
runAfter: [detect-changes]
|
||||||
|
taskRef:
|
||||||
|
name: run-tests
|
||||||
|
when:
|
||||||
|
- input: "$(tasks.detect-changes.results.changed-services)"
|
||||||
|
operator: notin
|
||||||
|
values: ["none", "infrastructure"]
|
||||||
|
- input: "$(params.skip-tests)"
|
||||||
|
operator: notin
|
||||||
|
values: ["true"]
|
||||||
|
workspaces:
|
||||||
|
- name: source
|
||||||
|
workspace: shared-workspace
|
||||||
|
params:
|
||||||
|
- name: services
|
||||||
|
value: $(tasks.detect-changes.results.changed-services)
|
||||||
|
- name: skip-tests
|
||||||
|
value: $(params.skip-tests)
|
||||||
|
|
||||||
|
# Stage 4: Build and push container images
|
||||||
|
- name: build-and-push
|
||||||
|
runAfter: [run-tests]
|
||||||
|
taskRef:
|
||||||
|
name: kaniko-build
|
||||||
|
when:
|
||||||
|
- input: "$(tasks.detect-changes.results.changed-services)"
|
||||||
|
operator: notin
|
||||||
|
values: ["none", "infrastructure"]
|
||||||
|
workspaces:
|
||||||
|
- name: source
|
||||||
|
workspace: shared-workspace
|
||||||
|
- name: docker-credentials
|
||||||
|
workspace: docker-credentials
|
||||||
|
params:
|
||||||
|
- name: services
|
||||||
|
value: $(tasks.detect-changes.results.changed-services)
|
||||||
|
- name: registry
|
||||||
|
value: $(params.registry)
|
||||||
|
- name: git-revision
|
||||||
|
value: $(params.git-revision)
|
||||||
|
|
||||||
|
# Stage 5: Update GitOps manifests
|
||||||
|
- name: update-gitops-manifests
|
||||||
|
runAfter: [build-and-push]
|
||||||
|
taskRef:
|
||||||
|
name: update-gitops
|
||||||
|
when:
|
||||||
|
- input: "$(tasks.detect-changes.results.changed-services)"
|
||||||
|
operator: notin
|
||||||
|
values: ["none", "infrastructure"]
|
||||||
|
- input: "$(tasks.build-and-push.results.build-status)"
|
||||||
|
operator: in
|
||||||
|
values: ["success", "partial"]
|
||||||
|
workspaces:
|
||||||
|
- name: source
|
||||||
|
workspace: shared-workspace
|
||||||
|
- name: git-credentials
|
||||||
|
workspace: git-credentials
|
||||||
|
params:
|
||||||
|
- name: services
|
||||||
|
value: $(tasks.detect-changes.results.changed-services)
|
||||||
|
- name: registry
|
||||||
|
value: $(params.registry)
|
||||||
|
- name: git-revision
|
||||||
|
value: $(params.git-revision)
|
||||||
|
- name: git-branch
|
||||||
|
value: $(params.git-branch)
|
||||||
|
- name: dry-run
|
||||||
|
value: $(params.dry-run)
|
||||||
|
|
||||||
|
# Final tasks that run regardless of pipeline success/failure
|
||||||
|
finally:
|
||||||
|
- name: pipeline-summary
|
||||||
|
taskRef:
|
||||||
|
name: pipeline-summary
|
||||||
|
params:
|
||||||
|
- name: changed-services
|
||||||
|
value: $(tasks.detect-changes.results.changed-services)
|
||||||
|
- name: git-revision
|
||||||
|
value: $(params.git-revision)
|
||||||
6
infrastructure/cicd/tekton/pipelines/kustomization.yaml
Normal file
6
infrastructure/cicd/tekton/pipelines/kustomization.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- ci-pipeline.yaml
|
||||||
|
- prod-deploy-pipeline.yaml
|
||||||
118
infrastructure/cicd/tekton/pipelines/prod-deploy-pipeline.yaml
Normal file
118
infrastructure/cicd/tekton/pipelines/prod-deploy-pipeline.yaml
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
# Production Deployment Pipeline for Bakery-IA
|
||||||
|
# This pipeline handles production deployments with manual approval gate
|
||||||
|
# It should be triggered after the CI pipeline succeeds
|
||||||
|
|
||||||
|
apiVersion: tekton.dev/v1beta1
|
||||||
|
kind: Pipeline
|
||||||
|
metadata:
|
||||||
|
name: bakery-ia-prod-deploy
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: pipeline
|
||||||
|
app.kubernetes.io/environment: production
|
||||||
|
spec:
|
||||||
|
workspaces:
|
||||||
|
- name: shared-workspace
|
||||||
|
description: Shared workspace for source code
|
||||||
|
- name: git-credentials
|
||||||
|
description: Git credentials for pushing GitOps updates
|
||||||
|
optional: true
|
||||||
|
params:
|
||||||
|
- name: git-url
|
||||||
|
type: string
|
||||||
|
description: Repository URL
|
||||||
|
- name: git-revision
|
||||||
|
type: string
|
||||||
|
description: Git revision/commit hash to deploy
|
||||||
|
- name: services
|
||||||
|
type: string
|
||||||
|
description: Comma-separated list of services to deploy
|
||||||
|
- name: registry
|
||||||
|
type: string
|
||||||
|
description: Container registry URL
|
||||||
|
- name: approver
|
||||||
|
type: string
|
||||||
|
description: Name of the person who approved this deployment
|
||||||
|
default: "automated"
|
||||||
|
- name: approval-ticket
|
||||||
|
type: string
|
||||||
|
description: Ticket/issue number for deployment approval
|
||||||
|
default: "N/A"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
# Stage 1: Fetch source code
|
||||||
|
- name: fetch-source
|
||||||
|
taskRef:
|
||||||
|
name: git-clone
|
||||||
|
workspaces:
|
||||||
|
- name: output
|
||||||
|
workspace: shared-workspace
|
||||||
|
params:
|
||||||
|
- name: url
|
||||||
|
value: $(params.git-url)
|
||||||
|
- name: revision
|
||||||
|
value: $(params.git-revision)
|
||||||
|
|
||||||
|
# Stage 2: Verify images exist in registry
|
||||||
|
- name: verify-images
|
||||||
|
runAfter: [fetch-source]
|
||||||
|
taskRef:
|
||||||
|
name: verify-images
|
||||||
|
params:
|
||||||
|
- name: services
|
||||||
|
value: $(params.services)
|
||||||
|
- name: registry
|
||||||
|
value: $(params.registry)
|
||||||
|
- name: git-revision
|
||||||
|
value: $(params.git-revision)
|
||||||
|
|
||||||
|
# Stage 3: Pre-deployment validation
|
||||||
|
- name: pre-deploy-validation
|
||||||
|
runAfter: [verify-images]
|
||||||
|
taskRef:
|
||||||
|
name: pre-deploy-validation
|
||||||
|
workspaces:
|
||||||
|
- name: source
|
||||||
|
workspace: shared-workspace
|
||||||
|
params:
|
||||||
|
- name: services
|
||||||
|
value: $(params.services)
|
||||||
|
- name: environment
|
||||||
|
value: "production"
|
||||||
|
|
||||||
|
# Stage 4: Update production manifests
|
||||||
|
- name: update-prod-manifests
|
||||||
|
runAfter: [pre-deploy-validation]
|
||||||
|
taskRef:
|
||||||
|
name: update-gitops
|
||||||
|
workspaces:
|
||||||
|
- name: source
|
||||||
|
workspace: shared-workspace
|
||||||
|
- name: git-credentials
|
||||||
|
workspace: git-credentials
|
||||||
|
params:
|
||||||
|
- name: services
|
||||||
|
value: $(params.services)
|
||||||
|
- name: registry
|
||||||
|
value: $(params.registry)
|
||||||
|
- name: git-revision
|
||||||
|
value: $(params.git-revision)
|
||||||
|
- name: git-branch
|
||||||
|
value: "main"
|
||||||
|
- name: dry-run
|
||||||
|
value: "false"
|
||||||
|
|
||||||
|
finally:
|
||||||
|
- name: deployment-summary
|
||||||
|
taskRef:
|
||||||
|
name: prod-deployment-summary
|
||||||
|
params:
|
||||||
|
- name: services
|
||||||
|
value: $(params.services)
|
||||||
|
- name: git-revision
|
||||||
|
value: $(params.git-revision)
|
||||||
|
- name: approver
|
||||||
|
value: $(params.approver)
|
||||||
|
- name: approval-ticket
|
||||||
|
value: $(params.approval-ticket)
|
||||||
6
infrastructure/cicd/tekton/rbac/kustomization.yaml
Normal file
6
infrastructure/cicd/tekton/rbac/kustomization.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- rbac.yaml
|
||||||
|
- resource-quota.yaml
|
||||||
159
infrastructure/cicd/tekton/rbac/rbac.yaml
Normal file
159
infrastructure/cicd/tekton/rbac/rbac.yaml
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
# Tekton RBAC Configuration for Bakery-IA CI/CD
|
||||||
|
# This file defines ServiceAccounts, Roles, and RoleBindings for Tekton
|
||||||
|
|
||||||
|
---
|
||||||
|
# ServiceAccount for Tekton Triggers EventListener
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: tekton-triggers-sa
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: triggers
|
||||||
|
|
||||||
|
---
|
||||||
|
# ServiceAccount for Pipeline execution
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: tekton-pipeline-sa
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: pipeline
|
||||||
|
|
||||||
|
---
|
||||||
|
# ClusterRole for Tekton Triggers to create PipelineRuns
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: tekton-triggers-role
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: triggers
|
||||||
|
rules:
|
||||||
|
# Ability to create PipelineRuns from triggers
|
||||||
|
- apiGroups: ["tekton.dev"]
|
||||||
|
resources: ["pipelineruns", "taskruns"]
|
||||||
|
verbs: ["create", "get", "list", "watch"]
|
||||||
|
# Ability to read pipelines and tasks
|
||||||
|
- apiGroups: ["tekton.dev"]
|
||||||
|
resources: ["pipelines", "tasks", "clustertasks"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
# Ability to manage PVCs for workspaces
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["persistentvolumeclaims"]
|
||||||
|
verbs: ["create", "get", "list", "watch", "delete"]
|
||||||
|
# Ability to read secrets for credentials
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["secrets"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
# Ability to read configmaps
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["configmaps"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
# Ability to manage events for logging
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["events"]
|
||||||
|
verbs: ["create", "patch"]
|
||||||
|
|
||||||
|
---
|
||||||
|
# ClusterRoleBinding for Tekton Triggers
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: tekton-triggers-binding
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: triggers
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: tekton-triggers-sa
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: tekton-triggers-role
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
|
---
|
||||||
|
# ClusterRole for Pipeline execution (needed for git operations and deployments)
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: tekton-pipeline-role
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: pipeline
|
||||||
|
rules:
|
||||||
|
# Ability to read/update deployments for GitOps
|
||||||
|
- apiGroups: ["apps"]
|
||||||
|
resources: ["deployments"]
|
||||||
|
verbs: ["get", "list", "watch", "patch", "update"]
|
||||||
|
# Ability to read secrets for credentials
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["secrets"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
# Ability to read configmaps
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["configmaps"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
# Ability to manage pods for build operations
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["pods", "pods/log"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
|
||||||
|
---
|
||||||
|
# ClusterRoleBinding for Pipeline execution
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: tekton-pipeline-binding
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: pipeline
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: tekton-pipeline-sa
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: tekton-pipeline-role
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
|
---
|
||||||
|
# Role for EventListener to access triggers resources
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: tekton-triggers-eventlistener-role
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: triggers
|
||||||
|
rules:
|
||||||
|
- apiGroups: ["triggers.tekton.dev"]
|
||||||
|
resources: ["eventlisteners", "triggerbindings", "triggertemplates", "triggers", "interceptors"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["configmaps", "secrets"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
|
||||||
|
---
|
||||||
|
# RoleBinding for EventListener
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: tekton-triggers-eventlistener-binding
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: triggers
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: tekton-triggers-sa
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: tekton-triggers-eventlistener-role
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
64
infrastructure/cicd/tekton/rbac/resource-quota.yaml
Normal file
64
infrastructure/cicd/tekton/rbac/resource-quota.yaml
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
# ResourceQuota for Tekton Pipelines Namespace
|
||||||
|
# Prevents resource exhaustion from runaway pipeline runs
|
||||||
|
#
|
||||||
|
# This quota limits:
|
||||||
|
# - Total CPU and memory that can be requested/used
|
||||||
|
# - Number of concurrent pods
|
||||||
|
# - Number of PVCs for workspaces
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ResourceQuota
|
||||||
|
metadata:
|
||||||
|
name: tekton-pipelines-quota
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: quota
|
||||||
|
spec:
|
||||||
|
hard:
|
||||||
|
# Limit total CPU
|
||||||
|
requests.cpu: "8"
|
||||||
|
limits.cpu: "16"
|
||||||
|
# Limit total memory
|
||||||
|
requests.memory: "16Gi"
|
||||||
|
limits.memory: "32Gi"
|
||||||
|
# Limit number of pods (controls concurrent pipeline tasks)
|
||||||
|
pods: "20"
|
||||||
|
# Limit PVCs (controls workspace storage)
|
||||||
|
persistentvolumeclaims: "10"
|
||||||
|
# Limit storage
|
||||||
|
requests.storage: "50Gi"
|
||||||
|
|
||||||
|
---
|
||||||
|
# LimitRange to set defaults and limits for individual pods
|
||||||
|
# Ensures every pod has resource requests/limits
|
||||||
|
apiVersion: v1
|
||||||
|
kind: LimitRange
|
||||||
|
metadata:
|
||||||
|
name: tekton-pipelines-limits
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: quota
|
||||||
|
spec:
|
||||||
|
limits:
|
||||||
|
# Default limits for containers
|
||||||
|
- type: Container
|
||||||
|
default:
|
||||||
|
cpu: "1"
|
||||||
|
memory: "1Gi"
|
||||||
|
defaultRequest:
|
||||||
|
cpu: "100m"
|
||||||
|
memory: "256Mi"
|
||||||
|
max:
|
||||||
|
cpu: "4"
|
||||||
|
memory: "8Gi"
|
||||||
|
min:
|
||||||
|
cpu: "50m"
|
||||||
|
memory: "64Mi"
|
||||||
|
# Limits for PVCs
|
||||||
|
- type: PersistentVolumeClaim
|
||||||
|
max:
|
||||||
|
storage: "10Gi"
|
||||||
|
min:
|
||||||
|
storage: "1Gi"
|
||||||
4
infrastructure/cicd/tekton/secrets/.gitignore
vendored
Normal file
4
infrastructure/cicd/tekton/secrets/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Ignore generated secrets
|
||||||
|
.webhook-secret
|
||||||
|
*-actual.yaml
|
||||||
|
sealed-secrets.yaml
|
||||||
167
infrastructure/cicd/tekton/secrets/generate-secrets.sh
Executable file
167
infrastructure/cicd/tekton/secrets/generate-secrets.sh
Executable file
@@ -0,0 +1,167 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Generate CI/CD Secrets for Bakery-IA
|
||||||
|
#
|
||||||
|
# This script creates Kubernetes secrets required for the CI/CD pipeline.
|
||||||
|
# Run this script once during initial setup.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./generate-secrets.sh [options]
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
# --registry-url Container registry URL (default: gitea.bakery-ia.local:5000)
|
||||||
|
# --gitea-user Gitea username (will prompt if not provided)
|
||||||
|
# --gitea-password Gitea password (will prompt if not provided)
|
||||||
|
# --dry-run Print commands without executing
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Default values
|
||||||
|
REGISTRY_URL="${REGISTRY_URL:-gitea.bakery-ia.local:5000}"
|
||||||
|
DRY_RUN=false
|
||||||
|
KUBECTL="kubectl"
|
||||||
|
|
||||||
|
# Check if running in microk8s
|
||||||
|
if command -v microk8s &> /dev/null; then
|
||||||
|
KUBECTL="microk8s kubectl"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
--registry-url)
|
||||||
|
REGISTRY_URL="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--gitea-user)
|
||||||
|
GITEA_USERNAME="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--gitea-password)
|
||||||
|
GITEA_PASSWORD="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--dry-run)
|
||||||
|
DRY_RUN=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "${RED}Unknown option: $1${NC}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo " Bakery-IA CI/CD Secrets Generator"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Prompt for credentials if not provided
|
||||||
|
if [ -z "$GITEA_USERNAME" ]; then
|
||||||
|
read -p "Enter Gitea username: " GITEA_USERNAME
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$GITEA_PASSWORD" ]; then
|
||||||
|
read -s -p "Enter Gitea password: " GITEA_PASSWORD
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate webhook secret
|
||||||
|
WEBHOOK_SECRET=$(openssl rand -hex 32)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}Configuration:${NC}"
|
||||||
|
echo " Registry URL: $REGISTRY_URL"
|
||||||
|
echo " Gitea User: $GITEA_USERNAME"
|
||||||
|
echo " Webhook Secret: ${WEBHOOK_SECRET:0:8}..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Function to create secret
|
||||||
|
create_secret() {
|
||||||
|
local cmd="$1"
|
||||||
|
if [ "$DRY_RUN" = true ]; then
|
||||||
|
echo -e "${YELLOW}[DRY-RUN]${NC} $cmd"
|
||||||
|
else
|
||||||
|
eval "$cmd"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ensure namespaces exist
|
||||||
|
echo -e "${GREEN}Creating namespaces if they don't exist...${NC}"
|
||||||
|
create_secret "$KUBECTL create namespace tekton-pipelines --dry-run=client -o yaml | $KUBECTL apply -f -"
|
||||||
|
create_secret "$KUBECTL create namespace flux-system --dry-run=client -o yaml | $KUBECTL apply -f -"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}Creating secrets...${NC}"
|
||||||
|
|
||||||
|
# 1. Webhook Secret
|
||||||
|
echo " Creating gitea-webhook-secret..."
|
||||||
|
create_secret "$KUBECTL create secret generic gitea-webhook-secret \
|
||||||
|
--namespace tekton-pipelines \
|
||||||
|
--from-literal=secretToken='$WEBHOOK_SECRET' \
|
||||||
|
--dry-run=client -o yaml | $KUBECTL apply -f -"
|
||||||
|
|
||||||
|
# 2. Registry Credentials (docker-registry type)
|
||||||
|
echo " Creating gitea-registry-credentials..."
|
||||||
|
create_secret "$KUBECTL create secret docker-registry gitea-registry-credentials \
|
||||||
|
--namespace tekton-pipelines \
|
||||||
|
--docker-server='$REGISTRY_URL' \
|
||||||
|
--docker-username='$GITEA_USERNAME' \
|
||||||
|
--docker-password='$GITEA_PASSWORD' \
|
||||||
|
--dry-run=client -o yaml | $KUBECTL apply -f -"
|
||||||
|
|
||||||
|
# 3. Git Credentials for Tekton
|
||||||
|
echo " Creating gitea-git-credentials..."
|
||||||
|
create_secret "$KUBECTL create secret generic gitea-git-credentials \
|
||||||
|
--namespace tekton-pipelines \
|
||||||
|
--from-literal=username='$GITEA_USERNAME' \
|
||||||
|
--from-literal=password='$GITEA_PASSWORD' \
|
||||||
|
--dry-run=client -o yaml | $KUBECTL apply -f -"
|
||||||
|
|
||||||
|
# 4. Flux Git Credentials
|
||||||
|
echo " Creating gitea-credentials for Flux..."
|
||||||
|
create_secret "$KUBECTL create secret generic gitea-credentials \
|
||||||
|
--namespace flux-system \
|
||||||
|
--from-literal=username='$GITEA_USERNAME' \
|
||||||
|
--from-literal=password='$GITEA_PASSWORD' \
|
||||||
|
--dry-run=client -o yaml | $KUBECTL apply -f -"
|
||||||
|
|
||||||
|
# Label all secrets
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}Adding labels to secrets...${NC}"
|
||||||
|
for ns in tekton-pipelines flux-system; do
|
||||||
|
for secret in gitea-webhook-secret gitea-registry-credentials gitea-git-credentials gitea-credentials; do
|
||||||
|
if $KUBECTL get secret "$secret" -n "$ns" &> /dev/null; then
|
||||||
|
create_secret "$KUBECTL label secret $secret -n $ns app.kubernetes.io/name=bakery-ia-cicd --overwrite 2>/dev/null || true"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
|
echo -e "${GREEN}Secrets created successfully!${NC}"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}IMPORTANT:${NC} Save this webhook secret for Gitea webhook configuration:"
|
||||||
|
echo ""
|
||||||
|
echo " Webhook Secret: $WEBHOOK_SECRET"
|
||||||
|
echo ""
|
||||||
|
echo "Configure this in Gitea:"
|
||||||
|
echo " 1. Go to Repository Settings > Webhooks"
|
||||||
|
echo " 2. Add webhook with URL: http://el-bakery-ia-listener.tekton-pipelines.svc.cluster.local:8080"
|
||||||
|
echo " 3. Set Secret to the webhook secret above"
|
||||||
|
echo " 4. Select events: Push"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Save webhook secret to a file for reference (gitignored)
|
||||||
|
if [ "$DRY_RUN" = false ]; then
|
||||||
|
echo "$WEBHOOK_SECRET" > "$(dirname "$0")/.webhook-secret"
|
||||||
|
chmod 600 "$(dirname "$0")/.webhook-secret"
|
||||||
|
echo "Webhook secret saved to .webhook-secret (gitignored)"
|
||||||
|
fi
|
||||||
19
infrastructure/cicd/tekton/secrets/kustomization.yaml
Normal file
19
infrastructure/cicd/tekton/secrets/kustomization.yaml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- secrets.yaml
|
||||||
|
|
||||||
|
# Note: In production, use sealed-secrets or external-secrets-operator
|
||||||
|
# to manage secrets securely. The secrets.yaml file contains placeholder
|
||||||
|
# values that must be replaced before deployment.
|
||||||
|
#
|
||||||
|
# Example using sealed-secrets:
|
||||||
|
# 1. Install sealed-secrets controller
|
||||||
|
# 2. Create SealedSecret resources instead of plain Secrets
|
||||||
|
# 3. Commit the SealedSecret manifests to Git (safe to commit)
|
||||||
|
#
|
||||||
|
# Example using external-secrets-operator:
|
||||||
|
# 1. Install external-secrets-operator
|
||||||
|
# 2. Configure a SecretStore (AWS Secrets Manager, HashiCorp Vault, etc.)
|
||||||
|
# 3. Create ExternalSecret resources that reference the SecretStore
|
||||||
79
infrastructure/cicd/tekton/secrets/secrets-template.yaml
Normal file
79
infrastructure/cicd/tekton/secrets/secrets-template.yaml
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
# CI/CD Secrets Template for Tekton Pipelines
|
||||||
|
#
|
||||||
|
# DO NOT commit this file with actual credentials!
|
||||||
|
# Use the generate-secrets.sh script to create secrets safely.
|
||||||
|
#
|
||||||
|
# For production, use one of these approaches:
|
||||||
|
# 1. Sealed Secrets: kubeseal < secrets.yaml > sealed-secrets.yaml
|
||||||
|
# 2. External Secrets Operator: Configure with your secret store
|
||||||
|
# 3. Manual creation: kubectl create secret ... (see generate-secrets.sh)
|
||||||
|
|
||||||
|
---
|
||||||
|
# Secret for Gitea webhook validation
|
||||||
|
# Used by EventListener to validate incoming webhooks
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: gitea-webhook-secret
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: triggers
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
# Generate with: openssl rand -hex 32
|
||||||
|
secretToken: "${WEBHOOK_SECRET_TOKEN}"
|
||||||
|
|
||||||
|
---
|
||||||
|
# Secret for Gitea container registry credentials
|
||||||
|
# Used by Kaniko to push images to Gitea registry
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: gitea-registry-credentials
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: build
|
||||||
|
type: kubernetes.io/dockerconfigjson
|
||||||
|
stringData:
|
||||||
|
.dockerconfigjson: |
|
||||||
|
{
|
||||||
|
"auths": {
|
||||||
|
"${REGISTRY_URL}": {
|
||||||
|
"username": "${GITEA_USERNAME}",
|
||||||
|
"password": "${GITEA_PASSWORD}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
---
|
||||||
|
# Secret for Git credentials (used by pipeline to push GitOps updates)
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: gitea-git-credentials
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: gitops
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
username: "${GITEA_USERNAME}"
|
||||||
|
password: "${GITEA_PASSWORD}"
|
||||||
|
|
||||||
|
---
|
||||||
|
# Secret for Flux GitRepository access
|
||||||
|
# Used by Flux to pull from Gitea repository
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: gitea-credentials
|
||||||
|
namespace: flux-system
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: flux
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
username: "${GITEA_USERNAME}"
|
||||||
|
password: "${GITEA_PASSWORD}"
|
||||||
98
infrastructure/cicd/tekton/secrets/secrets.yaml
Normal file
98
infrastructure/cicd/tekton/secrets/secrets.yaml
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
# CI/CD Secrets for Tekton Pipelines
|
||||||
|
#
|
||||||
|
# WARNING: This file contains EXAMPLE values only!
|
||||||
|
# DO NOT use these values in production.
|
||||||
|
#
|
||||||
|
# To create actual secrets, use ONE of these methods:
|
||||||
|
#
|
||||||
|
# Method 1 (Recommended): Use the generate-secrets.sh script
|
||||||
|
# ./generate-secrets.sh --gitea-user <username> --gitea-password <password>
|
||||||
|
#
|
||||||
|
# Method 2: Create secrets manually with kubectl
|
||||||
|
# kubectl create secret generic gitea-webhook-secret \
|
||||||
|
# --namespace tekton-pipelines \
|
||||||
|
# --from-literal=secretToken="$(openssl rand -hex 32)"
|
||||||
|
#
|
||||||
|
# Method 3: Use Sealed Secrets for GitOps
|
||||||
|
# kubeseal < secrets-template.yaml > sealed-secrets.yaml
|
||||||
|
#
|
||||||
|
# Method 4: Use External Secrets Operator
|
||||||
|
# Configure ESO to pull from your secret store (Vault, AWS SM, etc.)
|
||||||
|
|
||||||
|
---
|
||||||
|
# Example Secret for Gitea webhook validation
|
||||||
|
# Used by EventListener to validate incoming webhooks
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: gitea-webhook-secret
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: triggers
|
||||||
|
annotations:
|
||||||
|
note: "EXAMPLE - Replace with actual secret using generate-secrets.sh"
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
# Generate with: openssl rand -hex 32
|
||||||
|
secretToken: "example-webhook-token-do-not-use-in-production"
|
||||||
|
|
||||||
|
---
|
||||||
|
# Example Secret for Gitea container registry credentials
|
||||||
|
# Used by Kaniko to push images to Gitea registry
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: gitea-registry-credentials
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: build
|
||||||
|
annotations:
|
||||||
|
note: "EXAMPLE - Replace with actual secret using generate-secrets.sh"
|
||||||
|
type: kubernetes.io/dockerconfigjson
|
||||||
|
stringData:
|
||||||
|
.dockerconfigjson: |
|
||||||
|
{
|
||||||
|
"auths": {
|
||||||
|
"gitea.bakery-ia.local:5000": {
|
||||||
|
"username": "example-user",
|
||||||
|
"password": "example-password"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
---
|
||||||
|
# Example Secret for Git credentials (used by pipeline to push GitOps updates)
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: gitea-git-credentials
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: gitops
|
||||||
|
annotations:
|
||||||
|
note: "EXAMPLE - Replace with actual secret using generate-secrets.sh"
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
username: "example-user"
|
||||||
|
password: "example-password"
|
||||||
|
|
||||||
|
---
|
||||||
|
# Example Secret for Flux GitRepository access
|
||||||
|
# Used by Flux to pull from Gitea repository
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: gitea-credentials
|
||||||
|
namespace: flux-system
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: flux
|
||||||
|
annotations:
|
||||||
|
note: "EXAMPLE - Replace with actual secret using generate-secrets.sh"
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
username: "example-user"
|
||||||
|
password: "example-password"
|
||||||
154
infrastructure/cicd/tekton/tasks/detect-changes.yaml
Normal file
154
infrastructure/cicd/tekton/tasks/detect-changes.yaml
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
# Tekton Detect Changed Services Task for Bakery-IA CI/CD
|
||||||
|
# This task identifies which services have changed in the repository
|
||||||
|
|
||||||
|
apiVersion: tekton.dev/v1beta1
|
||||||
|
kind: Task
|
||||||
|
metadata:
|
||||||
|
name: detect-changed-services
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: detect
|
||||||
|
spec:
|
||||||
|
workspaces:
|
||||||
|
- name: source
|
||||||
|
description: Source code workspace
|
||||||
|
params:
|
||||||
|
- name: base-ref
|
||||||
|
type: string
|
||||||
|
description: Base reference for comparison (default HEAD~1)
|
||||||
|
default: "HEAD~1"
|
||||||
|
results:
|
||||||
|
- name: changed-services
|
||||||
|
description: Comma-separated list of changed services
|
||||||
|
- name: changed-files-count
|
||||||
|
description: Number of files changed
|
||||||
|
steps:
|
||||||
|
- name: detect
|
||||||
|
image: alpine/git:2.43.0
|
||||||
|
script: |
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SOURCE_PATH="$(workspaces.source.path)"
|
||||||
|
BASE_REF="$(params.base-ref)"
|
||||||
|
|
||||||
|
cd "$SOURCE_PATH"
|
||||||
|
|
||||||
|
echo "============================================"
|
||||||
|
echo "Detect Changed Services"
|
||||||
|
echo "============================================"
|
||||||
|
echo "Base ref: $BASE_REF"
|
||||||
|
echo "============================================"
|
||||||
|
|
||||||
|
# Get list of changed files compared to base reference
|
||||||
|
echo ""
|
||||||
|
echo "Detecting changed files..."
|
||||||
|
|
||||||
|
# Try to get diff, fall back to listing all files if this is the first commit
|
||||||
|
CHANGED_FILES=$(git diff --name-only "$BASE_REF" HEAD 2>/dev/null || git ls-tree -r HEAD --name-only)
|
||||||
|
|
||||||
|
FILE_COUNT=$(echo "$CHANGED_FILES" | grep -c "." || echo "0")
|
||||||
|
echo "Found $FILE_COUNT changed files"
|
||||||
|
echo "$FILE_COUNT" > $(results.changed-files-count.path)
|
||||||
|
|
||||||
|
if [ "$FILE_COUNT" = "0" ]; then
|
||||||
|
echo "No files changed"
|
||||||
|
echo "none" > $(results.changed-services.path)
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Changed files:"
|
||||||
|
echo "$CHANGED_FILES" | head -20
|
||||||
|
if [ "$FILE_COUNT" -gt 20 ]; then
|
||||||
|
echo "... and $((FILE_COUNT - 20)) more files"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Map files to services using simple shell (no bash arrays)
|
||||||
|
echo ""
|
||||||
|
echo "Mapping files to services..."
|
||||||
|
|
||||||
|
CHANGED_SERVICES=""
|
||||||
|
|
||||||
|
# Process each file
|
||||||
|
echo "$CHANGED_FILES" | while read -r file; do
|
||||||
|
if [ -z "$file" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check services directory
|
||||||
|
if echo "$file" | grep -q "^services/"; then
|
||||||
|
SERVICE=$(echo "$file" | cut -d'/' -f2)
|
||||||
|
if [ -n "$SERVICE" ] && ! echo "$CHANGED_SERVICES" | grep -q "$SERVICE"; then
|
||||||
|
if [ -z "$CHANGED_SERVICES" ]; then
|
||||||
|
CHANGED_SERVICES="$SERVICE"
|
||||||
|
else
|
||||||
|
CHANGED_SERVICES="$CHANGED_SERVICES,$SERVICE"
|
||||||
|
fi
|
||||||
|
echo "$CHANGED_SERVICES" > /tmp/services.txt
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check frontend
|
||||||
|
if echo "$file" | grep -q "^frontend/"; then
|
||||||
|
if ! echo "$CHANGED_SERVICES" | grep -q "frontend"; then
|
||||||
|
if [ -z "$CHANGED_SERVICES" ]; then
|
||||||
|
CHANGED_SERVICES="frontend"
|
||||||
|
else
|
||||||
|
CHANGED_SERVICES="$CHANGED_SERVICES,frontend"
|
||||||
|
fi
|
||||||
|
echo "$CHANGED_SERVICES" > /tmp/services.txt
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check gateway
|
||||||
|
if echo "$file" | grep -q "^gateway/"; then
|
||||||
|
if ! echo "$CHANGED_SERVICES" | grep -q "gateway"; then
|
||||||
|
if [ -z "$CHANGED_SERVICES" ]; then
|
||||||
|
CHANGED_SERVICES="gateway"
|
||||||
|
else
|
||||||
|
CHANGED_SERVICES="$CHANGED_SERVICES,gateway"
|
||||||
|
fi
|
||||||
|
echo "$CHANGED_SERVICES" > /tmp/services.txt
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check infrastructure
|
||||||
|
if echo "$file" | grep -q "^infrastructure/"; then
|
||||||
|
if ! echo "$CHANGED_SERVICES" | grep -q "infrastructure"; then
|
||||||
|
if [ -z "$CHANGED_SERVICES" ]; then
|
||||||
|
CHANGED_SERVICES="infrastructure"
|
||||||
|
else
|
||||||
|
CHANGED_SERVICES="$CHANGED_SERVICES,infrastructure"
|
||||||
|
fi
|
||||||
|
echo "$CHANGED_SERVICES" > /tmp/services.txt
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Read the accumulated services
|
||||||
|
if [ -f /tmp/services.txt ]; then
|
||||||
|
CHANGED_SERVICES=$(cat /tmp/services.txt)
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
|
||||||
|
# Output result
|
||||||
|
if [ -z "$CHANGED_SERVICES" ]; then
|
||||||
|
echo "No service changes detected"
|
||||||
|
echo "none" > $(results.changed-services.path)
|
||||||
|
else
|
||||||
|
echo "Detected changes in services: $CHANGED_SERVICES"
|
||||||
|
echo "$CHANGED_SERVICES" > $(results.changed-services.path)
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "============================================"
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 128Mi
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 64Mi
|
||||||
95
infrastructure/cicd/tekton/tasks/git-clone.yaml
Normal file
95
infrastructure/cicd/tekton/tasks/git-clone.yaml
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
# Tekton Git Clone Task for Bakery-IA CI/CD
|
||||||
|
# This task clones the source code repository
|
||||||
|
|
||||||
|
apiVersion: tekton.dev/v1beta1
|
||||||
|
kind: Task
|
||||||
|
metadata:
|
||||||
|
name: git-clone
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: source
|
||||||
|
spec:
|
||||||
|
workspaces:
|
||||||
|
- name: output
|
||||||
|
description: Workspace to clone the repository into
|
||||||
|
params:
|
||||||
|
- name: url
|
||||||
|
type: string
|
||||||
|
description: Repository URL to clone
|
||||||
|
- name: revision
|
||||||
|
type: string
|
||||||
|
description: Git revision to checkout
|
||||||
|
default: "main"
|
||||||
|
- name: depth
|
||||||
|
type: string
|
||||||
|
description: Git clone depth (0 for full history)
|
||||||
|
default: "1"
|
||||||
|
results:
|
||||||
|
- name: commit-sha
|
||||||
|
description: The commit SHA that was checked out
|
||||||
|
- name: commit-message
|
||||||
|
description: The commit message
|
||||||
|
steps:
|
||||||
|
- name: clone
|
||||||
|
image: alpine/git:2.43.0
|
||||||
|
script: |
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
URL="$(params.url)"
|
||||||
|
REVISION="$(params.revision)"
|
||||||
|
DEPTH="$(params.depth)"
|
||||||
|
OUTPUT_PATH="$(workspaces.output.path)"
|
||||||
|
|
||||||
|
echo "============================================"
|
||||||
|
echo "Git Clone Task"
|
||||||
|
echo "============================================"
|
||||||
|
echo "URL: $URL"
|
||||||
|
echo "Revision: $REVISION"
|
||||||
|
echo "Depth: $DEPTH"
|
||||||
|
echo "============================================"
|
||||||
|
|
||||||
|
# Clone with depth for faster checkout
|
||||||
|
if [ "$DEPTH" = "0" ]; then
|
||||||
|
echo "Cloning full repository..."
|
||||||
|
git clone "$URL" "$OUTPUT_PATH"
|
||||||
|
else
|
||||||
|
echo "Cloning with depth $DEPTH..."
|
||||||
|
git clone --depth "$DEPTH" "$URL" "$OUTPUT_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$OUTPUT_PATH"
|
||||||
|
|
||||||
|
# Fetch the specific revision if needed
|
||||||
|
if [ "$REVISION" != "main" ] && [ "$REVISION" != "master" ]; then
|
||||||
|
echo "Fetching revision: $REVISION"
|
||||||
|
git fetch --depth 1 origin "$REVISION" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Checkout the revision
|
||||||
|
echo "Checking out: $REVISION"
|
||||||
|
git checkout "$REVISION" 2>/dev/null || git checkout "origin/$REVISION"
|
||||||
|
|
||||||
|
# Get commit info
|
||||||
|
COMMIT_SHA=$(git rev-parse HEAD)
|
||||||
|
COMMIT_MSG=$(git log -1 --pretty=format:"%s")
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
echo "Clone Complete"
|
||||||
|
echo "============================================"
|
||||||
|
echo "Commit: $COMMIT_SHA"
|
||||||
|
echo "Message: $COMMIT_MSG"
|
||||||
|
echo "============================================"
|
||||||
|
|
||||||
|
# Write results
|
||||||
|
echo -n "$COMMIT_SHA" > $(results.commit-sha.path)
|
||||||
|
echo -n "$COMMIT_MSG" > $(results.commit-message.path)
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
200
infrastructure/cicd/tekton/tasks/kaniko-build.yaml
Normal file
200
infrastructure/cicd/tekton/tasks/kaniko-build.yaml
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
# Tekton Kaniko Build Task for Bakery-IA CI/CD
|
||||||
|
# This task builds and pushes container images using Kaniko
|
||||||
|
# Supports building multiple services from a comma-separated list
|
||||||
|
|
||||||
|
apiVersion: tekton.dev/v1beta1
|
||||||
|
kind: Task
|
||||||
|
metadata:
|
||||||
|
name: kaniko-build
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: build
|
||||||
|
spec:
|
||||||
|
workspaces:
|
||||||
|
- name: source
|
||||||
|
description: Source code workspace
|
||||||
|
- name: docker-credentials
|
||||||
|
description: Docker registry credentials
|
||||||
|
params:
|
||||||
|
- name: services
|
||||||
|
type: string
|
||||||
|
description: Comma-separated list of services to build
|
||||||
|
- name: registry
|
||||||
|
type: string
|
||||||
|
description: Container registry URL
|
||||||
|
- name: git-revision
|
||||||
|
type: string
|
||||||
|
description: Git revision for image tag
|
||||||
|
default: "latest"
|
||||||
|
results:
|
||||||
|
- name: built-images
|
||||||
|
description: List of successfully built images
|
||||||
|
- name: build-status
|
||||||
|
description: Overall build status (success/failure)
|
||||||
|
steps:
|
||||||
|
# Step 1: Setup docker credentials
|
||||||
|
- name: setup-docker-config
|
||||||
|
image: alpine:3.18
|
||||||
|
script: |
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
echo "Setting up Docker credentials..."
|
||||||
|
mkdir -p /kaniko/.docker
|
||||||
|
|
||||||
|
# Check if credentials secret is mounted
|
||||||
|
if [ -f "$(workspaces.docker-credentials.path)/config.json" ]; then
|
||||||
|
cp "$(workspaces.docker-credentials.path)/config.json" /kaniko/.docker/config.json
|
||||||
|
echo "Docker config copied from secret"
|
||||||
|
elif [ -f "$(workspaces.docker-credentials.path)/.dockerconfigjson" ]; then
|
||||||
|
cp "$(workspaces.docker-credentials.path)/.dockerconfigjson" /kaniko/.docker/config.json
|
||||||
|
echo "Docker config copied from .dockerconfigjson"
|
||||||
|
else
|
||||||
|
echo "Warning: No docker credentials found, builds may fail for private registries"
|
||||||
|
echo '{}' > /kaniko/.docker/config.json
|
||||||
|
fi
|
||||||
|
volumeMounts:
|
||||||
|
- name: docker-config
|
||||||
|
mountPath: /kaniko/.docker
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 64Mi
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 32Mi
|
||||||
|
|
||||||
|
# Step 2: Build each service iteratively
|
||||||
|
- name: build-services
|
||||||
|
image: gcr.io/kaniko-project/executor:v1.23.0
|
||||||
|
script: |
|
||||||
|
#!/busybox/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SERVICES="$(params.services)"
|
||||||
|
REGISTRY="$(params.registry)"
|
||||||
|
REVISION="$(params.git-revision)"
|
||||||
|
SOURCE_PATH="$(workspaces.source.path)"
|
||||||
|
BUILT_IMAGES=""
|
||||||
|
FAILED_SERVICES=""
|
||||||
|
|
||||||
|
echo "============================================"
|
||||||
|
echo "Starting build for services: $SERVICES"
|
||||||
|
echo "Registry: $REGISTRY"
|
||||||
|
echo "Tag: $REVISION"
|
||||||
|
echo "============================================"
|
||||||
|
|
||||||
|
# Skip if no services to build
|
||||||
|
if [ "$SERVICES" = "none" ] || [ -z "$SERVICES" ]; then
|
||||||
|
echo "No services to build, skipping..."
|
||||||
|
echo "none" > $(results.built-images.path)
|
||||||
|
echo "skipped" > $(results.build-status.path)
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Convert comma-separated list to space-separated
|
||||||
|
SERVICES_LIST=$(echo "$SERVICES" | tr ',' ' ')
|
||||||
|
|
||||||
|
for SERVICE in $SERVICES_LIST; do
|
||||||
|
# Trim whitespace
|
||||||
|
SERVICE=$(echo "$SERVICE" | tr -d ' ')
|
||||||
|
|
||||||
|
# Skip infrastructure changes (not buildable)
|
||||||
|
if [ "$SERVICE" = "infrastructure" ]; then
|
||||||
|
echo "Skipping infrastructure (not a buildable service)"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "--------------------------------------------"
|
||||||
|
echo "Building service: $SERVICE"
|
||||||
|
echo "--------------------------------------------"
|
||||||
|
|
||||||
|
# Determine Dockerfile path based on service type
|
||||||
|
if [ "$SERVICE" = "frontend" ]; then
|
||||||
|
DOCKERFILE_PATH="$SOURCE_PATH/frontend/Dockerfile"
|
||||||
|
CONTEXT_PATH="$SOURCE_PATH/frontend"
|
||||||
|
elif [ "$SERVICE" = "gateway" ]; then
|
||||||
|
DOCKERFILE_PATH="$SOURCE_PATH/gateway/Dockerfile"
|
||||||
|
CONTEXT_PATH="$SOURCE_PATH/gateway"
|
||||||
|
else
|
||||||
|
DOCKERFILE_PATH="$SOURCE_PATH/services/$SERVICE/Dockerfile"
|
||||||
|
CONTEXT_PATH="$SOURCE_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if Dockerfile exists
|
||||||
|
if [ ! -f "$DOCKERFILE_PATH" ]; then
|
||||||
|
echo "Warning: Dockerfile not found at $DOCKERFILE_PATH, skipping $SERVICE"
|
||||||
|
FAILED_SERVICES="$FAILED_SERVICES $SERVICE"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
IMAGE_NAME="$REGISTRY/bakery/$SERVICE:$REVISION"
|
||||||
|
IMAGE_NAME_LATEST="$REGISTRY/bakery/$SERVICE:latest"
|
||||||
|
|
||||||
|
echo "Dockerfile: $DOCKERFILE_PATH"
|
||||||
|
echo "Context: $CONTEXT_PATH"
|
||||||
|
echo "Image: $IMAGE_NAME"
|
||||||
|
|
||||||
|
# Run Kaniko build
|
||||||
|
/kaniko/executor \
|
||||||
|
--dockerfile="$DOCKERFILE_PATH" \
|
||||||
|
--context="$CONTEXT_PATH" \
|
||||||
|
--destination="$IMAGE_NAME" \
|
||||||
|
--destination="$IMAGE_NAME_LATEST" \
|
||||||
|
--cache=true \
|
||||||
|
--cache-ttl=24h \
|
||||||
|
--verbosity=info \
|
||||||
|
--snapshot-mode=redo \
|
||||||
|
--use-new-run
|
||||||
|
|
||||||
|
BUILD_EXIT_CODE=$?
|
||||||
|
|
||||||
|
if [ $BUILD_EXIT_CODE -eq 0 ]; then
|
||||||
|
echo "Successfully built and pushed: $IMAGE_NAME"
|
||||||
|
if [ -z "$BUILT_IMAGES" ]; then
|
||||||
|
BUILT_IMAGES="$IMAGE_NAME"
|
||||||
|
else
|
||||||
|
BUILT_IMAGES="$BUILT_IMAGES,$IMAGE_NAME"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Failed to build: $SERVICE (exit code: $BUILD_EXIT_CODE)"
|
||||||
|
FAILED_SERVICES="$FAILED_SERVICES $SERVICE"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
echo "Build Summary"
|
||||||
|
echo "============================================"
|
||||||
|
echo "Built images: $BUILT_IMAGES"
|
||||||
|
echo "Failed services: $FAILED_SERVICES"
|
||||||
|
|
||||||
|
# Write results
|
||||||
|
if [ -z "$BUILT_IMAGES" ]; then
|
||||||
|
echo "none" > $(results.built-images.path)
|
||||||
|
else
|
||||||
|
echo "$BUILT_IMAGES" > $(results.built-images.path)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$FAILED_SERVICES" ]; then
|
||||||
|
echo "partial" > $(results.build-status.path)
|
||||||
|
echo "Warning: Some services failed to build: $FAILED_SERVICES"
|
||||||
|
else
|
||||||
|
echo "success" > $(results.build-status.path)
|
||||||
|
fi
|
||||||
|
volumeMounts:
|
||||||
|
- name: docker-config
|
||||||
|
mountPath: /kaniko/.docker
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 0
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 2000m
|
||||||
|
memory: 4Gi
|
||||||
|
requests:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 1Gi
|
||||||
|
volumes:
|
||||||
|
- name: docker-config
|
||||||
|
emptyDir: {}
|
||||||
14
infrastructure/cicd/tekton/tasks/kustomization.yaml
Normal file
14
infrastructure/cicd/tekton/tasks/kustomization.yaml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- git-clone.yaml
|
||||||
|
- detect-changes.yaml
|
||||||
|
- run-tests.yaml
|
||||||
|
- kaniko-build.yaml
|
||||||
|
- update-gitops.yaml
|
||||||
|
- pipeline-summary.yaml
|
||||||
|
# Production deployment tasks
|
||||||
|
- verify-images.yaml
|
||||||
|
- pre-deploy-validation.yaml
|
||||||
|
- prod-deployment-summary.yaml
|
||||||
62
infrastructure/cicd/tekton/tasks/pipeline-summary.yaml
Normal file
62
infrastructure/cicd/tekton/tasks/pipeline-summary.yaml
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# Tekton Pipeline Summary Task for Bakery-IA CI/CD
|
||||||
|
# This task runs at the end of the pipeline and provides a summary
|
||||||
|
|
||||||
|
apiVersion: tekton.dev/v1beta1
|
||||||
|
kind: Task
|
||||||
|
metadata:
|
||||||
|
name: pipeline-summary
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: summary
|
||||||
|
spec:
|
||||||
|
params:
|
||||||
|
- name: changed-services
|
||||||
|
type: string
|
||||||
|
description: List of changed services
|
||||||
|
default: "none"
|
||||||
|
- name: git-revision
|
||||||
|
type: string
|
||||||
|
description: Git revision that was built
|
||||||
|
default: "unknown"
|
||||||
|
steps:
|
||||||
|
- name: summary
|
||||||
|
image: alpine:3.18
|
||||||
|
script: |
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
SERVICES="$(params.changed-services)"
|
||||||
|
REVISION="$(params.git-revision)"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
echo " Pipeline Execution Summary"
|
||||||
|
echo "============================================"
|
||||||
|
echo ""
|
||||||
|
echo "Git Revision: $REVISION"
|
||||||
|
echo "Changed Services: $SERVICES"
|
||||||
|
echo ""
|
||||||
|
echo "Timestamp: $(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ "$SERVICES" = "none" ] || [ -z "$SERVICES" ]; then
|
||||||
|
echo "No services were changed in this commit."
|
||||||
|
echo "Pipeline completed without building any images."
|
||||||
|
else
|
||||||
|
echo "The following services were processed:"
|
||||||
|
echo "$SERVICES" | tr ',' '\n' | while read service; do
|
||||||
|
echo " - $service"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 64Mi
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 32Mi
|
||||||
76
infrastructure/cicd/tekton/tasks/pre-deploy-validation.yaml
Normal file
76
infrastructure/cicd/tekton/tasks/pre-deploy-validation.yaml
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
# Task for pre-deployment validation
|
||||||
|
apiVersion: tekton.dev/v1beta1
|
||||||
|
kind: Task
|
||||||
|
metadata:
|
||||||
|
name: pre-deploy-validation
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: validation
|
||||||
|
spec:
|
||||||
|
workspaces:
|
||||||
|
- name: source
|
||||||
|
description: Source code workspace
|
||||||
|
params:
|
||||||
|
- name: services
|
||||||
|
type: string
|
||||||
|
description: Comma-separated list of services to validate
|
||||||
|
- name: environment
|
||||||
|
type: string
|
||||||
|
description: Target environment (staging/production)
|
||||||
|
default: "production"
|
||||||
|
results:
|
||||||
|
- name: validation-status
|
||||||
|
description: Status of validation (passed/failed)
|
||||||
|
steps:
|
||||||
|
- name: validate
|
||||||
|
image: registry.k8s.io/kustomize/kustomize:v5.3.0
|
||||||
|
script: |
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SOURCE_PATH="$(workspaces.source.path)"
|
||||||
|
SERVICES="$(params.services)"
|
||||||
|
ENVIRONMENT="$(params.environment)"
|
||||||
|
|
||||||
|
echo "============================================"
|
||||||
|
echo "Pre-Deployment Validation"
|
||||||
|
echo "============================================"
|
||||||
|
echo "Environment: $ENVIRONMENT"
|
||||||
|
echo "Services: $SERVICES"
|
||||||
|
echo "============================================"
|
||||||
|
|
||||||
|
cd "$SOURCE_PATH"
|
||||||
|
|
||||||
|
# Validate kustomization can be built
|
||||||
|
KUSTOMIZE_DIR="infrastructure/environments/$ENVIRONMENT"
|
||||||
|
|
||||||
|
if [ -d "$KUSTOMIZE_DIR" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "Validating kustomization..."
|
||||||
|
if kustomize build "$KUSTOMIZE_DIR" > /dev/null 2>&1; then
|
||||||
|
echo " ✓ Kustomization is valid"
|
||||||
|
else
|
||||||
|
echo " ✗ Kustomization validation failed"
|
||||||
|
echo "failed" > $(results.validation-status.path)
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Additional validation checks can be added here
|
||||||
|
# - Schema validation
|
||||||
|
# - Policy checks (OPA/Gatekeeper)
|
||||||
|
# - Security scanning
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
echo "All validations passed"
|
||||||
|
echo "============================================"
|
||||||
|
echo "passed" > $(results.validation-status.path)
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 256Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
# Task for production deployment summary
|
||||||
|
apiVersion: tekton.dev/v1beta1
|
||||||
|
kind: Task
|
||||||
|
metadata:
|
||||||
|
name: prod-deployment-summary
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: summary
|
||||||
|
spec:
|
||||||
|
params:
|
||||||
|
- name: services
|
||||||
|
type: string
|
||||||
|
description: List of deployed services
|
||||||
|
- name: git-revision
|
||||||
|
type: string
|
||||||
|
description: Git revision that was deployed
|
||||||
|
- name: approver
|
||||||
|
type: string
|
||||||
|
description: Name of the approver
|
||||||
|
- name: approval-ticket
|
||||||
|
type: string
|
||||||
|
description: Approval ticket number
|
||||||
|
steps:
|
||||||
|
- name: summary
|
||||||
|
image: alpine:3.18
|
||||||
|
script: |
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
echo " Production Deployment Summary"
|
||||||
|
echo "============================================"
|
||||||
|
echo ""
|
||||||
|
echo "Git Revision: $(params.git-revision)"
|
||||||
|
echo "Services: $(params.services)"
|
||||||
|
echo "Approved By: $(params.approver)"
|
||||||
|
echo "Approval Ticket: $(params.approval-ticket)"
|
||||||
|
echo "Timestamp: $(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
echo ""
|
||||||
|
echo "Deployment to production initiated."
|
||||||
|
echo "Flux CD will reconcile the changes."
|
||||||
|
echo ""
|
||||||
|
echo "Monitor deployment status with:"
|
||||||
|
echo " kubectl get kustomization -n flux-system"
|
||||||
|
echo " kubectl get pods -n bakery-ia"
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 64Mi
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 32Mi
|
||||||
205
infrastructure/cicd/tekton/tasks/run-tests.yaml
Normal file
205
infrastructure/cicd/tekton/tasks/run-tests.yaml
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
# Tekton Test Task for Bakery-IA CI/CD
|
||||||
|
# This task runs unit tests and linting for changed services
|
||||||
|
|
||||||
|
apiVersion: tekton.dev/v1beta1
|
||||||
|
kind: Task
|
||||||
|
metadata:
|
||||||
|
name: run-tests
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: test
|
||||||
|
spec:
|
||||||
|
workspaces:
|
||||||
|
- name: source
|
||||||
|
description: Source code workspace
|
||||||
|
params:
|
||||||
|
- name: services
|
||||||
|
type: string
|
||||||
|
description: Comma-separated list of services to test
|
||||||
|
- name: skip-lint
|
||||||
|
type: string
|
||||||
|
description: Skip linting if "true"
|
||||||
|
default: "false"
|
||||||
|
- name: skip-tests
|
||||||
|
type: string
|
||||||
|
description: Skip tests if "true"
|
||||||
|
default: "false"
|
||||||
|
results:
|
||||||
|
- name: test-status
|
||||||
|
description: Overall test status (passed/failed/skipped)
|
||||||
|
- name: tested-services
|
||||||
|
description: List of services that were tested
|
||||||
|
- name: failed-services
|
||||||
|
description: List of services that failed tests
|
||||||
|
steps:
|
||||||
|
- name: run-tests
|
||||||
|
image: python:3.11-slim
|
||||||
|
script: |
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SOURCE_PATH="$(workspaces.source.path)"
|
||||||
|
SERVICES="$(params.services)"
|
||||||
|
SKIP_LINT="$(params.skip-lint)"
|
||||||
|
SKIP_TESTS="$(params.skip-tests)"
|
||||||
|
|
||||||
|
TESTED_SERVICES=""
|
||||||
|
FAILED_SERVICES=""
|
||||||
|
OVERALL_STATUS="passed"
|
||||||
|
|
||||||
|
cd "$SOURCE_PATH"
|
||||||
|
|
||||||
|
echo "============================================"
|
||||||
|
echo "Running Tests"
|
||||||
|
echo "============================================"
|
||||||
|
echo "Services: $SERVICES"
|
||||||
|
echo "Skip Lint: $SKIP_LINT"
|
||||||
|
echo "Skip Tests: $SKIP_TESTS"
|
||||||
|
echo "============================================"
|
||||||
|
|
||||||
|
# Skip if no services to test
|
||||||
|
if [ "$SERVICES" = "none" ] || [ -z "$SERVICES" ]; then
|
||||||
|
echo "No services to test, skipping..."
|
||||||
|
echo "skipped" > $(results.test-status.path)
|
||||||
|
echo "none" > $(results.tested-services.path)
|
||||||
|
echo "none" > $(results.failed-services.path)
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install common test dependencies
|
||||||
|
echo ""
|
||||||
|
echo "Installing test dependencies..."
|
||||||
|
pip install --quiet pytest pytest-cov pytest-asyncio ruff mypy 2>/dev/null || true
|
||||||
|
|
||||||
|
# Convert comma-separated list to space-separated
|
||||||
|
SERVICES_LIST=$(echo "$SERVICES" | tr ',' ' ')
|
||||||
|
|
||||||
|
for SERVICE in $SERVICES_LIST; do
|
||||||
|
# Trim whitespace
|
||||||
|
SERVICE=$(echo "$SERVICE" | tr -d ' ')
|
||||||
|
|
||||||
|
# Skip infrastructure changes
|
||||||
|
if [ "$SERVICE" = "infrastructure" ]; then
|
||||||
|
echo "Skipping infrastructure (not testable)"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "--------------------------------------------"
|
||||||
|
echo "Testing service: $SERVICE"
|
||||||
|
echo "--------------------------------------------"
|
||||||
|
|
||||||
|
# Determine service path
|
||||||
|
if [ "$SERVICE" = "frontend" ]; then
|
||||||
|
SERVICE_PATH="$SOURCE_PATH/frontend"
|
||||||
|
elif [ "$SERVICE" = "gateway" ]; then
|
||||||
|
SERVICE_PATH="$SOURCE_PATH/gateway"
|
||||||
|
else
|
||||||
|
SERVICE_PATH="$SOURCE_PATH/services/$SERVICE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if service exists
|
||||||
|
if [ ! -d "$SERVICE_PATH" ]; then
|
||||||
|
echo "Warning: Service directory not found: $SERVICE_PATH"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$SERVICE_PATH"
|
||||||
|
SERVICE_FAILED=false
|
||||||
|
|
||||||
|
# Install service-specific dependencies if requirements.txt exists
|
||||||
|
if [ -f "requirements.txt" ]; then
|
||||||
|
echo "Installing service dependencies..."
|
||||||
|
pip install --quiet -r requirements.txt 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run linting (ruff)
|
||||||
|
if [ "$SKIP_LINT" != "true" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "Running linter (ruff)..."
|
||||||
|
if [ -d "app" ]; then
|
||||||
|
ruff check app/ --output-format=text 2>&1 || {
|
||||||
|
echo "Linting failed for $SERVICE"
|
||||||
|
SERVICE_FAILED=true
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
if [ "$SKIP_TESTS" != "true" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "Running tests (pytest)..."
|
||||||
|
if [ -d "tests" ]; then
|
||||||
|
pytest tests/ -v --tb=short 2>&1 || {
|
||||||
|
echo "Tests failed for $SERVICE"
|
||||||
|
SERVICE_FAILED=true
|
||||||
|
}
|
||||||
|
elif [ -d "app/tests" ]; then
|
||||||
|
pytest app/tests/ -v --tb=short 2>&1 || {
|
||||||
|
echo "Tests failed for $SERVICE"
|
||||||
|
SERVICE_FAILED=true
|
||||||
|
}
|
||||||
|
else
|
||||||
|
echo "No tests directory found, skipping tests"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Track results
|
||||||
|
if [ -z "$TESTED_SERVICES" ]; then
|
||||||
|
TESTED_SERVICES="$SERVICE"
|
||||||
|
else
|
||||||
|
TESTED_SERVICES="$TESTED_SERVICES,$SERVICE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$SERVICE_FAILED" = true ]; then
|
||||||
|
OVERALL_STATUS="failed"
|
||||||
|
if [ -z "$FAILED_SERVICES" ]; then
|
||||||
|
FAILED_SERVICES="$SERVICE"
|
||||||
|
else
|
||||||
|
FAILED_SERVICES="$FAILED_SERVICES,$SERVICE"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$SOURCE_PATH"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
echo "Test Summary"
|
||||||
|
echo "============================================"
|
||||||
|
echo "Tested services: $TESTED_SERVICES"
|
||||||
|
echo "Failed services: $FAILED_SERVICES"
|
||||||
|
echo "Overall status: $OVERALL_STATUS"
|
||||||
|
|
||||||
|
# Write results
|
||||||
|
echo "$OVERALL_STATUS" > $(results.test-status.path)
|
||||||
|
|
||||||
|
if [ -z "$TESTED_SERVICES" ]; then
|
||||||
|
echo "none" > $(results.tested-services.path)
|
||||||
|
else
|
||||||
|
echo "$TESTED_SERVICES" > $(results.tested-services.path)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$FAILED_SERVICES" ]; then
|
||||||
|
echo "none" > $(results.failed-services.path)
|
||||||
|
else
|
||||||
|
echo "$FAILED_SERVICES" > $(results.failed-services.path)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Exit with error if tests failed
|
||||||
|
if [ "$OVERALL_STATUS" = "failed" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "ERROR: Some tests failed!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "All tests passed!"
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 2Gi
|
||||||
|
requests:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 1Gi
|
||||||
302
infrastructure/cicd/tekton/tasks/update-gitops.yaml
Normal file
302
infrastructure/cicd/tekton/tasks/update-gitops.yaml
Normal file
@@ -0,0 +1,302 @@
|
|||||||
|
# Tekton Update GitOps Manifests Task for Bakery-IA CI/CD
|
||||||
|
# This task updates Kubernetes manifests with new image tags using Kustomize
|
||||||
|
# It uses a safer approach than sed for updating image references
|
||||||
|
|
||||||
|
apiVersion: tekton.dev/v1beta1
|
||||||
|
kind: Task
|
||||||
|
metadata:
|
||||||
|
name: update-gitops
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: gitops
|
||||||
|
spec:
|
||||||
|
workspaces:
|
||||||
|
- name: source
|
||||||
|
description: Source code workspace with Git repository
|
||||||
|
- name: git-credentials
|
||||||
|
description: Git credentials for pushing changes
|
||||||
|
optional: true
|
||||||
|
params:
|
||||||
|
- name: services
|
||||||
|
type: string
|
||||||
|
description: Comma-separated list of services to update
|
||||||
|
- name: registry
|
||||||
|
type: string
|
||||||
|
description: Container registry URL
|
||||||
|
- name: git-revision
|
||||||
|
type: string
|
||||||
|
description: Git revision for image tag
|
||||||
|
- name: git-branch
|
||||||
|
type: string
|
||||||
|
description: Target branch for GitOps updates
|
||||||
|
default: "main"
|
||||||
|
- name: dry-run
|
||||||
|
type: string
|
||||||
|
description: If "true", only show what would be changed without committing
|
||||||
|
default: "false"
|
||||||
|
results:
|
||||||
|
- name: updated-services
|
||||||
|
description: List of services that were updated
|
||||||
|
- name: commit-sha
|
||||||
|
description: Git commit SHA of the update (empty if dry-run)
|
||||||
|
steps:
|
||||||
|
- name: update-manifests
|
||||||
|
# Use alpine with curl to install kustomize
|
||||||
|
image: alpine:3.19
|
||||||
|
script: |
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Install kustomize
|
||||||
|
echo "Installing kustomize..."
|
||||||
|
wget -q "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" -O - | sh
|
||||||
|
mv kustomize /usr/local/bin/
|
||||||
|
echo "Kustomize version: $(kustomize version)"
|
||||||
|
|
||||||
|
SOURCE_PATH="$(workspaces.source.path)"
|
||||||
|
SERVICES="$(params.services)"
|
||||||
|
REGISTRY="$(params.registry)"
|
||||||
|
REVISION="$(params.git-revision)"
|
||||||
|
DRY_RUN="$(params.dry-run)"
|
||||||
|
UPDATED_SERVICES=""
|
||||||
|
|
||||||
|
cd "$SOURCE_PATH"
|
||||||
|
|
||||||
|
echo "============================================"
|
||||||
|
echo "GitOps Manifest Update"
|
||||||
|
echo "============================================"
|
||||||
|
echo "Services: $SERVICES"
|
||||||
|
echo "Registry: $REGISTRY"
|
||||||
|
echo "Revision: $REVISION"
|
||||||
|
echo "Dry Run: $DRY_RUN"
|
||||||
|
echo "============================================"
|
||||||
|
|
||||||
|
# Skip if no services to update
|
||||||
|
if [ "$SERVICES" = "none" ] || [ -z "$SERVICES" ]; then
|
||||||
|
echo "No services to update, skipping..."
|
||||||
|
echo "none" > $(results.updated-services.path)
|
||||||
|
echo "" > $(results.commit-sha.path)
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Define the kustomization directory
|
||||||
|
KUSTOMIZE_DIR="infrastructure/environments/prod"
|
||||||
|
|
||||||
|
# Check if kustomization.yaml exists, create if not
|
||||||
|
if [ ! -f "$KUSTOMIZE_DIR/kustomization.yaml" ]; then
|
||||||
|
echo "Creating kustomization.yaml in $KUSTOMIZE_DIR"
|
||||||
|
mkdir -p "$KUSTOMIZE_DIR"
|
||||||
|
printf '%s\n' \
|
||||||
|
"apiVersion: kustomize.config.k8s.io/v1beta1" \
|
||||||
|
"kind: Kustomization" \
|
||||||
|
"" \
|
||||||
|
"resources:" \
|
||||||
|
" - ../base" \
|
||||||
|
"" \
|
||||||
|
"images: []" \
|
||||||
|
> "$KUSTOMIZE_DIR/kustomization.yaml"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Convert comma-separated list to space-separated
|
||||||
|
SERVICES_LIST=$(echo "$SERVICES" | tr ',' ' ')
|
||||||
|
|
||||||
|
# Build the images section for kustomization
|
||||||
|
echo ""
|
||||||
|
echo "Updating image references..."
|
||||||
|
|
||||||
|
for SERVICE in $SERVICES_LIST; do
|
||||||
|
# Trim whitespace
|
||||||
|
SERVICE=$(echo "$SERVICE" | tr -d ' ')
|
||||||
|
|
||||||
|
# Skip infrastructure changes
|
||||||
|
if [ "$SERVICE" = "infrastructure" ]; then
|
||||||
|
echo "Skipping infrastructure (not a deployable service)"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Processing: $SERVICE"
|
||||||
|
|
||||||
|
# Determine the image name based on service
|
||||||
|
NEW_IMAGE="$REGISTRY/bakery/$SERVICE:$REVISION"
|
||||||
|
|
||||||
|
# Use kustomize to set the image
|
||||||
|
# This is safer than sed as it understands the YAML structure
|
||||||
|
cd "$SOURCE_PATH/$KUSTOMIZE_DIR"
|
||||||
|
|
||||||
|
# Check if this service has a deployment
|
||||||
|
SERVICE_DEPLOYMENT=""
|
||||||
|
if [ "$SERVICE" = "frontend" ]; then
|
||||||
|
SERVICE_DEPLOYMENT="frontend"
|
||||||
|
elif [ "$SERVICE" = "gateway" ]; then
|
||||||
|
SERVICE_DEPLOYMENT="gateway"
|
||||||
|
else
|
||||||
|
SERVICE_DEPLOYMENT="$SERVICE-service"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Update the kustomization with the new image
|
||||||
|
# Using kustomize edit to safely modify the file
|
||||||
|
kustomize edit set image "bakery/$SERVICE=$NEW_IMAGE" 2>/dev/null || \
|
||||||
|
kustomize edit set image "$SERVICE=$NEW_IMAGE" 2>/dev/null || \
|
||||||
|
echo "Note: Could not set image via kustomize edit, will use alternative method"
|
||||||
|
|
||||||
|
# Track updated services
|
||||||
|
if [ -z "$UPDATED_SERVICES" ]; then
|
||||||
|
UPDATED_SERVICES="$SERVICE"
|
||||||
|
else
|
||||||
|
UPDATED_SERVICES="$UPDATED_SERVICES,$SERVICE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$SOURCE_PATH"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Alternative: Update images in kustomization.yaml directly if kustomize edit didn't work
|
||||||
|
# This creates/updates an images section in the kustomization
|
||||||
|
echo ""
|
||||||
|
echo "Ensuring image overrides in kustomization.yaml..."
|
||||||
|
|
||||||
|
# Create a patch file for image updates
|
||||||
|
IMAGES_FILE="$KUSTOMIZE_DIR/images.yaml"
|
||||||
|
printf '%s\n' \
|
||||||
|
"# Auto-generated by CI/CD pipeline" \
|
||||||
|
"# Commit: $REVISION" \
|
||||||
|
"# Updated: $(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
|
||||||
|
"images:" \
|
||||||
|
> "$IMAGES_FILE"
|
||||||
|
|
||||||
|
for SERVICE in $SERVICES_LIST; do
|
||||||
|
SERVICE=$(echo "$SERVICE" | tr -d ' ')
|
||||||
|
if [ "$SERVICE" != "infrastructure" ]; then
|
||||||
|
printf '%s\n' \
|
||||||
|
" - name: bakery/$SERVICE" \
|
||||||
|
" newName: $REGISTRY/bakery/$SERVICE" \
|
||||||
|
" newTag: \"$REVISION\"" \
|
||||||
|
>> "$IMAGES_FILE"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Generated images.yaml:"
|
||||||
|
cat "$IMAGES_FILE"
|
||||||
|
|
||||||
|
# Validate the kustomization
|
||||||
|
echo ""
|
||||||
|
echo "Validating kustomization..."
|
||||||
|
cd "$SOURCE_PATH/$KUSTOMIZE_DIR"
|
||||||
|
if kustomize build . > /dev/null 2>&1; then
|
||||||
|
echo "Kustomization is valid"
|
||||||
|
else
|
||||||
|
echo "Warning: Kustomization validation failed, but continuing..."
|
||||||
|
fi
|
||||||
|
cd "$SOURCE_PATH"
|
||||||
|
|
||||||
|
# Write results
|
||||||
|
echo "$UPDATED_SERVICES" > $(results.updated-services.path)
|
||||||
|
|
||||||
|
if [ "$DRY_RUN" = "true" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
echo "DRY RUN - Changes not committed"
|
||||||
|
echo "============================================"
|
||||||
|
echo "Would update services: $UPDATED_SERVICES"
|
||||||
|
git diff --stat || true
|
||||||
|
echo "" > $(results.commit-sha.path)
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Committing changes..."
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
|
||||||
|
- name: commit-and-push
|
||||||
|
image: alpine/git:2.43.0
|
||||||
|
script: |
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SOURCE_PATH="$(workspaces.source.path)"
|
||||||
|
SERVICES="$(params.services)"
|
||||||
|
REVISION="$(params.git-revision)"
|
||||||
|
BRANCH="$(params.git-branch)"
|
||||||
|
DRY_RUN="$(params.dry-run)"
|
||||||
|
|
||||||
|
cd "$SOURCE_PATH"
|
||||||
|
|
||||||
|
if [ "$DRY_RUN" = "true" ]; then
|
||||||
|
echo "Dry run mode - skipping commit"
|
||||||
|
echo "" > $(results.commit-sha.path)
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$SERVICES" = "none" ] || [ -z "$SERVICES" ]; then
|
||||||
|
echo "No services to commit"
|
||||||
|
echo "" > $(results.commit-sha.path)
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if there are changes to commit
|
||||||
|
if git diff --quiet && git diff --cached --quiet; then
|
||||||
|
echo "No changes to commit"
|
||||||
|
echo "" > $(results.commit-sha.path)
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Configure git
|
||||||
|
git config --global user.name "bakery-ia-ci"
|
||||||
|
git config --global user.email "ci@bakery-ia.local"
|
||||||
|
git config --global --add safe.directory "$SOURCE_PATH"
|
||||||
|
|
||||||
|
# Setup git credentials if provided
|
||||||
|
if [ -d "$(workspaces.git-credentials.path)" ]; then
|
||||||
|
if [ -f "$(workspaces.git-credentials.path)/username" ] && [ -f "$(workspaces.git-credentials.path)/password" ]; then
|
||||||
|
GIT_USER=$(cat "$(workspaces.git-credentials.path)/username")
|
||||||
|
GIT_PASS=$(cat "$(workspaces.git-credentials.path)/password")
|
||||||
|
|
||||||
|
# Get the remote URL and inject credentials
|
||||||
|
REMOTE_URL=$(git remote get-url origin)
|
||||||
|
# Handle both http and https
|
||||||
|
if echo "$REMOTE_URL" | grep -q "^http"; then
|
||||||
|
REMOTE_URL=$(echo "$REMOTE_URL" | sed "s|://|://$GIT_USER:$GIT_PASS@|")
|
||||||
|
git remote set-url origin "$REMOTE_URL"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Stage changes
|
||||||
|
git add -A
|
||||||
|
|
||||||
|
# Create commit with detailed message
|
||||||
|
COMMIT_MSG=$(printf 'ci: Update image tags to %s\n\nServices updated: %s\n\nThis commit was automatically generated by the CI/CD pipeline.\nPipeline run triggered by commit: %s' "$REVISION" "$SERVICES" "$REVISION")
|
||||||
|
|
||||||
|
git commit -m "$COMMIT_MSG"
|
||||||
|
|
||||||
|
# Get the commit SHA
|
||||||
|
COMMIT_SHA=$(git rev-parse HEAD)
|
||||||
|
echo "$COMMIT_SHA" > $(results.commit-sha.path)
|
||||||
|
|
||||||
|
echo "Created commit: $COMMIT_SHA"
|
||||||
|
|
||||||
|
# Push changes
|
||||||
|
echo "Pushing to origin/$BRANCH..."
|
||||||
|
git push origin HEAD:"$BRANCH"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
echo "GitOps Update Complete"
|
||||||
|
echo "============================================"
|
||||||
|
echo "Commit: $COMMIT_SHA"
|
||||||
|
echo "Branch: $BRANCH"
|
||||||
|
echo "Services: $SERVICES"
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 128Mi
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 64Mi
|
||||||
91
infrastructure/cicd/tekton/tasks/verify-images.yaml
Normal file
91
infrastructure/cicd/tekton/tasks/verify-images.yaml
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
# Task to verify images exist in the registry before deploying
|
||||||
|
apiVersion: tekton.dev/v1beta1
|
||||||
|
kind: Task
|
||||||
|
metadata:
|
||||||
|
name: verify-images
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: validation
|
||||||
|
spec:
|
||||||
|
params:
|
||||||
|
- name: services
|
||||||
|
type: string
|
||||||
|
description: Comma-separated list of services to verify
|
||||||
|
- name: registry
|
||||||
|
type: string
|
||||||
|
description: Container registry URL
|
||||||
|
- name: git-revision
|
||||||
|
type: string
|
||||||
|
description: Git revision/tag to verify
|
||||||
|
results:
|
||||||
|
- name: verification-status
|
||||||
|
description: Status of image verification (success/failed)
|
||||||
|
- name: missing-images
|
||||||
|
description: List of images that were not found
|
||||||
|
steps:
|
||||||
|
- name: verify
|
||||||
|
image: gcr.io/go-containerregistry/crane:latest
|
||||||
|
script: |
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SERVICES="$(params.services)"
|
||||||
|
REGISTRY="$(params.registry)"
|
||||||
|
REVISION="$(params.git-revision)"
|
||||||
|
MISSING=""
|
||||||
|
|
||||||
|
echo "============================================"
|
||||||
|
echo "Verifying Images in Registry"
|
||||||
|
echo "============================================"
|
||||||
|
echo "Registry: $REGISTRY"
|
||||||
|
echo "Revision: $REVISION"
|
||||||
|
echo "Services: $SERVICES"
|
||||||
|
echo "============================================"
|
||||||
|
|
||||||
|
# Convert comma-separated list to space-separated
|
||||||
|
SERVICES_LIST=$(echo "$SERVICES" | tr ',' ' ')
|
||||||
|
|
||||||
|
for SERVICE in $SERVICES_LIST; do
|
||||||
|
SERVICE=$(echo "$SERVICE" | tr -d ' ')
|
||||||
|
|
||||||
|
if [ "$SERVICE" = "infrastructure" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
IMAGE="$REGISTRY/bakery/$SERVICE:$REVISION"
|
||||||
|
echo ""
|
||||||
|
echo "Checking: $IMAGE"
|
||||||
|
|
||||||
|
if crane manifest "$IMAGE" > /dev/null 2>&1; then
|
||||||
|
echo " ✓ Found"
|
||||||
|
else
|
||||||
|
echo " ✗ NOT FOUND"
|
||||||
|
if [ -z "$MISSING" ]; then
|
||||||
|
MISSING="$SERVICE"
|
||||||
|
else
|
||||||
|
MISSING="$MISSING,$SERVICE"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
|
||||||
|
if [ -n "$MISSING" ]; then
|
||||||
|
echo "ERROR: Missing images: $MISSING"
|
||||||
|
echo "failed" > $(results.verification-status.path)
|
||||||
|
echo "$MISSING" > $(results.missing-images.path)
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "All images verified successfully"
|
||||||
|
echo "success" > $(results.verification-status.path)
|
||||||
|
echo "none" > $(results.missing-images.path)
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 128Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 64Mi
|
||||||
35
infrastructure/cicd/tekton/triggers/event-listener.yaml
Normal file
35
infrastructure/cicd/tekton/triggers/event-listener.yaml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Tekton EventListener for Bakery-IA CI/CD
|
||||||
|
# This listener receives webhook events and triggers pipelines
|
||||||
|
|
||||||
|
apiVersion: triggers.tekton.dev/v1beta1
|
||||||
|
kind: EventListener
|
||||||
|
metadata:
|
||||||
|
name: bakery-ia-listener
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
spec:
|
||||||
|
serviceAccountName: tekton-triggers-sa
|
||||||
|
triggers:
|
||||||
|
- name: bakery-ia-gitea-trigger
|
||||||
|
bindings:
|
||||||
|
- ref: bakery-ia-trigger-binding
|
||||||
|
template:
|
||||||
|
ref: bakery-ia-trigger-template
|
||||||
|
# Using CEL interceptor for local development (no TLS/CA bundle required)
|
||||||
|
# The CEL interceptor is built-in and doesn't need external services
|
||||||
|
interceptors:
|
||||||
|
- name: "filter-push-events"
|
||||||
|
ref:
|
||||||
|
name: "cel"
|
||||||
|
params:
|
||||||
|
# Filter for push events from Gitea or GitHub
|
||||||
|
- name: "filter"
|
||||||
|
value: "header.match('X-Gitea-Event', 'push') || header.match('X-GitHub-Event', 'push')"
|
||||||
|
# Add overlays to standardize the payload
|
||||||
|
- name: "overlays"
|
||||||
|
value:
|
||||||
|
- key: "git_url"
|
||||||
|
expression: "body.repository.clone_url"
|
||||||
|
- key: "git_revision"
|
||||||
|
expression: "body.after"
|
||||||
|
- key: "git_branch"
|
||||||
|
expression: "body.ref.split('/')[2]"
|
||||||
9
infrastructure/cicd/tekton/triggers/kustomization.yaml
Normal file
9
infrastructure/cicd/tekton/triggers/kustomization.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
# NOTE: gitlab-interceptor.yaml removed - uses built-in Tekton Triggers interceptor
|
||||||
|
# The gitlab ClusterInterceptor is provided by Tekton Triggers installation
|
||||||
|
- event-listener.yaml
|
||||||
|
- trigger-template.yaml
|
||||||
|
- trigger-binding.yaml
|
||||||
31
infrastructure/cicd/tekton/triggers/trigger-binding.yaml
Normal file
31
infrastructure/cicd/tekton/triggers/trigger-binding.yaml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# Tekton TriggerBinding for Bakery-IA CI/CD
|
||||||
|
# This binding extracts parameters from Gitea webhook events
|
||||||
|
#
|
||||||
|
# Note: We use CEL overlay extensions for consistent field access
|
||||||
|
# The EventListener's CEL interceptor creates these extensions:
|
||||||
|
# - extensions.git_url: Repository clone URL
|
||||||
|
# - extensions.git_revision: Commit SHA (from body.after)
|
||||||
|
# - extensions.git_branch: Branch name (extracted from ref)
|
||||||
|
|
||||||
|
apiVersion: triggers.tekton.dev/v1beta1
|
||||||
|
kind: TriggerBinding
|
||||||
|
metadata:
|
||||||
|
name: bakery-ia-trigger-binding
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: triggers
|
||||||
|
spec:
|
||||||
|
params:
|
||||||
|
# Use CEL overlay extensions for consistent access across Git providers
|
||||||
|
- name: git-repo-url
|
||||||
|
value: $(extensions.git_url)
|
||||||
|
- name: git-revision
|
||||||
|
value: $(extensions.git_revision)
|
||||||
|
- name: git-branch
|
||||||
|
value: $(extensions.git_branch)
|
||||||
|
# Direct body access for fields not in overlays
|
||||||
|
- name: git-repo-name
|
||||||
|
value: $(body.repository.name)
|
||||||
|
- name: git-repo-full-name
|
||||||
|
value: $(body.repository.full_name)
|
||||||
86
infrastructure/cicd/tekton/triggers/trigger-template.yaml
Normal file
86
infrastructure/cicd/tekton/triggers/trigger-template.yaml
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
# Tekton TriggerTemplate for Bakery-IA CI/CD
|
||||||
|
# This template defines how PipelineRuns are created when triggers fire
|
||||||
|
#
|
||||||
|
# Registry URL Configuration:
|
||||||
|
# The registry URL is configured via the 'registry' parameter.
|
||||||
|
# Default value should match pipeline-config ConfigMap's REGISTRY_URL.
|
||||||
|
# To change the registry, update BOTH:
|
||||||
|
# 1. This template's default value
|
||||||
|
# 2. The pipeline-config ConfigMap
|
||||||
|
|
||||||
|
apiVersion: triggers.tekton.dev/v1beta1
|
||||||
|
kind: TriggerTemplate
|
||||||
|
metadata:
|
||||||
|
name: bakery-ia-trigger-template
|
||||||
|
namespace: tekton-pipelines
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
app.kubernetes.io/component: triggers
|
||||||
|
spec:
|
||||||
|
params:
|
||||||
|
- name: git-repo-url
|
||||||
|
description: The git repository URL
|
||||||
|
- name: git-revision
|
||||||
|
description: The git revision/commit hash
|
||||||
|
- name: git-branch
|
||||||
|
description: The git branch name
|
||||||
|
default: "main"
|
||||||
|
- name: git-repo-name
|
||||||
|
description: The git repository name
|
||||||
|
default: "bakery-ia"
|
||||||
|
- name: git-repo-full-name
|
||||||
|
description: The full repository name (org/repo)
|
||||||
|
default: "bakery/bakery-ia"
|
||||||
|
# Registry URL - keep in sync with pipeline-config ConfigMap
|
||||||
|
- name: registry-url
|
||||||
|
description: Container registry URL
|
||||||
|
default: "gitea.bakery-ia.local:5000"
|
||||||
|
resourcetemplates:
|
||||||
|
- apiVersion: tekton.dev/v1beta1
|
||||||
|
kind: PipelineRun
|
||||||
|
metadata:
|
||||||
|
generateName: bakery-ia-ci-run-
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: bakery-ia-cicd
|
||||||
|
tekton.dev/pipeline: bakery-ia-ci
|
||||||
|
triggers.tekton.dev/trigger: bakery-ia-gitea-trigger
|
||||||
|
annotations:
|
||||||
|
# Track the source commit
|
||||||
|
bakery-ia.io/git-revision: $(tt.params.git-revision)
|
||||||
|
bakery-ia.io/git-branch: $(tt.params.git-branch)
|
||||||
|
spec:
|
||||||
|
pipelineRef:
|
||||||
|
name: bakery-ia-ci
|
||||||
|
serviceAccountName: tekton-pipeline-sa
|
||||||
|
workspaces:
|
||||||
|
- name: shared-workspace
|
||||||
|
volumeClaimTemplate:
|
||||||
|
spec:
|
||||||
|
accessModes: ["ReadWriteOnce"]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 5Gi
|
||||||
|
- name: docker-credentials
|
||||||
|
secret:
|
||||||
|
secretName: gitea-registry-credentials
|
||||||
|
- name: git-credentials
|
||||||
|
secret:
|
||||||
|
secretName: gitea-git-credentials
|
||||||
|
params:
|
||||||
|
- name: git-url
|
||||||
|
value: $(tt.params.git-repo-url)
|
||||||
|
- name: git-revision
|
||||||
|
value: $(tt.params.git-revision)
|
||||||
|
- name: git-branch
|
||||||
|
value: $(tt.params.git-branch)
|
||||||
|
# Use template parameter for registry URL
|
||||||
|
- name: registry
|
||||||
|
value: $(tt.params.registry-url)
|
||||||
|
- name: skip-tests
|
||||||
|
value: "false"
|
||||||
|
- name: dry-run
|
||||||
|
value: "false"
|
||||||
|
# Timeout for the entire pipeline run
|
||||||
|
timeouts:
|
||||||
|
pipeline: "1h0m0s"
|
||||||
|
tasks: "45m0s"
|
||||||
@@ -7,7 +7,6 @@ metadata:
|
|||||||
app.kubernetes.io/name: bakery-ia
|
app.kubernetes.io/name: bakery-ia
|
||||||
app.kubernetes.io/component: config
|
app.kubernetes.io/component: config
|
||||||
data:
|
data:
|
||||||
# ================================================================
|
|
||||||
# ENVIRONMENT & BUILD SETTINGS
|
# ENVIRONMENT & BUILD SETTINGS
|
||||||
# ================================================================
|
# ================================================================
|
||||||
ENVIRONMENT: "development"
|
ENVIRONMENT: "development"
|
||||||
@@ -31,7 +30,7 @@ data:
|
|||||||
BUILD_DATE: "2024-01-20T10:00:00Z"
|
BUILD_DATE: "2024-01-20T10:00:00Z"
|
||||||
VCS_REF: "latest"
|
VCS_REF: "latest"
|
||||||
IMAGE_TAG: "latest"
|
IMAGE_TAG: "latest"
|
||||||
DOMAIN: "bakery.yourdomain.com"
|
DOMAIN: "bakewise.ai"
|
||||||
AUTO_RELOAD: "false"
|
AUTO_RELOAD: "false"
|
||||||
PROFILING_ENABLED: "false"
|
PROFILING_ENABLED: "false"
|
||||||
MOCK_EXTERNAL_APIS: "false"
|
MOCK_EXTERNAL_APIS: "false"
|
||||||
@@ -177,13 +176,13 @@ data:
|
|||||||
# ================================================================
|
# ================================================================
|
||||||
# EMAIL CONFIGURATION
|
# EMAIL CONFIGURATION
|
||||||
# ================================================================
|
# ================================================================
|
||||||
SMTP_HOST: "smtp.gmail.com"
|
SMTP_HOST: "email-smtp.bakery-ia.svc.cluster.local"
|
||||||
SMTP_PORT: "587"
|
SMTP_PORT: "587"
|
||||||
SMTP_TLS: "true"
|
SMTP_TLS: "true"
|
||||||
SMTP_SSL: "false"
|
SMTP_SSL: "false"
|
||||||
DEFAULT_FROM_EMAIL: "noreply@bakeryforecast.es"
|
DEFAULT_FROM_EMAIL: "noreply@bakewise.ai"
|
||||||
DEFAULT_FROM_NAME: "Bakery-Forecast"
|
DEFAULT_FROM_NAME: "Bakery-Forecast"
|
||||||
EMAIL_FROM_ADDRESS: "alerts@bakery.local"
|
EMAIL_FROM_ADDRESS: "alerts@bakewise.ai"
|
||||||
EMAIL_FROM_NAME: "Bakery Alert System"
|
EMAIL_FROM_NAME: "Bakery Alert System"
|
||||||
|
|
||||||
# ================================================================
|
# ================================================================
|
||||||
@@ -444,6 +443,13 @@ data:
|
|||||||
SIGNOZ_ENDPOINT: "http://signoz.bakery-ia.svc.cluster.local:8080"
|
SIGNOZ_ENDPOINT: "http://signoz.bakery-ia.svc.cluster.local:8080"
|
||||||
SIGNOZ_FRONTEND_URL: "https://monitoring.bakery-ia.local"
|
SIGNOZ_FRONTEND_URL: "https://monitoring.bakery-ia.local"
|
||||||
|
|
||||||
|
# ================================================================
|
||||||
|
# DISTRIBUTION & ROUTING OPTIMIZATION SETTINGS
|
||||||
|
# ================================================================
|
||||||
|
VRP_TIME_LIMIT_SECONDS: "30"
|
||||||
|
VRP_DEFAULT_VEHICLE_CAPACITY_KG: "1000"
|
||||||
|
VRP_AVERAGE_SPEED_KMH: "30"
|
||||||
|
|
||||||
# ================================================================
|
# ================================================================
|
||||||
# REPLENISHMENT PLANNING SETTINGS
|
# REPLENISHMENT PLANNING SETTINGS
|
||||||
# ================================================================
|
# ================================================================
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- configmap.yaml
|
||||||
|
- secrets.yaml
|
||||||
@@ -160,8 +160,12 @@ metadata:
|
|||||||
app.kubernetes.io/component: notifications
|
app.kubernetes.io/component: notifications
|
||||||
type: Opaque
|
type: Opaque
|
||||||
data:
|
data:
|
||||||
SMTP_USER: eW91ci1lbWFpbEBnbWFpbC5jb20= # your-email@gmail.com
|
# SMTP credentials for internal Mailu server
|
||||||
SMTP_PASSWORD: eW91ci1hcHAtc3BlY2lmaWMtcGFzc3dvcmQ= # your-app-specific-password
|
# These are used by notification-service to send emails via mailu-smtp
|
||||||
|
SMTP_USER: cG9zdG1hc3RlckBiYWtld2lzZS5haQ== # postmaster@bakewise.ai
|
||||||
|
SMTP_PASSWORD: VzJYS2tSdUxpT25ZS2RCWVFTQXJvbjFpeWtFU1M1b2I= # W2XKkRuLiOnYKdBYQSAron1iykESS5ob
|
||||||
|
# Dovecot admin password for IMAP management
|
||||||
|
DOVEADM_PASSWORD: WnZhMzNoaVBJc2ZtV3RxUlBWV29taTRYZ2xLTlZPcHY= # Zva33hiPIsfmWtqRPVWomi4XglKNVOpv
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
159
infrastructure/environments/dev/k8s-manifests/kustomization.yaml
Normal file
159
infrastructure/environments/dev/k8s-manifests/kustomization.yaml
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
metadata:
|
||||||
|
name: bakery-ia-dev
|
||||||
|
|
||||||
|
# NOTE: Do NOT set a global namespace here.
|
||||||
|
# Each resource already has its namespace explicitly defined.
|
||||||
|
# A global namespace would incorrectly transform cluster-scoped resources
|
||||||
|
# like cert-manager namespaces.
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- ../../../environments/common/configs
|
||||||
|
- ../../../platform/infrastructure
|
||||||
|
- ../../../platform/cert-manager
|
||||||
|
- ../../../platform/networking/ingress/overlays/dev
|
||||||
|
- ../../../platform/storage
|
||||||
|
- ../../../platform/mail/mailu
|
||||||
|
- ../../../services/databases
|
||||||
|
- ../../../services/microservices
|
||||||
|
# NOTE: cicd is NOT included here - it's deployed manually via Tilt triggers
|
||||||
|
# Run 'tilt trigger tekton-install' followed by 'tilt trigger tekton-pipelines-deploy'
|
||||||
|
# - ../../../cicd
|
||||||
|
- dev-certificate.yaml
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dev-specific patches
|
||||||
|
patches:
|
||||||
|
- target:
|
||||||
|
kind: ConfigMap
|
||||||
|
name: bakery-config
|
||||||
|
patch: |-
|
||||||
|
- op: replace
|
||||||
|
path: /data/ENVIRONMENT
|
||||||
|
value: "development"
|
||||||
|
- op: replace
|
||||||
|
path: /data/DEBUG
|
||||||
|
value: "true"
|
||||||
|
# Suspend nominatim in dev to save resources
|
||||||
|
- target:
|
||||||
|
kind: StatefulSet
|
||||||
|
name: nominatim
|
||||||
|
patch: |-
|
||||||
|
- op: replace
|
||||||
|
path: /spec/replicas
|
||||||
|
value: 0
|
||||||
|
# Suspend nominatim-init job in dev (not needed when nominatim is scaled to 0)
|
||||||
|
- target:
|
||||||
|
kind: Job
|
||||||
|
name: nominatim-init
|
||||||
|
patch: |-
|
||||||
|
- op: replace
|
||||||
|
path: /spec/suspend
|
||||||
|
value: true
|
||||||
|
# Mailu TLS: Use self-signed dev certificate
|
||||||
|
- target:
|
||||||
|
kind: Deployment
|
||||||
|
name: mailu-front
|
||||||
|
patch: |-
|
||||||
|
- op: replace
|
||||||
|
path: /spec/template/spec/volumes/1/secret/secretName
|
||||||
|
value: "bakery-dev-tls-cert"
|
||||||
|
# Mailu Config: Update for dev environment
|
||||||
|
- target:
|
||||||
|
kind: ConfigMap
|
||||||
|
name: mailu-config
|
||||||
|
patch: |-
|
||||||
|
- op: replace
|
||||||
|
path: /data/DOMAIN
|
||||||
|
value: "bakery-ia.local"
|
||||||
|
- op: replace
|
||||||
|
path: /data/HOSTNAMES
|
||||||
|
value: "mail.bakery-ia.local"
|
||||||
|
- op: replace
|
||||||
|
path: /data/RELAY_LOGIN
|
||||||
|
value: "postmaster@bakery-ia.local"
|
||||||
|
- op: replace
|
||||||
|
path: /data/WEBMAIL_ADMIN
|
||||||
|
value: "admin@bakery-ia.local"
|
||||||
|
|
||||||
|
labels:
|
||||||
|
- includeSelectors: true
|
||||||
|
pairs:
|
||||||
|
environment: development
|
||||||
|
tier: local
|
||||||
|
|
||||||
|
# Dev image overrides - use local registry to avoid Docker Hub rate limits
|
||||||
|
# IMPORTANT: All image names must be lowercase (Docker requirement)
|
||||||
|
# The prepull-base-images.sh script converts names to lowercase when pushing to local registry
|
||||||
|
images:
|
||||||
|
# Database images
|
||||||
|
- name: postgres
|
||||||
|
newName: localhost:5000/postgres_17-alpine
|
||||||
|
newTag: latest
|
||||||
|
- name: redis
|
||||||
|
newName: localhost:5000/redis_7.4-alpine
|
||||||
|
newTag: latest
|
||||||
|
- name: rabbitmq
|
||||||
|
newName: localhost:5000/rabbitmq_4.1-management-alpine
|
||||||
|
newTag: latest
|
||||||
|
# Utility images
|
||||||
|
- name: busybox
|
||||||
|
newName: localhost:5000/busybox_1.36
|
||||||
|
newTag: latest
|
||||||
|
- name: curlimages/curl
|
||||||
|
newName: localhost:5000/curlimages_curl_latest
|
||||||
|
newTag: latest
|
||||||
|
- name: bitnami/kubectl
|
||||||
|
newName: localhost:5000/bitnami_kubectl_latest
|
||||||
|
newTag: latest
|
||||||
|
# Alpine variants
|
||||||
|
- name: alpine
|
||||||
|
newName: localhost:5000/alpine_3.19
|
||||||
|
newTag: latest
|
||||||
|
- name: alpine/git
|
||||||
|
newName: localhost:5000/alpine_git_2.43.0
|
||||||
|
newTag: latest
|
||||||
|
# CI/CD images (cached locally for consistency)
|
||||||
|
- name: gcr.io/kaniko-project/executor
|
||||||
|
newName: localhost:5000/gcr.io_kaniko-project_executor_v1.23.0
|
||||||
|
newTag: latest
|
||||||
|
- name: gcr.io/go-containerregistry/crane
|
||||||
|
newName: localhost:5000/gcr.io_go-containerregistry_crane_latest
|
||||||
|
newTag: latest
|
||||||
|
- name: registry.k8s.io/kustomize/kustomize
|
||||||
|
newName: localhost:5000/registry.k8s.io_kustomize_kustomize_v5.3.0
|
||||||
|
newTag: latest
|
||||||
|
# Storage images (lowercase - RELEASE becomes release)
|
||||||
|
- name: minio/minio
|
||||||
|
newName: localhost:5000/minio_minio_release.2024-11-07t00-52-20z
|
||||||
|
newTag: latest
|
||||||
|
- name: minio/mc
|
||||||
|
newName: localhost:5000/minio_mc_release.2024-11-17t19-35-25z
|
||||||
|
newTag: latest
|
||||||
|
# Geocoding
|
||||||
|
- name: mediagis/nominatim
|
||||||
|
newName: localhost:5000/mediagis_nominatim_4.4
|
||||||
|
newTag: latest
|
||||||
|
# Python base image
|
||||||
|
- name: python
|
||||||
|
newName: localhost:5000/python_3.11-slim
|
||||||
|
newTag: latest
|
||||||
|
# Mail server (Mailu)
|
||||||
|
- name: ghcr.io/mailu/nginx
|
||||||
|
newName: localhost:5000/ghcr.io_mailu_nginx_2024.06
|
||||||
|
newTag: latest
|
||||||
|
- name: ghcr.io/mailu/admin
|
||||||
|
newName: localhost:5000/ghcr.io_mailu_admin_2024.06
|
||||||
|
newTag: latest
|
||||||
|
- name: ghcr.io/mailu/postfix
|
||||||
|
newName: localhost:5000/ghcr.io_mailu_postfix_2024.06
|
||||||
|
newTag: latest
|
||||||
|
- name: ghcr.io/mailu/dovecot
|
||||||
|
newName: localhost:5000/ghcr.io_mailu_dovecot_2024.06
|
||||||
|
newTag: latest
|
||||||
|
- name: ghcr.io/mailu/rspamd
|
||||||
|
newName: localhost:5000/ghcr.io_mailu_rspamd_2024.06
|
||||||
|
newTag: latest
|
||||||
@@ -4,18 +4,28 @@ kind: Kustomization
|
|||||||
metadata:
|
metadata:
|
||||||
name: bakery-ia-prod
|
name: bakery-ia-prod
|
||||||
|
|
||||||
namespace: bakery-ia
|
# NOTE: Do NOT set a global namespace here.
|
||||||
|
# Each resource already has its namespace explicitly defined.
|
||||||
|
# A global namespace would incorrectly transform cluster-scoped resources
|
||||||
|
# like flux-system and cert-manager namespaces.
|
||||||
|
|
||||||
resources:
|
resources:
|
||||||
- ../../base
|
- ../../../environments/common/configs
|
||||||
- prod-ingress.yaml
|
- ../../../platform/infrastructure
|
||||||
|
- ../../../platform/cert-manager
|
||||||
|
- ../../../platform/networking/ingress/overlays/prod
|
||||||
|
- ../../../platform/storage
|
||||||
|
- ../../../platform/mail/mailu
|
||||||
|
- ../../../services/databases
|
||||||
|
- ../../../services/microservices
|
||||||
|
- ../../../cicd
|
||||||
|
- prod-certificate.yaml
|
||||||
|
|
||||||
|
|
||||||
# SigNoz is managed via Helm deployment (see infrastructure/helm/deploy-signoz.sh)
|
# SigNoz is managed via Helm deployment (see infrastructure/helm/deploy-signoz.sh)
|
||||||
# Monitoring is handled by SigNoz (no separate monitoring components needed)
|
# Monitoring is handled by SigNoz (no separate monitoring components needed)
|
||||||
# SigNoz paths are now included in the main ingress (ingress-https.yaml)
|
# SigNoz paths are now included in the main ingress (ingress-https.yaml)
|
||||||
|
|
||||||
patchesStrategicMerge:
|
|
||||||
- storage-patch.yaml
|
|
||||||
|
|
||||||
labels:
|
labels:
|
||||||
- includeSelectors: true
|
- includeSelectors: true
|
||||||
pairs:
|
pairs:
|
||||||
@@ -159,8 +169,17 @@ patches:
|
|||||||
limits:
|
limits:
|
||||||
memory: "1Gi"
|
memory: "1Gi"
|
||||||
cpu: "500m"
|
cpu: "500m"
|
||||||
|
# Mailu TLS: Use Let's Encrypt production certificate
|
||||||
|
- target:
|
||||||
|
kind: Deployment
|
||||||
|
name: mailu-front
|
||||||
|
patch: |-
|
||||||
|
- op: replace
|
||||||
|
path: /spec/template/spec/volumes/1/secret/secretName
|
||||||
|
value: "bakery-ia-prod-tls-cert"
|
||||||
|
|
||||||
images:
|
images:
|
||||||
|
# Application services
|
||||||
- name: bakery/auth-service
|
- name: bakery/auth-service
|
||||||
newTag: latest
|
newTag: latest
|
||||||
- name: bakery/tenant-service
|
- name: bakery/tenant-service
|
||||||
@@ -193,6 +212,58 @@ images:
|
|||||||
newTag: latest
|
newTag: latest
|
||||||
- name: bakery/dashboard
|
- name: bakery/dashboard
|
||||||
newTag: latest
|
newTag: latest
|
||||||
|
# =============================================================================
|
||||||
|
# Production Base Images - mapped to production registry
|
||||||
|
# TODO: Update PROD_REGISTRY_URL to your production registry (e.g., ghcr.io/your-org)
|
||||||
|
# =============================================================================
|
||||||
|
# Database images (using canonical Docker Hub - no rate limits in prod with auth)
|
||||||
|
- name: postgres
|
||||||
|
newTag: 17-alpine
|
||||||
|
- name: redis
|
||||||
|
newTag: 7.4-alpine
|
||||||
|
- name: rabbitmq
|
||||||
|
newTag: 4.1-management-alpine
|
||||||
|
# Utility images
|
||||||
|
- name: busybox
|
||||||
|
newTag: "1.36"
|
||||||
|
- name: curlimages/curl
|
||||||
|
newTag: latest
|
||||||
|
- name: bitnami/kubectl
|
||||||
|
newTag: latest
|
||||||
|
# Alpine variants
|
||||||
|
- name: alpine
|
||||||
|
newTag: "3.19"
|
||||||
|
- name: alpine/git
|
||||||
|
newTag: 2.43.0
|
||||||
|
# CI/CD images (GCR/registry.k8s.io - no rate limits)
|
||||||
|
- name: gcr.io/kaniko-project/executor
|
||||||
|
newTag: v1.23.0
|
||||||
|
- name: gcr.io/go-containerregistry/crane
|
||||||
|
newTag: latest
|
||||||
|
- name: registry.k8s.io/kustomize/kustomize
|
||||||
|
newTag: v5.3.0
|
||||||
|
# Storage images
|
||||||
|
- name: minio/minio
|
||||||
|
newTag: RELEASE.2024-11-07T00-52-20Z
|
||||||
|
- name: minio/mc
|
||||||
|
newTag: RELEASE.2024-11-17T19-35-25Z
|
||||||
|
# Geocoding
|
||||||
|
- name: mediagis/nominatim
|
||||||
|
newTag: "4.4"
|
||||||
|
# Python base image
|
||||||
|
- name: python
|
||||||
|
newTag: 3.11-slim
|
||||||
|
# Mail server (Mailu) - using canonical GHCR names
|
||||||
|
- name: ghcr.io/mailu/nginx
|
||||||
|
newTag: "2024.06"
|
||||||
|
- name: ghcr.io/mailu/admin
|
||||||
|
newTag: "2024.06"
|
||||||
|
- name: ghcr.io/mailu/postfix
|
||||||
|
newTag: "2024.06"
|
||||||
|
- name: ghcr.io/mailu/dovecot
|
||||||
|
newTag: "2024.06"
|
||||||
|
- name: ghcr.io/mailu/rspamd
|
||||||
|
newTag: "2024.06"
|
||||||
|
|
||||||
replicas:
|
replicas:
|
||||||
- name: auth-service
|
- name: auth-service
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
apiVersion: cert-manager.io/v1
|
||||||
|
kind: Certificate
|
||||||
|
metadata:
|
||||||
|
name: bakery-ia-prod-tls-cert
|
||||||
|
namespace: bakery-ia
|
||||||
|
spec:
|
||||||
|
# Let's Encrypt certificate for production
|
||||||
|
secretName: bakery-ia-prod-tls-cert
|
||||||
|
|
||||||
|
# Certificate duration and renewal
|
||||||
|
duration: 2160h # 90 days (Let's Encrypt default)
|
||||||
|
renewBefore: 360h # 15 days before expiry
|
||||||
|
|
||||||
|
# Subject configuration
|
||||||
|
subject:
|
||||||
|
organizations:
|
||||||
|
- Bakery IA
|
||||||
|
|
||||||
|
# Common name
|
||||||
|
commonName: bakewise.ai
|
||||||
|
|
||||||
|
# DNS names this certificate is valid for
|
||||||
|
dnsNames:
|
||||||
|
- bakewise.ai
|
||||||
|
- www.bakewise.ai
|
||||||
|
- mail.bakewise.ai
|
||||||
|
- monitoring.bakewise.ai
|
||||||
|
- gitea.bakewise.ai
|
||||||
|
- api.bakewise.ai
|
||||||
|
|
||||||
|
# Use Let's Encrypt production issuer
|
||||||
|
issuerRef:
|
||||||
|
name: letsencrypt-production
|
||||||
|
kind: ClusterIssuer
|
||||||
|
group: cert-manager.io
|
||||||
|
|
||||||
|
# Private key configuration
|
||||||
|
privateKey:
|
||||||
|
algorithm: RSA
|
||||||
|
encoding: PKCS1
|
||||||
|
size: 2048
|
||||||
|
|
||||||
|
# Usages
|
||||||
|
usages:
|
||||||
|
- server auth
|
||||||
|
- client auth
|
||||||
|
- digital signature
|
||||||
|
- key encipherment
|
||||||
@@ -1,299 +0,0 @@
|
|||||||
# Bakery IA Kubernetes Configuration
|
|
||||||
|
|
||||||
This directory contains Kubernetes manifests for deploying the Bakery IA platform in local development and production environments with HTTPS support using cert-manager and NGINX ingress.
|
|
||||||
|
|
||||||
## Quick Start
|
|
||||||
|
|
||||||
Deploy the entire platform with these 4 commands:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. Start Colima with adequate resources
|
|
||||||
colima start --cpu 6 --memory 12 --disk 120 --runtime docker --profile k8s-local
|
|
||||||
|
|
||||||
# 2. Create Kind cluster with permanent localhost access
|
|
||||||
kind create cluster --config kind-config.yaml
|
|
||||||
|
|
||||||
# 3. Install NGINX Ingress Controller
|
|
||||||
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
|
|
||||||
kubectl wait --namespace ingress-nginx --for=condition=ready pod --selector=app.kubernetes.io/component=controller --timeout=300s
|
|
||||||
|
|
||||||
# 4. Deploy with Tilt
|
|
||||||
tilt up
|
|
||||||
|
|
||||||
# 🎉 Access at: http://localhost (or see Tilt for individual service ports)
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Note**: The kind-config.yaml already configures port mappings (30080→80, 30443→443) for localhost access, so no additional service patching is needed. The NGINX Ingress for Kind uses NodePort by default on those exact ports.
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
Install the following tools on macOS:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Install via Homebrew
|
|
||||||
brew install colima kind kubectl skaffold
|
|
||||||
|
|
||||||
# Verify installations
|
|
||||||
colima version && kind version && kubectl version --client && skaffold version
|
|
||||||
```
|
|
||||||
|
|
||||||
## Directory Structure
|
|
||||||
|
|
||||||
```
|
|
||||||
infrastructure/kubernetes/
|
|
||||||
├── base/ # Base Kubernetes resources
|
|
||||||
│ ├── namespace.yaml # Namespace definition
|
|
||||||
│ ├── configmap.yaml # Shared configuration
|
|
||||||
│ ├── secrets.yaml # Base64 encoded secrets
|
|
||||||
│ ├── ingress-https.yaml # HTTPS ingress rules
|
|
||||||
│ ├── kustomization.yaml # Base kustomization
|
|
||||||
│ └── components/ # Individual component manifests
|
|
||||||
│ ├── cert-manager/ # Certificate management
|
|
||||||
│ ├── auth/ # Authentication service
|
|
||||||
│ ├── tenant/ # Tenant management
|
|
||||||
│ ├── training/ # ML training service
|
|
||||||
│ ├── forecasting/ # Demand forecasting
|
|
||||||
│ ├── sales/ # Sales management
|
|
||||||
│ ├── external/ # External API service
|
|
||||||
│ ├── notification/ # Notification service
|
|
||||||
│ ├── inventory/ # Inventory management
|
|
||||||
│ ├── recipes/ # Recipe management
|
|
||||||
│ ├── suppliers/ # Supplier management
|
|
||||||
│ ├── pos/ # Point of sale
|
|
||||||
│ ├── orders/ # Order management
|
|
||||||
│ ├── production/ # Production planning
|
|
||||||
│ ├── alert-processor/ # Alert processing
|
|
||||||
│ ├── frontend/ # React frontend
|
|
||||||
│ ├── databases/ # Database deployments
|
|
||||||
│ └── infrastructure/ # Gateway & monitoring
|
|
||||||
└── overlays/
|
|
||||||
└── dev/ # Development environment
|
|
||||||
├── kustomization.yaml # Dev-specific configuration
|
|
||||||
└── dev-patches.yaml # Development patches
|
|
||||||
```
|
|
||||||
|
|
||||||
## Access URLs
|
|
||||||
|
|
||||||
### Primary Access (Standard Web Ports)
|
|
||||||
- **Frontend**: https://localhost
|
|
||||||
- **API Gateway**: https://localhost/api
|
|
||||||
|
|
||||||
### Named Host Access (Optional)
|
|
||||||
Add to `/etc/hosts` for named access:
|
|
||||||
```bash
|
|
||||||
echo "127.0.0.1 bakery-ia.local" | sudo tee -a /etc/hosts
|
|
||||||
echo "127.0.0.1 api.bakery-ia.local" | sudo tee -a /etc/hosts
|
|
||||||
echo "127.0.0.1 monitoring.bakery-ia.local" | sudo tee -a /etc/hosts
|
|
||||||
```
|
|
||||||
|
|
||||||
Then access via:
|
|
||||||
- **Frontend**: https://bakery-ia.local
|
|
||||||
- **API**: https://api.bakery-ia.local
|
|
||||||
- **Monitoring**: https://monitoring.bakery-ia.local
|
|
||||||
|
|
||||||
### Direct Service Access (Development)
|
|
||||||
- **Frontend**: http://localhost:3000
|
|
||||||
- **Gateway**: http://localhost:8000
|
|
||||||
|
|
||||||
## Development Workflow
|
|
||||||
|
|
||||||
### Start Development Environment
|
|
||||||
```bash
|
|
||||||
# Start development mode with hot-reload using Tilt
|
|
||||||
tilt up
|
|
||||||
|
|
||||||
# Or start in background
|
|
||||||
tilt up --stream
|
|
||||||
```
|
|
||||||
|
|
||||||
### Key Features
|
|
||||||
- ✅ **Hot-reload development** - Automatic rebuilds on code changes
|
|
||||||
- ✅ **Permanent localhost access** - No port forwarding needed
|
|
||||||
- ✅ **HTTPS by default** - Local CA certificates for secure development
|
|
||||||
- ✅ **Microservices architecture** - All services deployed together
|
|
||||||
- ✅ **Database management** - PostgreSQL, Redis, and RabbitMQ included
|
|
||||||
|
|
||||||
### Monitor and Debug
|
|
||||||
```bash
|
|
||||||
# Check all resources
|
|
||||||
kubectl get all -n bakery-ia
|
|
||||||
|
|
||||||
# View logs
|
|
||||||
kubectl logs -n bakery-ia deployment/auth-service -f
|
|
||||||
|
|
||||||
# Check ingress status
|
|
||||||
kubectl get ingress -n bakery-ia
|
|
||||||
|
|
||||||
# Debug certificate issues
|
|
||||||
kubectl describe certificate bakery-ia-tls-cert -n bakery-ia
|
|
||||||
```
|
|
||||||
|
|
||||||
## Certificate Management
|
|
||||||
|
|
||||||
The platform uses cert-manager for automatic HTTPS certificate generation:
|
|
||||||
|
|
||||||
- **Local CA**: For development (default)
|
|
||||||
- **Let's Encrypt Staging**: For testing
|
|
||||||
- **Let's Encrypt Production**: For production deployments
|
|
||||||
|
|
||||||
### Trust Local Certificates
|
|
||||||
```bash
|
|
||||||
# Export CA certificate
|
|
||||||
kubectl get secret local-ca-key-pair -n cert-manager -o jsonpath='{.data.tls\.crt}' | base64 -d > bakery-ia-ca.crt
|
|
||||||
|
|
||||||
# Trust in macOS
|
|
||||||
open bakery-ia-ca.crt
|
|
||||||
# In Keychain Access, set "bakery-ia-local-ca" to "Always Trust"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configuration Management
|
|
||||||
|
|
||||||
### Secrets
|
|
||||||
Base64-encoded secrets are stored in `base/secrets.yaml`. For production:
|
|
||||||
- Use external secret management (HashiCorp Vault, AWS Secrets Manager)
|
|
||||||
- Never commit real secrets to version control
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Encode secrets
|
|
||||||
echo -n "your-secret-value" | base64
|
|
||||||
|
|
||||||
# Decode secrets
|
|
||||||
echo "eW91ci1zZWNyZXQtdmFsdWU=" | base64 -d
|
|
||||||
```
|
|
||||||
|
|
||||||
### Environment Configuration
|
|
||||||
Development-specific settings are in `overlays/dev/`:
|
|
||||||
- **Resource limits**: Reduced for local development
|
|
||||||
- **Image pull policy**: Never (for local images)
|
|
||||||
- **Debug settings**: Enabled
|
|
||||||
- **CORS**: Configured for localhost
|
|
||||||
|
|
||||||
## Scaling and Resource Management
|
|
||||||
|
|
||||||
### Scale Services
|
|
||||||
```bash
|
|
||||||
# Scale individual service
|
|
||||||
kubectl scale -n bakery-ia deployment/auth-service --replicas=3
|
|
||||||
|
|
||||||
# Or update kustomization.yaml replicas section
|
|
||||||
```
|
|
||||||
|
|
||||||
### Resource Configuration
|
|
||||||
Development environment uses minimal resources:
|
|
||||||
- **Databases**: 64Mi-256Mi memory, 25m-200m CPU
|
|
||||||
- **Services**: 64Mi-256Mi memory, 25m-200m CPU
|
|
||||||
- **Training Service**: 256Mi-1Gi memory (ML workloads)
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Common Issues
|
|
||||||
|
|
||||||
1. **Images not found**
|
|
||||||
```bash
|
|
||||||
# Build images with Skaffold
|
|
||||||
skaffold build --profile=dev
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Database corruption after restart**
|
|
||||||
```bash
|
|
||||||
# Delete corrupted PVC and restart
|
|
||||||
kubectl delete pod -n bakery-ia -l app.kubernetes.io/name=inventory-db
|
|
||||||
kubectl delete pvc -n bakery-ia inventory-db-pvc
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **HTTPS certificate not issued**
|
|
||||||
```bash
|
|
||||||
# Check cert-manager logs
|
|
||||||
kubectl logs -n cert-manager deployment/cert-manager
|
|
||||||
kubectl describe certificate bakery-ia-tls-cert -n bakery-ia
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Port conflicts**
|
|
||||||
```bash
|
|
||||||
# Check what's using ports 80/443
|
|
||||||
sudo lsof -i :80 -i :443
|
|
||||||
```
|
|
||||||
|
|
||||||
### Debug Commands
|
|
||||||
```bash
|
|
||||||
# Get cluster events
|
|
||||||
kubectl get events -n bakery-ia --sort-by='.firstTimestamp'
|
|
||||||
|
|
||||||
# Resource usage
|
|
||||||
kubectl top pods -n bakery-ia
|
|
||||||
kubectl top nodes
|
|
||||||
|
|
||||||
# Execute in pod
|
|
||||||
kubectl exec -n bakery-ia -it <pod-name> -- bash
|
|
||||||
```
|
|
||||||
|
|
||||||
## Cleanup
|
|
||||||
|
|
||||||
### Quick Cleanup
|
|
||||||
```bash
|
|
||||||
# Stop Skaffold (Ctrl+C or)
|
|
||||||
skaffold delete --profile=dev
|
|
||||||
```
|
|
||||||
|
|
||||||
### Complete Cleanup
|
|
||||||
```bash
|
|
||||||
# Delete everything
|
|
||||||
kubectl delete namespace bakery-ia
|
|
||||||
kind delete cluster --name bakery-ia-local
|
|
||||||
colima stop --profile k8s-local
|
|
||||||
```
|
|
||||||
|
|
||||||
### Restart Sequence
|
|
||||||
```bash
|
|
||||||
# Post-restart startup (or use kubernetes_restart.sh script)
|
|
||||||
colima start --cpu 6 --memory 12 --disk 120 --runtime docker --profile k8s-local
|
|
||||||
kind create cluster --config kind-config.yaml
|
|
||||||
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
|
|
||||||
kubectl wait --namespace ingress-nginx --for=condition=ready pod --selector=app.kubernetes.io/component=controller --timeout=300s
|
|
||||||
tilt up
|
|
||||||
```
|
|
||||||
|
|
||||||
## Production Deployment
|
|
||||||
|
|
||||||
### Production URLs
|
|
||||||
|
|
||||||
The production environment uses the following domains:
|
|
||||||
|
|
||||||
- **Main Application**: https://bakewise.ai
|
|
||||||
- Frontend application and all public pages
|
|
||||||
- API endpoints: https://bakewise.ai/api/v1/...
|
|
||||||
|
|
||||||
- **Monitoring Stack**: https://monitoring.bakewise.ai
|
|
||||||
- Grafana: https://monitoring.bakewise.ai/grafana
|
|
||||||
- Prometheus: https://monitoring.bakewise.ai/prometheus
|
|
||||||
- Jaeger: https://monitoring.bakewise.ai/jaeger
|
|
||||||
- AlertManager: https://monitoring.bakewise.ai/alertmanager
|
|
||||||
|
|
||||||
### Production Configuration
|
|
||||||
|
|
||||||
The production overlay (`overlays/prod/`) includes:
|
|
||||||
- **Domain Configuration**: bakewise.ai with Let's Encrypt certificates
|
|
||||||
- **High Availability**: Multi-replica deployments (2-3 replicas per service)
|
|
||||||
- **Enhanced Security**: Rate limiting, CORS restrictions, security headers
|
|
||||||
- **Monitoring**: Full observability stack with Prometheus, Grafana, Jaeger
|
|
||||||
|
|
||||||
### Production Considerations
|
|
||||||
|
|
||||||
For production deployment:
|
|
||||||
|
|
||||||
- **Security**: Implement RBAC, network policies, pod security standards
|
|
||||||
- **Monitoring**: Deploy Prometheus, Grafana, and alerting
|
|
||||||
- **Backup**: Database backup strategies
|
|
||||||
- **High Availability**: Multi-replica deployments with anti-affinity
|
|
||||||
- **External Secrets**: Use managed secret services
|
|
||||||
- **TLS**: Production Let's Encrypt certificates
|
|
||||||
- **CI/CD**: Automated deployment pipelines
|
|
||||||
- **DNS**: Configure DNS A/CNAME records pointing to your cluster's load balancer
|
|
||||||
|
|
||||||
## Next Steps
|
|
||||||
|
|
||||||
1. Add comprehensive monitoring and logging
|
|
||||||
2. Implement automated testing
|
|
||||||
3. Set up CI/CD pipelines
|
|
||||||
4. Add health checks and metrics endpoints
|
|
||||||
5. Implement proper backup strategies
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: cert-manager
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: cert-manager-webhook
|
|
||||||
namespace: cert-manager
|
|
||||||
---
|
|
||||||
# Cert-manager installation using Helm repository
|
|
||||||
# This will be installed via kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml
|
|
||||||
# The actual installation will be done via command line, this file documents the resources
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: distribution-service-config
|
|
||||||
data:
|
|
||||||
# Service settings
|
|
||||||
SERVICE_NAME: "distribution-service"
|
|
||||||
APP_NAME: "Bakery Distribution Service"
|
|
||||||
DESCRIPTION: "Distribution service for enterprise tier bakery management"
|
|
||||||
VERSION: "1.0.0"
|
|
||||||
|
|
||||||
# Database settings
|
|
||||||
DB_POOL_SIZE: "10"
|
|
||||||
DB_MAX_OVERFLOW: "20"
|
|
||||||
DB_POOL_TIMEOUT: "30"
|
|
||||||
DB_POOL_RECYCLE: "3600"
|
|
||||||
DB_POOL_PRE_PING: "true"
|
|
||||||
DB_ECHO: "false"
|
|
||||||
|
|
||||||
# Redis settings
|
|
||||||
REDIS_DB: "7" # Use separate database for distribution service
|
|
||||||
REDIS_MAX_CONNECTIONS: "50"
|
|
||||||
REDIS_RETRY_ON_TIMEOUT: "true"
|
|
||||||
REDIS_SOCKET_KEEPALIVE: "true"
|
|
||||||
|
|
||||||
# RabbitMQ settings
|
|
||||||
RABBITMQ_EXCHANGE: "bakery_events"
|
|
||||||
RABBITMQ_QUEUE_PREFIX: "distribution"
|
|
||||||
RABBITMQ_RETRY_ATTEMPTS: "3"
|
|
||||||
RABBITMQ_RETRY_DELAY: "5"
|
|
||||||
|
|
||||||
# Authentication settings
|
|
||||||
JWT_ALGORITHM: "HS256"
|
|
||||||
JWT_ACCESS_TOKEN_EXPIRE_MINUTES: "30"
|
|
||||||
JWT_REFRESH_TOKEN_EXPIRE_DAYS: "7"
|
|
||||||
ENABLE_SERVICE_AUTH: "true"
|
|
||||||
|
|
||||||
# HTTP client settings
|
|
||||||
HTTP_TIMEOUT: "30"
|
|
||||||
HTTP_RETRIES: "3"
|
|
||||||
HTTP_RETRY_DELAY: "1.0"
|
|
||||||
|
|
||||||
# CORS settings
|
|
||||||
CORS_ORIGINS: "http://localhost:3000,http://localhost:3001"
|
|
||||||
CORS_ALLOW_CREDENTIALS: "true"
|
|
||||||
CORS_ALLOW_METHODS: "GET,POST,PUT,DELETE,PATCH,OPTIONS"
|
|
||||||
CORS_ALLOW_HEADERS: "*"
|
|
||||||
|
|
||||||
# Rate limiting
|
|
||||||
RATE_LIMIT_ENABLED: "true"
|
|
||||||
RATE_LIMIT_REQUESTS: "100"
|
|
||||||
RATE_LIMIT_WINDOW: "60"
|
|
||||||
RATE_LIMIT_BURST: "10"
|
|
||||||
|
|
||||||
# Monitoring and observability
|
|
||||||
LOG_LEVEL: "INFO"
|
|
||||||
PROMETHEUS_ENABLED: "true"
|
|
||||||
PROMETHEUS_PORT: "9090"
|
|
||||||
JAEGER_ENABLED: "false"
|
|
||||||
JAEGER_AGENT_HOST: "jaeger-agent"
|
|
||||||
JAEGER_AGENT_PORT: "6831"
|
|
||||||
|
|
||||||
# Health check settings
|
|
||||||
HEALTH_CHECK_TIMEOUT: "30"
|
|
||||||
HEALTH_CHECK_INTERVAL: "30"
|
|
||||||
|
|
||||||
# Business rules
|
|
||||||
MAX_FORECAST_DAYS: "30"
|
|
||||||
MIN_HISTORICAL_DAYS: "60"
|
|
||||||
CONFIDENCE_THRESHOLD: "0.8"
|
|
||||||
|
|
||||||
# Routing optimization settings
|
|
||||||
VRP_TIME_LIMIT_SECONDS: "30"
|
|
||||||
VRP_DEFAULT_VEHICLE_CAPACITY_KG: "1000"
|
|
||||||
VRP_AVERAGE_SPEED_KMH: "30"
|
|
||||||
|
|
||||||
# Service-specific settings
|
|
||||||
DISTRIBUTION_SERVICE_URL: "http://distribution-service:8000"
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: distribution-service
|
|
||||||
labels:
|
|
||||||
app: distribution-service
|
|
||||||
tier: backend
|
|
||||||
spec:
|
|
||||||
replicas: 2
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: distribution-service
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: distribution-service
|
|
||||||
tier: backend
|
|
||||||
spec:
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: dockerhub-creds
|
|
||||||
containers:
|
|
||||||
- name: distribution-service
|
|
||||||
image: bakery/distribution-service:latest
|
|
||||||
imagePullPolicy: Always
|
|
||||||
ports:
|
|
||||||
- containerPort: 8000
|
|
||||||
name: http
|
|
||||||
env:
|
|
||||||
- name: DATABASE_URL
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: database-secret
|
|
||||||
key: url
|
|
||||||
- name: REDIS_URL
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: redis-secret
|
|
||||||
key: url
|
|
||||||
- name: RABBITMQ_URL
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: rabbitmq-secret
|
|
||||||
key: url
|
|
||||||
- name: JWT_SECRET_KEY
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: auth-secret
|
|
||||||
key: jwt-secret
|
|
||||||
- name: ENVIRONMENT
|
|
||||||
value: "production"
|
|
||||||
- name: LOG_LEVEL
|
|
||||||
value: "INFO"
|
|
||||||
- name: DB_POOL_SIZE
|
|
||||||
value: "10"
|
|
||||||
- name: DB_MAX_OVERFLOW
|
|
||||||
value: "20"
|
|
||||||
- name: REDIS_MAX_CONNECTIONS
|
|
||||||
value: "50"
|
|
||||||
- name: HTTP_TIMEOUT
|
|
||||||
value: "30"
|
|
||||||
- name: HTTP_RETRIES
|
|
||||||
value: "3"
|
|
||||||
# OpenTelemetry Configuration
|
|
||||||
- name: OTEL_COLLECTOR_ENDPOINT
|
|
||||||
value: "http://signoz-otel-collector.bakery-ia.svc.cluster.local:4318"
|
|
||||||
- name: OTEL_EXPORTER_OTLP_ENDPOINT
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: bakery-config
|
|
||||||
key: OTEL_EXPORTER_OTLP_ENDPOINT
|
|
||||||
- name: OTEL_SERVICE_NAME
|
|
||||||
value: "distribution-service"
|
|
||||||
- name: ENABLE_TRACING
|
|
||||||
value: "true"
|
|
||||||
# Logging Configuration
|
|
||||||
- name: OTEL_LOGS_EXPORTER
|
|
||||||
value: "otlp"
|
|
||||||
- name: OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED
|
|
||||||
value: "true"
|
|
||||||
# Metrics Configuration
|
|
||||||
- name: ENABLE_OTEL_METRICS
|
|
||||||
value: "true"
|
|
||||||
- name: ENABLE_SYSTEM_METRICS
|
|
||||||
value: "true"
|
|
||||||
livenessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /health
|
|
||||||
port: 8000
|
|
||||||
initialDelaySeconds: 30
|
|
||||||
periodSeconds: 10
|
|
||||||
timeoutSeconds: 5
|
|
||||||
readinessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /health
|
|
||||||
port: 8000
|
|
||||||
initialDelaySeconds: 5
|
|
||||||
periodSeconds: 5
|
|
||||||
timeoutSeconds: 3
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "250m"
|
|
||||||
limits:
|
|
||||||
memory: "512Mi"
|
|
||||||
cpu: "500m"
|
|
||||||
securityContext:
|
|
||||||
runAsNonRoot: true
|
|
||||||
runAsUser: 1000
|
|
||||||
allowPrivilegeEscalation: false
|
|
||||||
readOnlyRootFilesystem: false
|
|
||||||
capabilities:
|
|
||||||
drop:
|
|
||||||
- ALL
|
|
||||||
securityContext:
|
|
||||||
runAsNonRoot: true
|
|
||||||
runAsUser: 1000
|
|
||||||
fsGroup: 2000
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: distribution-service
|
|
||||||
labels:
|
|
||||||
app: distribution-service
|
|
||||||
tier: backend
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
app.kubernetes.io/name: distribution-service
|
|
||||||
ports:
|
|
||||||
- protocol: TCP
|
|
||||||
port: 8000
|
|
||||||
targetPort: 8000
|
|
||||||
name: http
|
|
||||||
type: ClusterIP
|
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: {{SERVICE_NAME}}-service
|
|
||||||
namespace: bakery-ia
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: {{SERVICE_NAME}}-service
|
|
||||||
app.kubernetes.io/component: microservice
|
|
||||||
app.kubernetes.io/part-of: bakery-ia
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app.kubernetes.io/name: {{SERVICE_NAME}}-service
|
|
||||||
app.kubernetes.io/component: microservice
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: {{SERVICE_NAME}}-service
|
|
||||||
app.kubernetes.io/component: microservice
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: {{SERVICE_NAME}}-service
|
|
||||||
image: bakery/{{SERVICE_NAME}}-service:latest
|
|
||||||
ports:
|
|
||||||
- containerPort: 8000
|
|
||||||
name: http
|
|
||||||
env:
|
|
||||||
- name: ENVIRONMENT
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: bakery-config
|
|
||||||
key: ENVIRONMENT
|
|
||||||
- name: DEBUG
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: bakery-config
|
|
||||||
key: DEBUG
|
|
||||||
- name: LOG_LEVEL
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: bakery-config
|
|
||||||
key: LOG_LEVEL
|
|
||||||
- name: {{SERVICE_NAME_UPPER}}_DB_HOST
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: bakery-config
|
|
||||||
key: {{SERVICE_NAME_UPPER}}_DB_HOST
|
|
||||||
- name: {{SERVICE_NAME_UPPER}}_DB_PORT
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: bakery-config
|
|
||||||
key: DB_PORT
|
|
||||||
- name: {{SERVICE_NAME_UPPER}}_DB_NAME
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: bakery-config
|
|
||||||
key: {{SERVICE_NAME_UPPER}}_DB_NAME
|
|
||||||
- name: {{SERVICE_NAME_UPPER}}_DB_USER
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: database-secrets
|
|
||||||
key: {{SERVICE_NAME_UPPER}}_DB_USER
|
|
||||||
- name: {{SERVICE_NAME_UPPER}}_DB_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: database-secrets
|
|
||||||
key: {{SERVICE_NAME_UPPER}}_DB_PASSWORD
|
|
||||||
- name: REDIS_HOST
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: bakery-config
|
|
||||||
key: REDIS_HOST
|
|
||||||
- name: REDIS_PORT
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: bakery-config
|
|
||||||
key: REDIS_PORT
|
|
||||||
- name: REDIS_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: redis-secrets
|
|
||||||
key: REDIS_PASSWORD
|
|
||||||
- name: RABBITMQ_HOST
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: bakery-config
|
|
||||||
key: RABBITMQ_HOST
|
|
||||||
- name: RABBITMQ_PORT
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: bakery-config
|
|
||||||
key: RABBITMQ_PORT
|
|
||||||
- name: RABBITMQ_USER
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: rabbitmq-secrets
|
|
||||||
key: RABBITMQ_USER
|
|
||||||
- name: RABBITMQ_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: rabbitmq-secrets
|
|
||||||
key: RABBITMQ_PASSWORD
|
|
||||||
- name: AUTH_SERVICE_URL
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: bakery-config
|
|
||||||
key: AUTH_SERVICE_URL
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "100m"
|
|
||||||
limits:
|
|
||||||
memory: "512Mi"
|
|
||||||
cpu: "500m"
|
|
||||||
livenessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /health/live
|
|
||||||
port: 8000
|
|
||||||
initialDelaySeconds: 30
|
|
||||||
timeoutSeconds: 5
|
|
||||||
periodSeconds: 10
|
|
||||||
failureThreshold: 3
|
|
||||||
readinessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /health/ready
|
|
||||||
port: 8000
|
|
||||||
initialDelaySeconds: 15
|
|
||||||
timeoutSeconds: 3
|
|
||||||
periodSeconds: 5
|
|
||||||
failureThreshold: 5
|
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: {{SERVICE_NAME}}-service
|
|
||||||
namespace: bakery-ia
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: {{SERVICE_NAME}}-service
|
|
||||||
app.kubernetes.io/component: microservice
|
|
||||||
spec:
|
|
||||||
type: ClusterIP
|
|
||||||
ports:
|
|
||||||
- port: 8000
|
|
||||||
targetPort: 8000
|
|
||||||
protocol: TCP
|
|
||||||
name: http
|
|
||||||
selector:
|
|
||||||
app.kubernetes.io/name: {{SERVICE_NAME}}-service
|
|
||||||
app.kubernetes.io/component: microservice
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
name: bakery-ingress-https
|
|
||||||
namespace: bakery-ia
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: bakery-ia
|
|
||||||
app.kubernetes.io/component: ingress
|
|
||||||
annotations:
|
|
||||||
# Nginx ingress controller annotations
|
|
||||||
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
|
||||||
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
|
||||||
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
|
|
||||||
nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
|
|
||||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
|
|
||||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
|
|
||||||
# SSE and WebSocket configuration for long-lived connections
|
|
||||||
nginx.ingress.kubernetes.io/proxy-buffering: "off"
|
|
||||||
nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
|
|
||||||
nginx.ingress.kubernetes.io/upstream-keepalive-timeout: "3600"
|
|
||||||
# WebSocket upgrade support
|
|
||||||
nginx.ingress.kubernetes.io/websocket-services: "gateway-service"
|
|
||||||
# CORS configuration for HTTPS
|
|
||||||
nginx.ingress.kubernetes.io/enable-cors: "true"
|
|
||||||
nginx.ingress.kubernetes.io/cors-allow-origin: "https://your-domain.com" # To be overridden in overlays
|
|
||||||
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, OPTIONS, PATCH"
|
|
||||||
nginx.ingress.kubernetes.io/cors-allow-headers: "Content-Type, Authorization, X-Requested-With, Accept, Origin, Cache-Control"
|
|
||||||
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
|
|
||||||
# Cert-manager annotations for automatic certificate issuance
|
|
||||||
# Using issuer appropriate for environment
|
|
||||||
cert-manager.io/cluster-issuer: "letsencrypt-prod" # To be overridden in dev overlay
|
|
||||||
spec:
|
|
||||||
ingressClassName: nginx
|
|
||||||
tls:
|
|
||||||
- hosts:
|
|
||||||
- your-domain.com # To be overridden in overlays
|
|
||||||
secretName: bakery-tls-cert # To be overridden in overlays
|
|
||||||
rules:
|
|
||||||
- host: your-domain.com # To be overridden in overlays
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- path: /
|
|
||||||
pathType: Prefix
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: frontend-service
|
|
||||||
port:
|
|
||||||
number: 3000
|
|
||||||
- path: /api
|
|
||||||
pathType: Prefix
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: gateway-service
|
|
||||||
port:
|
|
||||||
number: 8000
|
|
||||||
- host: api.your-domain.com # To be overridden in overlays
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- path: /
|
|
||||||
pathType: Prefix
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: gateway-service
|
|
||||||
port:
|
|
||||||
number: 8000
|
|
||||||
# Note: SigNoz monitoring is deployed via Helm in the 'signoz' namespace
|
|
||||||
# SigNoz creates its own Ingress via Helm chart configuration
|
|
||||||
# Access at: https://monitoring.your-domain.com/ (configured in signoz-values.yaml)
|
|
||||||
# SignOz ingress is managed separately - no need to configure here
|
|
||||||
@@ -1,181 +0,0 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
||||||
kind: Kustomization
|
|
||||||
|
|
||||||
metadata:
|
|
||||||
name: bakery-ia-base
|
|
||||||
|
|
||||||
resources:
|
|
||||||
# Base configuration
|
|
||||||
- namespace.yaml
|
|
||||||
- configmap.yaml
|
|
||||||
- secrets.yaml
|
|
||||||
- ingress-https.yaml
|
|
||||||
|
|
||||||
# TLS configuration
|
|
||||||
- configmaps/postgres-logging-config.yaml
|
|
||||||
- secrets/postgres-tls-secret.yaml
|
|
||||||
- secrets/redis-tls-secret.yaml
|
|
||||||
|
|
||||||
# Additional configs
|
|
||||||
- configs/postgres-init-config.yaml
|
|
||||||
|
|
||||||
# MinIO Storage (with TLS)
|
|
||||||
- components/minio/minio-secrets.yaml
|
|
||||||
- secrets/minio-tls-secret.yaml
|
|
||||||
- components/minio/minio-pvc.yaml
|
|
||||||
- components/minio/minio-deployment.yaml
|
|
||||||
- jobs/minio-bucket-init-job.yaml
|
|
||||||
|
|
||||||
# Migration jobs
|
|
||||||
- migrations/auth-migration-job.yaml
|
|
||||||
- migrations/tenant-migration-job.yaml
|
|
||||||
# Note: tenant-seed-pilot-coupon-job.yaml removed - pilot coupon is now seeded
|
|
||||||
# automatically during tenant-service startup (see app/jobs/startup_seeder.py)
|
|
||||||
- migrations/training-migration-job.yaml
|
|
||||||
- migrations/forecasting-migration-job.yaml
|
|
||||||
- migrations/sales-migration-job.yaml
|
|
||||||
- migrations/external-migration-job.yaml
|
|
||||||
- migrations/notification-migration-job.yaml
|
|
||||||
- migrations/inventory-migration-job.yaml
|
|
||||||
- migrations/recipes-migration-job.yaml
|
|
||||||
- migrations/suppliers-migration-job.yaml
|
|
||||||
- migrations/pos-migration-job.yaml
|
|
||||||
- migrations/orders-migration-job.yaml
|
|
||||||
- migrations/production-migration-job.yaml
|
|
||||||
- migrations/alert-processor-migration-job.yaml
|
|
||||||
- migrations/demo-session-migration-job.yaml
|
|
||||||
- migrations/procurement-migration-job.yaml
|
|
||||||
- migrations/orchestrator-migration-job.yaml
|
|
||||||
- migrations/ai-insights-migration-job.yaml
|
|
||||||
- migrations/distribution-migration-job.yaml
|
|
||||||
- migrations/demo-seed-rbac.yaml
|
|
||||||
|
|
||||||
# External data initialization job (v2.0)
|
|
||||||
- jobs/external-data-init-job.yaml
|
|
||||||
|
|
||||||
# CronJobs
|
|
||||||
- cronjobs/demo-cleanup-cronjob.yaml
|
|
||||||
- cronjobs/external-data-rotation-cronjob.yaml
|
|
||||||
|
|
||||||
# Infrastructure components
|
|
||||||
- components/databases/redis.yaml
|
|
||||||
- components/databases/rabbitmq.yaml
|
|
||||||
- components/infrastructure/gateway-service.yaml
|
|
||||||
|
|
||||||
# Distribution service
|
|
||||||
- components/distribution/distribution-deployment.yaml
|
|
||||||
- components/distribution/distribution-configmap.yaml
|
|
||||||
|
|
||||||
# Nominatim geocoding service
|
|
||||||
- components/nominatim/nominatim.yaml
|
|
||||||
- jobs/nominatim-init-job.yaml
|
|
||||||
|
|
||||||
# Cert manager cluster issuers
|
|
||||||
- components/cert-manager/cluster-issuer-staging.yaml
|
|
||||||
- components/cert-manager/local-ca-issuer.yaml
|
|
||||||
|
|
||||||
# Database services
|
|
||||||
- components/databases/auth-db.yaml
|
|
||||||
- components/databases/tenant-db.yaml
|
|
||||||
- components/databases/training-db.yaml
|
|
||||||
- components/databases/forecasting-db.yaml
|
|
||||||
- components/databases/sales-db.yaml
|
|
||||||
- components/databases/external-db.yaml
|
|
||||||
- components/databases/notification-db.yaml
|
|
||||||
- components/databases/inventory-db.yaml
|
|
||||||
- components/databases/recipes-db.yaml
|
|
||||||
- components/databases/suppliers-db.yaml
|
|
||||||
- components/databases/pos-db.yaml
|
|
||||||
- components/databases/orders-db.yaml
|
|
||||||
- components/databases/production-db.yaml
|
|
||||||
- components/databases/procurement-db.yaml
|
|
||||||
- components/databases/orchestrator-db.yaml
|
|
||||||
- components/databases/alert-processor-db.yaml
|
|
||||||
- components/databases/ai-insights-db.yaml
|
|
||||||
- components/databases/distribution-db.yaml
|
|
||||||
|
|
||||||
# Demo session components
|
|
||||||
- components/demo-session/database.yaml
|
|
||||||
- components/demo-session/rbac.yaml
|
|
||||||
- components/demo-session/service.yaml
|
|
||||||
- components/demo-session/deployment.yaml
|
|
||||||
|
|
||||||
# Demo cleanup worker (background job processor)
|
|
||||||
- deployments/demo-cleanup-worker.yaml
|
|
||||||
|
|
||||||
# Microservices
|
|
||||||
- components/auth/auth-service.yaml
|
|
||||||
- components/tenant/tenant-service.yaml
|
|
||||||
- components/training/training-service.yaml
|
|
||||||
- components/forecasting/forecasting-service.yaml
|
|
||||||
- components/sales/sales-service.yaml
|
|
||||||
- components/external/external-service.yaml
|
|
||||||
- components/notification/notification-service.yaml
|
|
||||||
- components/inventory/inventory-service.yaml
|
|
||||||
- components/recipes/recipes-service.yaml
|
|
||||||
- components/suppliers/suppliers-service.yaml
|
|
||||||
- components/pos/pos-service.yaml
|
|
||||||
- components/orders/orders-service.yaml
|
|
||||||
- components/production/production-service.yaml
|
|
||||||
- components/procurement/procurement-service.yaml
|
|
||||||
- components/orchestrator/orchestrator-service.yaml
|
|
||||||
- components/alert-processor/alert-processor.yaml
|
|
||||||
- components/ai-insights/ai-insights-service.yaml
|
|
||||||
|
|
||||||
# Frontend
|
|
||||||
- components/frontend/frontend-service.yaml
|
|
||||||
|
|
||||||
# HorizontalPodAutoscalers (for production autoscaling)
|
|
||||||
- components/hpa/orders-hpa.yaml
|
|
||||||
- components/hpa/forecasting-hpa.yaml
|
|
||||||
- components/hpa/notification-hpa.yaml
|
|
||||||
|
|
||||||
labels:
|
|
||||||
- includeSelectors: true
|
|
||||||
pairs:
|
|
||||||
app.kubernetes.io/part-of: bakery-ia
|
|
||||||
app.kubernetes.io/managed-by: kustomize
|
|
||||||
|
|
||||||
images:
|
|
||||||
- name: bakery/auth-service
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/tenant-service
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/training-service
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/forecasting-service
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/sales-service
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/external-service
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/notification-service
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/inventory-service
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/recipes-service
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/suppliers-service
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/pos-service
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/orders-service
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/production-service
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/procurement-service
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/orchestrator-service
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/alert-processor
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/ai-insights-service
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/demo-session-service
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/gateway
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/dashboard
|
|
||||||
newTag: latest
|
|
||||||
- name: bakery/distribution-service
|
|
||||||
newTag: latest
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
apiVersion: apiserver.config.k8s.io/v1
|
|
||||||
kind: EncryptionConfiguration
|
|
||||||
resources:
|
|
||||||
- resources:
|
|
||||||
- secrets
|
|
||||||
providers:
|
|
||||||
- aescbc:
|
|
||||||
keys:
|
|
||||||
- name: key1
|
|
||||||
secret: 2eAEevJmGb+y0bPzYhc4qCpqUa3r5M5Kduch1b4olHE=
|
|
||||||
- identity: {}
|
|
||||||
@@ -1,699 +0,0 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
||||||
kind: Kustomization
|
|
||||||
|
|
||||||
metadata:
|
|
||||||
name: bakery-ia-dev
|
|
||||||
|
|
||||||
# Note: Removed global namespace to prevent monitoring namespace conflict
|
|
||||||
# All base resources already have namespace: bakery-ia defined
|
|
||||||
|
|
||||||
resources:
|
|
||||||
- ../../base
|
|
||||||
- dev-ingress.yaml
|
|
||||||
# SigNoz is managed via Helm deployment (see Tiltfile signoz-deploy)
|
|
||||||
# Monitoring is handled by SigNoz (no separate monitoring components needed)
|
|
||||||
# Dev-Prod Parity: Enable HTTPS with self-signed certificates
|
|
||||||
- dev-certificate.yaml
|
|
||||||
# SigNoz paths are now included in the main ingress (ingress-https.yaml)
|
|
||||||
|
|
||||||
# Exclude nominatim from dev to save resources
|
|
||||||
# Using scale to 0 for StatefulSet to prevent pod creation
|
|
||||||
patches:
|
|
||||||
# Override specific ConfigMap values for development
|
|
||||||
- target:
|
|
||||||
kind: ConfigMap
|
|
||||||
name: bakery-config
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /data/ENVIRONMENT
|
|
||||||
value: "development"
|
|
||||||
- op: replace
|
|
||||||
path: /data/DEBUG
|
|
||||||
value: "true"
|
|
||||||
- op: replace
|
|
||||||
path: /data/LOG_LEVEL
|
|
||||||
value: "DEBUG"
|
|
||||||
- op: replace
|
|
||||||
path: /data/AUTO_RELOAD
|
|
||||||
value: "true"
|
|
||||||
- op: replace
|
|
||||||
path: /data/PROFILING_ENABLED
|
|
||||||
value: "true"
|
|
||||||
- op: replace
|
|
||||||
path: /data/MOCK_EXTERNAL_APIS
|
|
||||||
value: "false"
|
|
||||||
- op: replace
|
|
||||||
path: /data/TESTING
|
|
||||||
value: "false"
|
|
||||||
- op: replace
|
|
||||||
path: /data/DOMAIN
|
|
||||||
value: "localhost"
|
|
||||||
- op: replace
|
|
||||||
path: /data/API_DOCS_ENABLED
|
|
||||||
value: "true"
|
|
||||||
- op: replace
|
|
||||||
path: /data/CORS_ORIGINS
|
|
||||||
value: "http://frontend-service:3000,http://localhost:3000,http://localhost:3001,http://localhost,http://127.0.0.1:3000,http://127.0.0.1:3001,http://bakery-ia.local,https://localhost,https://127.0.0.1"
|
|
||||||
- op: replace
|
|
||||||
path: /data/VITE_ENVIRONMENT
|
|
||||||
value: "development"
|
|
||||||
- op: replace
|
|
||||||
path: /data/VITE_API_URL
|
|
||||||
value: "/api"
|
|
||||||
- op: replace
|
|
||||||
path: /data/STRIPE_PUBLISHABLE_KEY
|
|
||||||
value: "pk_test_your_stripe_publishable_key_here"
|
|
||||||
- op: replace
|
|
||||||
path: /data/SQUARE_ENVIRONMENT
|
|
||||||
value: "sandbox"
|
|
||||||
- op: replace
|
|
||||||
path: /data/TOAST_ENVIRONMENT
|
|
||||||
value: "sandbox"
|
|
||||||
- op: replace
|
|
||||||
path: /data/LIGHTSPEED_ENVIRONMENT
|
|
||||||
value: "sandbox"
|
|
||||||
- op: replace
|
|
||||||
path: /data/RATE_LIMIT_ENABLED
|
|
||||||
value: "true" # Changed from false for dev-prod parity
|
|
||||||
- op: add
|
|
||||||
path: /data/RATE_LIMIT_PER_MINUTE
|
|
||||||
value: "1000" # High limit for development (prod: 60)
|
|
||||||
- op: replace
|
|
||||||
path: /data/DB_FORCE_RECREATE
|
|
||||||
value: "false"
|
|
||||||
- op: add
|
|
||||||
path: /data/DEVELOPMENT_MODE
|
|
||||||
value: "true"
|
|
||||||
- op: add
|
|
||||||
path: /data/DEBUG_LOGGING
|
|
||||||
value: "true"
|
|
||||||
- op: add
|
|
||||||
path: /data/SKIP_MIGRATION_VERSION_CHECK
|
|
||||||
value: "false"
|
|
||||||
- target:
|
|
||||||
kind: StatefulSet
|
|
||||||
name: nominatim
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/replicas
|
|
||||||
value: 0
|
|
||||||
# Suspend nominatim-init job in dev (not needed when nominatim is scaled to 0)
|
|
||||||
- target:
|
|
||||||
kind: Job
|
|
||||||
name: nominatim-init
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/suspend
|
|
||||||
value: true
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: auth-db
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: redis
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: rabbitmq
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "128Mi"
|
|
||||||
cpu: "100m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "300m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: auth-service
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "128Mi"
|
|
||||||
cpu: "50m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: frontend
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/imagePullPolicy
|
|
||||||
value: Never
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "512Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
limits:
|
|
||||||
memory: "1Gi"
|
|
||||||
cpu: "1000m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: gateway
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/imagePullPolicy
|
|
||||||
value: Never
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "128Mi"
|
|
||||||
cpu: "100m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: alert-processor
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
# Database patches
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: external-db
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: forecasting-db
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: inventory-db
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: notification-db
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: orders-db
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: pos-db
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: production-db
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: recipes-db
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: sales-db
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: suppliers-db
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: tenant-db
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: training-db
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: ai-insights-db
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
# Service patches
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: external-service
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: forecasting-service
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: inventory-service
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: notification-service
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: orders-service
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: pos-service
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: production-service
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: recipes-service
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: sales-service
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: suppliers-service
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: tenant-service
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "64Mi"
|
|
||||||
cpu: "25m"
|
|
||||||
limits:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "200m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: training-service
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "100m"
|
|
||||||
limits:
|
|
||||||
memory: "1Gi"
|
|
||||||
cpu: "500m"
|
|
||||||
- target:
|
|
||||||
group: apps
|
|
||||||
version: v1
|
|
||||||
kind: Deployment
|
|
||||||
name: ai-insights-service
|
|
||||||
patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/template/spec/containers/0/resources
|
|
||||||
value:
|
|
||||||
requests:
|
|
||||||
memory: "128Mi"
|
|
||||||
cpu: "50m"
|
|
||||||
limits:
|
|
||||||
memory: "512Mi"
|
|
||||||
cpu: "300m"
|
|
||||||
|
|
||||||
secretGenerator:
|
|
||||||
- name: dev-secrets
|
|
||||||
literals:
|
|
||||||
- DEV_MODE=true
|
|
||||||
|
|
||||||
labels:
|
|
||||||
- includeSelectors: true
|
|
||||||
pairs:
|
|
||||||
environment: development
|
|
||||||
tier: local
|
|
||||||
|
|
||||||
images:
|
|
||||||
- name: bakery/auth-service
|
|
||||||
newTag: dev
|
|
||||||
- name: bakery/tenant-service
|
|
||||||
newTag: dev
|
|
||||||
- name: bakery/training-service
|
|
||||||
newTag: dev
|
|
||||||
- name: bakery/forecasting-service
|
|
||||||
newTag: dev
|
|
||||||
- name: bakery/sales-service
|
|
||||||
newTag: dev
|
|
||||||
- name: bakery/external-service
|
|
||||||
newTag: dev
|
|
||||||
- name: bakery/notification-service
|
|
||||||
newTag: dev
|
|
||||||
- name: bakery/inventory-service
|
|
||||||
newTag: dev
|
|
||||||
- name: bakery/recipes-service
|
|
||||||
newTag: dev
|
|
||||||
- name: bakery/suppliers-service
|
|
||||||
newTag: dev
|
|
||||||
- name: bakery/pos-service
|
|
||||||
newTag: dev
|
|
||||||
- name: bakery/orders-service
|
|
||||||
newTag: dev
|
|
||||||
- name: bakery/production-service
|
|
||||||
newTag: dev
|
|
||||||
- name: bakery/alert-processor
|
|
||||||
newTag: dev
|
|
||||||
- name: bakery/ai-insights-service
|
|
||||||
newTag: dev
|
|
||||||
- name: bakery/demo-session-service
|
|
||||||
newTag: dev
|
|
||||||
- name: bakery/gateway
|
|
||||||
newTag: dev
|
|
||||||
- name: bakery/dashboard
|
|
||||||
newTag: dev
|
|
||||||
|
|
||||||
replicas:
|
|
||||||
# Dev-Prod Parity: Run 2 replicas of critical services
|
|
||||||
# This helps catch load balancing, session management, and race condition issues
|
|
||||||
- name: auth-service
|
|
||||||
count: 2 # Increased from 1 for dev-prod parity
|
|
||||||
- name: tenant-service
|
|
||||||
count: 1
|
|
||||||
- name: training-service
|
|
||||||
count: 2 # Safe with MinIO storage
|
|
||||||
- name: forecasting-service
|
|
||||||
count: 1
|
|
||||||
- name: sales-service
|
|
||||||
count: 1
|
|
||||||
- name: external-service
|
|
||||||
count: 1
|
|
||||||
- name: notification-service
|
|
||||||
count: 1
|
|
||||||
- name: inventory-service
|
|
||||||
count: 1
|
|
||||||
- name: recipes-service
|
|
||||||
count: 1
|
|
||||||
- name: suppliers-service
|
|
||||||
count: 1
|
|
||||||
- name: pos-service
|
|
||||||
count: 1
|
|
||||||
- name: orders-service
|
|
||||||
count: 1
|
|
||||||
- name: production-service
|
|
||||||
count: 1
|
|
||||||
- name: alert-processor
|
|
||||||
count: 1
|
|
||||||
- name: ai-insights-service
|
|
||||||
count: 1
|
|
||||||
- name: demo-session-service
|
|
||||||
count: 1
|
|
||||||
- name: gateway
|
|
||||||
count: 2 # Increased from 1 for dev-prod parity
|
|
||||||
- name: frontend
|
|
||||||
count: 1
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
name: bakery-ingress-prod
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: bakery-ia
|
|
||||||
app.kubernetes.io/component: ingress
|
|
||||||
annotations:
|
|
||||||
# Nginx ingress controller annotations
|
|
||||||
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
|
||||||
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
|
||||||
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
|
|
||||||
nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
|
|
||||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
|
|
||||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
|
|
||||||
|
|
||||||
# CORS configuration for production
|
|
||||||
nginx.ingress.kubernetes.io/enable-cors: "true"
|
|
||||||
nginx.ingress.kubernetes.io/cors-allow-origin: "https://bakewise.ai"
|
|
||||||
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, OPTIONS, PATCH"
|
|
||||||
nginx.ingress.kubernetes.io/cors-allow-headers: "Content-Type, Authorization, X-Requested-With, Accept, Origin"
|
|
||||||
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
|
|
||||||
|
|
||||||
# Security headers
|
|
||||||
nginx.ingress.kubernetes.io/configuration-snippet: |
|
|
||||||
more_set_headers "X-Frame-Options: DENY";
|
|
||||||
more_set_headers "X-Content-Type-Options: nosniff";
|
|
||||||
more_set_headers "X-XSS-Protection: 1; mode=block";
|
|
||||||
more_set_headers "Referrer-Policy: strict-origin-when-cross-origin";
|
|
||||||
|
|
||||||
# Rate limiting
|
|
||||||
nginx.ingress.kubernetes.io/limit-rps: "100"
|
|
||||||
nginx.ingress.kubernetes.io/limit-connections: "50"
|
|
||||||
|
|
||||||
# Cert-manager annotations for automatic certificate issuance
|
|
||||||
cert-manager.io/cluster-issuer: "letsencrypt-production"
|
|
||||||
cert-manager.io/acme-challenge-type: http01
|
|
||||||
|
|
||||||
spec:
|
|
||||||
ingressClassName: nginx
|
|
||||||
tls:
|
|
||||||
- hosts:
|
|
||||||
- bakewise.ai
|
|
||||||
- monitoring.bakewise.ai
|
|
||||||
secretName: bakery-ia-prod-tls-cert
|
|
||||||
rules:
|
|
||||||
- host: bakewise.ai
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- path: /
|
|
||||||
pathType: Prefix
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: frontend-service
|
|
||||||
port:
|
|
||||||
number: 3000
|
|
||||||
- path: /api/v1
|
|
||||||
pathType: Prefix
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: gateway-service
|
|
||||||
port:
|
|
||||||
number: 8000
|
|
||||||
# SigNoz Monitoring on subdomain (deployed via Helm in bakery-ia namespace)
|
|
||||||
- host: monitoring.bakewise.ai
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- path: /
|
|
||||||
pathType: Prefix
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: signoz
|
|
||||||
port:
|
|
||||||
number: 8080
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
# SigNoz Helm Chart Values - Customized for Bakery IA
|
|
||||||
# https://github.com/SigNoz/charts
|
|
||||||
|
|
||||||
# Global settings
|
|
||||||
global:
|
|
||||||
storageClass: "standard"
|
|
||||||
|
|
||||||
# Frontend configuration
|
|
||||||
frontend:
|
|
||||||
service:
|
|
||||||
type: ClusterIP
|
|
||||||
port: 3301
|
|
||||||
ingress:
|
|
||||||
enabled: true
|
|
||||||
hosts:
|
|
||||||
- host: localhost
|
|
||||||
paths:
|
|
||||||
- path: /signoz
|
|
||||||
pathType: Prefix
|
|
||||||
annotations:
|
|
||||||
nginx.ingress.kubernetes.io/rewrite-target: /$2
|
|
||||||
|
|
||||||
# Query Service configuration
|
|
||||||
queryService:
|
|
||||||
replicaCount: 1
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 100m
|
|
||||||
memory: 256Mi
|
|
||||||
limits:
|
|
||||||
cpu: 200m
|
|
||||||
memory: 512Mi
|
|
||||||
|
|
||||||
# AlertManager configuration
|
|
||||||
alertmanager:
|
|
||||||
replicaCount: 1
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 50m
|
|
||||||
memory: 128Mi
|
|
||||||
limits:
|
|
||||||
cpu: 100m
|
|
||||||
memory: 256Mi
|
|
||||||
|
|
||||||
# ClickHouse configuration
|
|
||||||
clickhouse:
|
|
||||||
persistence:
|
|
||||||
enabled: true
|
|
||||||
size: 10Gi
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 500m
|
|
||||||
memory: 1Gi
|
|
||||||
limits:
|
|
||||||
cpu: 1000m
|
|
||||||
memory: 2Gi
|
|
||||||
|
|
||||||
# OpenTelemetry Collector configuration
|
|
||||||
otelCollector:
|
|
||||||
enabled: true
|
|
||||||
config:
|
|
||||||
exporters:
|
|
||||||
otlp:
|
|
||||||
endpoint: "signoz-query-service:8080"
|
|
||||||
service:
|
|
||||||
pipelines:
|
|
||||||
traces:
|
|
||||||
receivers: [otlp]
|
|
||||||
exporters: [otlp]
|
|
||||||
metrics:
|
|
||||||
receivers: [otlp]
|
|
||||||
exporters: [otlp]
|
|
||||||
logs:
|
|
||||||
receivers: [otlp]
|
|
||||||
exporters: [otlp]
|
|
||||||
|
|
||||||
# Resource optimization for development
|
|
||||||
# These can be increased for production
|
|
||||||
development: true
|
|
||||||
@@ -349,18 +349,20 @@ podDisruptionBudget:
|
|||||||
## Monitoring and Alerting
|
## Monitoring and Alerting
|
||||||
|
|
||||||
### Email Alerts (Production)
|
### Email Alerts (Production)
|
||||||
Configure SMTP in production values:
|
Configure SMTP in production values (using Mailu with Mailgun relay):
|
||||||
```yaml
|
```yaml
|
||||||
signoz:
|
signoz:
|
||||||
env:
|
env:
|
||||||
signoz_smtp_enabled: "true"
|
signoz_smtp_enabled: "true"
|
||||||
signoz_smtp_host: "smtp.gmail.com"
|
signoz_smtp_host: "mailu-smtp.bakery-ia.svc.cluster.local"
|
||||||
signoz_smtp_port: "587"
|
signoz_smtp_port: "587"
|
||||||
signoz_smtp_from: "alerts@bakewise.ai"
|
signoz_smtp_from: "alerts@bakewise.ai"
|
||||||
signoz_smtp_username: "alerts@bakewise.ai"
|
signoz_smtp_username: "alerts@bakewise.ai"
|
||||||
# Set via secret: signoz_smtp_password
|
# Set via secret: signoz_smtp_password
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Note**: Signoz now uses the internal Mailu SMTP service, which relays to Mailgun for better deliverability and centralized email management.
|
||||||
|
|
||||||
### Slack Alerts (Production)
|
### Slack Alerts (Production)
|
||||||
Configure webhook in Alertmanager:
|
Configure webhook in Alertmanager:
|
||||||
```yaml
|
```yaml
|
||||||
@@ -373,6 +375,69 @@ alertmanager:
|
|||||||
channel: '#alerts-critical'
|
channel: '#alerts-critical'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Mailgun Integration for Alert Emails
|
||||||
|
|
||||||
|
Signoz has been configured to use Mailgun for sending alert emails through the Mailu SMTP service. This provides:
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- Better email deliverability through Mailgun's infrastructure
|
||||||
|
- Centralized email management via Mailu
|
||||||
|
- Improved tracking and analytics for alert emails
|
||||||
|
- Compliance with email sending best practices
|
||||||
|
|
||||||
|
**Architecture:**
|
||||||
|
```
|
||||||
|
Signoz Alertmanager → Mailu SMTP → Mailgun Relay → Recipients
|
||||||
|
```
|
||||||
|
|
||||||
|
**Configuration Requirements:**
|
||||||
|
|
||||||
|
1. **Mailu Configuration** (`infrastructure/platform/mail/mailu/mailu-configmap.yaml`):
|
||||||
|
```yaml
|
||||||
|
RELAYHOST: "smtp.mailgun.org:587"
|
||||||
|
RELAY_LOGIN: "postmaster@bakewise.ai"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Mailu Secrets** (`infrastructure/platform/mail/mailu/mailu-secrets.yaml`):
|
||||||
|
```yaml
|
||||||
|
RELAY_PASSWORD: "<mailgun-api-key>" # Base64 encoded Mailgun API key
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **DNS Configuration** (required for Mailgun):
|
||||||
|
```
|
||||||
|
# MX record
|
||||||
|
bakewise.ai. IN MX 10 mail.bakewise.ai.
|
||||||
|
|
||||||
|
# SPF record (authorize Mailgun)
|
||||||
|
bakewise.ai. IN TXT "v=spf1 include:mailgun.org ~all"
|
||||||
|
|
||||||
|
# DKIM record (provided by Mailgun)
|
||||||
|
m1._domainkey.bakewise.ai. IN TXT "v=DKIM1; k=rsa; p=<mailgun-public-key>"
|
||||||
|
|
||||||
|
# DMARC record
|
||||||
|
_dmarc.bakewise.ai. IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@bakewise.ai"
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Signoz SMTP Configuration** (already configured in `signoz-values-prod.yaml`):
|
||||||
|
```yaml
|
||||||
|
signoz_smtp_host: "mailu-smtp.bakery-ia.svc.cluster.local"
|
||||||
|
signoz_smtp_port: "587"
|
||||||
|
signoz_smtp_from: "alerts@bakewise.ai"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Testing the Integration:**
|
||||||
|
|
||||||
|
1. Trigger a test alert from Signoz UI
|
||||||
|
2. Check Mailu logs: `kubectl logs -f mailu-smtp-<pod-id> -n bakery-ia`
|
||||||
|
3. Check Mailgun dashboard for delivery status
|
||||||
|
4. Verify email receipt in destination inbox
|
||||||
|
|
||||||
|
**Troubleshooting:**
|
||||||
|
|
||||||
|
- **SMTP Authentication Failed**: Verify Mailu credentials and Mailgun API key
|
||||||
|
- **Email Delivery Delays**: Check Mailu queue with `kubectl exec -it mailu-smtp-<pod-id> -n bakery-ia -- mailq`
|
||||||
|
- **SPF/DKIM Issues**: Verify DNS records and Mailgun domain verification
|
||||||
|
|
||||||
### Self-Monitoring
|
### Self-Monitoring
|
||||||
SigNoz monitors itself:
|
SigNoz monitors itself:
|
||||||
```yaml
|
```yaml
|
||||||
@@ -71,9 +71,9 @@ signoz:
|
|||||||
# Only enable if you have a stable OpAMP backend server
|
# Only enable if you have a stable OpAMP backend server
|
||||||
signoz_opamp_server_enabled: "false"
|
signoz_opamp_server_enabled: "false"
|
||||||
# signoz_opamp_server_endpoint: "0.0.0.0:4320"
|
# signoz_opamp_server_endpoint: "0.0.0.0:4320"
|
||||||
# SMTP configuration for email alerts
|
# SMTP configuration for email alerts - now using Mailu as SMTP server
|
||||||
signoz_smtp_enabled: "true"
|
signoz_smtp_enabled: "true"
|
||||||
signoz_smtp_host: "smtp.gmail.com"
|
signoz_smtp_host: "email-smtp.bakery-ia.svc.cluster.local"
|
||||||
signoz_smtp_port: "587"
|
signoz_smtp_port: "587"
|
||||||
signoz_smtp_from: "alerts@bakewise.ai"
|
signoz_smtp_from: "alerts@bakewise.ai"
|
||||||
signoz_smtp_username: "alerts@bakewise.ai"
|
signoz_smtp_username: "alerts@bakewise.ai"
|
||||||
@@ -136,7 +136,7 @@ alertmanager:
|
|||||||
config:
|
config:
|
||||||
global:
|
global:
|
||||||
resolve_timeout: 5m
|
resolve_timeout: 5m
|
||||||
smtp_smarthost: 'smtp.gmail.com:587'
|
smtp_smarthost: 'email-smtp.bakery-ia.svc.cluster.local:587'
|
||||||
smtp_from: 'alerts@bakewise.ai'
|
smtp_from: 'alerts@bakewise.ai'
|
||||||
smtp_auth_username: 'alerts@bakewise.ai'
|
smtp_auth_username: 'alerts@bakewise.ai'
|
||||||
smtp_auth_password: '${SMTP_PASSWORD}'
|
smtp_auth_password: '${SMTP_PASSWORD}'
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user