kforward is a lightweight, simple CLI tool designed to streamline local development for applications interacting with Kubernetes services. Built with Go, it allows you to easily access services running inside your cluster using their standard service names, without the hassle of managing multiple kubectl port-forward sessions.
Developing applications locally that need to communicate with services inside a Kubernetes cluster often involves friction:
- Tedious Port-Forwarding: Managing multiple
kubectl port-forwardcommands in separate terminals for each required service is cumbersome, error-prone, and doesn't scale well. - Configuration Changes: Hardcoding
localhost:PORTaddresses in local configurations is inconvenient and differs from how the application runs in the cluster. - Complex Alternatives: Tools like Telepresence or mirrord are powerful but can be complex to set up, require specific cluster configurations, or might be overkill for simply accessing internal services.
kforward aims to address these challenges by providing a simpler approach:
- π Simple & Reliable: Provides a straightforward local HTTP proxy interface while using the battle-tested
kubectl port-forwardfor the actual tunneling. - kubectl Automation: Automatically finds target pods and manages the lifecycle of required
kubectl port-forwardprocesses for specified services or entire namespaces. - π¦ Single Binary: The
kforwardtool itself is a single static Go binary, easy to install and run. (Note: Requireskubectlto be installed and available in your PATH). - π Use Native Service Names: Allows your local application to use standard Kubernetes service DNS names (e.g.,
my-service.my-namespace.svc.cluster.local) without code changes, just by configuring the proxy. - β Improved Developer Experience: Reduces the friction of managing port forwards manually, making local development against Kubernetes smoother and less error-prone.
By automating kubectl port-forward management behind a simple proxy, kforward helps developers focus on coding, reduce configuration errors, and maintain consistency between local and cluster environments.
- CLI Interface: Simple command-line interface to start the proxy and specify targets.
- Kubeconfig Autodetection: Automatically uses your currently configured
kubectlcontext. - Context Override: Supports specifying a Kubernetes context via the
--contextflag. - kubectl Process Management:
- Automatically finds ready pods for specified services.
- Starts
kubectl port-forwardprocesses in the background for required services/ports. - Manages and terminates these background
kubectlprocesses gracefully whenkforwardexits.
- Targeted Service Forwarding: Manages forwards for one or more specific services (
namespace/service-name). - Namespace-Wide Forwarding: Manages forwards for all non-headless services and their ports within a specified namespace.
- Local HTTP Proxy: Runs a local proxy server (default port
1080) that handles:- Standard HTTP requests.
- Dynamic Connection Routing: Routes incoming proxy requests to the correct background
kubectl port-forwardprocess based on the requested service name and port. - Configurable Proxy Port: Allows specifying a different local port for the HTTP proxy server using the
--portflag. - Status Check: Includes a
kforward statuscommand to view active port forwards managed by a runningkforward proxyinstance (connects to the proxy's admin server). - Configurable Admin Port: Allows specifying a different local port for the admin server using the
--admin-portflag on theproxycommand (default1081).
kforward runs as a local Go process that acts as a central manager and proxy. It uses client-go to query the Kubernetes API and os/exec to launch and manage kubectl port-forward processes. Your local application connects to the kforward proxy, which then routes traffic through the appropriate kubectl tunnel.
+------------------------------------------+ +--------------------------------+ +-------------------------+
| Your Local Machine | | Kubernetes Cluster | | Target Pod (in K8s) |
| | | | | |
| +----------------+ | | +-------------------------+ | | +-------------------+ |
| | Your Local App |--------------------->|----->| | kforward HTTP Proxy | | | | Your App's Backend| |
| | (e.g., my-app) | | | | (Go Process) | | | | (e.g., Port 8080) | |
| | Configured with| | | | Listens on :1080 | | | +---------^---------+ |
| | proxy settings | | | +-----------+-------------+ | | | kubectl tunnel|
| +----------------+ | | | | | | established |
| | | | Uses | +-----------+-----------+
| | | | manager to find | ^
| | | | local port map | |
| | | v | |
| | | +-----------+-------------+ | |
| +------------------+<-------------------|------| | kubectl port-fwd Proc 1 |<--+ K8s API Server |
| | localhost:10001 | Dials local port | | | (Background Process) |---| (Port Forward) |
| +------------------+ | | +-------------------------+ | |
| | | | |
| +------------------+ | | +-------------------------+ | |
| | localhost:10002 |<-------------------|------| | kubectl port-fwd Proc 2 |<--+ K8s API Server |
| +------------------+ | | | (Background Process) |---| (Port Forward) |
| ^ | | +-------------------------+ |
| | kforward Manager starts | +--------------------------------+
| | & manages these kubectl processes |
| | based on user flags. |
+------------------------------------------+
Key Components & Flow:
- kforward Application (Local Host):
- Runs directly on your machine (
./kforward). - Starts a local HTTP proxy server (e.g., on
localhost:1080). - Uses your
kubeconfigandclient-goto connect to the Kubernetes API Server to get service/pod information. - Based on the
--namespaceor--serviceflags, the Manager component identifies necessary port forwards. - For each required forward, the Manager launches a
kubectl port-forward pod/... <local-port>:<pod-port>command as a background process. It keeps track of which service/port maps to which local port (e.g.,10001,10002).
- Runs directly on your machine (
- Local Development Application (
my-app):- Your application that needs to talk to K8s services.
- Configured to use the kforward HTTP proxy (e.g., via
export http_proxy=http://localhost:1080). - Makes requests using the standard Kubernetes service DNS name (e.g.,
http://hello-app-service.default.svc.cluster.local).
- Request Handling:
- The request from
my-appis directed to the localkforwardproxy (localhost:1080). - The HTTP Proxy component receives the request.
- It identifies the target Kubernetes service (e.g.,
hello-app-service.default) and port (e.g., 80). - It asks the Manager for the local port that corresponds to this target (e.g.,
10001). - The proxy then dials the local port (
localhost:10001).
- It identifies the target Kubernetes service (e.g.,
- The background
kubectl port-forwardprocess listening onlocalhost:10001receives this connection. kubectlhandles the secure tunneling through the K8s API Server to the actual Pod (e.g.,hello-app-deployment-xxxx:8080).- The response travels back through the
kubectltunnel, to thekforwardproxy, and finally to yourmy-app.
- The request from
kforward statusCommand (Local Host):- You run
kforward statusin a separate terminal. - This command connects to the Admin HTTP server (e.g.,
localhost:1081) of the runningkforward proxyinstance. - The Admin server asks the Manager for the current list of active forwards.
- The
statuscommand receives this list and displays it in a table format.
- You run
This guide helps you install and run kforward locally to access services in your existing Kubernetes cluster using Homebrew.
1. Prerequisites:
- Homebrew: Must be installed on your macOS or Linux system. (Installation Guide)
kubectl: Required bykforwardto interact with your cluster. If you don't have it, Homebrew will install it automatically when you installkforward. You can verify yourkubectlinstallation afterwards withkubectl version --client.- A Kubernetes cluster: (e.g., Minikube, Kind, Docker Desktop K8s, or a remote cluster) accessible via your
kubectlconfiguration.
2. Install kforward using Homebrew:
-
Open your terminal and run the following commands:
# 1. Add the kforward Tap (only needed once) brew tap sanspareilsmyn/kforward # 2. Install kforward (this will also install kubectl if needed) brew install kforward
-
Updating kforward: To get the latest version in the future, run:
brew upgrade kforward
3. Deploy a Test Service (if needed):
- To test
kforward, you need a service running in your cluster. If you don't have one, you can deploy the examplehello-app:- Clone the
kforwardrepository (optional, just to get the example file):# You don't need the full source code just to run kforward if installed via brew # But you might want it for the examples git clone https://github.com/sanspareilsmyn/kforward.git cd kforward
- Apply the example manifest:
kubectl apply -f examples/hello-app.yaml [-n your-namespace]
- Clone the
- Verify the deployment and service are running:
kubectl get deployment hello-app-deployment [-n your-namespace] kubectl get service hello-app-service [-n your-namespace]
4. Run kforward:
- Start the proxy, specifying the target namespace or service(s). Keep this terminal running.
- Use
--contextif your desired cluster isn't the default. Find contexts withkubectl config get-contexts.# Example 1: Manage forwards for all services in 'default' namespace using 'docker-desktop' context kforward proxy --context docker-desktop --namespace default --port 1080# Example 2: Manage forward for only 'hello-app-service' in 'default' namespace kforward proxy --context docker-desktop --service default/hello-app-service --port 1080 - Watch the logs. You should see:
- Confirmation of the Kubernetes context being used.
- Messages indicating
kubectl port-forwardprocesses are being started (e.g.,Starting kubectl process: ...). - The HTTP Proxy server listening message (e.g.,
Starting HTTP proxy server on :1080).
5. Configure Your Client Environment:
- In a separate terminal, set the
http_proxyenvironment variables (lowercase recommended).# If kforward is running on port 1080 export http_proxy="http://localhost:1080"
- Alternatively (Command-Specific): Prefix your command directly:
http_proxy="http://localhost:1080" curl ... - Alternatively (curl direct flag): Use
curl -x http://localhost:1080 ...
- Alternatively (Command-Specific): Prefix your command directly:
6. Test the Connection:
- From the terminal where you set the proxy environment variables, use
curl(or your browser/application) to access the service using its Kubernetes DNS name.# Test hello-app-service (HTTP on service port 80 in default namespace) curl http://hello-app-service.default.svc.cluster.local # Test another service (replace names/ports/namespaces accordingly) # curl http://my-api.my-namespace.svc.cluster.local:8080
- Check the
kforwardlogs (first terminal) for activity:Received request,Rewriting request,DialContext called,Found local forward address,Successfully dialed. - You should receive the correct response in your
curlterminal (e.g., the "Hello, world!" message fromhello-app).
7. Stopping kforward:
- Go back to the first terminal (where
kforward proxyis running) and pressCtrl+C. kforwardshould log that it's stopping the proxy server and terminating the backgroundkubectlprocesses.- In the second terminal, unset the proxy environment variables if you used
export:unset http_proxy no_proxy
7. Check Forward Status (Optional):
- While the
kforward proxyis still running (in the first terminal), open a third terminal. - Run the
kforward statuscommand. If the admin server is running on a non-default port, specify it using--admin-port.# If admin server is running on the default port 1081 kforward status # If admin server is running on port 9091 (from Example 2 in Step 4) # kforward status --admin-port 9091
- This will connect to the proxy's admin server and display a table of active forwards (Namespace, Service Name, Service Port, Local Port). Example output:
Active kforward Port Forwards: NAMESPACE SERVICE NAME SERVICE PORT LOCAL PORT --------- ------------ ------------ ---------- default hello-app-service 80 10001
We welcome contributions! Please see CONTRIBUTING.md for details on how to contribute.
Licensed under the Apache License, Version 2.0. See LICENSE for the full license text.
