proxy: should add PingPeriod for websocket translator

IIUC, before using the translator handler, the ping data can be delivered from
the client to the runtime side since kube-apiserver does not parse any client
data. However, with WebSocket, the server responds with a pong to the client
without forwarding the data to the runtime side. If a proxy is present, it may
close the connection due to inactivity. SPDY's PingPeriod can help address this
issue.

Signed-off-by: Wei Fu <fuweid89@gmail.com>
Co-authored-by: Antonio Ojea <aojea@google.com>
This commit is contained in:
Wei Fu 2025-02-12 21:39:59 -05:00
parent 215a9101a7
commit dc59c0246f
2 changed files with 12 additions and 1 deletions

View File

@ -21,6 +21,7 @@ import (
"net/http" "net/http"
"net/url" "net/url"
"strconv" "strconv"
"time"
"github.com/mxk/go-flowrate/flowrate" "github.com/mxk/go-flowrate/flowrate"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
@ -70,7 +71,7 @@ func (h *StreamTranslatorHandler) ServeHTTP(w http.ResponseWriter, req *http.Req
defer websocketStreams.conn.Close() defer websocketStreams.conn.Close()
// Creating SPDY executor, ensuring redirects are not followed. // Creating SPDY executor, ensuring redirects are not followed.
spdyRoundTripper, err := spdy.NewRoundTripperWithConfig(spdy.RoundTripperConfig{UpgradeTransport: h.Transport}) spdyRoundTripper, err := spdy.NewRoundTripperWithConfig(spdy.RoundTripperConfig{UpgradeTransport: h.Transport, PingPeriod: 5 * time.Second})
if err != nil { if err != nil {
websocketStreams.writeStatus(apierrors.NewInternalError(err)) //nolint:errcheck websocketStreams.writeStatus(apierrors.NewInternalError(err)) //nolint:errcheck
metrics.IncStreamTranslatorRequest(req.Context(), strconv.Itoa(http.StatusInternalServerError)) metrics.IncStreamTranslatorRequest(req.Context(), strconv.Itoa(http.StatusInternalServerError))

View File

@ -501,6 +501,16 @@ var _ = SIGDescribe("Kubectl client", func() {
} }
}) })
// https://issues.k8s.io/128314
f.It(f.WithSlow(), "should support exec idle connections", func(ctx context.Context) {
ginkgo.By("executing a command in the container")
execOutput := e2ekubectl.RunKubectlOrDie(ns, "exec", podRunningTimeoutArg, simplePodName, "--", "/bin/sh", "-c", "sleep 320 && echo running in container")
if expected, got := "running in container", strings.TrimSpace(execOutput); expected != got {
framework.Failf("Unexpected kubectl exec output. Wanted %q, got %q", expected, got)
}
})
ginkgo.It("should support exec through kubectl proxy", func(ctx context.Context) { ginkgo.It("should support exec through kubectl proxy", func(ctx context.Context) {
_ = getTestContextHost() _ = getTestContextHost()