-
Notifications
You must be signed in to change notification settings - Fork 1.6k
KEP-5695: kubectl reverse port-forward #5697
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
KEP-5695: kubectl reverse port-forward #5697
Conversation
Add reverse port-forwarding capability to kubectl, enabling pods to connect to services running on the developer's local machine. This addresses kubernetes/kubernetes#20227 which has been open since 2016 with significant community interest. Signed-off-by: Willian Paixao <[email protected]>
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: willianpaixao The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
|
Welcome @willianpaixao! |
|
Hi @willianpaixao. Thanks for your PR. I'm waiting for a github.com member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces KEP-5695, which proposes adding reverse port-forwarding capability to kubectl port-forward. This feature would enable containers in Kubernetes pods to connect back to services running on a developer's local machine, similar to SSH's -R flag. This addresses a long-standing feature request from 2016 (issue #20227).
- Adds a new
--reverseflag tokubectl port-forwardfor reverse tunneling - Introduces protocol extensions to support bidirectional streaming between pods and local machines
- Includes comprehensive graduation criteria from alpha (v1.34) through GA (v1.36)
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
| keps/sig-cli/5695-kubectl-reverse-port-forward/kep.yaml | Defines KEP metadata including feature gates (KubectlReversePortForward), milestones, and basic metrics configuration |
| keps/sig-cli/5695-kubectl-reverse-port-forward/README.md | Comprehensive KEP documentation covering motivation, design details, test plans, graduation criteria, and production readiness considerations |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Detail required unit tests and existing test infrastructure. - Update E2E test requirements. - Update Graduation Criteria to include enabling existing test stubs. - Update Implementation History with test infrastructure preparation. Signed-off-by: Willian Paixao <[email protected]>
Signed-off-by: Willian Paixao <[email protected]>
|
@aojea all your comments, as well as Copilot's, were addressed. Thank you for the review, happy to keep the discussion open. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - Detection: New connection attempts fail with error: `reverse port-forward connection limit reached` | ||
| - Mitigations: This is intentional rate limiting to prevent resource exhaustion. User can | ||
| wait for existing connections to close, or adjust the limit if appropriate for their use case. | ||
| - Diagnostics: Metric `kubectl_portforward_reverse_connections_rejected_total{reason="limit"}` will increment. |
Copilot
AI
Nov 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The metric name referenced here (kubectl_portforward_reverse_connections_rejected_total) is not defined in the metrics list in kep.yaml (lines 44-49) or in the SLI section (lines 526-530). If this metric will be collected, it should be added to the metrics list in kep.yaml.
| kubectl port-forward pod-name 8080:80 | ||
|
|
||
| # New reverse port-forward syntax | ||
| kubectl port-forward --reverse pod-name 8080:80 | ||
| # or | ||
| kubectl port-forward -R pod-name 8080:80 | ||
|
|
||
| # Multiple ports (both forward and reverse) | ||
| kubectl port-forward --reverse pod-name 8080:80 9090:9000 | ||
| ``` | ||
|
|
||
| **Port Specification Semantics:** | ||
| - Forward mode (existing): `LOCAL_PORT:REMOTE_PORT` - local port forwards to remote port | ||
| - Reverse mode (new): `REMOTE_PORT:LOCAL_PORT` - remote port forwards to local port |
Copilot
AI
Nov 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential confusion in port specification semantics: The documentation states that in reverse mode REMOTE_PORT:LOCAL_PORT means "remote port forwards to local port", but this contradicts the user story examples where 8080:8080 is used symmetrically.
For example, line 132 shows kubectl port-forward --reverse mypod 8080:8080 with the comment "Those connections get tunneled back to your local machine's port 8080", which suggests the format is still LOCAL:REMOTE or at least ambiguous.
Please clarify the port specification format consistently throughout the document. If it truly reverses to REMOTE:LOCAL (like SSH -R), make this very clear in all examples and add a warning about the semantic change.
| kubectl port-forward pod-name 8080:80 | |
| # New reverse port-forward syntax | |
| kubectl port-forward --reverse pod-name 8080:80 | |
| # or | |
| kubectl port-forward -R pod-name 8080:80 | |
| # Multiple ports (both forward and reverse) | |
| kubectl port-forward --reverse pod-name 8080:80 9090:9000 | |
| ``` | |
| **Port Specification Semantics:** | |
| - Forward mode (existing): `LOCAL_PORT:REMOTE_PORT` - local port forwards to remote port | |
| - Reverse mode (new): `REMOTE_PORT:LOCAL_PORT` - remote port forwards to local port | |
| # Format: LOCAL_PORT:REMOTE_PORT (local port forwards to remote port in the pod) | |
| kubectl port-forward pod-name 8080:80 | |
| # New reverse port-forward syntax | |
| # Format: REMOTE_PORT:LOCAL_PORT (remote port in the pod forwards to local port on your machine) | |
| kubectl port-forward --reverse pod-name 8080:80 | |
| # or | |
| kubectl port-forward -R pod-name 8080:80 | |
| # Multiple ports (reverse mode) | |
| # Format: REMOTE_PORT1:LOCAL_PORT1 REMOTE_PORT2:LOCAL_PORT2 ... | |
| kubectl port-forward --reverse pod-name 8080:80 9090:9000 |
⚠️ WARNING:
In reverse mode (--reverseor-R), the port specification format is reversed compared to forward mode.
- Forward mode:
LOCAL_PORT:REMOTE_PORT(local → pod)- Reverse mode:
REMOTE_PORT:LOCAL_PORT(pod → local)
This is similar to SSH's-Rflag, but can be confusing if you are used to the defaultkubectl port-forwardsyntax.
Double-check your port order when using reverse mode to avoid unexpected behavior!
Port Specification Semantics:
- Forward mode (existing):
LOCAL_PORT:REMOTE_PORT— local port forwards to remote port in the pod - Reverse mode (new):
REMOTE_PORT:LOCAL_PORT— remote port in the pod forwards to local port on your machine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be very honest I went back-and-forth with that in my mind while writing that, so it might be inconsistent.
What would be a good pattern?
| **4. Container Runtime Changes** (External repositories): | ||
|
|
||
| Changes required in container runtimes to support reverse port-forwarding: | ||
|
|
||
| **containerd** (`containerd/containerd`): | ||
| - Modify streaming server ([`internal/cri/streamingserver/server.go`](https://github.com/containerd/containerd/blob/main/internal/cri/streamingserver/server.go)) | ||
| - Add reverse port-forward handler endpoint | ||
| - Implement network namespace listener creation | ||
| - Handle bidirectional streaming for reverse connections | ||
|
|
||
| **cri-o** (`cri-o/cri-o`): | ||
| - Modify port forward implementation ([`server/container_portforward.go`](https://github.com/cri-o/cri-o/blob/main/server/container_portforward.go)) | ||
| - Add reverse mode support to port forward handler | ||
| - Implement listener in container network namespace | ||
| - Stream reverse connections back to kubelet | ||
|
|
||
| **Note**: This KEP requires coordinated changes across multiple projects (kubernetes, containerd, cri-o). Implementation will need agreement and collaboration from runtime maintainers. |
Copilot
AI
Nov 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistency: The flow diagram shows that kubelet creates the listener in the pod's network namespace (line 272), but the Implementation Overview section states this will be done using "native Go listeners" in the kubelet (line 230). However, the container runtime changes section (lines 240-256) indicates that containerd and cri-o need to implement this functionality. Please clarify which component is actually responsible for creating the listener in the pod's network namespace - is it kubelet or the container runtime?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Opsie, yeah, it makes sense, I'll take a closer look at it later.
|
|
||
| #### Story 3: Database Migration from Local Tools | ||
|
|
||
| As a database administrator, I want to run database migration tools from my local machine against a database pod without exposing the database outside the cluster, using a secure reverse tunnel. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: clarify that this is a schema update, not a data move
|
|
||
| 1. **Security Consideration**: Reverse port-forwarding exposes local services to remote pods. Users must understand the security implications and only use this feature in development/debugging scenarios. | ||
|
|
||
| 2. **Network Namespace**: The listening port is created in the pod's network namespace, accessible only to processes within that pod (not to other pods in the cluster). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we assuming that the Pod is running on a Linux node? Windows doesn't have network namespaces.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally have zero knowledge on Windows implementation, would need help on that to expand the KEP.
| - Handle incoming pod connections and stream them to kubectl | ||
| - Clean up listeners when kubectl disconnects | ||
|
|
||
| **3. Protocol Changes** (`pkg/kubelet/cri/streaming/portforward/`): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I want to deny reverse proxy and allow forward proxy, will I be able to write a policy (eg Rego) to enforce this?
The answer should be Yes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also good point, I should clarify that. Thanks.
| - Connection refused on local port | ||
| - Network namespace access failures | ||
| - Stream protocol errors | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the container runtime doesn't support this kind of proxying?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aojea raised this point so I've started to dig and create issues in the respective projects.
| # The following PRR answers are required at alpha release | ||
| # List the feature gate name and the components for which it must be enabled | ||
| feature-gates: | ||
| - name: KubectlReversePortForward |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This name implies that the client is kubectl. It can be but doesn't have to be. I would rename the feature gate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I didn't consider other clients. Before renaming, do you think this KEP belongs to SIG-CLI or SIG-NODE?
|
|
||
| - **Step 8**: Verify pod and network connectivity: | ||
|
|
||
| ```bash |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: the script is not valid bash
| - **Step 9**: If all else fails, disable the feature and use forward port-forward | ||
| to verify base functionality: | ||
|
|
||
| ```bash |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: the script is not valid bash
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sorry, can you be more specific? The syntax is valid.
Is it because I've omitted the launch of the nginx container?
| Extend API server to proxy connections between pods and external endpoints. | ||
|
|
||
| **Rejected because**: API server should not be in the data path for debugging tools. This is a kubectl/kubelet concern. | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could also launch an ephemeral container to achieve this aim.
What type of PR is this?
/kind kep
What this PR does / why we need it:
Adds KEP for reverse port-forwarding in kubectl, addressing long-standing issue kubernetes/kubernetes#20227.
Which issue(s) this PR fixes:
Fixes #5695
Addresses kubernetes/kubernetes#20227
Special notes for your reviewer:
This KEP proposes adding `--reverse` flag to `kubectl port-forward` to enable
reverse tunneling (pod → local machine), similar to SSH's `-R` flag.
This has been a requested feature since 2016 and received a PoC implementation
in 2017 (PR kubernetes/kubernetes#57320) that was deferred pending SPDY deprecation.
/sig cli
/sig node