Files
tusuii 73bd35173c
Some checks failed
scrum-manager/pipeline/head There was a failure building this commit
fix: k8s on-premise deployment and session persistence
Database fixes:
- Add hostPath.type=DirectoryOrCreate so kubelet auto-creates /mnt/data/mysql
- Add fsGroup=999 so MySQL process can write to the hostPath volume
- Add MYSQL_ROOT_HOST=% to allow backend pods to authenticate as root
- Fix liveness/readiness probes to include credentials (-p$MYSQL_ROOT_PASSWORD)
- Increase probe initialDelaySeconds (30/60s) for slow first-run init
- Add 15s grace sleep in backend initContainer after MySQL TCP is up
- Add persistentVolumeReclaimPolicy=Retain to prevent accidental data loss
- Explicit accessModes+resources in PVC patch to avoid list merge ambiguity
- Add nodeAffinity comment in PV for multi-node cluster guidance

Ingress/nginx fixes:
- Remove broken rewrite-target=/ that was rewriting all paths (incl /api) to /
- Route /socket.io directly to backend for WebSocket support
- Add /socket.io/ proxy location to both nginx.conf and K8s ConfigMap

Frontend fix:
- Persist currentUser to localStorage on login so page refresh no longer
  clears session and redirects users back to the login page

Tooling:
- Add k8s/overlays/on-premise/deploy.sh for one-command deployment

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 22:51:57 +05:30

96 lines
5.1 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# ── Scrum Manager — On-Premise Kubernetes Deploy Script ─────────────────────
# Run from the project root: bash k8s/overlays/on-premise/deploy.sh
# ────────────────────────────────────────────────────────────────────────────
OVERLAY="k8s/overlays/on-premise"
NAMESPACE="scrum-manager"
REGISTRY="${REGISTRY:-}" # Optional: set to your registry, e.g. "192.168.1.10:5000"
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
info() { echo -e "${GREEN}[INFO]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
error() { echo -e "${RED}[ERROR]${NC} $*"; exit 1; }
# ── Pre-flight checks ────────────────────────────────────────────────────────
info "Checking prerequisites..."
command -v kubectl >/dev/null 2>&1 || error "kubectl not found"
command -v docker >/dev/null 2>&1 || error "docker not found"
kubectl cluster-info >/dev/null 2>&1 || error "Cannot reach Kubernetes cluster. Check kubeconfig."
info "Prerequisites OK."
# ── Multi-node: hostPath nodeAffinity reminder ───────────────────────────────
NODE_COUNT=$(kubectl get nodes --no-headers 2>/dev/null | wc -l)
if [ "$NODE_COUNT" -gt 1 ]; then
warn "Multi-node cluster detected ($NODE_COUNT nodes)."
warn "MySQL data is stored at /mnt/data/mysql on ONE node only."
warn "Open k8s/overlays/on-premise/mysql-pv.yaml and uncomment"
warn "the nodeAffinity block, setting it to the correct node hostname."
warn "Run: kubectl get nodes to list hostnames."
read -rp "Press ENTER to continue anyway, or Ctrl+C to abort and fix first..."
fi
# ── Build Docker images ──────────────────────────────────────────────────────
info "Building Docker images..."
BACKEND_TAG="${REGISTRY:+${REGISTRY}/}scrum-backend:latest"
FRONTEND_TAG="${REGISTRY:+${REGISTRY}/}scrum-frontend:latest"
docker build -t "$BACKEND_TAG" -f server/Dockerfile server/
docker build -t "$FRONTEND_TAG" -f Dockerfile .
# ── Push or load images into cluster ────────────────────────────────────────
if [ -n "$REGISTRY" ]; then
info "Pushing images to registry $REGISTRY..."
docker push "$BACKEND_TAG"
docker push "$FRONTEND_TAG"
else
warn "No REGISTRY set. Attempting to load images via 'docker save | ssh'..."
warn "If you have a single-node cluster and Docker runs on the same host,"
warn "set imagePullPolicy: Never in the deployments (already set)."
warn "For multi-node, set REGISTRY=<your-registry> before running this script."
warn ""
warn " Alternatively, load images manually on each node with:"
warn " docker save scrum-backend:latest | ssh NODE docker load"
warn " docker save scrum-frontend:latest | ssh NODE docker load"
fi
# ── Apply Kubernetes manifests ────────────────────────────────────────────────
info "Applying manifests via kustomize..."
kubectl apply -k "$OVERLAY"
# ── Wait for rollout ──────────────────────────────────────────────────────────
info "Waiting for MySQL to become ready (this can take up to 90s on first run)..."
kubectl rollout status deployment/mysql -n "$NAMESPACE" --timeout=120s || \
warn "MySQL rollout timed out — check: kubectl describe pod -l app.kubernetes.io/name=mysql -n $NAMESPACE"
info "Waiting for backend..."
kubectl rollout status deployment/backend -n "$NAMESPACE" --timeout=90s || \
warn "Backend rollout timed out — check: kubectl logs -l app.kubernetes.io/name=backend -n $NAMESPACE"
info "Waiting for frontend..."
kubectl rollout status deployment/frontend -n "$NAMESPACE" --timeout=60s || \
warn "Frontend rollout timed out."
# ── Show access info ──────────────────────────────────────────────────────────
echo ""
info "Deploy complete! Access the app:"
NODEPORT=$(kubectl get svc frontend -n "$NAMESPACE" -o jsonpath='{.spec.ports[0].nodePort}' 2>/dev/null || echo "")
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}' 2>/dev/null || echo "<NODE-IP>")
if [ -n "$NODEPORT" ]; then
echo ""
echo -e " NodePort: ${GREEN}http://${NODE_IP}:${NODEPORT}${NC}"
fi
echo ""
echo -e " Ingress: ${GREEN}http://scrum.local${NC} (add '$NODE_IP scrum.local' to /etc/hosts)"
echo ""
echo "Useful commands:"
echo " kubectl get pods -n $NAMESPACE"
echo " kubectl logs -f deployment/backend -n $NAMESPACE"
echo " kubectl logs -f deployment/mysql -n $NAMESPACE"