@@ -91,9 +91,8 @@ tags, and then generate with `hack/update-toc.sh`.
91
91
- [ Background: <code >RemoteCommand</code > Subprotocol] ( #background--subprotocol )
92
92
- [ Background: API Server and Kubelet <code >UpgradeAwareProxy</code >] ( #background-api-server-and-kubelet- )
93
93
- [ 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--- )
95
95
- [ Proposal: API Server <code >StreamTranslatorProxy</code >] ( #proposal-api-server- )
96
- - [ Beta: Port Forward Subprotocol] ( #beta-port-forward-subprotocol )
97
96
- [ Pre-GA: Kubelet <code >StreamTranslatorProxy</code >] ( #pre-ga-kubelet- )
98
97
- [ Test Plan] ( #test-plan )
99
98
- [ Prerequisite testing updates] ( #prerequisite-testing-updates )
@@ -102,8 +101,7 @@ tags, and then generate with `hack/update-toc.sh`.
102
101
- [ e2e tests] ( #e2e-tests )
103
102
- [ Graduation Criteria] ( #graduation-criteria )
104
103
- [ Alpha] ( #alpha )
105
- - [ Beta (RemoteCommand)] ( #beta-remotecommand )
106
- - [ Beta (PortForward)] ( #beta-portforward )
104
+ - [ Beta] ( #beta )
107
105
- [ GA] ( #ga )
108
106
- [ Upgrade / Downgrade Strategy] ( #upgrade--downgrade-strategy )
109
107
- [ Version Skew Strategy] ( #version-skew-strategy )
@@ -187,8 +185,8 @@ Some Kubernetes clients need to communicate with the API Server using a bi-direc
187
185
streaming protocol, instead of the standard HTTP request/response mechanism. A streaming
188
186
protocol provides the ability to read and write arbitrary data messages between the
189
187
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
192
190
of ` kubectl exec ` primitives so it utilizes streaming as well). Currently,
193
191
the bi-directional streaming solution for these ` kubectl ` commands is SPDY/3.1. For
194
192
the communication leg between ` kubectl ` and the API Server, this enhancement transitions
@@ -226,14 +224,9 @@ know that this has succeeded?
226
224
` kubectl exec ` , ` kubectl attach ` , and ` kubectl cp ` for the communication leg
227
225
between ` kubectl ` and the API Server.
228
226
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- ) .
237
230
238
231
### Non-Goals
239
232
@@ -291,14 +284,7 @@ Go in to as much detail as necessary here.
291
284
This might be a good place to talk about core concepts and how they relate.
292
285
-->
293
286
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
302
288
303
289
### Risks and Mitigations
304
290
@@ -400,7 +386,7 @@ proxy that knows how to deal with the connection upgrade handshake.
400
386
### Proposal: ` kubectl ` WebSocket Executor and Fallback Executor
401
387
402
388
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` ).
404
390
Additionally, we propose creating a ` FallbackExecutor ` to address client/server version
405
391
skew. The ` FallbackExecutor ` first attempts to upgrade the connection with the
406
392
` WebSocketExecutor ` , then falls back to the legacy ` SPDYExecutor ` , if the upgrade is
@@ -417,14 +403,14 @@ affect the perceived performance.
417
403
3 . As releases increment, the probablity of a WebSocket enabled ` kubectl ` communicating
418
404
with an older non-WebSocket enabled API Server decreases.
419
405
420
- ### Proposal: ` K8s-Websocket- Protocol: stream-translate ` Header
406
+ ### Proposal: New ` RemoteCommand ` Sub- Protocol Version - ` v5.channel.k8s.io `
421
407
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 .
428
414
429
415
### Proposal: API Server ` StreamTranslatorProxy `
430
416
@@ -434,21 +420,11 @@ Currently, the API Server role within client/container streaming is to proxy the
434
420
data stream using the ` UpgradeAwareProxy ` . This enhancement proposes to modify the
435
421
SPDY data stream between ` kubectl ` and the API Server by conditionally adding a
436
422
` 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).
452
428
453
429
### Pre-GA: Kubelet ` StreamTranslatorProxy `
454
430
@@ -459,8 +435,7 @@ the Kubelet. Both the API Server and the Kubelet stream data messages using the
459
435
` UpgradeAwareProxy ` . Since the initial plan is to modify the ` UpgradeAwareProxy `
460
436
in the API Server to delegate to the ` StreamTranslatorProxy ` , it will be straightforward
461
437
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.
464
439
465
440
The final communication leg to transition from SPDY to WebSockets will be the one
466
441
from Kubelet to the Container Runtimes. Since this communication happens within a
@@ -523,8 +498,20 @@ this SDPY to WebSockets migration.
523
498
- ` k8s.io/kubernetes/staging/src/k8s.io/kubectl/pkg/cmd/attach ` : ` 2023-06-05 ` - ` 43.4% `
524
499
- ` k8s.io/kubernetes/staging/src/k8s.io/kubectl/pkg/cmd/cp ` : ` 2023-06-05 ` - ` 66.3% `
525
500
- ` 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% `
527
501
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.
528
515
529
516
##### Integration tests
530
517
@@ -546,19 +533,8 @@ https://storage.googleapis.com/k8s-triage/index.html
546
533
547
534
-->
548
535
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.
562
538
563
539
##### e2e tests
564
540
@@ -645,44 +621,29 @@ in back-to-back releases.
645
621
646
622
#### Alpha
647
623
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.
648
627
- ` WebSocketExecutor ` and ` FallbackExecutor ` completed and functional behind the ` kubectl `
649
628
environment variable KUBECTL_REMOTE_COMMAND_WEBSOCKETS which is ** OFF** by default.
650
629
- ` StreamTranslatorProxy ` successfully integrated into the ` UpgradeAwareProxy `
651
630
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.
669
634
670
- #### Beta (PortForward)
635
+ #### Beta
671
636
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.
680
640
681
641
#### GA
682
642
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
685
645
non-flaky for two weeks.
646
+ - Extend the WebSockets communication leg from the API Server to Kubelet.
686
647
687
648
### Upgrade / Downgrade Strategy
688
649
@@ -723,11 +684,12 @@ This feature needs to take into account the following version skew scenarios:
723
684
does not support the newer ` StreamTranslator ` proxy.
724
685
725
686
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
727
690
` SDPY/RemoteCommand ` . The streaming functionality in this case will work exactly
728
691
as it has for the last several years.
729
692
730
-
731
693
2 . A legacy non-WebSockets enabled ` kubectl ` communicating with a newer API Server that
732
694
supports the newer ` StreamTranslator ` proxy.
733
695
@@ -1159,7 +1121,7 @@ Major milestones might include:
1159
1121
- when the KEP was retired or superseded
1160
1122
-->
1161
1123
1162
- - First Kubernetes release where initial version of KEP available: v1.28
1124
+ - First Kubernetes release where initial version of KEP available: v1.29
1163
1125
1164
1126
## Drawbacks
1165
1127
0 commit comments