fwkeeper
Port forwarding made easy. A Kubernetes port forwarding tool that automatically maintains persistent port forwards to pods with automatic reconnection and failure recovery.
Features
- π Automatic Port Forwarding: Maintains persistent port forwards to Kubernetes pods
- π Automatic Reconnection: Automatically reconnects on pod restarts or connection failures
- βοΈ Easy Configuration: CUE-based configuration for simple pod forwarding setup
- π Structured Logging: Comprehensive logging with configurable levels and pretty-printing
- π Kubernetes Integration: Seamless integration with your Kubernetes cluster (local or in-cluster)
- π Multiple Forwards: Support for multiple simultaneous port forwards
Installation
Prerequisites
- Go 1.25.1 or later
- Access to a Kubernetes cluster (local kubeconfig or in-cluster)
- kubectl configured (for cluster access)
Build from Source
git clone <repository-url>
cd fwkeeper
go build -o fwkeeper ./
The binary will be created as fwkeeper in the current directory.
Quick Start
1. Create a Configuration File
Create a fwkeeper.cue file:
logs: {
level: "debug"
pretty: true
}
forwards: [
{
name: "postgres"
ports: ["5432"]
namespace: "default"
resource: "postgres-pod"
},
{
name: "api"
ports: ["8080:8080", "9000:9000"]
namespace: "api"
resource: "api-server-deployment-abc123"
}
]
2. Run fwkeeper
./fwkeeper run -c fwkeeper.cue
Or using the default fwkeeper.cue:
./fwkeeper run
3. Access Your Services
The port forwards are now active. Connect to your services:
# Connect to postgres
psql -h localhost -p 5432
# Connect to API
curl http://localhost:8080
Configuration
fwkeeper uses CUE for configuration validation and schema enforcement.
Top-Level Structure
logs: { ... }
forwards: [ ... ]
Logs Configuration
logs: {
level: "debug" # "error", "warn", "info", "debug", "trace" (default: "info")
pretty: true # Pretty-print logs to console (default: false)
}
Port Forward Configuration
forwards: [
{
name: "service-name" # Unique identifier for this forward
ports: ["8080", "9000:3000"] # Local:remote port mappings
namespace: "default" # Kubernetes namespace
resource: "pod-name" # Pod name to forward to
},
# ... more forwards
]
Port Mapping Syntax:
"8080" - Forward local port 8080 to pod port 8080
"8080:9000" - Forward local port 8080 to pod port 9000
Validation Rules:
- Port numbers must be between 1 and 65535
- Each forward must have a unique name
- Namespace and resource (pod name) must be specified
Environment Variables
# Override kubeconfig location
KUBECONFIG=/path/to/kubeconfig ./fwkeeper run
# Use default kubeconfig locations
# 1. $KUBECONFIG environment variable
# 2. ~/.kube/config
# 3. In-cluster config (if running inside Kubernetes)
Usage
Basic Commands
# Show help
./fwkeeper --help
# Run with default config (fwkeeper.cue)
./fwkeeper run
# Run with custom config file
./fwkeeper run -c /path/to/config.cue
# Show command help
./fwkeeper run --help
Exit and Shutdown
Press Ctrl+C to gracefully stop fwkeeper. It will:
- Cancel all active port forwards
- Close connections
- Print shutdown message
Examples
Example 1: Database Access
Forward to a PostgreSQL database pod:
logs: {
level: "info"
pretty: true
}
forwards: [
{
name: "database"
ports: ["5432"]
namespace: "databases"
resource: "postgres-primary"
}
]
Then connect:
psql -h localhost -p 5432 -U myuser -d mydb
Example 2: Development Environment
Forward multiple services for local development:
logs: {
level: "debug"
pretty: true
}
forwards: [
{
name: "api-server"
ports: ["8000:8000"]
namespace: "development"
resource: "api-server"
},
{
name: "frontend"
ports: ["3000:3000"]
namespace: "development"
resource: "frontend"
},
{
name: "postgres"
ports: ["5432:5432"]
namespace: "databases"
resource: "postgres-dev"
},
{
name: "redis"
ports: ["6379:6379"]
namespace: "databases"
resource: "redis-dev"
}
]
Example 3: Multiple Ports on Same Pod
Forward multiple ports from a single pod:
forwards: [
{
name: "api-services"
ports: ["8000:8000", "9000:9000", "5000:5000"]
namespace: "api"
resource: "api-pod"
}
]
Logging
Log Levels
- error: Only errors
- warn: Warnings and errors
- info: General information (default)
- debug: Detailed debugging information
- trace: Very detailed tracing information
Log Output
Logs are written to stderr. Each log entry includes:
- Timestamp (Unix milliseconds)
- Log level
- Message
- Error details (when applicable)
Pretty Printing
Enable pretty-printed logs for development:
logs: {
pretty: true
}
Output will include timestamps and color-coded levels for better readability.
Troubleshooting
"Pod not in running state"
The pod exists but isn't currently running. Check pod status:
kubectl get pods -n <namespace> <pod-name>
kubectl describe pod -n <namespace> <pod-name>
"Connection refused" or "Connection reset"
The pod restarted or the port-forward connection dropped. fwkeeper will automatically reconnect with exponential backoff (starting at 100ms, up to 30s). Check logs for details.
"Unable to connect to kubeconfig"
Verify your kubeconfig:
# Check KUBECONFIG env var
echo $KUBECONFIG
# Test cluster access
kubectl cluster-info
# Set correct kubeconfig
export KUBECONFIG=~/.kube/config
./fwkeeper run
Configuration Validation Errors
Verify your CUE configuration syntax and against the schema:
# Check for CUE syntax errors in your config file
# Ensure all fields match the required structure in schema.cue
Common issues:
- Missing required fields (name, ports, namespace, resource)
- Invalid port numbers (not 1-65535)
- Malformed port specifications (should be "port" or "local:remote")
Debug Logs
Enable debug logging to see detailed information:
logs: {
level: "debug"
pretty: true
}
Development
Project Structure
fwkeeper/
βββ cmd/ # CLI command definitions
β βββ root.go # Root command
β βββ run.go # Run command
βββ internal/
β βββ app/ # Application orchestration
β β βββ runner.go # Main runner and lifecycle management
β βββ bootstrap/ # Dependency injection setup
β βββ config/ # Configuration loading and validation
β β βββ schema.cue # CUE schema definition
β βββ forwarder/ # Port forwarding logic
β β βββ forwarder.go # Individual pod port forwarder
β βββ kubernetes/ # Kubernetes client setup
β βββ locator/ # Pod discovery and location
β β βββ locator.go # Pod/service locator implementations
β βββ logger/ # Logging setup
βββ main.go # Application entry point
βββ go.mod # Go module definition
βββ go.sum # Dependency checksums
βββ fwkeeper.cue # Default configuration
βββ README.md # This file
Building
# Build the binary
go build -o fwkeeper ./
# Build with version info
go build -ldflags="-X main.version=v1.0.0" -o fwkeeper ./
Running Tests
# Run all tests
go test ./...
# Run with verbose output
go test -v ./...
# Run specific test
go test -run TestName ./path/to/package
Code Quality
# Format code
go fmt ./...
# Run static analysis
go vet ./...
# Run golangci-lint (if installed)
golangci-lint run ./...
Dependencies
Key dependencies:
Architecture
Key Components
- Runner: Orchestrates port forwarders, manages context and graceful shutdown
- Forwarder: Implements individual pod port forwarding with automatic reconnection
- Config: CUE-based configuration parsing and validation
- Logger: Structured logging with zerolog
- Kubernetes Integration: Handles kubeconfig loading and client initialization
Port Forward Flow
- Read configuration from CUE file
- Load Kubernetes credentials
- For each forward:
- Locate the pod
- Verify pod is running
- Establish SPDY connection to pod
- Forward ports
- Reconnect on failure (exponential backoff: 100ms β 30s with jitter)
- Listen for interrupt signal (Ctrl+C)
- Gracefully shutdown all forwarders
License
This project is under MIT License
Support
For issues, questions, or contributions, please visit the repository.