A simple and powerful tool for port forwarding to internal services and domain names accessible within a Kubernetes cluster, without requiring any setup or modifications on the cluster itself.
Perfect for accessing cluster-internal resources locally:
- Database Access: Connect to RDS instances or databases that are only accessible within your EKS/GKE cluster
- Internal Services: Access microservices that don't have public endpoints
- Development & Debugging: Test and debug applications that depend on cluster-internal resources
When you DON'T need this tool:
- If you already have a VPN solution that makes internal domain names available on your local machine
Download the latest binary from the Release Page
See the Build from Source section below.
- kubectl CLI: Must be installed and configured to access your target Kubernetes cluster
- Cluster Access: The tool uses your current kubectl context/cluster configuration
Get help and see all available options:
kportfwd --helpYou can use kportfwd in two ways: with a configuration file or with command line options.
Run with a configuration file:
kportfwd --config /path/to/config.yamlRun with command line options (no config file needed):
# port forward multiple address (comma separated)
kportfwd -t pod/app=backend -n default -c service -f "postgres:5432,rabbitmq:5672,{{.REDIS_HOST}}:{{.REDIS_PORT}}"Run with elevated permissions (recommended):
sudo kportfwd --config /path/to/config.yamlπ‘ Why sudo?
- Updates
/etc/hostsso you can access internal services by name- Adds virtual IP addresses to your network interface. This lets you run multiple services on the same port (like having two databases both on port 5432, but using different IPs representing different host names)
To avoid typing your password every time, you can configure sudo to not require a password for kportfwd:
Setup (one-time only):
# Edit sudoers file safely
sudo visudo -f /etc/sudoers.d/kportfwdAdd one of these lines to the file:
# For your specific user (replace 'username' with your actual username):
username ALL=(root) NOPASSWD: /usr/local/bin/kportfwd
# Or for all admin users:
%admin ALL=(root) NOPASSWD: /usr/local/bin/kportfwdAfter setup, run without password prompts:
sudo kportfwd --config config.yaml # No password required!π Security Note: This is safe because it only applies to the specific
kportfwdbinary path. Make sure the path matches where you installed kportfwd (usewhich kportfwdto check).
Create a YAML configuration file that defines your port forwarding rules:
# Target pod configuration - where the forwarder agent will be deployed
target:
pod:
labelSelector: "app=backend,!job-name" # Kubernetes label selector to find target pod
container: service # Container name within the pod
namespace: default # Kubernetes namespace
# Port forwarding rules
forwards:
- name: "redis-cache" # Optional: Human-readable name
localAddr: "localhost:6379" # Optional: Local binding address
sourceAddr: ":50001" # Optional: Port on forwarder agent (auto-assigned if empty)
targetAddr: "{{REDIS_HOST}}:{{REDIS_PORT}}" # Target address (supports Go templates)
- name: "postgres-db"
localAddr: "192.168.0.126:5432" # Creates network alias (requires sudo)
targetAddr: "internal.postgresql:5432" # Direct service address| Field | Required | Description |
|---|---|---|
target.pod.labelSelector |
β | Kubernetes label selector to identify the target pod |
target.pod.container |
β | Container name where the forwarder agent will run |
target.pod.namespace |
β | Kubernetes namespace to search for the pod |
forwards[].name |
β | Human-readable identifier for the forwarding rule |
forwards[].localAddr |
β | Local address to bind to (defaults to sourceAddr if empty) |
forwards[].sourceAddr |
β | Address on forwarder agent (auto-assigned port β₯50000 if empty) |
forwards[].targetAddr |
β | Final destination address within the cluster |
You can use Go template syntax to extract values from environment variables in the target pod:
targetAddr: "{{.SERVICE_NAME}}.{{.NAMESPACE}}.svc.cluster.local:{{.PORT}}"Available template functions:
{{.ENV_VAR_NAME}}- Access environment variable{{splitAt "string" "separator" index}}- Split string and get element at index
For simple use cases, you can use a minimal configuration:
target:
pod:
labelSelector: "app=backend"
container: service
namespace: default
forwards:
- targetAddr: "{{REDIS_HOST}}:{{REDIS_PORT}}" # Uses env vars from target pod
- targetAddr: "internal.postgresql:5432" # Direct service addressπ How it works: When
localAddrandsourceAddrare omitted, the tool automatically assigns available local IP addresses and ports.
The tool creates a multi-hop forwarding tunnel:
Local Machine β Target Pod (Forwarder Agent) β Cluster Service
:8080 :50001 internal.db:5432
- Agent Deployment: A lightweight forwarder agent is deployed to your target pod
- Tunnel Creation: Local traffic is forwarded to the agent via Kubernetes port-forwarding
- Internal Routing: The agent forwards traffic to internal cluster services/domains
- Seamless Access: Internal services become accessible on your local machine
make- Build automation tooldocker- Container runtime for building cross-platform binariesgo- Go programming language (for local installation)
Build for specific platforms:
# Build for macOS
make build-macos
# Build for Linux
make build-linuxInstall locally (macOS):
make install-macosπ Note: Make sure your Go binary directory (
$GOPATH/binor$HOME/go/bin) is in yourPATHenvironment variable.
# Clone the repository
git clone https://github.com/abdularis/kportfwd.git
cd kportfwd
# Build for your current platform
go build -o kportfwd ./cmd/portfwd
# Make it executable and move to PATH
chmod +x kportfwd
sudo mv kportfwd /usr/local/bin/