【BUG Fix】Rancher 接入 OIDC 遭遇 502:一次由 Nginx 响应头缓冲区引发的认证故障
一、问题背景最近在为 Rancher 接入 Casdoor OIDC 统一身份认证时遇到了一个比较隐蔽的问题Casdoor 认证成功Token 交换正常但 Rancher 最终登录接口返回 HTTP 502 Bad Gateway。环境如下组件版本或配置Rancherv2.14.2KubernetesK3sIngress Controlleringress-nginx身份认证CasdoorGeneric OIDC外部代理NginxRancher 域名rancher.xxxx.cnCasdoor 域名auth.xxxx.cn整体访问链路Browser │ ▼ 雷池 WAF / Nginx │ ▼ K8s Nginx Ingress │ ▼ Rancher │ ▼ Casdoor OIDC故障表现非常奇怪可以正常跳转 Casdoor 登录。Casdoor 登录成功并返回 Authorization Code。浏览器访问 Rancher/dashboard/auth/verify。Rancher 调用/v1-public/login立即返回 502。Rancher 普通日志基本没有异常。重放登录请求却返回 Token 已使用的错误。# 502 访问日志192.168.1.1|-|10/Oct/2026:08:18:09 0000|rancher.xxxx.cn|POST /v1-public/login HTTP/1.1|502|552|https://rancher.xxxxx.cn/dashboard/auth/verify?codexxxxstatexxxxxisshttps://auth.xxxx.com|Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/154.0.0.0 Safari/537.36最初怀疑的是 OIDC 配置、UserInfo Claims、PKCE 或 Casdoor Token 交换问题。但最终证明根因是 Nginx 反向代理缓冲区过小无法接收 Rancher 登录时返回的较大 HTTP 响应头。参考资料https://kubernetes.github.io/ingress-nginx/examples/customization/jwt/二、第一步确认浏览器报错位置打开浏览器开发者工具F12 → Network重新执行 OIDC 登录发现失败请求为POST https://rancher.xxxx.cn/v1-public/login HTTP/1.1 502 Bad Gateway响应中可以看到Server: Tengine此时不能简单认定是雷池返回的错误。由于存在多层代理需要逐级判断浏览器 │ ├── 外层 WAF / Nginx │ ├── K8s Ingress Nginx │ └── Rancher Pod502 可能来自任意一个反向代理节点。另外重复提交同一个 Authorization Code 并不是有效的排查方法因为 OIDC 授权码只能使用一次。三、第二步检查 Casdoor OIDC 认证是否成功查看 Casdoor 前面的 Nginx 访问日志筛选以下接口/login/oauth/authorize /.well-known/openid-configuration /api/login/oauth/access_token /.well-known/jwks /api/userinfo实际排查时发现GET /login/oauth/authorize 302 GET /.well-known/openid-configuration 200 POST /api/login/oauth/access_token 200 GET /.well-known/jwks 200 GET /api/userinfo 200这些请求均正常。这说明Authorization Code 已经成功交换 Token。Rancher 成功获取 JWT 签名公钥。Rancher 成功调用 UserInfo 接口。但需要注意UserInfo 返回 HTTP 200并不能完全证明用户 Claims 已经被 Rancher 正确处理。因此下一步需要进入 Rancher 服务端排查。四、第三步查看 Rancher 日志4.1 确认 Rancher Pod本次环境为 K3s使用本地 kubeconfigexport KUBECONFIG/etc/rancher/k3s/k3s.yaml kubectl -n cattle-system get pods -l apprancher4.2 查看 Rancher 普通日志kubectl -n cattle-system logs \ -l apprancher \ --all-containerstrue \ --since30m \ --prefixtrue \ --max-log-requests10筛选认证错误kubectl -n cattle-system logs \ -l apprancher \ --all-containerstrue \ --since30m \ --max-log-requests10 \ | grep -Ei oidc|oauth|login|token|error|failed|x509最初只发现failed exchanging token: oauth2: invalid_grant authorization code has been used for token这是由于重复使用已经消费的 Authorization Code 所导致。而新一轮正常认证并没有对应的错误日志。4.3 开启 Rancher Debug 日志这是整个排查过程中非常重要的一步。Rancher 可以通过 Pod 内的loglevel命令动态修改日志级别不需要重启 Pod。kubectl -n cattle-system get pods -l apprancher \ -o jsonpath{range .items[*]}{.metadata.name}{\n}{end} \ | while read pod; do kubectl -n cattle-system exec $pod \ -c rancher -- loglevel --set debug done然后实时查看kubectl -n cattle-system logs \ -l apprancher \ -c rancher \ --since1m \ --prefixtrue \ --max-log-requests10 \ -f \ | grep -Ei oidc|oauth|login|userinfo|claim|principal|error重新登录后得到以下关键日志[DEBUG] [oidc] Redirecting to IdP for provider: genericoidc [DEBUG] OpenIDCProvider: UpdateToken: access token has been refreshed [DEBUG] OpenIDCProvider: getUserInfo: getting user info for user [DEBUG] OpenIDCProvider: using groups claim [DEBUG] OpenIDCProvider: using roles claim [DEBUG] OpenIDCProvider: loginuser: checking users access to rancher说明 Rancher 已经进入 OIDC 后半段处理流程包括 UserInfo、Groups、Roles 和用户访问授权检查。虽然当时仍然无法确认 Rancher 是否已经成功完成 Session 创建但结合 Casdoor 的正常接口响应认证协议本身的问题可能性进一步降低。排查完毕后恢复日志级别kubectl -n cattle-system get pods -l apprancher \ -o jsonpath{range .items[*]}{.metadata.name}{\n}{end} \ | while read pod; do kubectl -n cattle-system exec $pod \ -c rancher -- loglevel --set info done五、第四步定位 Kubernetes Ingress既然 Casdoor 请求正常、Rancher 又没有明确的应用层错误接下来需要排查代理层。5.1 确定 Rancher 使用哪个 Ingress Controllerkubectl -n cattle-system get ingress -o wide实际返回NAME CLASS HOSTS ADDRESS rancher nginx rancher..xxxx.cn 10.10.5.30可以看到CLASS nginx说明 Rancher 使用的是 Nginx Ingress而不是 K3s 默认可能安装的 Traefik。查看所有 IngressClasskubectl get ingressclass5.2 找到 Nginx Ingress Controller Podkubectl get pods -A | grep -Ei ingress-nginx|nginx-ingress实际结果ingress-nginx ingress-nginx-controller-7d6xxxx6d6-6cm94 1/1 Running说明 Controller 位于Namespace: ingress-nginx5.3 查看 Ingress 日志实时查看kubectl -n ingress-nginx logs \ -l app.kubernetes.io/componentcontroller \ --all-containerstrue \ --since10m \ --prefixtrue \ --max-log-requests10 \ -f筛选异常kubectl -n ingress-nginx logs \ -l app.kubernetes.io/componentcontroller \ --all-containerstrue \ --since30m \ --tail2000 \ | grep -Ei 502|too big header|upstream|v1-public/login5.4 终于找到根因Ingress 日志中出现POST /v1-public/login HTTP/1.1 502 upstream sent too big header while reading response header from upstream同时可以看到对应的上游地址upstream: http://10.42.0.202:80/v1-public/login以及upstream_status: 502这条错误直接指向了 Nginx。Rancher 返回的 HTTP 响应头超过了 Nginx 接收上游响应头的缓冲区大小Nginx 在读取响应头时失败最终向客户端返回 502。这也解释了三个奇怪的现象Casdoor Token 已经成功使用。Rancher 没有明显的 OIDC ERROR。浏览器几乎立即收到 502而不是等待超时。六、第五步修复 Ingress 响应头缓冲区Ingress Nginx 的proxy-buffer-size默认通常为4k。本次将其调整为32k。执行kubectl -n cattle-system annotate ingress rancher \ nginx.ingress.kubernetes.io/proxy-buffer-size32k \ --overwrite查看配置kubectl -n cattle-system get ingress rancher \ -o jsonpath{.metadata.annotations.nginx\.ingress\.kubernetes\.io/proxy-buffer-size}{\n}预期输出32kIngress Controller 通常会自动重新加载配置不需要重启 Rancher。修改后重新执行完整的 OIDC 登录流程502 问题得到解决。如果通过 Helm 管理 Rancher建议同步写入 Helm Values避免后续升级时配置被覆盖ingress: extraAnnotations: nginx.ingress.kubernetes.io/proxy-buffer-size: 32k注意直接修改 Ingress Annotation 会持久保存到 Kubernetes 中重启不会丢失但 Helm Upgrade 或重新创建资源可能覆盖它。七、第六步修复外部 Nginx 的同类问题本次排查过程中还发现外层普通 Nginx 反向代理也可能存在相同的响应头缓冲限制。在对应网站的server或location中增加proxy_buffer_size 32k; proxy_buffers 8 32k; proxy_busy_buffers_size 64k;例如server { listen 443 ssl; server_name rancher.xxxx.cn; # 原有 SSL 配置 location / { proxy_pass http://your-upstream; proxy_buffer_size 32k; proxy_buffers 8 32k; proxy_busy_buffers_size 64k; } }保留原有proxy_pass和其他代理配置不需要覆盖整个 Nginx 配置。其中最关键的是proxy_buffer_size 32k;它控制 Nginx 用于读取上游响应头的缓冲区大小。修改后检查并重载nginx -t nginx -s reload注意Ingress Nginx 和外层 Nginx 是两个独立的代理层修改其中一层不会自动影响另一层。八、最终总结本次问题并不是 Casdoor 认证失败而是OIDC 登录成功后的 HTTP 响应处理失败。完整定位过程浏览器发现 /v1-public/login 502 ↓ 检查 Casdoor OIDC 日志 Token / JWKS / UserInfo 全部 200 ↓ 检查 Rancher 普通日志 未发现当前请求的明确认证错误 ↓ 开启 Rancher Debug 确认进入 UserInfo 和用户访问检查 ↓ 检查 K8s Ingress 类型 确认使用 ingress-nginx ↓ 查看 Ingress Controller 错误日志 upstream sent too big header ↓ 调整 proxy_buffer_size 为 32k ↓ 重新登录问题解决排障经验1. HTTP 502 不一定是后端业务错误。如果应用日志没有异常应该优先检查反向代理日志尤其是 Nginx 的 upstream 相关错误。2. OIDC 授权码只能使用一次。重放认证请求出现invalid_grant是正常现象不能据此认定第一次认证失败。3. 多层代理必须逐级排查。浏览器看到的Server: Tengine不一定代表错误由 Tengine 生成。应该依次检查 WAF、外层 Nginx、K8s Ingress 和业务 Pod。4. Nginx 响应头缓冲区不足可能导致瞬时 502。尤其是 Rancher 这种具有复杂认证和 Session 机制的系统登录时可能产生较大的响应头。5. 修改前先找证据。upstream sent too big header才是本次故障的决定性证据。不要一看到 502 就盲目增加超时时间、关闭 WAF 或修改 OIDC 参数。最终解决方案针对 Rancher 的 Nginx 代理链路将**proxy_buffer_size**调整为**32k**。