Apache APISIX 是 Apache 软件基金会下的云原生 API 网关,它兼具动态、实时、高性能等特点,提供了负载均衡、动态上游、灰度发布(金丝雀发布)、服务熔断、身份认证、可观测性等丰富的流量管理功能。很多场景下,我们可以选择在APISIX中使用CORS(跨源资源共享)来解决跨域问题。

APISIX提供了CRD和Annotations模式来启用CORS。本文主要介绍如何在APISIX Ingress Annotations模式下启用CORS。

环境:

应用 信息
Kubernetes v1.25.7
apisix apache/apisix:3.4.0-debian
apisix-ingress-controller apache/apisix-ingress-controller:1.6.0

IngressAnnotations模式

IngressAnnotations模式,可以通过在Ingress资源上添加注释来配置APISIX的行为。比如添加一个CORS注释来指示APISIX启用CORS:

annotations
    k8s.apisix.apache.org/enable-cors: "true"
    kubernetes.io/ingress.class: apisix

接着,我们以给一个Http服务my-service, 创建了一个Ingress资源的例子来演示, Ingress详细如下:

创建Ingress

创建my-service的ingress资源:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: match-ingress
  namespace: my-ns
  annotations:
    k8s.apisix.apache.org/enable-cors: "true"
    kubernetes.io/ingress.class: apisix
spec:
  rules:
  - http:
      paths:
      - backend:
          service:
            name: my-service
            port:
              number: 8000
        path: /v2
        pathType: Prefix

在这个示例中,我们添加了【k8s.apisix.apache.org/enable-cors: “true”】的注释, 即启用cors功能,默认允许来自任何源的请求访问my-service的API。

Dashboard启用CORS

打开APISIX Dashboard界面:在【插件】中查找“CORS” 。单击该插件,然后单击“启用”。

然后,可以在路由点击查看my-service的对应路由,如下:

{
  "uris": [
    "/v2/",
    "/v2/*"
  ],
  "name": "ing_my-service-ingress_cfc81dbe",
  "desc": "Created by apisix-ingress-controller, DO NOT modify it manually",
  "plugins": {
    "cors": {
      "allow_credential": false,
      "allow_headers": "*",
      "allow_methods": "*",
      "allow_origins": "*",
      "expose_headers": "*",
      "max_age": 5
    }
  },
  "upstream_id": "7c630009",
  "labels": {
    "managed-by": "apisix-ingress-controller"
  },
  "status": 1
}

plugins.cors为跨域的对应规则配置,说明插件启用成功。

测试

然后我们向my-service的发起一个测试请求:

curl -i -k 'http://[my-cluster-ip:nodeport]/v2/my-service/api/geeker'   -X OPTIONS \
   -H "Access-Control-Allow-Origin: *" \
   -H "Access-Control-Request-Method: POST" \
   -H "Access-Control-Request-Headers: content-type" \
   -H "Origin: http://localhost/" 
   

输出:

HTTP/1.1 200 OK
Date: Sat, 15 Jul 2023 13:53:57 GMT
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: APISIX/3.4.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: *
Access-Control-Max-Age: 5
Access-Control-Expose-Headers: *
Access-Control-Allow-Headers: *

如果返回结果中出现 CORS 相关的 header( ccess-Control-Allow-Origin: * < Access-Control-Allow-Methods: * < Access-Control-Allow-Headers: * < Access-Control-Expose-Headers: * < Access-Control-Max-Age: 5 ),则代表插件生效、跨域成功。

遇到的问题

在增加好ingress后测试API,发现没有CORS 相关的 header

,跨域失败

HTTP/1.1 200 OK
Content-Length: 0
Connection: keep-alive
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Origin: *
Date: Sat, 15 Jul 2023 13:46:16 GMT
Server: APISIX/3.4.0

经检查,是ApiSix的config配置有误,在配置的插件里,开启了其他插件,没有包括cors,导致插件不生效。去掉后,重启插件配置生效、跨域成功。

plugins:
  # the plugins you enabled
  - log-rotate
  - proxy-rewrite

参考