通过Ingress暴露的前端无法访问Kubernetes集群内部API服务
问题原因分析
你的核心错误在于试图让浏览器直接访问Kubernetes集群内部的Service域名(api.microservices.svc.cluster.local),这完全不可行:
- 集群内部Service域名仅能在集群Pod网络中解析和访问,浏览器运行在用户设备上,不在集群网络范围内,既无法解析该域名,也无法连通ClusterIP服务。
- 混合内容拦截:前端通过HTTPS加载,浏览器禁止发起HTTP请求(内部Service仅提供HTTP服务),触发安全拦截。
- CORS拦截:即使域名可访问,
api.microservices.svc.cluster.local与app.testing.tech属于不同源,且该内部域名不在浏览器允许的合法跨域协议/域名范围内,触发CORS限制。
解决方案
推荐两种可行方案,优先选择第一种(更安全、无跨域问题):
方案1:通过前端Ingress路径转发API请求(推荐)
在前端的Ingress中添加路径规则,将/api/*前缀的请求转发到后端API服务,前端使用相对路径调用API,避免跨域和混合内容问题。
修改前端Ingress配置:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: app namespace: apps annotations: kubernetes.io/ingress.class: nginx cert-manager.io/cluster-issuer: letsencrypt-prod external-dns.alpha.kubernetes.io/hostname: app.testing.tech nginx.ingress.kubernetes.io/enable-cors: "true" nginx.ingress.kubernetes.io/cors-allow-headers: "DNT, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Range, Authorization, Cookie" nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, OPTIONS, DELETE" nginx.ingress.kubernetes.io/cors-allow-credentials: "true" nginx.ingress.kubernetes.io/cors-expose-headers: "*" # 重写路径,移除/api前缀后转发到API服务 nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: rules: - host: app.testing.tech http: paths: - path: / pathType: Prefix backend: service: name: app port: number: 80 # 添加API路径转发规则 - path: /api(/|$)(.*) pathType: Prefix backend: service: name: api namespace: microservices port: number: 80 tls: - hosts: - app.testing.tech secretName: app-tls-secret
将前端的API环境变量设置为/api(相对路径),比如请求地址改为/api/auth/login,所有API请求都会通过https://app.testing.tech/api/*转发到后端,与前端同域名,无跨域和混合内容问题。
方案2:为API配置独立Ingress并处理CORS
如果必须使用独立的API域名(api.testing.tech),需为API添加Ingress并配置CORS允许前端域名。
创建API的Ingress配置:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: api namespace: microservices annotations: kubernetes.io/ingress.class: nginx cert-manager.io/cluster-issuer: letsencrypt-prod external-dns.alpha.kubernetes.io/hostname: api.testing.tech # 配置CORS允许前端域名 nginx.ingress.kubernetes.io/enable-cors: "true" nginx.ingress.kubernetes.io/cors-allow-origin: "https://app.testing.tech" nginx.ingress.kubernetes.io/cors-allow-headers: "DNT, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Range, Authorization, Cookie" nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, OPTIONS, DELETE" nginx.ingress.kubernetes.io/cors-allow-credentials: "true" nginx.ingress.kubernetes.io/cors-expose-headers: "*" spec: rules: - host: api.testing.tech http: paths: - path: / pathType: Prefix backend: service: name: api port: number: 80 tls: - hosts: - api.testing.tech secretName: api-tls-secret
将前端的API环境变量设置为https://api.testing.tech,确保请求使用HTTPS,同时CORS规则允许前端来源,即可解决错误。
关于Istio的补充
你之前尝试Istio未解决问题,大概率是因为前端仍在请求集群内部Service域名,而非通过Istio的Ingress Gateway暴露的外部地址。若使用Istio,需为API配置VirtualService并通过Gateway暴露,同时前端请求该外部地址,而非内部域名。
内容的提问来源于stack exchange,提问作者oskarfightingthekube
相关产品推荐
相关产品推荐

