Kubectl代理经NGINX转发访问报invalid upgrade response错误
故障核心原因
你当前的NGINX配置对所有请求无差别强制携带Connection: upgrade请求头,直接触发了协议校验冲突。
kubectl proxy的协议处理逻辑是:只有收到客户端明确发起的WebSocket升级请求时,才会返回101 Switching Protocols的升级响应;像你用curl访问/api这类普通的REST API请求,本来应该返回200状态码的普通HTTP响应,根本不需要走协议升级流程。
现在NGINX给所有请求都硬塞了WebSocket升级要求,相当于强制kubectl proxy对所有请求走升级判断逻辑;但普通API请求本身只会返回200响应,不会返回101升级状态码,kubectl proxy检测到要求升级的请求实际拿到了200响应,就直接抛出invalid upgrade response: status code 200的报错。
具体修复步骤
- 移除NGINX配置里写死的
proxy_set_header Connection "upgrade";固定规则,换成根据请求特征动态生成的连接头配置:只有客户端真的发起WebSocket升级请求时,才透传对应的Upgrade/Connection头,普通API请求保持默认的HTTP交互逻辑。 - 调整后的完整配置参考(原有SSL配置、反向代理地址保持不变):
首先在NGINX的http块层级(和server块同级的全局配置位置)加上映射规则,判断当前请求是否是WebSocket升级请求:
# http块下的全局映射规则 map $http_upgrade $connection_upgrade { default upgrade; '' close; }
然后修改对应server块的location配置:
server { server_name kubernates.example.com; listen 443 ssl; listen 80; include ssl_standart_conf; location / { proxy_pass http://192.168.1.2:8001/; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_redirect off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; # 替换原来写死的Connection头,使用动态映射的变量 proxy_set_header Connection $connection_upgrade; # 补充长连接超时配置,适配WebSocket日志流、exec操作的长连接场景 proxy_read_timeout 3600s; proxy_send_timeout 3600s; } }
- 配置修改完成后,先校验NGINX配置语法无错误,再重载配置生效。重新执行
curl https://kubernates.example.com/api即可正常拿到Kubernetes API的返回结构,不会再触发升级响应不匹配的报错。
风险提示:当前启动的kubectl proxy没有任何内置身份校验机制,直接暴露到公网会导致整个集群被未授权访问,在接入GitLab CI/CD流程前,必须在公网入口补充身份认证逻辑,禁止无校验的代理节点直接暴露公网。
内容的提问来源于stack exchange,提问作者Sergius
相关产品推荐
相关产品推荐

