#!/bin/bash # Setup script voor EveAI Dev Kind Cluster # File: setup-dev-cluster.sh set -e echo "🚀 Setting up EveAI Dev Kind Cluster..." CLUSTER_NAME="eveai-dev-cluster" # Colors voor output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Function voor colored output print_status() { echo -e "${BLUE}[INFO]${NC} $1" } print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } # Check if required tools are installed check_prerequisites() { print_status "Checking prerequisites..." if ! command -v kind &> /dev/null; then print_error "kind is not installed. Please install kind first." echo "Install via: go install sigs.k8s.io/kind@latest" exit 1 fi if ! command -v kubectl &> /dev/null; then print_error "kubectl is not installed. Please install kubectl first." exit 1 fi if ! command -v podman &> /dev/null; then print_error "podman is not installed. Please install podman first." exit 1 fi if ! command -v envsubst &> /dev/null; then print_error "envsubst is not installed. Please install envsubst first" fi print_success "All prerequisites are installed" } # Create host directories for persistent volumes create_host_directories() { print_status "Creating host directories for persistent storage..." BASE_DIR="$HOME/k8s-data/dev" directories=( "$BASE_DIR/minio" "$BASE_DIR/redis" "$BASE_DIR/logs" "$BASE_DIR/prometheus" "$BASE_DIR/grafana" "$BASE_DIR/certs" ) for dir in "${directories[@]}"; do if [ ! -d "$dir" ]; then mkdir -p "$dir" print_status "Created directory: $dir" else print_status "Directory already exists: $dir" fi done # Set proper permissions # chmod -R 755 "$BASE_DIR" print_success "Host directories created and configured" } # Create Kind cluster create_cluster() { print_status "Creating Kind cluster..." if kind get clusters | grep -q "eveai-dev-cluster"; then print_warning "Cluster 'eveai-dev-cluster' already exists" echo -n "Do you want to delete and recreate it? (y/N): " read -r response if [[ "$response" =~ ^[Yy]$ ]]; then print_status "Deleting existing cluster..." kind delete cluster --name eveai-dev-cluster else print_status "Using existing cluster" return 0 fi fi KIND_CONFIG="kind-dev-cluster.yaml" if [ ! -f "${KIND_CONFIG}" ]; then print_error "Config '${KIND_CONFIG}' niet gevonden in $(pwd)" exit 1 fi print_status "Creating new Kind cluster with configuration..." # Genereer expanded config met envsubst EXPANDED_CONFIG="$(mktemp --suffix=.yaml)" envsubst < "${KIND_CONFIG}" > "${EXPANDED_CONFIG}" # Voorkeursmethode: start in user-scope met expliciete delegatie if command -v systemd-run >/dev/null 2>&1; then systemd-run --scope --user -p "Delegate=yes" \ env KIND_EXPERIMENTAL_PROVIDER=podman \ kind create cluster --name "${CLUSTER_NAME}" --config "${EXPANDED_CONFIG}" else # Fallback print_warning "Start zonder systemd-run scope; kan mislukken bij ontbrekende delegatie." kind create cluster --name "${CLUSTER_NAME}" --config "${EXPANDED_CONFIG}" fi # Cleanup temporary config rm -f "${EXPANDED_CONFIG}" # Wait for cluster to be ready print_status "Waiting for cluster to be ready..." kubectl wait --for=condition=Ready nodes --all --timeout=300s # Update CA certificates in Kind node if command -v podman &> /dev/null; then podman exec eveai-dev-cluster-control-plane update-ca-certificates podman exec eveai-dev-cluster-control-plane systemctl restart containerd else docker exec eveai-dev-cluster-control-plane update-ca-certificates docker exec eveai-dev-cluster-control-plane systemctl restart containerd fi print_success "Kind cluster created successfully" } # Configure container resource limits to prevent CRI issues configure_container_limits() { print_status "Configuring container resource limits..." # Configure file descriptor and inotify limits to prevent CRI plugin failures podman exec "${CLUSTER_NAME}-control-plane" sh -c ' echo "fs.inotify.max_user_instances = 1024" >> /etc/sysctl.conf echo "fs.inotify.max_user_watches = 524288" >> /etc/sysctl.conf echo "fs.file-max = 2097152" >> /etc/sysctl.conf sysctl -p ' # Restart containerd to apply new limits print_status "Restarting containerd with new limits..." podman exec "${CLUSTER_NAME}-control-plane" systemctl restart containerd # Wait for containerd to stabilize sleep 10 # Restart kubelet to ensure proper CRI communication podman exec "${CLUSTER_NAME}-control-plane" systemctl restart kubelet print_success "Container limits configured and services restarted" } # Verify CRI status and functionality verify_cri_status() { print_status "Verifying CRI status..." # Wait for services to stabilize sleep 15 # Test CRI connectivity if podman exec "${CLUSTER_NAME}-control-plane" crictl version &>/dev/null; then print_success "CRI is functional" # Show CRI version info print_status "CRI version information:" podman exec "${CLUSTER_NAME}-control-plane" crictl version else print_error "CRI is not responding - checking containerd logs" podman exec "${CLUSTER_NAME}-control-plane" journalctl -u containerd --no-pager -n 20 print_error "Checking kubelet logs" podman exec "${CLUSTER_NAME}-control-plane" journalctl -u kubelet --no-pager -n 10 return 1 fi # Verify node readiness print_status "Waiting for node to become Ready..." local max_attempts=30 local attempt=0 while [ $attempt -lt $max_attempts ]; do if kubectl get nodes | grep -q "Ready"; then print_success "Node is Ready" return 0 fi attempt=$((attempt + 1)) print_status "Attempt $attempt/$max_attempts - waiting for node readiness..." sleep 10 done print_error "Node failed to become Ready within timeout" kubectl get nodes -o wide return 1 } # Install Ingress Controller install_ingress_controller() { print_status "Installing NGINX Ingress Controller..." # Install NGINX Ingress Controller for Kind kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/kind/deploy.yaml # Wait for Ingress Controller to be ready print_status "Waiting for Ingress Controller to be ready..." kubectl wait --namespace ingress-nginx \ --for=condition=ready pod \ --selector=app.kubernetes.io/component=controller \ --timeout=300s if [ $? -eq 0 ]; then print_success "NGINX Ingress Controller installed and ready" else print_error "Failed to install or start Ingress Controller" exit 1 fi # Verify Ingress Controller status print_status "Ingress Controller status:" kubectl get pods -n ingress-nginx kubectl get services -n ingress-nginx } # Apply Kubernetes manifests apply_manifests() { print_status "Applying Kubernetes manifests..." # Apply in correct order manifests=( "persistent-volumes.yaml" "config-secrets.yaml" ) for manifest in "${manifests[@]}"; do if [ -f "$manifest" ]; then print_status "Applying $manifest..." kubectl apply -f "$manifest" else print_warning "Manifest $manifest not found, skipping..." fi done print_success "Base manifests applied successfully" } # Verify cluster status verify_cluster() { print_status "Verifying cluster status..." # Check nodes print_status "Cluster nodes:" kubectl get nodes # Check namespaces print_status "Namespaces:" kubectl get namespaces # Check persistent volumes print_status "Persistent volumes:" kubectl get pv # Check if registry is accessible from cluster print_status "Testing registry connectivity..." if kubectl run test-registry --image=registry.ask-eve-ai-local.com/josakola/nginx:latest --dry-run=server &> /dev/null; then print_success "Registry is accessible from cluster" kubectl delete pod test-registry --ignore-not-found=true &> /dev/null || true else print_warning "Registry connectivity test failed - this might be expected if images aren't pushed yet" fi } # Main execution main() { echo "==================================================" echo "🏗️ EveAI Dev Kind Cluster Setup" echo "==================================================" check_prerequisites create_host_directories create_cluster configure_container_limits verify_cri_status install_ingress_controller apply_manifests verify_cluster echo "" echo "==================================================" print_success "EveAI Dev Kind Cluster setup completed!" echo "==================================================" echo "" echo "📋 Next steps:" echo "1. Deploy your application services using: ./deploy-all-services.sh" echo "2. Access services via Ingress: http://minty.ask-eve-ai-local.com:3080" echo "" echo "🔧 Useful commands:" echo " kubectl config current-context # Verify you're using the right cluster" echo " kubectl get all -n eveai-dev # Check all resources in dev namespace" echo " kubectl get ingress -n eveai-dev # Check Ingress resources" echo " kind delete cluster --name eveai-dev-cluster # Delete cluster when done" echo "" echo "📊 Service Access (via Ingress):" echo " - Main App: http://minty.ask-eve-ai-local.com:3080/admin/" echo " - API: http://minty.ask-eve-ai-local.com:3080/api/" echo " - Chat Client: http://minty.ask-eve-ai-local.com:3080/chat-client/" echo " - Static Files: http://minty.ask-eve-ai-local.com:3080/static/" } # Run main function main "$@"