Skip to content

Streaming exec/attach fails with kubelet 1.36.x: relative BaseURL (no scheme) misinterpreted as HTTPS #569

Description

@Maksim-Siniugin

What happened?

kubectl exec/kubectl run -it/kubectl attach fail against pods when using
cri-dockerd as the CRI shim with kubelet/kubectl v1.36.2. The kubelet proxies
the exec/attach request to the address cri-dockerd's streaming server returns,
but errors out because the client attempts a TLS handshake against a plain
HTTP server:

warning: couldn't attach to pod/tlsdbg, falling back to streaming logs: Internal error occurred: error sending request: Post "//127.0.0.1:35417/cri/attach/WwJa7gGv": http: server gave HTTP response to HTTPS client

Note the URL has no scheme (//127.0.0.1:35417/...), which matches the
comment in cmd/server.go:

https://github.com/Mirantis/cri-dockerd/blob/master/cmd/server.go#L186-L194

// Initialize streaming configuration. (Not using TLS now)
streamingConfig := &streaming.Config{
    // Use a relative redirect (no scheme or host).
    BaseURL: &url.URL{Path: "/cri/"},
    Addr:    resolvedAddr,
    ...

Isolating the cause

  • crictl --runtime-endpoint unix:///run/cri-dockerd.sock exec -it <id> sh
    works fine — cri-dockerd's own streaming server is healthy and reachable.
  • The failure only happens when the request goes through kubelet's
    exec/attach proxy path (kubectl exec/run -it/attach).
  • Ruled out: kube-proxy / NodePort-vs-ephemeral-port overlap (reproduced on a
    cluster with no kube-proxy, Antrea in proxyAll mode); explicit
    --streaming-bind-addr=127.0.0.1 (no effect, same error, just a different
    loopback port).
  • Same exact Kubernetes/Docker/cri-dockerd version combo previously worked
    fine on another cluster; only relevant delta found across many rounds of
    debugging.

Fix that resolves it

Explicitly setting Scheme and Host on BaseURL instead of leaving it as a
scheme-less relative URL fixes the issue completely:

streamingConfig := &streaming.Config{
    BaseURL: &url.URL{
        Scheme: "http",
        Host:   resolvedAddr,
        Path:   "/cri/",
    },
    Addr: resolvedAddr,
    ...

Built and deployed this patch and kubectl exec -it / kubectl run -it work
correctly again.

Environment

  • cri-dockerd version: 0.4.4
  • Docker version: 29.6.2
  • kubelet/kubectl version: 1.36.2
  • CNI: Antrea (reproduced both with kube-proxy and with kube-proxy disabled +
    Antrea proxyAll)
  • OS: Arch Linux, kernel 7.1.4-arch1-1 #1 SMP PREEMPT_DYNAMIC Sat, 18 Jul 2026 17:30:57 +0000 x86_64 GNU/Linux

Expected behavior

kubectl exec -it/kubectl run -it/kubectl attach should work normally
with the default (unpatched) cri-dockerd configuration.

Additional context

This looks like a compatibility regression between newer kubelet's
exec/attach proxy handling (k8s.io/apimachinery/pkg/util/proxy.UpgradeAwareHandler)
and cri-dockerd's intentionally scheme-less "relative redirect" BaseURL. A
similar symptom (identical error string, same log line format) was reported
independently for k3s's embedded docker/cri shim on Docker 29.4.1:
k3s-io/k3s#14017

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions