From 9caf95bb7a8cb95167d410934d4388e563bcf116 Mon Sep 17 00:00:00 2001 From: William Valentin Date: Sun, 14 Sep 2025 23:18:04 -0700 Subject: [PATCH] refactor: simplify k8s deployment to pure kubectl - Remove kustomization.yaml and all kustomize references - Remove deploy-pi.sh and vpa-pi-helper.sh helper scripts - Remove redundant ConfigMap from vpa.yaml - Update README.md to focus on standard kubectl commands - Keep deployment simple with just YAML files and kubectl - Maintain Pi 5 optimizations and VPA functionality - No complex tooling required for deployment --- k8s/README.md | 491 ++++++++++++++++++++++++++++++++++++++++++++ k8s/configmap.yaml | 58 ++++++ k8s/deployment.yaml | 74 +++++++ k8s/ingress.yaml | 27 +++ k8s/service.yaml | 16 ++ k8s/vpa.yaml | 29 +++ 6 files changed, 695 insertions(+) create mode 100644 k8s/README.md create mode 100644 k8s/configmap.yaml create mode 100644 k8s/deployment.yaml create mode 100644 k8s/ingress.yaml create mode 100644 k8s/service.yaml create mode 100644 k8s/vpa.yaml diff --git a/k8s/README.md b/k8s/README.md new file mode 100644 index 0000000..6639e1a --- /dev/null +++ b/k8s/README.md @@ -0,0 +1,491 @@ +# UnitForge Raspberry Pi Kubernetes Deployment + +Lightweight Kubernetes deployment optimized for Raspberry Pi 5 clusters. + +## 🍓 Pi Cluster Requirements + +### Hardware +- **Raspberry Pi 5** (4GB+ RAM recommended) +- **SD Card**: 32GB+ Class 10 or better +- **Network**: Gigabit Ethernet preferred +- **Power**: Official Pi 5 power supply + +### Software +- **OS**: Raspberry Pi OS 64-bit or Ubuntu 22.04 LTS +- **Kubernetes**: 1.25+ (k3s recommended for Pi) +- **Container Runtime**: containerd or Docker +- **Ingress**: NGINX Ingress Controller + +## 📁 Simplified Structure + +``` +k8s/ +├── namespace.yaml # Dedicated namespace +├── configmap.yaml # Application configuration +├── deployment.yaml # Single replica deployment +├── service.yaml # ClusterIP service +├── ingress.yaml # Local domain ingress +└── vpa.yaml # Vertical Pod Autoscaler for Pi +``` + +**Simple kubectl deployment** - No kustomize, scripts, or complex tooling required! + +## 🚀 Quick Deployment + +### Apply All Resources +```bash +# Create namespace (optional) +kubectl create namespace unitforge + +# Apply all resources to specific namespace +kubectl apply -f k8s/ -n unitforge + +# Or apply to default namespace +kubectl apply -f k8s/ + +# Check status +kubectl get all -n unitforge +``` + +### Step-by-Step Deploy +```bash +# Create namespace (optional) +kubectl create namespace unitforge + +# Apply resources in order +kubectl apply -f k8s/namespace.yaml +kubectl apply -f k8s/configmap.yaml -n unitforge +kubectl apply -f k8s/deployment.yaml -n unitforge +kubectl apply -f k8s/service.yaml -n unitforge +kubectl apply -f k8s/ingress.yaml -n unitforge +kubectl apply -f k8s/vpa.yaml -n unitforge +``` + +## 🔧 Pi Optimizations + +### Resource Limits +- **Memory**: 128Mi request, 256Mi limit (VPA optimized) +- **CPU**: 100m request, 300m limit (VPA optimized) +- **Workers**: 2 (down from 4) +- **Replicas**: 1 (sufficient for Pi cluster) +- **VPA**: Enabled for automatic resource optimization + +### Simplified Configuration +- **No HPA**: Single replica, manual scaling +- **No TLS**: HTTP only for simplicity +- **No NetworkPolicy**: Simplified networking +- **No Kustomize**: Standard kubectl commands only +- **Basic probes**: Longer timeouts for Pi performance +- **Minimal metrics**: Disabled to save resources + +### Local Domains +- `unitforge.local` - Primary access +- `unitforge.pi` - Alternative domain + +## 🌐 Access Setup + +### Add to /etc/hosts +```bash +# Replace with your Pi node IP +echo " unitforge.local" >> /etc/hosts +echo " unitforge.pi" >> /etc/hosts +``` + +### Get Node IP +```bash +# Find your Pi node IP +kubectl get nodes -o wide + +# Or get ingress IP +kubectl get ingress unitforge -n unitforge +``` + +### Access Methods +```bash +# Browser access +http://unitforge.local +http://unitforge.pi + +# Port forwarding +kubectl port-forward service/unitforge 8080:80 -n unitforge +# Then: http://localhost:8080 + +# Direct pod access +kubectl port-forward pod/ 8080:8000 -n unitforge +``` + +## 📊 Pi Cluster Management + +### Check Deployment +```bash +# Overall status (replace unitforge with your namespace) +kubectl get all -n unitforge + +# Pod details +kubectl describe pod -l app=unitforge -n unitforge + +# Logs +kubectl logs -f deployment/unitforge -n unitforge + +# Resource usage +kubectl top pods -n unitforge + +# If using current namespace, omit -n flag +kubectl get all +kubectl logs -f deployment/unitforge +``` + +### Common Operations +```bash +# Restart deployment (adjust namespace as needed) +kubectl rollout restart deployment/unitforge -n unitforge + +# Scale (if needed) +kubectl scale deployment unitforge --replicas=2 -n unitforge + +# Update image +kubectl set image deployment/unitforge unitforge=new-image:tag -n unitforge + +# Delete everything +kubectl delete namespace unitforge +# Or if using default namespace +kubectl delete -f k8s/ +``` + +### Troubleshooting +```bash +# Check events (adjust namespace as needed) +kubectl get events -n unitforge --sort-by='.lastTimestamp' + +# Pod shell access +kubectl exec -it deployment/unitforge -n unitforge -- /bin/bash + +# Check node resources +kubectl describe node + +# Check disk space +kubectl exec -it deployment/unitforge -n unitforge -- df -h + +# For current namespace, omit -n flag +kubectl get events --sort-by='.lastTimestamp' +kubectl exec -it deployment/unitforge -- /bin/bash +``` + +## 🤖 Vertical Pod Autoscaler (VPA) + +### VPA Benefits for Pi Clusters +- **Automatic optimization**: Adjusts resource requests based on actual usage +- **Pi hardware awareness**: Conservative limits for ARM64 architecture +- **Memory efficiency**: Critical for Pi nodes with limited RAM +- **Cost optimization**: Right-sizing for Pi cluster resources + +### VPA Configuration +```bash +# Check if VPA is installed +kubectl get crd verticalpodautoscalers.autoscaling.k8s.io + +# Apply VPA configuration +kubectl apply -f vpa.yaml -n unitforge + +# Monitor VPA recommendations +kubectl get vpa unitforge-vpa -n unitforge +kubectl describe vpa unitforge-vpa -n unitforge + +# Check current pod resources +kubectl get pods -l app=unitforge -n unitforge -o wide +kubectl top pods -l app=unitforge -n unitforge +``` + +### VPA Resource Bounds (Pi Optimized) +```yaml +# CPU bounds for Pi 5 +minAllowed: + cpu: 50m # Minimal baseline + memory: 64Mi # Absolute minimum +maxAllowed: + cpu: 500m # Conservative Pi 5 limit + memory: 512Mi # Safe for 4-8GB Pi +``` + +### Installing VPA on Pi Cluster +```bash +# Install VPA components (if not already installed) +kubectl apply -f https://github.com/kubernetes/autoscaler/releases/latest/download/vpa-release.yaml + +# Verify VPA installation +kubectl get pods -n kube-system | grep vpa + +# Check VPA CRDs +kubectl get crd | grep verticalpodautoscaler +``` + +### VPA Management Commands +```bash +# Check VPA status +kubectl get vpa unitforge-vpa -n unitforge -o wide + +# Apply VPA to unitforge namespace +kubectl apply -f vpa.yaml -n unitforge + +# Monitor resource usage +kubectl top pods -l app=unitforge -n unitforge +kubectl describe pods -l app=unitforge -n unitforge + +# Restart deployment to apply recommendations +kubectl rollout restart deployment/unitforge -n unitforge + +# Delete VPA if needed +kubectl delete vpa unitforge-vpa -n unitforge +``` + +### VPA Monitoring +```bash +# View VPA recommendations +kubectl describe vpa unitforge-vpa -n unitforge + +# Check current vs recommended resources +kubectl get vpa unitforge-vpa -n unitforge -o yaml + +# Monitor pod resource usage +kubectl top pods -l app=unitforge -n unitforge --containers + +# Pi-specific monitoring +vcgencmd measure_temp # Pi temperature +htop # System resources +iostat -x 1 5 # I/O performance + +# Simple VPA status check +kubectl get vpa -n unitforge +``` + +## 🔧 Configuration + +### Environment Variables (ConfigMap) +```yaml +# Key Pi-optimized settings +WORKERS: "2" # Reduced for Pi +MAX_CONNECTIONS: "50" # Lower limit +REQUEST_TIMEOUT: "60" # Longer for Pi +ENABLE_API_METRICS: "false" # Disabled to save resources +COMPRESS_RESPONSES: "true" # Reduce bandwidth +``` + +### Resource Tuning +```yaml +# For Pi 4 (4GB) - reduce further +resources: + requests: + memory: "96Mi" + cpu: "50m" + limits: + memory: "192Mi" + cpu: "200m" + +# For Pi 5 (8GB) - can increase +resources: + requests: + memory: "256Mi" + cpu: "200m" + limits: + memory: "512Mi" + cpu: "500m" +``` + +## 🍓 Pi-Specific Tips + +### Performance +- **Use fast SD cards**: Class 10, U3, or A1/A2 rated +- **Enable cgroups**: Add to `/boot/cmdline.txt`: + ``` + cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory + ``` +- **Increase swap**: For memory-constrained Pis +- **Use SSD**: Boot from SSD for better I/O performance + +### Networking +- **Use wired connections**: Ethernet preferred over WiFi +- **Local DNS**: Consider Pi-hole for local resolution +- **MetalLB**: For LoadBalancer services in bare metal + +### Storage +- **EmptyDir volumes**: Used for temporary files +- **Local storage**: Consider local-path-provisioner +- **NFS**: For shared storage across Pi nodes + +## 🔍 Monitoring on Pi + +### Basic Monitoring +```bash +# Node resources +kubectl top nodes + +# Pod resources (adjust namespace as needed) +kubectl top pods -n unitforge +# Or current namespace +kubectl top pods + +# System resources on Pi +htop +iostat +free -h +df -h +``` + +### Simple Metrics +```bash +# Application health +curl http://unitforge.local/health + +# Basic load test +for i in {1..10}; do + curl -s http://unitforge.local/health > /dev/null + echo "Request $i completed" +done + +```bash +# VPA resource monitoring +kubectl get vpa -n unitforge +kubectl describe vpa unitforge-vpa -n unitforge + +# Watch VPA recommendations +watch kubectl describe vpa unitforge-vpa -n unitforge +``` + +## 🚨 Common Pi Issues + +### Memory Pressure +```bash +# Check memory usage +kubectl describe node + +# Check pod memory usage +kubectl top pods -n unitforge + +# Check VPA recommendations +kubectl describe vpa unitforge-vpa -n unitforge + +# Apply VPA recommendations +kubectl rollout restart deployment/unitforge -n unitforge + +# Reduce resource requests manually if needed +# Edit deployment.yaml resources section +``` + +### Storage Full +```bash +# Check disk usage (adjust namespace as needed) +kubectl exec -it deployment/unitforge -n unitforge -- df -h + +# Clean Docker images on nodes +docker system prune -f +``` + +### Slow Performance +```bash +# Check I/O wait +iostat -x 1 5 + +# Consider moving to SSD +# Check SD card health +``` + +### Network Issues +```bash +# Check ingress controller +kubectl get pods -n ingress-nginx + +# Test internal networking (adjust namespace as needed) +kubectl exec -it deployment/unitforge -n unitforge -- wget -qO- http://unitforge/health + +# Test service connectivity +kubectl exec -it deployment/unitforge -n unitforge -- wget -qO- http://unitforge.unitforge.svc.cluster.local/health +``` + +## 📚 Standard Kubernetes Workflows + +### Deployment Management +```bash +# Check deployment status +kubectl rollout status deployment/unitforge -n unitforge + +# View deployment history +kubectl rollout history deployment/unitforge -n unitforge + +# Rollback deployment +kubectl rollout undo deployment/unitforge -n unitforge + +# Restart deployment +kubectl rollout restart deployment/unitforge -n unitforge +``` + +### Configuration Updates +```bash +# Update configmap +kubectl apply -f k8s/configmap.yaml -n unitforge + +# Force pod restart to pick up config changes +kubectl rollout restart deployment/unitforge -n unitforge + +# Edit configmap directly +kubectl edit configmap unitforge-config -n unitforge +``` + +### Resource Management +```bash +# Scale deployment +kubectl scale deployment unitforge --replicas=2 -n unitforge + +# VPA-based resource optimization +kubectl apply -f vpa.yaml -n unitforge +kubectl rollout restart deployment/unitforge -n unitforge + +# Manual resource updates (if VPA not used) +kubectl patch deployment unitforge -n unitforge -p '{"spec":{"template":{"spec":{"containers":[{"name":"unitforge","resources":{"limits":{"memory":"512Mi"}}}]}}}}' + +# Get resource usage and VPA recommendations +kubectl top pods -n unitforge +kubectl describe vpa unitforge-vpa -n unitforge +kubectl describe deployment unitforge -n unitforge +``` + +## 📚 Pi Cluster Resources + +### K3s Installation +```bash +# Master node +curl -sfL https://get.k3s.io | sh - + +# Worker nodes +curl -sfL https://get.k3s.io | K3S_URL=https://:6443 K3S_TOKEN= sh - +``` + +### Useful Pi Tools +- **k3s**: Lightweight Kubernetes for Pi +- **kubectl**: Standard Kubernetes CLI (no kustomize needed) +- **k9s**: Terminal UI for Kubernetes +- **htop**: System monitoring +- **vcgencmd**: Pi-specific commands + +## 🎯 Production on Pi + +### High Availability +- **Multiple Pi nodes**: 3+ for redundancy +- **Shared storage**: NFS or distributed storage +- **Load balancing**: MetalLB or external LB +- **Backup strategy**: Regular etcd backups + +### Security +- **Network segmentation**: VLANs for cluster traffic +- **Firewall rules**: iptables or ufw configuration +- **Regular updates**: Keep Pi OS and k3s updated +- **Monitoring**: Basic Prometheus setup + +### Scaling +- **Horizontal**: Add more Pi nodes +- **Vertical**: Upgrade to Pi 5 with more RAM +- **Storage**: Add USB SSDs for better performance +- **Network**: Ensure gigabit switches + +--- + +**UnitForge on Pi** - Making systemd management portable! 🍓🚀 diff --git a/k8s/configmap.yaml b/k8s/configmap.yaml new file mode 100644 index 0000000..89b313e --- /dev/null +++ b/k8s/configmap.yaml @@ -0,0 +1,58 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: unitforge-config + labels: + app: unitforge + component: config +data: + # Application Information + APP_NAME: "UnitForge" + APP_VERSION: "1.0.0" + APP_DESCRIPTION: "Create, validate, and manage systemd unit files" + + # Server Configuration + HOST: "0.0.0.0" + PORT: "8000" + DEBUG: "false" + ENVIRONMENT: "production" + LOG_LEVEL: "info" + RELOAD: "false" + WORKERS: "2" + + # API Configuration + DOCS_URL: "/api/docs" + REDOC_URL: "/api/redoc" + + # CORS Configuration + CORS_ORIGINS: "*" + + # File Upload Settings + MAX_UPLOAD_SIZE: "2097152" + ALLOWED_EXTENSIONS: "['.service', '.timer', '.socket', '.mount', '.target', '.path']" + + # Feature Flags + ENABLE_API_METRICS: "false" + ENABLE_REQUEST_LOGGING: "true" + ENABLE_TEMPLATE_CACHING: "true" + ENABLE_VALIDATION_CACHING: "true" + + # Performance Settings (optimized for Pi) + REQUEST_TIMEOUT: "60" + KEEPALIVE_TIMEOUT: "10" + MAX_CONNECTIONS: "50" + + # Monitoring + HEALTH_CHECK_ENABLED: "true" + METRICS_ENABLED: "false" + + # Asset Optimization + MINIFY_ASSETS: "true" + COMPRESS_RESPONSES: "true" + HOT_RELOAD: "false" + SOURCE_MAPS: "false" + + # Documentation + API_DOCS_ENABLED: "true" + SWAGGER_UI_ENABLED: "true" + REDOC_ENABLED: "true" diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml new file mode 100644 index 0000000..8198044 --- /dev/null +++ b/k8s/deployment.yaml @@ -0,0 +1,74 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: unitforge + labels: + app: unitforge + component: webapp +spec: + replicas: 1 + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + selector: + matchLabels: + app: unitforge + template: + metadata: + labels: + app: unitforge + component: webapp + spec: + containers: + - name: unitforge + image: gitea-http.taildb3494.ts.net/will/unitforge:latest + imagePullPolicy: Always + ports: + - name: http + containerPort: 8000 + protocol: TCP + env: + - name: HOST + value: "0.0.0.0" + - name: PORT + value: "8000" + - name: DEBUG + value: "false" + - name: ENVIRONMENT + value: "production" + - name: LOG_LEVEL + value: "info" + - name: RELOAD + value: "false" + - name: WORKERS + value: "2" + envFrom: + - configMapRef: + name: unitforge-config + resources: + requests: + memory: "128Mi" + cpu: "100m" + limits: + memory: "256Mi" + cpu: "300m" + livenessProbe: + httpGet: + path: /health + port: http + initialDelaySeconds: 60 + periodSeconds: 30 + timeoutSeconds: 10 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /health + port: http + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + restartPolicy: Always + terminationGracePeriodSeconds: 30 diff --git a/k8s/ingress.yaml b/k8s/ingress.yaml new file mode 100644 index 0000000..9fa53fc --- /dev/null +++ b/k8s/ingress.yaml @@ -0,0 +1,27 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: unitforge + labels: + app: unitforge + component: ingress + annotations: + kubernetes.io/ingress.class: "nginx" + nginx.ingress.kubernetes.io/rewrite-target: / + nginx.ingress.kubernetes.io/proxy-body-size: "5m" + nginx.ingress.kubernetes.io/proxy-connect-timeout: "10" + nginx.ingress.kubernetes.io/proxy-send-timeout: "30" + nginx.ingress.kubernetes.io/proxy-read-timeout: "30" +spec: + ingressClassName: nginx + rules: + - host: app.unitforge.192.168.153.243.nip.io + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: unitforge + port: + number: 8000 diff --git a/k8s/service.yaml b/k8s/service.yaml new file mode 100644 index 0000000..a81dee8 --- /dev/null +++ b/k8s/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: unitforge + labels: + app: unitforge + component: webapp +spec: + type: ClusterIP + ports: + - name: http + port: 8000 + targetPort: http + protocol: TCP + selector: + app: unitforge diff --git a/k8s/vpa.yaml b/k8s/vpa.yaml new file mode 100644 index 0000000..e39c505 --- /dev/null +++ b/k8s/vpa.yaml @@ -0,0 +1,29 @@ +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: unitforge-vpa + labels: + app: unitforge + component: vpa + platform: raspberry-pi +spec: + targetRef: + apiVersion: apps/v1 + kind: Deployment + name: unitforge + updatePolicy: + updateMode: "Auto" + minReplicas: 1 + resourcePolicy: + containerPolicies: + - containerName: unitforge + # Pi 5 optimized resource bounds + minAllowed: + cpu: 50m + memory: 64Mi + maxAllowed: + cpu: 500m # Conservative limit for Pi 5 + memory: 512Mi # Pi 5 can handle this but keep reasonable + # Controlled resource recommendations for Pi hardware + controlledResources: ["cpu", "memory"] + controlledValues: Requests