
前后端分离部署到 K8s 后,跨域(CORS)是最常见的坑之一。在 Ingress Nginx 层统一配 CORS 头,比在每个后端服务里单独处理省事得多。
下面用一套完整示例走一遍:前端页面 → 后端服务 → Ingress 配置 → 部署验证。
前端页面(cors-demo.html):
<!DOCTYPE html>
<html>
<head>
<title>CORS测试页面</title>
<script>
asyncfunctiontestCORS(endpoint) {
try {
constresponse=awaitfetch(`https://api.demo.com${endpoint}`);
constdata=awaitresponse.text();
alert(`成功: ${data}`);
} catch (error) {
alert(`失败: ${error.message}`);
}
}
</script>
</head>
<body>
<h2>CORS测试页面</h2>
<buttononclick="testCORS('/api/health')">测试健康检查</button>
<buttononclick="testCORS('/api/user')">测试用户信息</button>
</body>
</html>后端服务(Go,main.go):
packagemain
import (
"fmt"
"net/http"
"os"
)
funcmain() {
http.HandleFunc("/api/health", func(whttp.ResponseWriter, r*http.Request) {
w.Header().Set("Content-Type", "application/json")
fmt.Fprintf(w, `{"status": "healthy", "service": "demo-api"}`)
})
http.HandleFunc("/api/user", func(whttp.ResponseWriter, r*http.Request) {
w.Header().Set("Content-Type", "application/json")
fmt.Fprintf(w, `{"id": 1, "name": "张三", "email": "zhangsan@example.com"}`)
})
port :=os.Getenv("PORT")
ifport=="" {
port="8080"
}
fmt.Printf("服务启动在端口 %s\n", port)
http.ListenAndServe(":"+port, nil)
}后端 Deployment + Service(backend-deployment.yaml):
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-backend
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: demo-backend
template:
metadata:
labels:
app: demo-backend
spec:
containers:
- name: backend
image: demo-backend:latest
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"
---
apiVersion: v1
kind: Service
metadata:
name: demo-backend-service
spec:
selector:
app: demo-backend
ports:
- port: 80
targetPort: 8080Ingress 配置(ingress-with-cors.yaml)—— 核心就是 annotations:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress
namespace: default
annotations:
# 启用CORS支持
nginx.ingress.kubernetes.io/enable-cors: "true"
# 允许的来源域名 - 生产环境请替换为实际域名
nginx.ingress.kubernetes.io/cors-allow-origin: "https://frontend.demo.com, http://localhost:3000"
# 允许的HTTP方法
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, OPTIONS"
# 允许的请求头
nginx.ingress.kubernetes.io/cors-allow-headers: >
DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,
Cache-Control,Content-Type,Range,Authorization,X-CSRF-Token
# 允许暴露的响应头
nginx.ingress.kubernetes.io/cors-expose-headers: >
Content-Length,Content-Range,X-Total-Count
# 预检请求缓存时间(48小时)
nginx.ingress.kubernetes.io/cors-max-age: "172800"
# 允许携带凭据(如Cookies)
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
# 开发环境:允许所有来源(慎用于生产)
# nginx.ingress.kubernetes.io/cors-allow-origin: "*"
# 注意:使用"*"时,cors-allow-credentials必须为false
spec:
ingressClassName: nginx
rules:
- host: api.demo.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: demo-backend-service
port:
number: 80应用配置:
kubectl apply -f backend-deployment.yaml
kubectl apply -f ingress-with-cors.yaml
# 确认 Ingress 状态
kubectl get ingress api-ingress
kubectl describe ingress api-ingressIngress 创建成功后,describe 输出里应该能看到所有 CORS 注解:
NAME CLASS HOSTS ADDRESS PORTS AGE
api-ingress nginx api.demo.com 192.168.49.2 80 2m
Annotations:
nginx.ingress.kubernetes.io/cors-allow-credentials: true
nginx.ingress.kubernetes.io/cors-allow-headers: DNT,Keep-Alive,User-Agent...
nginx.ingress.kubernetes.io/cors-allow-methods: GET,POST,PUT,DELETE,OPTIONS
nginx.ingress.kubernetes.io/cors-allow-origin: https://frontend.demo.com,http://localhost:3000
nginx.ingress.kubernetes.io/cors-expose-headers: Content-Length,Content-Range,X-Total-Count
nginx.ingress.kubernetes.io/cors-max-age: 172800
nginx.ingress.kubernetes.io/enable-cors: true测试预检请求(OPTIONS):
curl-X OPTIONS \
-H"Origin: https://frontend.demo.com" \
-H"Access-Control-Request-Method: GET" \
-H"Access-Control-Request-Headers: Content-Type, Authorization" \
-v https://api.demo.com/api/health正常返回 204,响应头带 CORS 信息:
< HTTP/2 204
< server: nginx/1.25.3
< date: Mon, 07 Apr 2026 14:50:00 GMT
< access-control-allow-origin: https://frontend.demo.com
< access-control-allow-methods: GET,POST,PUT,DELETE,OPTIONS
< access-control-allow-headers: DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-CSRF-Token
< access-control-max-age: 172800
< access-control-allow-credentials: true测试实际 API 请求:
curl -H "Origin: https://frontend.demo.com" \ -H "Authorization: Bearer test-token" \ https://api.demo.com/api/user返回:
{"id": 1, "name": "张三", "email": "zhangsan@example.com"}浏览器端打开 cors-demo.html 点击按钮,配置正确时能正常弹出数据;如果 Origin 不在白名单里,控制台会报 CORS 拦截错误。
开发环境可以宽松一些:
annotations: nginx.ingress.kubernetes.io/enable-cors: "true" nginx.ingress.kubernetes.io/cors-allow-origin: "*" nginx.ingress.kubernetes.io/cors-allow-methods: "*" nginx.ingress.kubernetes.io/cors-allow-headers: "*" nginx.ingress.kubernetes.io/cors-allow-credentials: "false"生产环境收紧:
annotations: nginx.ingress.kubernetes.io/enable-cors: "true" nginx.ingress.kubernetes.io/cors-allow-origin: "https://www.yourdomain.com" nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, OPTIONS" nginx.ingress.kubernetes.io/cors-allow-headers: "Authorization, Content-Type" nginx.ingress.kubernetes.io/cors-allow-credentials: "true" nginx.ingress.kubernetes.io/configuration-snippet: | # 额外的安全头 add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always;CORS 配置不生效
进 Ingress Controller Pod 里确认 nginx.conf 里有没有 CORS 相关配置:
kubectl exec -it <nginx-ingress-pod> -- cat /etc/nginx/nginx.conf | grep -A5 -B5 "cors" kubectl logs -n ingress-nginx <controller-pod> | grep -i corsOPTIONS 返回 405
要么后端应用没处理 OPTIONS 方法,要么 Ingress Nginx 版本太旧不支持 CORS 注解。升级 Ingress Controller 或在后端加上 OPTIONS 处理。
Credentials 相关
cors-allow-credentials: "true" 时有三个注意点:
credentials: 'include'cors-allow-origin 不能用 "*",必须写具体域名Access-Control-Allow-Credentials: true“无他,惟手熟尔”!有需要的用起来!
如果你觉得这篇文章有用,欢迎点赞、转发、收藏、留言、推荐❤!