解决kubernetes中应用的跨域问题有几种方式?

kubernetes与spring cloud 的结合中,由于前后端分别部署在了不同的pod中,所以在访问的时候会产生跨域问题。那解决应用的跨域问题有几种方式?

1回答

zzhengleizzhenglei  技术经理 , 太平洋保险
zhuhaiqiang赞同了此回答
kubernetes与spring cloud 的结合中,由于前后端分别部署在了不同的pod中,所以在访问的时候会产生跨域问题,有三种解决方式。 一、在集群中部署nginx pod对后端应用进行代理 我们的前端应用为crm-web,后端应用为crm-portal,每个应用对应一个ClusterIP形式的service。 我们在集...显示全部

kubernetes与spring cloud 的结合中,由于前后端分别部署在了不同的pod中,所以在访问的时候会产生跨域问题,有三种解决方式。

一、在集群中部署nginx pod对后端应用进行代理

我们的前端应用为crm-web,后端应用为crm-portal,每个应用对应一个ClusterIP形式的service。

我们在集群中创建一个nginx,设置为允许跨域,代理后端pod。

1、创建nginx的confmap
1)首先准备nginx的配置文件nginx.conf
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

2、创建nginx的deployment和service

配置文件如下:

> 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,此时跨域问题就解决了。

二、在集群外部署nginx解决跨域问题

这种方法首先要将后端的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进行配置

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服务时使用。

收起
 2020-02-17
浏览581

提问者

乃伊组特系统管理员, 平安银行

问题状态

  • 发布时间:2020-02-14
  • 关注会员:2 人
  • 问题浏览:1684
  • 最近回答:2020-02-17