Kubernetes 1.36 SPDY to WebSocket Migration
Kubernetes 1.36 continues migrating kubectl exec/attach/port-forward from SPDY to WebSockets. Understand the changes and troubleshoot connection issues.
π‘ Quick Answer: Kubernetes 1.36 continues the SPDY to WebSocket transition (KEP-4006).
kubectl exec,attach, andport-forwardnow use WebSockets by default, improving compatibility with modern proxies, load balancers, and service meshes.
The Problem
SPDY is a deprecated Google protocol (superseded by HTTP/2 in 2015). Kubernetes still used it for streaming connections:
- Proxy incompatibility: Many reverse proxies (nginx, Cloudflare, cloud ALBs) donβt support SPDY
- Firewall issues: SPDY upgrade requests blocked by security appliances
- No standard support: Modern HTTP libraries dropped SPDY support
- Connection drops: SPDY connections through corporate proxies timeout or fail silently
- Service mesh conflicts: Istio/Envoy struggle with SPDY streams
The Solution
WebSocket is the modern standard for bidirectional streaming. Kubernetes is migrating all streaming APIs to use WebSocket.
Whatβs Changed in 1.36
# These commands now use WebSocket by default:
kubectl exec -it pod-name -- /bin/sh
kubectl attach -it pod-name
kubectl port-forward pod-name 8080:80
kubectl cp file.txt pod-name:/tmp/
kubectl logs -f pod-name # Already used HTTP/chunked, unaffectedVerify WebSocket Is Being Used
# Enable verbose logging to see the connection protocol
kubectl exec -v=6 -it my-pod -- /bin/sh
# Look for: "websocket" in the upgrade header
# Check API server supports WebSocket
kubectl get --raw /api/v1 | jq '.serverAddressByClientCIDRs'Force SPDY Fallback (If Needed)
# Environment variable to force SPDY (temporary workaround)
export KUBECTL_REMOTE_COMMAND_WEBSOCKETS=false
kubectl exec -it my-pod -- /bin/sh
# Or in kubeconfig
apiVersion: v1
kind: Config
preferences:
remoteCommandWebsockets: falseProxy and Load Balancer Configuration
# Nginx reverse proxy β WebSocket support
server {
listen 443 ssl;
server_name k8s-api.example.com;
location / {
proxy_pass https://kube-apiserver:6443;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade"; # Required for WebSocket
proxy_set_header Host $host;
proxy_read_timeout 3600s; # Long-lived connections
}
}# HAProxy configuration
frontend k8s_api
bind *:6443 ssl crt /etc/ssl/k8s.pem
default_backend k8s_apiserver
backend k8s_apiserver
option httpchk GET /healthz
http-request set-header Connection "upgrade" if { hdr(Upgrade) -m found }
server api1 10.0.0.1:6443 ssl verify none check# AWS ALB Ingress β WebSocket support is automatic
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
# WebSocket supported by default on ALB β no special config neededIstio Service Mesh Compatibility
# Istio DestinationRule for WebSocket connections to API server
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: kube-apiserver
spec:
host: kubernetes.default.svc
trafficPolicy:
connectionPool:
http:
h2UpgradePolicy: UPGRADE # Allow WebSocket upgrade
idleTimeout: 3600sCommon Issues
kubectl exec fails with βerror: unable to upgrade connectionβ
- Cause: Proxy between kubectl and API server doesnβt support WebSocket
- Fix: Update proxy config to pass WebSocket upgrade headers; or set
KUBECTL_REMOTE_COMMAND_WEBSOCKETS=false
Connection drops after 60 seconds
- Cause: Proxy or load balancer has short idle timeout
- Fix: Increase
proxy_read_timeout(nginx) or idle timeout (ALB) to 3600s
Port-forward stops working through VPN
- Cause: Corporate VPN/proxy strips WebSocket upgrade headers
- Fix: Use SPDY fallback via environment variable until VPN is updated
Best Practices
- Test
kubectl execthrough your full network path β proxies, LBs, VPNs - Update reverse proxies β ensure WebSocket upgrade headers are passed
- Set long idle timeouts β WebSocket connections are long-lived (exec sessions)
- Keep SPDY fallback available β for environments that canβt upgrade yet
- Monitor connection failures β track WebSocket upgrade errors in API server logs
Key Takeaways
- SPDY to WebSocket transition continues in Kubernetes 1.36 (KEP-4006)
kubectl exec,attach,port-forwarduse WebSocket by default- Better compatibility with modern proxies, load balancers, and service meshes
- SPDY fallback available via
KUBECTL_REMOTE_COMMAND_WEBSOCKETS=false - Update proxy configurations to pass WebSocket upgrade headers

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
