Skip to content

Commit 35d022e

Browse files
committed
Update WebSocket KEP to reflect latest
1 parent a2fb02e commit 35d022e

File tree

2 files changed

+58
-96
lines changed

2 files changed

+58
-96
lines changed

keps/sig-api-machinery/4006-transition-spdy-to-websockets/README.md

Lines changed: 54 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,8 @@ tags, and then generate with `hack/update-toc.sh`.
9191
- [Background: <code>RemoteCommand</code> Subprotocol](#background--subprotocol)
9292
- [Background: API Server and Kubelet <code>UpgradeAwareProxy</code>](#background-api-server-and-kubelet-)
9393
- [Proposal: <code>kubectl</code> WebSocket Executor and Fallback Executor](#proposal--websocket-executor-and-fallback-executor)
94-
- [Proposal: <code>K8s-Websocket-Protocol: stream-translate</code> Header](#proposal--header)
94+
- [Proposal: New <code>RemoteCommand</code> Sub-Protocol Version - <code>v5.channel.k8s.io</code>](#proposal-new--sub-protocol-version---)
9595
- [Proposal: API Server <code>StreamTranslatorProxy</code>](#proposal-api-server-)
96-
- [Beta: Port Forward Subprotocol](#beta-port-forward-subprotocol)
9796
- [Pre-GA: Kubelet <code>StreamTranslatorProxy</code>](#pre-ga-kubelet-)
9897
- [Test Plan](#test-plan)
9998
- [Prerequisite testing updates](#prerequisite-testing-updates)
@@ -102,8 +101,7 @@ tags, and then generate with `hack/update-toc.sh`.
102101
- [e2e tests](#e2e-tests)
103102
- [Graduation Criteria](#graduation-criteria)
104103
- [Alpha](#alpha)
105-
- [Beta (RemoteCommand)](#beta-remotecommand)
106-
- [Beta (PortForward)](#beta-portforward)
104+
- [Beta](#beta)
107105
- [GA](#ga)
108106
- [Upgrade / Downgrade Strategy](#upgrade--downgrade-strategy)
109107
- [Version Skew Strategy](#version-skew-strategy)
@@ -187,8 +185,8 @@ Some Kubernetes clients need to communicate with the API Server using a bi-direc
187185
streaming protocol, instead of the standard HTTP request/response mechanism. A streaming
188186
protocol provides the ability to read and write arbitrary data messages between the
189187
client and server, instead of providing a single response to a client request.
190-
For example, the commands `kubectl exec`, `kubectl attach`, and `kubectl port-forward`
191-
all benefit from a bi-directional streaming protocol (`kubectl cp` is build on top
188+
For example, the commands `kubectl exec` and `kubectl attach`
189+
both benefit from a bi-directional streaming protocol (`kubectl cp` is build on top
192190
of `kubectl exec` primitives so it utilizes streaming as well). Currently,
193191
the bi-directional streaming solution for these `kubectl` commands is SPDY/3.1. For
194192
the communication leg between `kubectl` and the API Server, this enhancement transitions
@@ -226,14 +224,9 @@ know that this has succeeded?
226224
`kubectl exec`, `kubectl attach`, and `kubectl cp` for the communication leg
227225
between `kubectl` and the API Server.
228226

229-
2. Transition the bi-directional streaming protocol from SPDY/3.1 to WebSockets
230-
for `kubectl port-forward` for the communication leg between `kubectl` and the API
231-
Server (alpha in v1.29).
232-
233-
3. Extend the WebSockets communication leg from the API Server to Kubelet
234-
*before* the current leg goes GA (probably in v1.30). After this extension, WebSockets
235-
streaming will occur between `kubectl` and Kubelet (proxied through the API Server).
236-
This plan is described at [Pre-GA: Kubelet](#pre-ga-kubelet-).
227+
2. Extend the WebSockets communication leg from the API Server to Kubelet. After this
228+
extension, WebSockets streaming will occur between `kubectl` and Kubelet (proxied
229+
through the API Server). This plan is described at [Pre-GA: Kubelet](#pre-ga-kubelet-).
237230

238231
### Non-Goals
239232

@@ -291,14 +284,7 @@ Go in to as much detail as necessary here.
291284
This might be a good place to talk about core concepts and how they relate.
292285
-->
293286

294-
Initial work on the `PortForward` subprotocol over WebSockets will begin in the
295-
next release (v1.29). While the streaming `kubectl` commands are similar in the
296-
eyes of the users, the streamed data messages are significantly different. Work
297-
on moving the `PortForward` subprotocol to WebSockets from SPDY was started in 2017
298-
with the following [Support websockets from client portforwarding #50428](https://github.com/kubernetes/kubernetes/pull/50428)
299-
PR. But this PR was abandoned and closed when the author realized the significant
300-
scope of the effort. For this reason, we have staggered the development of the subprotocols
301-
by initially prioritizing the `RemoteCommand` subprotocol.
287+
N/A
302288

303289
### Risks and Mitigations
304290

@@ -400,7 +386,7 @@ proxy that knows how to deal with the connection upgrade handshake.
400386
### Proposal: `kubectl` WebSocket Executor and Fallback Executor
401387

402388
This enhancement proposes adding a `WebSocketExecutor` to `kubectl`, implementing
403-
the WebSocket client using the latest subprotocol version (`v4.channel.k8s.io`).
389+
the WebSocket client using a new subprotocol version (`v5.channel.k8s.io`).
404390
Additionally, we propose creating a `FallbackExecutor` to address client/server version
405391
skew. The `FallbackExecutor` first attempts to upgrade the connection with the
406392
`WebSocketExecutor`, then falls back to the legacy `SPDYExecutor`, if the upgrade is
@@ -417,14 +403,14 @@ affect the perceived performance.
417403
3. As releases increment, the probablity of a WebSocket enabled `kubectl` communicating
418404
with an older non-WebSocket enabled API Server decreases.
419405

420-
### Proposal: `K8s-Websocket-Protocol: stream-translate` Header
406+
### Proposal: New `RemoteCommand` Sub-Protocol Version - `v5.channel.k8s.io`
421407

422-
In addition to the current SPDY-based clients, there are other current WebSocket clients,
423-
including a javascript/browser-based client. In order to distinguish these older
424-
WebSocket clients from the new stream-translated WebSocket clients, we propose adding
425-
a new header `K8s-Websocket-Protocol: stream-translate`. As described further in the
426-
next `Proposal` section, this header allows newer clients to delegate to the
427-
`StreamTranslatorProxy` to translate WebSockets data messages to SPDY.
408+
The latest RemoteCommand version does not address an important protocol feature--a
409+
stream `CLOSE` signal. In order to communicate to another endpoint that the current
410+
stream of sending data is complete, a `CLOSE` signal is necessary. This problem
411+
currently arises when sending data over the STDIN stream, and it is more fully described
412+
in the following issue: [exec over web sockets protocol is flawed](https://github.com/kubernetes/kubernetes/issues/89899).
413+
A new RemoteCommand version (`v5.channel.k8s.io`) adds this `CLOSE` signal.
428414

429415
### Proposal: API Server `StreamTranslatorProxy`
430416

@@ -434,21 +420,11 @@ Currently, the API Server role within client/container streaming is to proxy the
434420
data stream using the `UpgradeAwareProxy`. This enhancement proposes to modify the
435421
SPDY data stream between `kubectl` and the API Server by conditionally adding a
436422
`StreamTranslatorProxy` at the API Server. If the request is for a WebSocket upgrade
437-
with the header `K8s-Websocket-Protocol: stream-translate`, the `UpgradeAwareProxy`
438-
will delegate to the `StreamTranslatorProxy`. This translation proxy terminates the
439-
WebSocket connection, and it de-multiplexes the various streams in order to pass the
440-
data on to a SPDY connection, which continues upstream (to Kubelet and eventually
441-
the container runtime).
442-
443-
### Beta: Port Forward Subprotocol
444-
445-
This KEP addresses only the `RemoteCommand` subprotocol, but the intent is to immediately
446-
follow on with a new `PortForward` subprotocol over WebSockets. Even though the subprotocols
447-
are completely different, in the eyes of the users, the `kubectl` streaming commands (`exec`,
448-
`attach`, `cp`, and `port-forward`) are very similar. Our plan is to go alpha for `RemoteCommand`
449-
in v1.28. For v1.29, we will create an alpha for `PortForward` and go beta for `RemoteCommand`.
450-
For v1.30, we will go beta for `PortForward`, and we will not go GA for either subprotocol
451-
unless both subprotocols are ready for GA.
423+
with the protocol request for `RemoteCommand: v5.channel.k8s.io` , the handler will
424+
delegate to the `StreamTranslatorProxy` instead of the `UpgradeAwareProxy`. This
425+
translation proxy terminates the WebSocket connection, and it de-multiplexes the
426+
various streams in order to pass the data on to a SPDY connection, which continues
427+
upstream (to Kubelet and eventually the container runtime).
452428

453429
### Pre-GA: Kubelet `StreamTranslatorProxy`
454430

@@ -459,8 +435,7 @@ the Kubelet. Both the API Server and the Kubelet stream data messages using the
459435
`UpgradeAwareProxy`. Since the initial plan is to modify the `UpgradeAwareProxy`
460436
in the API Server to delegate to the `StreamTranslatorProxy`, it will be straightforward
461437
to transition this next communication leg by moving the integrated `StreamTranslatorProxy`
462-
from the API Server to the Kubelet. This communication leg will upgraded to WebSockets
463-
*before* the first let goes GA.
438+
from the API Server to the Kubelet.
464439

465440
The final communication leg to transition from SPDY to WebSockets will be the one
466441
from Kubelet to the Container Runtimes. Since this communication happens within a
@@ -523,8 +498,20 @@ this SDPY to WebSockets migration.
523498
- `k8s.io/kubernetes/staging/src/k8s.io/kubectl/pkg/cmd/attach`: `2023-06-05` - `43.4%`
524499
- `k8s.io/kubernetes/staging/src/k8s.io/kubectl/pkg/cmd/cp`: `2023-06-05` - `66.3%`
525500
- `k8s.io/kubernetes/staging/src/k8s.io/kubectl/pkg/cmd/exec`: `2023-06-05` - `70.0%`
526-
- `k8s.io/kubernetes/staging/src/k8s.io/kubectl/pkg/cmd/portforward`: `2023-06-05` - `76.5%`
527501

502+
An important set of tests for this migration will be **loopback** tests, which exercise the
503+
WebSocket client and the StreamTranslator proxy. These tests create two test servers: a
504+
proxy server handling the stream translation, and a fake SPDY server which sends received data
505+
from one stream (e.g. stdin) back down another stream (e.g. stdout). These tests
506+
send random data from the WebSocket client to the StreamTranslator proxy, which then
507+
sends the data to the test SPDY server.
508+
509+
WebSocket client <-> Proxy Server (StreamTranslator) <-> SPDY Server
510+
511+
Once the data is received back at the WebSocket client on the separate stream, it
512+
is compared to the data that was sent to ensure the data is the same. These **loopback**
513+
tests have been implemented in a proof-of-concept PR, validating the various streams sent
514+
over the WebSocket connection by the client through the StreamTranslator proxy.
528515

529516
##### Integration tests
530517

@@ -546,19 +533,8 @@ https://storage.googleapis.com/k8s-triage/index.html
546533
547534
-->
548535

549-
An important integration test for this migration will be a **loopback** test, exercising the
550-
WebSocket client and the StreamTranslator proxy. This test creates two test servers: a
551-
proxy server handling the stream translation, and a SPDY server which sends received data
552-
from one stream (e.g. stdin) back down another stream (e.g. stdout). This test will
553-
send random data from the WebSocket client to the StreamTranslator proxy, which then
554-
sends the data to the test SPDY server.
555-
556-
WebSocket client <-> Proxy Server (StreamTranslator) <-> SPDY Server
557-
558-
Once the data is received back at the WebSocket client on the separate stream, it
559-
is compared to the data that was sent to ensure the data is the same. This **loopback**
560-
test has been implemented in a proof-of-concept PR, validating the WebSocket client
561-
and the StreamTranslator proxy.
536+
No integration tests are planned for alpha. Previously mentioned unit tests and current
537+
e2e tests provide sufficient.
562538

563539
##### e2e tests
564540

@@ -645,44 +621,29 @@ in back-to-back releases.
645621

646622
#### Alpha
647623

624+
- Implement the alpha version of the `RemoteCommand` subprotocol, and surface the new
625+
`kubectl exec`, `kubectl cp`, and `kubectl attach` behind a `kubectl` environment
626+
variable which is **OFF** by default.
648627
- `WebSocketExecutor` and `FallbackExecutor` completed and functional behind the `kubectl`
649628
environment variable KUBECTL_REMOTE_COMMAND_WEBSOCKETS which is **OFF** by default.
650629
- `StreamTranslatorProxy` successfully integrated into the `UpgradeAwareProxy`
651630
behind an API Server feature flag which is off by default.
652-
- Initial unit tests completed and enabled.
653-
- Initial integration tests completed and enabled.
654-
- Initial e2e tests completed and enabled.
655-
656-
#### Beta (RemoteCommand)
657-
658-
- `WebSocketExecutor` and `FallbackExecutor` completed and functional behind the `kubectl`
659-
environment variable KUBECTL_REMOTE_COMMAND_WEBSOCKETS which is **ON** by default.
660-
- `StreamTranslatorProxy` successfully integrated into the `UpgradeAwareProxy`
661-
behind an API Server feature flag which is **on** by default.
662-
- Implement the alpha version of the `PortForward` subprotocol, and surface the new
663-
`kubectl port-forward` behind a `kubectl` environment variable which is **OFF** by default.
664-
- `PortForwardProxy` successfully integrated into the `UpgradeAwareProxy`
665-
behind an API Server feature flag which is off by default.
666-
- Additional unit tests completed and enabled.
667-
- Additional integration tests completed and enabled.
668-
- Additional e2e tests completed and enabled.
631+
- Initial `exec`, `cp`, and `attach` unit tests completed and enabled.
632+
- Existing `exec`, `cp`, and `attach` integration tests continue to work.
633+
- Existing `exec`, `cp`, and `attach` e2e tests continue to work.
669634

670-
#### Beta (PortForward)
635+
#### Beta
671636

672-
- Implement the beta version of the `PortForward` subprotocol, and surface the new
673-
`kubectl port-forward` behind a `kubectl` environment variable which is **ON**
674-
by default.
675-
- `PortForwardProxy` successfully integrated into the `UpgradeAwareProxy`
676-
behind an API Server feature flag which is **on** by default.
677-
- Additional unit tests completed and enabled.
678-
- Additional integration tests completed and enabled.
679-
- Additional e2e tests completed and enabled.
637+
- Additional `exec`, `cp`, and `attach` unit tests completed and enabled.
638+
- Additional `exec`, `cp`, and `attach` integration tests completed and enabled.
639+
- Additional `exec`, `cp`, and `attach` e2e tests completed and enabled.
680640

681641
#### GA
682642

683-
- Conformance tests for `RemoteCommand` and `PortForward` completed and enabled.
684-
- Conformance tests for `RemoteCommand` and `PortForward` have been stable and
643+
- Conformance tests for `RemoteCommand` completed and enabled.
644+
- Conformance tests for `RemoteCommand` have been stable and
685645
non-flaky for two weeks.
646+
- Extend the WebSockets communication leg from the API Server to Kubelet.
686647

687648
### Upgrade / Downgrade Strategy
688649

@@ -723,11 +684,12 @@ This feature needs to take into account the following version skew scenarios:
723684
does not support the newer `StreamTranslator` proxy.
724685

725686
In this case, the initial upgrade request for `WebSockets/RemoteCommand` will
726-
fail, and the `FallbackExecutor` will follow up with a legacy upgrade request for
687+
fail, because the `WebSockets` upgrade request `v5.channel.k8s.io` will be proxied
688+
to the current container runtime which only supports up to version `v4.channel.k8s.io`.
689+
The `FallbackExecutor` will follow up with a subsequent legacy upgrade request for
727690
`SDPY/RemoteCommand`. The streaming functionality in this case will work exactly
728691
as it has for the last several years.
729692

730-
731693
2. A legacy non-WebSockets enabled `kubectl` communicating with a newer API Server that
732694
supports the newer `StreamTranslator` proxy.
733695

@@ -1159,7 +1121,7 @@ Major milestones might include:
11591121
- when the KEP was retired or superseded
11601122
-->
11611123

1162-
- First Kubernetes release where initial version of KEP available: v1.28
1124+
- First Kubernetes release where initial version of KEP available: v1.29
11631125

11641126
## Drawbacks
11651127

keps/sig-api-machinery/4006-transition-spdy-to-websockets/kep.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ stage: alpha
2121
# The most recent milestone for which work toward delivery of this KEP has been
2222
# done. This can be the current (upcoming) milestone, if it is being actively
2323
# worked on.
24-
latest-milestone: "v1.28"
24+
latest-milestone: "v1.29"
2525

2626
# The milestone at which this feature was, or is targeted to be, at each stage.
2727
milestone:
28-
alpha: "v1.28"
29-
beta: "v1.29"
30-
stable: "v1.30"
28+
alpha: "v1.29"
29+
beta: "v1.30"
30+
stable: "v1.31"
3131

3232
# The following PRR answers are required at alpha release
3333
# List the feature gate name and the components for which it must be enabled

0 commit comments

Comments
 (0)