Kubernetes问题:ELB未按Nginx配置重定向至HTTPS
你的问题根源在于AWS经典ELB的转发模式以及Nginx对带下划线请求头的默认处理规则,下面一步步拆解并解决:
1. 为什么重定向不生效?
当前你的Service配置中,端口的protocol是TCP,这会让kops创建的AWS经典ELB以四层TCP模式转发流量,而非七层HTTP模式。在TCP模式下,ELB仅透传字节流,不会解析HTTP请求,因此不会自动添加X-Forwarded-Proto这类标识原始请求协议的HTTP头。
同时,Nginx默认会忽略带下划线的请求头(比如X-Forwarded-Proto),即便后续ELB能发送这个头,Nginx也无法读取到$http_x_forwarded_proto变量,导致你的重定向条件无法正确触发。
2. 分步解决方案
步骤1:修改Service配置,启用ELB七层HTTP转发
在Service的metadata.annotations中添加service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http,让ELB切换为HTTP模式转发流量。此时ELB会自动解析HTTP请求,并为每个请求添加X-Forwarded-Proto头(HTTP请求对应值为http,HTTPS请求对应值为https):
apiVersion: v1 kind: Service metadata: name: ui annotations: service.beta.kubernetes.io/aws-load-balancer-ssl-cert: <certificate_id> service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443" # 添加这行,启用HTTP后端协议转发 service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http spec: ports: - name: http port: 80 targetPort: ui-port protocol: TCP - name: https port: 443 targetPort: ui-port protocol: TCP selector: els-pod: ui type: LoadBalancer
修改后执行kubectl apply -f <service-file.yaml>更新Service,ELB会自动同步配置(通常需要1-2分钟生效)。
步骤2:调整Nginx配置,允许处理带下划线的请求头
在Nginx的server块中添加underscores_in_headers on;,确保Nginx能读取X-Forwarded-Proto这个带下划线的请求头:
server { # 必须添加这行,允许处理带下划线的请求头 underscores_in_headers on; listen 80; # 重定向逻辑:如果原始请求是HTTP,跳转至HTTPS if ($http_x_forwarded_proto != 'https') { rewrite ^ https://$host$request_uri? permanent; } # 你的其他location配置... }
(可选)优化重定向逻辑,避免Nginx if的潜在问题
Nginx的if指令在部分场景下可能出现意外行为,推荐用map指令替代,写法更稳健:
# 在server块外部定义map规则 map $http_x_forwarded_proto $redirect_to_https { default 0; http 1; } server { underscores_in_headers on; listen 80; if ($redirect_to_https) { return 301 https://$host$request_uri; } # 你的其他配置... }
3. 验证配置
更新Nginx镜像并重新部署Deployment后,用HTTP访问你的域名my-k8s.mydomain.org,应该会自动跳转到HTTPS。
如果想快速验证逻辑是否正确,可以进入UI Pod内部模拟ELB请求:
kubectl exec -it <ui-pod-name> -- /bin/bash # 模拟HTTP请求(X-Forwarded-Proto为http) curl -I -H "X-Forwarded-Proto: http" localhost # 应返回301重定向到https://localhost/... # 模拟HTTPS请求(X-Forwarded-Proto为https) curl -I -H "X-Forwarded-Proto: https" localhost # 应返回200 OK,无重定向
内容的提问来源于stack exchange,提问作者pkaramol

