如何在NGINX Ingress Controller中保留Host头的标准端口(如80/443)
我通过Kubernetes和NGINX Ingress Controller部署了MinIO,MinIO API需要依赖Host头中的端口信息来计算签名。测试环境中,NGINX Ingress Controller运行在1个工作节点上,请求链路为:dotnet-client ===> Nginx Ingress controller ===> MinIO deployment。
dotnet-client发送的请求中Host头包含:80:
- - - - - - - - - - BEGIN REQUEST - - - - - - - - - - GET http://minio.vobaitap.online/ HTTP/1.1 Host: minio.vobaitap.online:80 x-amz-content-sha256: *** x-amz-date: 20240817T074728Z Authorization: ***, SignedHeaders=host;x-amz-content-sha256;x-amz-date, *** - - - - - - - - - - END REQUEST - - - - - - - - - -
通过tcpdump捕获到工作节点收到的请求中Host头确实包含:80,但MinIO部署的追踪结果显示Host头的:80被移除,导致请求被拦截:
minio.vobaitap.online [REQUEST s3.ListBuckets] [2024-08-17T14:47:39.854] [Client IP: 118.70.99.75] minio.vobaitap.online GET / minio.vobaitap.online Proto: HTTP/1.1 minio.vobaitap.online Host: minio.vobaitap.online minio.vobaitap.online Accept-Encoding: gzip, deflate minio.vobaitap.online User-Agent: MinIO (Microsoft Windows 10.0.22631;X64) minio-dotnet/1.0.9 minio.vobaitap.online X-Real-Ip: 118.70.99.75 minio.vobaitap.online Authorization: ***, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=*** minio.vobaitap.online X-Forwarded-For: 118.70.99.75 minio.vobaitap.online X-Forwarded-Host: minio.vobaitap.online minio.vobaitap.online Accept: application/json, text/json, text/x-json, text/javascript, application/xml, text/xml minio.vobaitap.online Traceparent: *** minio.vobaitap.online X-Amz-Date: 20240817T074728Z minio.vobaitap.online X-Forwarded-Port: 80 minio.vobaitap.online X-Forwarded-Proto: http minio.vobaitap.online Connection: close minio.vobaitap.online Content-Length: 0 minio.vobaitap.online X-Amz-Content-Sha256: ***
我的初始Ingress配置如下:
kind: Ingress apiVersion: networking.k8s.io/v1 metadata: name: minio-ingress namespace: minio spec: ingressClassName: nginx rules: - host: minio.vobaitap.online http: paths: - path: / pathType: Prefix backend: service: name: minio-service port: number: 9000
我尝试使用nginx.org/proxy-set-headers注解,但MinIO API返回错误:mc.exe: Unable to listen to http trace. Failed to parse server response (unexpected end of JSON input):.,错误配置如下:
kind: Ingress apiVersion: networking.k8s.io/v1 metadata: name: minio-ingress namespace: minio annotations: nginx.org/proxy-set-headers: "Host" spec: ingressClassName: nginx ...
版本信息:Nginx Ingress 3.6.1、Kubernetes 1.29.6、minio-dotnet 1.0.9(来自NuGet包MinIO 3.1.13)。
请问如何在Host头中保留:80端口?
解决方案
方法1:使用nginx.org/upstream-vhost注解(推荐)
直接在Ingress的注解中添加nginx.org/upstream-vhost: "$http_host",该配置会让NGINX将客户端发送的完整Host头(包含端口)转发给MinIO后端。
修改后的完整Ingress配置:
kind: Ingress apiVersion: networking.k8s.io/v1 metadata: name: minio-ingress namespace: minio annotations: nginx.org/upstream-vhost: "$http_host" spec: ingressClassName: nginx rules: - host: minio.vobaitap.online http: paths: - path: / pathType: Prefix backend: service: name: minio-service port: number: 9000
方法2:通过ConfigMap配置代理头
如果需要自定义多个请求头,可以通过ConfigMap来配置:
- 创建存储代理头规则的ConfigMap:
apiVersion: v1 kind: ConfigMap metadata: name: minio-proxy-headers namespace: minio data: Host: "$http_host"
- 在Ingress中引用该ConfigMap:
kind: Ingress apiVersion: networking.k8s.io/v1 metadata: name: minio-ingress namespace: minio annotations: nginx.org/proxy-set-headers: "minio/minio-proxy-headers" spec: ingressClassName: nginx rules: - host: minio.vobaitap.online http: paths: - path: / pathType: Prefix backend: service: name: minio-service port: number: 9000
错误原因说明
你之前使用nginx.org/proxy-set-headers: "Host"的配置是错误的,该注解的取值应该是ConfigMap的完整名称(格式为<命名空间>/<ConfigMap名称>),而非直接写请求头名称。错误的配置导致NGINX生成了无效的转发规则,最终让MinIO无法解析请求返回错误。
内容的提问来源于stack exchange,提问作者NguyenVanDai

