kubernetes与spring cloud 的结合中,由于前后端分别部署在了不同的pod中,所以在访问的时候会产生跨域问题。那解决应用的跨域问题有几种方式?
kubernetes与spring cloud 的结合中,由于前后端分别部署在了不同的pod中,所以在访问的时候会产生跨域问题,有三种解决方式。
一、在集群中部署nginx pod对后端应用进行代理
我们的前端应用为crm-web,后端应用为crm-portal,每个应用对应一个ClusterIP形式的service。
我们在集群中创建一个nginx,设置为允许跨域,代理后端pod。
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 8090;
server_name localhost;
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
proxy_pass http://crm-portal-svc.dev.svc.cluster.local:8091; #service地址
if ($request_method = OPTIONS){
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE';
add_header 'Access-Control-Allow-Headers' 'reqid, nid, host, x-real-ip, x-forwarded-ip, event-type, event-id, accept, content-type';
proxy_pass http://crm-portal-svc.dev.svc.cluster.local:8091; #service地址
return 200;
}
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
注意:配置文件中的proxy_pass http://crm-portal-svc.dev.svc.cluster.local:8091; crm-portal-svc.dev.svc.cluster.local为service在kubernetes中的url。
2)创建nginx的configmap
配置文件如下:
> vim nginx.conf
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
namespace: dev
spec:
type: NodePort
selector:
app: nginx
ports:
- name: http
port: 8090
targetPort: 8090
nodePort: 30014
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx
namespace: dev
labels:
addonmanager.kubernetes.io/mode: Reconcile
spec:
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.12.2
ports:
- containerPort: 80
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/
volumes:
- name: config-volume
configMap:
name: nginx-cors-test
items:
- key: nginx.conf
path: nginx.conf
创建nginx应用和service。
> kubectl apply -f nginx.conf -n dev
> kubectl get svc -n dev
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
crm-portal -svc ClusterIP 10.108.158.149 <none> 8091/TCP 6d1h
crm-web-svc NodePort 10.107.246.255 <none> 8080:30000/TCP 6d1h
nginx NodePort 10.105.241.12 <none> 8090:30014/TCP 55m
可以见到多了一个类型为NodePort的svc通过宿主机主机的30014端口,
我们在前端的js中配置后端的调用url为宿主机的ip:30014,此时跨域问题就解决了。
这种方法首先要将后端的service也创建成Nodeport的形式。
> kubectl get po -n dev
NAME READY STATUS RESTARTS AGE
crm-portal-deployment-7c6f544855-l8qr8 1/1 Running 0 117m
crm-web-deployment-5cf8447595-h7qms 1/1 Running 0 17m
> kubectl get svc -n dev
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
crm-portal -svc NodePort 10.108.158.149 <none> 8091:30001/TCP 6d1h
crm-web-svc NodePort 10.107.246.255 <none> 8080:30000/TCP 6d1h
然后再集群外找一台机器部署nginx,并代理至宿主机的30001端口,具体参考:nginx 配置允许跨域
最后在前端的js中配置后端的调用IP 为nginx的地址即可。
ingress配置规则如下:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-myapp
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/Access-Control-Allow-Origin: '*'
nginx.ingress.kubernetes.io/cors-allow-headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization
nginx.ingress.kubernetes.io/cors-allow-methods: 'PUT, GET, POST, OPTIONS'
nginx.ingress.kubernetes.io/cors-allow-origin: '*'
nginx.ingress.kubernetes.io/enable-cors: 'true'
nginx.ingress.kubernetes.io/service-weight: ''
spec:
rules:
- host: myapp.ingress.com
http:
paths:
- path:
backend:
serviceName: crm-portal-svc
servicePort: 8091
这种方式需要配置host的域名信息,在访问时 要求前端应用将配置的域名解析成宿主机的IP ,如果前端应用在pod中,需要修改pod的hosts文件(参考:docker/k8s修改容器hosts文件)若架构中又没有DNS服务器时, 不建议使用。
总结
前两种方式原理上区别不大,
但第一种方式使用pod的方式部署nginx,节省了主机资源和宿主机的port资源,符合容器化的初衷。
第三种方式建议前端页面在集群外,或者有DNS服务时使用。
收起