A modern Kubernetes job manager with multi-cluster support that allows you to create, monitor, and manage jobs from existing deployments across multiple EKS clusters.
- 🚀 Deployment-based Job Creation: Create Kubernetes jobs from existing deployment specifications
- 🌐 Multi-Cluster Management: Connect and manage multiple EKS clusters from a single interface
- 🔄 Cross-namespace Support: Work with deployments across different namespaces
- 🖥️ Modern Web Interface: Responsive web UI with dark mode support
- 📊 Real-time Logs: View job logs with proper formatting
- 🔍 Job Persistence: Track jobs created by Spawnr using Kubernetes labels
- 🗑️ Complete Job Management: Create, monitor, refresh status, and delete jobs with automatic pod cleanup
- 🔌 Cluster Connectivity Testing: Verify cluster connections before use
- 🔐 AWS IAM Integration: Uses IAM Roles for Service Accounts (IRSA) for secure EKS access
- 📋 Cluster Cards: Visual representation of configured clusters with status indicators
- 🔄 Easy Cluster Switching: Switch between local and remote EKS clusters seamlessly
- 🔒 Certificate Management: Automatic fetching and storage of cluster CA certificates
- 🌓 Dark Mode: Toggle between light and dark themes with persistent preferences
- 📑 Tabbed Interface: Separate tabs for Jobs and Cluster management
- ✅ Input Validation: Automatic sanitization of job names to meet Kubernetes requirements
- 🔔 Smart Notifications: Non-intrusive alerts that don't disrupt the layout
The fastest way to get started:
# Add the Helm repository
helm repo add spawnr https://jordanvanderlinden.github.io/spawnr/
helm repo update
# Install Spawnr
helm install spawnr spawnr/spawnr --namespace spawnr --create-namespace
# Access the UI
kubectl port-forward -n spawnr svc/spawnr 8080:80Then open http://localhost:8080 in your browser.
For production deployments with IRSA, see Kubernetes Deployment below.
- Go 1.25+
- Docker (for building images)
- kubectl configured with access to a Kubernetes cluster
- Helm 3+ (for Kubernetes deployment)
- AWS CLI (for EKS cluster management)
-
Clone the repository:
git clone https://github.com/jordanvanderlinden/spawnr.git cd spawnr -
Install dependencies:
go mod download
-
Run the application:
go run main.go
-
Access the web interface: Open http://localhost:8080 in your browser
-
Add the Helm repository:
helm repo add spawnr https://jordanvanderlinden.github.io/spawnr/ helm repo update
-
Install with default values:
# Create namespace kubectl create namespace spawnr # Install the Helm chart helm install spawnr spawnr/spawnr --namespace spawnr
-
Install with custom values:
# Create a values.yaml file with your configuration helm install spawnr spawnr/spawnr --namespace spawnr -f custom-values.yaml -
Configure IAM Role for Service Account (IRSA):
- Create an IAM role with EKS access permissions
- Set the role ARN in your values file or use
--set:helm install spawnr spawnr/spawnr \ --namespace spawnr \ --set serviceAccount.annotations."eks\.amazonaws\.io/role-arn"="arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME"
Or in
values.yaml:serviceAccount: annotations: eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME
-
Access the application:
# Port forward to access locally kubectl port-forward -n spawnr svc/spawnr 8080:80Then open http://localhost:8080 in your browser
For a complete list of configuration options, see helm/spawnr/values.yaml or run:
helm show values spawnr/spawnr# Build for production (multi-arch)
docker build --platform linux/amd64 -t spawnr:latest .
# Push to your registry
docker tag spawnr:latest YOUR_REGISTRY/spawnr:latest
docker push YOUR_REGISTRY/spawnr:latest- Select Cluster: Choose the cluster you want to work with (Local or remote EKS clusters)
- Select Namespace: Pick the namespace containing your deployments
- Select Deployment: Choose a deployment to base your job on
- Configure Job:
- Enter a job name (will be auto-sanitized if needed)
- Specify the command to run in the container
- Create Job: Click "Create Job" to launch your job
- Monitor Jobs:
- View all jobs created by Spawnr across namespaces
- Click "View Logs" to see job output
- Use "Refresh" to update job statuses
- Delete jobs when no longer needed (automatically cleans up pods)
- View Clusters: See all configured clusters with their status
- Test Connectivity: Click "Test Connection" to verify cluster access
- Add New Cluster:
- Click "Add New Cluster"
- Fill in the required information:
- Cluster Name: The actual EKS cluster name
- Friendly Name: Display name for the cluster
- Role ARN: AWS IAM role ARN for cluster access
- Endpoint URL: EKS cluster endpoint URL
- Certificate Authority (Optional): Base64-encoded CA cert (auto-fetched if not provided)
- Delete Cluster: Remove clusters you no longer need (Local cluster cannot be deleted)
Click the moon/sun icon in the navigation bar to toggle between light and dark modes. Your preference is automatically saved.
- Web Interface: Modern HTML/CSS/JavaScript frontend with Bootstrap 5.3
- API Server: Gin-based HTTP server with RESTful endpoints
- Kubernetes Client: Go client-go library for cluster interaction
- Multi-Cluster Manager: Handles switching between different Kubernetes contexts
- Job Controller: Manages job lifecycle, monitoring, and cleanup
- RBAC: Proper role-based access control for Kubernetes resources
- IRSA: IAM Roles for Service Accounts for secure AWS access
- Security Context: Non-root user with appropriate permissions
- TLS: Secure communication with Kubernetes API servers
- Image Security: Multi-stage builds with minimal attack surface
Jobs created by Spawnr are labeled with:
labels:
app.kubernetes.io/managed-by: spawnrThis allows Spawnr to track and display jobs across all namespaces, providing persistence between browser sessions.
GET /api/clusters- List all configured clustersPOST /api/clusters- Add a new clusterPOST /api/clusters/switch- Switch to a different clusterGET /api/clusters/:name- Get cluster informationDELETE /api/clusters/:name- Remove a cluster
GET /api/namespaces- List namespaces in the current clusterGET /api/deployments- List deployments in the current namespaceGET /api/deployments/:namespace/:name- Get deployment details
GET /api/jobs- List all jobs managed by Spawnr (across all namespaces)POST /api/jobs- Create a new jobGET /api/jobs/:namespace/:name- Get job detailsDELETE /api/jobs/:namespace/:name- Delete a job (and its pods)GET /api/jobs/:namespace/:name/logs- Get job logsGET /api/jobs/:namespace/:name/watch- Watch job events (SSE)
PORT: Server port (default: 8080)GIN_MODE: Gin mode (debug/release)POD_NAMESPACE: Current namespace (injected by Kubernetes)AWS_SDK_LOAD_CONFIG: Enable AWS SDK config loading (set to "true")AWS_EC2_METADATA_DISABLED: Control EC2 metadata access (set to "false")HOME: Home directory for AWS CLI cache (set to "/tmp" in container)
Key configuration options in helm/spawnr/values.yaml:
image:
repository: spawnr
pullPolicy: Always
tag: "latest"
serviceAccount:
create: true
annotations:
eks.amazonaws.com/role-arn: "" # Set your IAM role ARN here
rbac:
create: true
rules:
- apiGroups: [""]
resources: ["namespaces", "pods", "secrets"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list"]
- apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["get", "list", "create", "delete", "watch"]
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128MiRemote EKS clusters are stored as Kubernetes secrets with the label spawnr.io/cluster: "true":
apiVersion: v1
kind: Secret
metadata:
name: eks-cluster-name
namespace: spawnr
labels:
spawnr.io/cluster: "true"
type: Opaque
data:
cluster-name: <base64-encoded-cluster-name>
friendly-name: <base64-encoded-display-name>
endpoint: <base64-encoded-endpoint-url>
role-arn: <base64-encoded-iam-role-arn>
certificate-authority-data: <base64-encoded-ca-cert>spawnr/
├── main.go # Application entry point
├── go.mod # Go module definition
├── internal/
│ ├── handlers/
│ │ └── handlers.go # HTTP request handlers
│ ├── k8s/
│ │ └── client.go # Kubernetes client and multi-cluster logic
│ └── server/
│ └── server.go # HTTP server setup and routing
├── web/
│ ├── static/
│ │ └── app.js # Frontend JavaScript application
│ └── templates/
│ └── index.html # Main HTML template
├── helm/spawnr/ # Helm chart
│ ├── Chart.yaml
│ ├── values.yaml
│ └── templates/
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── rbac.yaml
│ ├── serviceaccount.yaml
│ └── hpa.yaml
├── Dockerfile # Production multi-stage build
└── README.md
# Build the binary
go build -o spawnr main.go
# Build Docker image for production
docker build --platform linux/amd64 -t spawnr:latest .
# Build and push to ECR (example)
docker build --platform linux/amd64 -t 123456789.dkr.ecr.us-east-1.amazonaws.com/spawnr:latest .
docker push 123456789.dkr.ecr.us-east-1.amazonaws.com/spawnr:latest# Run unit tests
go test ./...
# Run with verbose output
go test -v ./...
# Test with coverage
go test -cover ./...Spawnr requires the following Kubernetes permissions:
- Namespaces:
get,list,watch- To discover available namespaces - Deployments:
get,list- To read deployment specifications - Jobs:
get,list,create,delete,watch- To manage job lifecycle - Pods:
get,list,delete- To view logs and cleanup orphaned pods - Secrets:
get,list,watch,create,delete- To store cluster configurations
These are defined in the Helm chart's rbac.yaml template.
- Verify IRSA Configuration: Ensure your service account has the correct IAM role annotation
- Check AWS Permissions: The IAM role must have permissions to call EKS APIs
- Test Connectivity: Use the "Test Connection" button in the Clusters tab
- Check Logs: View pod logs with
kubectl logs -n spawnr deployment/spawnr
- Check RBAC: Ensure the service account has permissions to create jobs
- Verify Deployment: Make sure the source deployment exists in the selected namespace
- Review Logs: Check the job logs for container-specific errors
If you see TLS certificate errors:
- Provide the CA certificate when adding the cluster
- Or let Spawnr auto-fetch it (requires AWS CLI access)
- Check that the certificate-authority-data is stored in the cluster secret
This project uses GitHub Actions for automated releases and deployments:
When commits are pushed to master, the following happens automatically:
-
Semantic Release: Analyzes commit messages to determine version bump
feat:commits trigger minor version bump (e.g., 1.0.0 → 1.1.0)fix:commits trigger patch version bump (e.g., 1.0.0 → 1.0.1)BREAKING CHANGE:orfeat!:triggers major version bump (e.g., 1.0.0 → 2.0.0)
-
Docker Image Build & Push: Multi-architecture images built and pushed to GitHub Container Registry
- Tagged with version (e.g.,
ghcr.io/jordanvanderlinden/spawnr:1.2.3) - Tagged with
latest
- Tagged with version (e.g.,
-
Helm Chart Release: Chart packaged and published to GitHub Pages
- Chart version updated to match release version
- Available via Helm repository
This project follows Conventional Commits:
# Feature (minor version bump)
feat(clusters): add connectivity testing
# Bug fix (patch version bump)
fix(jobs): resolve pod cleanup issue
# Breaking change (major version bump)
feat!: redesign API endpoints
# Documentation, no release
docs: update installation guideFor more details, see CONTRIBUTING.md.
- Fork the repository
- Create a feature branch (
git checkout -b feat/amazing-feature) - Make your changes using conventional commits
- Add tests if applicable
- Commit your changes (
git commit -m 'feat: add some amazing feature') - Push to the branch (
git push origin feat/amazing-feature) - Open a Pull Request
See CONTRIBUTING.md for detailed guidelines.
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with Gin Web Framework
- Kubernetes client-go library
- Bootstrap 5.3 for the UI
- Font Awesome for icons