23 KiB
| template_id | template_name | version | category | personas | technologies | complexity | estimated_time | dependencies | tags | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| deployment-guide-comprehensive | Comprehensive Deployment Guide Template | 1.0.0 | persona |
|
|
advanced | 120-180 minutes |
|
|
Deployment Guide: {{PROJECT_NAME}}
Deployment Overview
Project: {{PROJECT_NAME}}
Environment: {{TARGET_ENVIRONMENT}}
Platform: {{DEPLOYMENT_PLATFORM}}
Technology Stack: {{TECHNOLOGY_STACK}}
Deployment Method: {{DEPLOYMENT_METHOD}}
Last Updated: {{LAST_UPDATED}}
Deployment Summary
{{DEPLOYMENT_SUMMARY_DESCRIPTION}}
Prerequisites
- {{PREREQUISITE_1}}
- {{PREREQUISITE_2}}
- {{PREREQUISITE_3}}
Architecture Overview
Deployment Architecture Diagram
graph TB
subgraph "Load Balancer"
LB[Azure Load Balancer]
end
subgraph "Web Tier"
W1[React App Instance 1]
W2[React App Instance 2]
end
subgraph "API Tier"
A1[Node.js API Instance 1]
A2[Node.js API Instance 2]
A3[ASP.NET API Instance 1]
A4[ASP.NET API Instance 2]
end
subgraph "Data Tier"
DB[(PostgreSQL)]
CACHE[(Redis Cache)]
end
LB --> W1
LB --> W2
W1 --> A1
W1 --> A3
W2 --> A2
W2 --> A4
A1 --> DB
A2 --> DB
A3 --> DB
A4 --> DB
A1 --> CACHE
A2 --> CACHE
A3 --> CACHE
A4 --> CACHE
Component Distribution
- Frontend: {{FRONTEND_DEPLOYMENT_DETAILS}}
- Backend APIs: {{BACKEND_DEPLOYMENT_DETAILS}}
- Database: {{DATABASE_DEPLOYMENT_DETAILS}}
- Cache: {{CACHE_DEPLOYMENT_DETAILS}}
Environment Configuration
Development Environment
```yaml
docker-compose.dev.yml
version: '3.8' services: frontend: build: context: ./frontend dockerfile: Dockerfile.dev ports: - "3000:3000" environment: - NODE_ENV=development - REACT_APP_API_URL=http://localhost:5000 volumes: - ./frontend:/app - /app/node_modules
nodejs-api: build: context: ./backend/nodejs dockerfile: Dockerfile.dev ports: - "5000:5000" environment: - NODE_ENV=development - DATABASE_URL={{DEV_DATABASE_URL}} - REDIS_URL={{DEV_REDIS_URL}} volumes: - ./backend/nodejs:/app - /app/node_modules
aspnet-api: build: context: ./backend/aspnet dockerfile: Dockerfile.dev ports: - "5001:80" environment: - ASPNETCORE_ENVIRONMENT=Development - ConnectionStrings__DefaultConnection={{DEV_DATABASE_URL}} - Redis__ConnectionString={{DEV_REDIS_URL}} volumes: - ./backend/aspnet:/app
postgres: image: postgres:15 ports: - "5432:5432" environment: - POSTGRES_DB={{DEV_DB_NAME}} - POSTGRES_USER={{DEV_DB_USER}} - POSTGRES_PASSWORD={{DEV_DB_PASSWORD}} volumes: - postgres_data:/var/lib/postgresql/data
redis: image: redis:7-alpine ports: - "6379:6379"
volumes: postgres_data:
### Production Environment
\```yaml
# docker-compose.prod.yml
version: '3.8'
services:
frontend:
build:
context: ./frontend
dockerfile: Dockerfile.prod
ports:
- "80:80"
environment:
- NODE_ENV=production
- REACT_APP_API_URL={{PROD_API_URL}}
nodejs-api:
build:
context: ./backend/nodejs
dockerfile: Dockerfile.prod
ports:
- "5000:5000"
environment:
- NODE_ENV=production
- DATABASE_URL={{PROD_DATABASE_URL}}
- REDIS_URL={{PROD_REDIS_URL}}
deploy:
replicas: 2
resources:
limits:
memory: 512M
reservations:
memory: 256M
aspnet-api:
build:
context: ./backend/aspnet
dockerfile: Dockerfile.prod
ports:
- "5001:80"
environment:
- ASPNETCORE_ENVIRONMENT=Production
- ConnectionStrings__DefaultConnection={{PROD_DATABASE_URL}}
- Redis__ConnectionString={{PROD_REDIS_URL}}
deploy:
replicas: 2
resources:
limits:
memory: 512M
reservations:
memory: 256M
Containerization
Frontend Dockerfile (React)
```dockerfile
Dockerfile.prod for React frontend
FROM node:18-alpine as build
WORKDIR /app COPY package*.json ./ RUN npm ci --only=production
COPY . . RUN npm run build
FROM nginx:alpine COPY --from=build /app/build /usr/share/nginx/html COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
### Backend Dockerfile (Node.js)
\```dockerfile
# Dockerfile.prod for Node.js API
FROM node:18-alpine
WORKDIR /app
# Copy package files
COPY package*.json ./
RUN npm ci --only=production
# Copy source code
COPY . .
# Create non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001
USER nodejs
EXPOSE 5000
CMD ["node", "server.js"]
Backend Dockerfile (ASP.NET)
```dockerfile
Dockerfile.prod for ASP.NET API
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base WORKDIR /app EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build WORKDIR /src COPY ["{{PROJECT_NAME}}.csproj", "."] RUN dotnet restore "{{PROJECT_NAME}}.csproj" COPY . . WORKDIR "/src/." RUN dotnet build "{{PROJECT_NAME}}.csproj" -c Release -o /app/build
FROM build AS publish RUN dotnet publish "{{PROJECT_NAME}}.csproj" -c Release -o /app/publish
FROM base AS final WORKDIR /app COPY --from=publish /app/publish . ENTRYPOINT ["dotnet", "{{PROJECT_NAME}}.dll"]
## Kubernetes Deployment
### Namespace Configuration
\```yaml
# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: {{PROJECT_NAME}}
labels:
name: {{PROJECT_NAME}}
Frontend Deployment
```yaml
frontend-deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: frontend namespace: {{PROJECT_NAME}} spec: replicas: 2 selector: matchLabels: app: frontend template: metadata: labels: app: frontend spec: containers: - name: frontend image: {{CONTAINER_REGISTRY}}/{{PROJECT_NAME}}-frontend:{{VERSION}} ports: - containerPort: 80 env: - name: REACT_APP_API_URL value: "{{API_URL}}" resources: requests: memory: "128Mi" cpu: "100m" limits: memory: "256Mi" cpu: "200m"
apiVersion: v1 kind: Service metadata: name: frontend-service namespace: {{PROJECT_NAME}} spec: selector: app: frontend ports:
- port: 80 targetPort: 80 type: LoadBalancer
### Backend API Deployments
\```yaml
# nodejs-api-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nodejs-api
namespace: {{PROJECT_NAME}}
spec:
replicas: 2
selector:
matchLabels:
app: nodejs-api
template:
metadata:
labels:
app: nodejs-api
spec:
containers:
- name: nodejs-api
image: {{CONTAINER_REGISTRY}}/{{PROJECT_NAME}}-nodejs-api:{{VERSION}}
ports:
- containerPort: 5000
env:
- name: NODE_ENV
value: "production"
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: database-secret
key: connection-string
- name: REDIS_URL
valueFrom:
secretKeyRef:
name: redis-secret
key: connection-string
resources:
requests:
memory: "256Mi"
cpu: "200m"
limits:
memory: "512Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: nodejs-api-service
namespace: {{PROJECT_NAME}}
spec:
selector:
app: nodejs-api
ports:
- port: 5000
targetPort: 5000
Database Configuration
```yaml
postgres-deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: postgres namespace: {{PROJECT_NAME}} spec: replicas: 1 selector: matchLabels: app: postgres template: metadata: labels: app: postgres spec: containers: - name: postgres image: postgres:15 ports: - containerPort: 5432 env: - name: POSTGRES_DB value: "{{DATABASE_NAME}}" - name: POSTGRES_USER valueFrom: secretKeyRef: name: database-secret key: username - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: database-secret key: password volumeMounts: - name: postgres-storage mountPath: /var/lib/postgresql/data resources: requests: memory: "512Mi" cpu: "300m" limits: memory: "1Gi" cpu: "500m" volumes: - name: postgres-storage persistentVolumeClaim: claimName: postgres-pvc
apiVersion: v1 kind: Service metadata: name: postgres-service namespace: {{PROJECT_NAME}} spec: selector: app: postgres ports:
- port: 5432 targetPort: 5432
## CI/CD Pipeline
### GitHub Actions Workflow
\```yaml
# .github/workflows/deploy.yml
name: Deploy to Production
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Run linting
run: npm run lint
- name: Security audit
run: npm audit
build-and-push:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v3
- name: Login to Container Registry
uses: docker/login-action@v2
with:
registry: {{CONTAINER_REGISTRY}}
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Build and push Frontend
uses: docker/build-push-action@v4
with:
context: ./frontend
file: ./frontend/Dockerfile.prod
push: true
tags: {{CONTAINER_REGISTRY}}/{{PROJECT_NAME}}-frontend:${{ github.sha }}
- name: Build and push Node.js API
uses: docker/build-push-action@v4
with:
context: ./backend/nodejs
file: ./backend/nodejs/Dockerfile.prod
push: true
tags: {{CONTAINER_REGISTRY}}/{{PROJECT_NAME}}-nodejs-api:${{ github.sha }}
- name: Build and push ASP.NET API
uses: docker/build-push-action@v4
with:
context: ./backend/aspnet
file: ./backend/aspnet/Dockerfile.prod
push: true
tags: {{CONTAINER_REGISTRY}}/{{PROJECT_NAME}}-aspnet-api:${{ github.sha }}
deploy:
needs: build-and-push
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v3
- name: Setup kubectl
uses: azure/setup-kubectl@v3
with:
version: 'latest'
- name: Set up Kubeconfig
run: |
echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > kubeconfig
export KUBECONFIG=kubeconfig
- name: Deploy to Kubernetes
run: |
sed -i 's/{{VERSION}}/${{ github.sha }}/g' k8s/*.yaml
kubectl apply -f k8s/
kubectl rollout status deployment/frontend -n {{PROJECT_NAME}}
kubectl rollout status deployment/nodejs-api -n {{PROJECT_NAME}}
kubectl rollout status deployment/aspnet-api -n {{PROJECT_NAME}}
Infrastructure as Code
Terraform Configuration
# main.tf
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~>3.0"
}
}
}
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "main" {
name = "{{PROJECT_NAME}}-rg"
location = "{{AZURE_REGION}}"
}
resource "azurerm_kubernetes_cluster" "main" {
name = "{{PROJECT_NAME}}-aks"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
dns_prefix = "{{PROJECT_NAME}}-aks"
default_node_pool {
name = "default"
node_count = {{NODE_COUNT}}
vm_size = "{{VM_SIZE}}"
}
identity {
type = "SystemAssigned"
}
tags = {
Environment = "{{ENVIRONMENT}}"
Project = "{{PROJECT_NAME}}"
}
}
resource "azurerm_postgresql_server" "main" {
name = "{{PROJECT_NAME}}-postgres"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
administrator_login = "{{DB_ADMIN_USER}}"
administrator_login_password = "{{DB_ADMIN_PASSWORD}}"
sku_name = "{{POSTGRES_SKU}}"
version = "{{POSTGRES_VERSION}}"
storage_mb = {{POSTGRES_STORAGE_MB}}
backup_retention_days = {{BACKUP_RETENTION_DAYS}}
geo_redundant_backup_enabled = {{GEO_REDUNDANT_BACKUP}}
auto_grow_enabled = true
public_network_access_enabled = false
ssl_enforcement_enabled = true
ssl_minimal_tls_version_enforced = "TLS1_2"
}
resource "azurerm_redis_cache" "main" {
name = "{{PROJECT_NAME}}-redis"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
capacity = {{REDIS_CAPACITY}}
family = "{{REDIS_FAMILY}}"
sku_name = "{{REDIS_SKU}}"
enable_non_ssl_port = false
minimum_tls_version = "1.2"
redis_configuration {
enable_authentication = true
}
}
Monitoring and Observability
Application Insights Configuration
```yaml
monitoring-deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: monitoring-agent namespace: {{PROJECT_NAME}} spec: replicas: 1 selector: matchLabels: app: monitoring-agent template: metadata: labels: app: monitoring-agent spec: containers: - name: prometheus image: prom/prometheus:latest ports: - containerPort: 9090 volumeMounts: - name: prometheus-config mountPath: /etc/prometheus - name: grafana image: grafana/grafana:latest ports: - containerPort: 3000 env: - name: GF_SECURITY_ADMIN_PASSWORD valueFrom: secretKeyRef: name: monitoring-secret key: grafana-password volumes: - name: prometheus-config configMap: name: prometheus-config
### Logging Configuration
\```yaml
# logging-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: fluent-bit-config
namespace: {{PROJECT_NAME}}
data:
fluent-bit.conf: |
[SERVICE]
Flush 1
Log_Level info
Daemon off
Parsers_File parsers.conf
HTTP_Server On
HTTP_Listen 0.0.0.0
HTTP_Port 2020
[INPUT]
Name tail
Path /var/log/containers/*.log
Parser docker
Tag kube.*
Refresh_Interval 5
Mem_Buf_Limit 50MB
Skip_Long_Lines On
[FILTER]
Name kubernetes
Match kube.*
Kube_URL https://kubernetes.default.svc:443
Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
Kube_Tag_Prefix kube.var.log.containers.
Merge_Log On
Keep_Log Off
[OUTPUT]
Name azure
Match *
Customer_ID {{LOG_ANALYTICS_WORKSPACE_ID}}
Shared_Key {{LOG_ANALYTICS_SHARED_KEY}}
Log_Type {{PROJECT_NAME}}_logs
Security Configuration
Network Policies
```yaml
network-policy.yaml
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: {{PROJECT_NAME}}-network-policy namespace: {{PROJECT_NAME}} spec: podSelector: {} policyTypes:
- Ingress
- Egress ingress:
- from:
- namespaceSelector: matchLabels: name: {{PROJECT_NAME}} ports:
- protocol: TCP port: 80
- protocol: TCP port: 5000
- protocol: TCP port: 5001 egress:
- to:
- namespaceSelector: matchLabels: name: {{PROJECT_NAME}} ports:
- protocol: TCP port: 5432
- protocol: TCP port: 6379
- to: []
ports:
- protocol: TCP port: 443
- protocol: TCP port: 53
- protocol: UDP port: 53
### Secret Management
\```yaml
# secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: database-secret
namespace: {{PROJECT_NAME}}
type: Opaque
data:
connection-string: {{BASE64_ENCODED_DB_CONNECTION}}
username: {{BASE64_ENCODED_DB_USERNAME}}
password: {{BASE64_ENCODED_DB_PASSWORD}}
---
apiVersion: v1
kind: Secret
metadata:
name: redis-secret
namespace: {{PROJECT_NAME}}
type: Opaque
data:
connection-string: {{BASE64_ENCODED_REDIS_CONNECTION}}
---
apiVersion: v1
kind: Secret
metadata:
name: api-keys
namespace: {{PROJECT_NAME}}
type: Opaque
data:
jwt-secret: {{BASE64_ENCODED_JWT_SECRET}}
api-key: {{BASE64_ENCODED_API_KEY}}
Backup and Disaster Recovery
Database Backup Strategy
```bash #!/bin/bash
backup-database.sh
Configuration
BACKUP_DIR="/backups" DB_HOST="{{DATABASE_HOST}}" DB_NAME="{{DATABASE_NAME}}" DB_USER="{{DATABASE_USER}}" RETENTION_DAYS=30
Create backup directory
mkdir -p $BACKUP_DIR
Generate backup filename with timestamp
BACKUP_FILE="BACKUP_DIR/{DB_NAME}$(date +%Y%m%d%H%M%S).sql"
Create database backup
pg_dump -h $DB_HOST -U $DB_USER -d $DB_NAME > $BACKUP_FILE
Compress backup
gzip $BACKUP_FILE
Upload to cloud storage
az storage blob upload
--account-name {{STORAGE_ACCOUNT}}
--container-name backups
--name "database/$(basename $BACKUP_FILE.gz)"
--file "$BACKUP_FILE.gz"
Clean up old local backups
find $BACKUP_DIR -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete
echo "Backup completed: $BACKUP_FILE.gz"
### Disaster Recovery Plan
1. **RTO (Recovery Time Objective):** {{RTO_TARGET}}
2. **RPO (Recovery Point Objective):** {{RPO_TARGET}}
3. **Backup Frequency:** {{BACKUP_FREQUENCY}}
4. **Recovery Procedures:** {{RECOVERY_PROCEDURES}}
## Performance Optimization
### Resource Limits and Requests
\```yaml
# resource-optimization.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: {{PROJECT_NAME}}-limits
namespace: {{PROJECT_NAME}}
spec:
limits:
- default:
memory: "512Mi"
cpu: "500m"
defaultRequest:
memory: "256Mi"
cpu: "200m"
type: Container
Horizontal Pod Autoscaler
```yaml
hpa.yaml
apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: frontend-hpa namespace: {{PROJECT_NAME}} spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: frontend minReplicas: 2 maxReplicas: 10 metrics:
- type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70
- type: Resource resource: name: memory target: type: Utilization averageUtilization: 80
## Troubleshooting
### Common Issues and Solutions
#### Issue: Pod Startup Failures
**Symptoms:** Pods stuck in `CrashLoopBackOff` or `ImagePullBackOff`
**Solutions:**
1. Check image availability: `kubectl describe pod <pod-name>`
2. Verify resource limits: `kubectl get events`
3. Check logs: `kubectl logs <pod-name>`
#### Issue: Database Connection Failures
**Symptoms:** API services unable to connect to database
**Solutions:**
1. Verify database service: `kubectl get svc postgres-service`
2. Check network policies: `kubectl get networkpolicy`
3. Validate secrets: `kubectl get secret database-secret -o yaml`
#### Issue: High Memory Usage
**Symptoms:** Pods being killed due to OOMKilled
**Solutions:**
1. Increase memory limits in deployment
2. Optimize application memory usage
3. Implement memory profiling
### Debugging Commands
\```bash
# Check pod status
kubectl get pods -n {{PROJECT_NAME}}
# View pod logs
kubectl logs -f <pod-name> -n {{PROJECT_NAME}}
# Describe pod for events
kubectl describe pod <pod-name> -n {{PROJECT_NAME}}
# Execute into pod for debugging
kubectl exec -it <pod-name> -n {{PROJECT_NAME}} -- /bin/bash
# Check resource usage
kubectl top pods -n {{PROJECT_NAME}}
# View service endpoints
kubectl get endpoints -n {{PROJECT_NAME}}
Rollback Procedures
Automated Rollback
```bash #!/bin/bash
rollback.sh
NAMESPACE="{{PROJECT_NAME}}" DEPLOYMENT_NAME="$1" REVISION="$2"
if [ -z "$DEPLOYMENT_NAME" ] || [ -z "$REVISION" ]; then echo "Usage: $0 " exit 1 fi
echo "Rolling back $DEPLOYMENT_NAME to revision $REVISION..."
kubectl rollout undo deployment/$DEPLOYMENT_NAME --to-revision=$REVISION -n $NAMESPACE
echo "Waiting for rollback to complete..." kubectl rollout status deployment/$DEPLOYMENT_NAME -n $NAMESPACE
echo "Rollback completed successfully"
### Manual Rollback Steps
1. **Identify target revision:** `kubectl rollout history deployment/<name>`
2. **Execute rollback:** `kubectl rollout undo deployment/<name> --to-revision=<number>`
3. **Verify rollback:** `kubectl rollout status deployment/<name>`
4. **Validate functionality:** Run health checks and integration tests
## Maintenance Procedures
### Regular Maintenance Tasks
1. **Weekly:**
- Review resource usage and scaling metrics
- Check backup integrity
- Update security patches
2. **Monthly:**
- Review and rotate secrets
- Analyze performance metrics
- Update dependencies
3. **Quarterly:**
- Disaster recovery testing
- Security audit
- Capacity planning review
### Maintenance Windows
- **Scheduled Maintenance:** {{MAINTENANCE_SCHEDULE}}
- **Emergency Maintenance:** {{EMERGENCY_PROCEDURES}}
- **Communication Plan:** {{MAINTENANCE_COMMUNICATION}}
---
## Template Usage Notes
### Variable Substitution Guide
Replace all `{{VARIABLE_NAME}}` placeholders with environment-specific information.
### Customization Options
- Adapt cloud provider configurations (Azure/AWS/GCP)
- Modify container orchestration platform (Kubernetes/Docker Swarm)
- Customize monitoring and logging solutions
- Adjust security policies based on compliance requirements
### Quality Validation Checklist
- [ ] All deployment configurations are tested
- [ ] Security policies are implemented and validated
- [ ] Monitoring and alerting are configured
- [ ] Backup and disaster recovery procedures are tested
- [ ] Performance optimization is implemented
- [ ] Troubleshooting procedures are documented
- [ ] Rollback procedures are tested and validated
### Integration Points
- **BMAD Personas:** DevOps Documentation Specialist, Cross-Platform Integration Specialist
- **Follow-up Templates:** Monitoring Template, Security Template
- **Quality Standards:** BMAD Method deployment quality framework
---
**Template Version:** 1.0.0
**Last Updated:** {{CURRENT_DATE}}
**Template Owner:** BMAD Method Team