✅ Validation Results: - PPO training: 24.2s (1 epoch, 950 samples, dim=225) - Feature extraction: 105μs/bar (9.5x faster than target) - Model checkpoint: 293KB (147KB actor + 146KB critic) - GPU memory: 145MB used (96.4% headroom) - Zero dimension mismatches 📊 Success Criteria (5/5): ✅ Feature dimension = 225 (Wave C 201 + Wave D 24) ✅ Model state_dim = 225 ✅ Training completed without errors ✅ Checkpoint saved successfully ✅ No dimension mismatch errors 📁 Training Data Ready: - ES.FUT: 2.9MB, 180 days - NQ.FUT: 4.4MB, 180 days - 6E.FUT: 2.8MB, 180 days - ZN.FUT: 65KB, 90 days (clean) 🚀 Next: Full production model retraining (4 models, ~10min GPU time) 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
8.9 KiB
8.9 KiB
Zero-Downtime Deployment Guide
Last Updated: 2025-10-22 Target: Production environments Expected Downtime: 0 seconds Deployment Time: 15-25 minutes
Overview
This guide details strategies for deploying Foxhunt updates without service interruptions using rolling updates, blue-green deployments, and canary releases.
Rolling Update (Default Strategy)
Kubernetes RollingUpdate
# Deployment strategy configuration
spec:
replicas: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2 # Max 2 extra pods during update
maxUnavailable: 1 # Max 1 pod unavailable during update
Deployment Procedure
# Update image tag
kubectl set image deployment/foxhunt-trading-service \
trading-service=ghcr.io/your-org/foxhunt/trading-service:v0.1.6 \
-n foxhunt
# Monitor rollout
kubectl rollout status deployment/foxhunt-trading-service -n foxhunt
# Waiting for deployment "foxhunt-trading-service" rollout to finish: 2 out of 5 new replicas have been updated...
# deployment "foxhunt-trading-service" successfully rolled out
# Verify no downtime
while true; do
curl -sf http://api.foxhunt.example.com/health && echo " OK" || echo " FAILED"
sleep 1
done
Blue-Green Deployment
Setup
# Create Blue (current) and Green (new) deployments
cat > blue-green-deployment.yaml <<'EOF'
---
# Blue Deployment (Current - v0.1.5)
apiVersion: apps/v1
kind: Deployment
metadata:
name: foxhunt-trading-service-blue
namespace: foxhunt
labels:
version: v0.1.5
deployment: blue
spec:
replicas: 5
selector:
matchLabels:
app: trading-service
version: v0.1.5
template:
metadata:
labels:
app: trading-service
version: v0.1.5
spec:
containers:
- name: trading-service
image: ghcr.io/your-org/foxhunt/trading-service:v0.1.5
ports:
- containerPort: 50052
---
# Green Deployment (New - v0.1.6)
apiVersion: apps/v1
kind: Deployment
metadata:
name: foxhunt-trading-service-green
namespace: foxhunt
labels:
version: v0.1.6
deployment: green
spec:
replicas: 5
selector:
matchLabels:
app: trading-service
version: v0.1.6
template:
metadata:
labels:
app: trading-service
version: v0.1.6
spec:
containers:
- name: trading-service
image: ghcr.io/your-org/foxhunt/trading-service:v0.1.6
ports:
- containerPort: 50052
---
# Service (points to Blue initially)
apiVersion: v1
kind: Service
metadata:
name: foxhunt-trading-service
namespace: foxhunt
spec:
selector:
app: trading-service
version: v0.1.5 # Points to Blue
ports:
- port: 50052
targetPort: 50052
EOF
kubectl apply -f blue-green-deployment.yaml
Switch Traffic to Green
# Verify Green deployment is healthy
kubectl get pods -n foxhunt -l version=v0.1.6
# NAME READY STATUS RESTARTS AGE
# foxhunt-trading-service-green-abc123 1/1 Running 0 2m
# foxhunt-trading-service-green-def456 1/1 Running 0 2m
# foxhunt-trading-service-green-ghi789 1/1 Running 0 2m
# Run smoke tests on Green
kubectl port-forward -n foxhunt svc/foxhunt-trading-service-green 50052:50052 &
grpc_health_probe -addr=localhost:50052
# status: SERVING
# Switch service to Green (instant cutover)
kubectl patch service foxhunt-trading-service -n foxhunt \
-p '{"spec":{"selector":{"version":"v0.1.6"}}}'
# Verify traffic switched
kubectl describe service foxhunt-trading-service -n foxhunt | grep Selector
# Selector: app=trading-service,version=v0.1.6
# Monitor for 10 minutes, then delete Blue
sleep 600
kubectl delete deployment foxhunt-trading-service-blue -n foxhunt
Rollback (if issues detected)
# Instant rollback to Blue
kubectl patch service foxhunt-trading-service -n foxhunt \
-p '{"spec":{"selector":{"version":"v0.1.5"}}}'
# Traffic immediately returns to Blue
Canary Deployment
Istio Canary with Traffic Splitting
# Install Istio (if not already installed)
istioctl install --set profile=default -y
# Create VirtualService for canary
cat > canary-virtualservice.yaml <<'EOF'
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: trading-service-canary
namespace: foxhunt
spec:
hosts:
- foxhunt-trading-service
http:
- match:
- headers:
canary:
exact: "true"
route:
- destination:
host: foxhunt-trading-service
subset: v0.1.6
weight: 100
- route:
- destination:
host: foxhunt-trading-service
subset: v0.1.5
weight: 95 # 95% to stable
- destination:
host: foxhunt-trading-service
subset: v0.1.6
weight: 5 # 5% to canary
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: trading-service-canary
namespace: foxhunt
spec:
host: foxhunt-trading-service
subsets:
- name: v0.1.5
labels:
version: v0.1.5
- name: v0.1.6
labels:
version: v0.1.6
EOF
kubectl apply -f canary-virtualservice.yaml
Gradual Traffic Shift
# Start with 5% canary traffic
kubectl patch virtualservice trading-service-canary -n foxhunt --type=json \
-p='[{"op": "replace", "path": "/spec/http/1/route/0/weight", "value": 95},
{"op": "replace", "path": "/spec/http/1/route/1/weight", "value": 5}]'
# Monitor canary metrics for 15 minutes
# If metrics are good, increase to 25%
kubectl patch virtualservice trading-service-canary -n foxhunt --type=json \
-p='[{"op": "replace", "path": "/spec/http/1/route/0/weight", "value": 75},
{"op": "replace", "path": "/spec/http/1/route/1/weight", "value": 25}]'
# Continue incrementing: 5% → 25% → 50% → 75% → 100%
# Final cutover (100% to canary)
kubectl patch virtualservice trading-service-canary -n foxhunt --type=json \
-p='[{"op": "replace", "path": "/spec/http/1/route/0/weight", "value": 0},
{"op": "replace", "path": "/spec/http/1/route/1/weight", "value": 100}]'
Automated Canary with Flagger
# Install Flagger
kubectl apply -k github.com/fluxcd/flagger//kustomize/istio
# Create Canary resource
cat > trading-service-canary.yaml <<'EOF'
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: foxhunt-trading-service
namespace: foxhunt
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: foxhunt-trading-service
service:
port: 50052
analysis:
interval: 1m
threshold: 5
maxWeight: 50
stepWeight: 10
metrics:
- name: request-success-rate
thresholdRange:
min: 99
interval: 1m
- name: request-duration
thresholdRange:
max: 500
interval: 1m
webhooks:
- name: load-test
url: http://flagger-loadtester/
timeout: 5s
metadata:
cmd: "hey -z 1m -q 10 -c 2 http://foxhunt-trading-service:50052/"
EOF
kubectl apply -f trading-service-canary.yaml
# Flagger automatically manages canary rollout
# Monitor progress
kubectl describe canary foxhunt-trading-service -n foxhunt
Database Migration with Zero Downtime
Backward-Compatible Migrations
-- BAD: Breaking change (immediate column drop)
ALTER TABLE orders DROP COLUMN legacy_field;
-- GOOD: Multi-step migration
-- Step 1 (Deploy with code supporting both old/new schema)
ALTER TABLE orders ADD COLUMN new_field TEXT;
UPDATE orders SET new_field = legacy_field WHERE new_field IS NULL;
-- Step 2 (Wait 24 hours, deploy code using only new_field)
-- Step 3 (After verifying no errors, drop old column)
ALTER TABLE orders DROP COLUMN legacy_field;
Migration Deployment Procedure
# Step 1: Apply additive migration
kubectl exec -n foxhunt foxhunt-postgresql-0 -- \
psql -U foxhunt -d foxhunt < migrations/045_add_new_field.up.sql
# Step 2: Deploy application code (supports both schemas)
kubectl set image deployment/foxhunt-trading-service \
trading-service=ghcr.io/your-org/foxhunt/trading-service:v0.1.6-migration \
-n foxhunt
# Step 3: Wait 24 hours, verify no errors
# Step 4: Deploy final code (uses only new schema)
kubectl set image deployment/foxhunt-trading-service \
trading-service=ghcr.io/your-org/foxhunt/trading-service:v0.1.6-final \
-n foxhunt
# Step 5: Drop old column (after 7 days)
kubectl exec -n foxhunt foxhunt-postgresql-0 -- \
psql -U foxhunt -d foxhunt < migrations/046_drop_legacy_field.up.sql
Pre-Deployment Checklist
- All tests pass in CI/CD pipeline
- Database migrations are backward-compatible
- Rollback plan documented and tested
- Monitoring dashboards configured for new version
- Alert thresholds reviewed and updated
- On-call engineer notified and available
- Deployment window scheduled (prefer off-peak hours)
- Backup created within last 1 hour
- Canary deployment enabled for high-risk changes
End of Zero-Downtime Deployment Guide