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

参考

本文主要学习记录Kubernetes集群暴露服务的方式: Ingress。

简介

Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。

IngressController 为了让 Ingress 资源工作,集群必须有一个正在运行的 Ingress 控制器。

上图清晰标识出了Ingress的流量走向,其中:

  • Ingress基于DNS名称(host)或URL路径把请求转发⾄指定的Service资源的规则。它仅是⼀组路由规则的集合。
  • Ingress控制器是真正实现“流量穿透”,可以由具有反向代理(HTTP/HTTPS)功能的服务程序实现 , 然后根据这些规则的匹配机制路由请求流量

Ingress 资源声明

Ingress是Kubernetes API的标准资源类型之⼀ ,一个最小Ingress例子:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: minimal-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx-example
  rules:
  - http:
      paths:
      - path: /testpath
        pathType: Prefix
        backend:
          service:
            name: test
            port:
              number: 80

其中:

  • Ingress 需要指定 apiVersion、kind、 metadata和 spec 字段。
  • Ingress 对象的命名必须是合法的 DNS 子域名名称。
  • Ingress annotations 来配置一些选项, ⽤于识别其所属的Ingress控制器的类别。
  • Ingress rules 提供了配置负载均衡器或者代理服务器所需的所有信息。 最重要的是,其中包含与所有传入请求匹配的规则列表。 Ingress 资源仅支持用于转发 HTTP(S) 流量的规则。

更多参考: https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/

Ingress Controller

Ingress控制器可以由任何具有反向代理(HTTP/HTTPS)功能的服务程序实现,目前支持和维护 AWS、 GCE 和 Nginx Ingress 控制器。

  • Nginx Ingress 作为反向代理和负载均衡器。
  • Apache APISIX Ingress 控制器 是一个基于 Apache APISIX 网关 的 Ingress 控制器。

更多参考:https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress-controllers/

安装 Ingress Nginx

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.0.0/deploy/static/provider/cloud/deploy.yaml  -O ingress-nginx-deploy.yaml

kubectl apply -f  ingress-nginx-deploy.yaml

观测是否成功:

kubectl get pods -n ingress-nginx --watch

如果成功的话,查看namespace下所有的资源信息

root@master:/home/master# kubectl get all -n ingress-nginx
NAME                                            READY   STATUS    RESTARTS   AGE
pod/ingress-nginx-controller-123456   1/1     Running   0          1h

NAME                                         TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)                      AGE
service/ingress-nginx-controller             LoadBalancer   10.104.182.98    192.168.1.100   80:31666/TCP,443:31888/TCP   1d
service/ingress-nginx-controller-admission   ClusterIP      10.111.228.99   <none>         443/TCP                      1d

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ingress-nginx-controller   1/1     1            1           1d

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/ingress-nginx-controller-123456   1         1         1      1d

NAME                                       COMPLETIONS   DURATION   AGE
job.batch/ingress-nginx-admission-create   1/1           1s         1d
job.batch/ingress-nginx-admission-patch    1/1           2s         1d

使用Ingress 发布 Tomcat

部署Tomcat Service

  1. 创建deployment

        kubectl create deployment web --image=tomcat:8.0.50-jre8-alpine
    
  2. 将 Deployment 暴露出来

    kubectl expose deployment web --type=NodePort --port=8080
    
    
  3. 将 Deployment 暴露出来

    root@master:/home/master# kubectl get service web
        NAME   TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
        web    NodePort   10.100.183.22   <none>        8080:32562/TCP   30s
    
  4. 验证nodeport 是否正常访问 tomcat ,浏览器访问 http://matster_ip:32562

  5. 创建 ingress

 apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: ingressfoo
      annotations:
        kubernetes.io/ingress.class: "nginx"
      namespace: default
    spec:
      rules:
      - host: ingressfoo.io
        http:
          paths:
          - backend:
              service:
                name: web
                port:
                  number: 8080
            path: /bar
            pathType: Prefix

查看ingress是否创建成功

root@master:/home/master# kubectl get ingress
NAME         CLASS    HOSTS                     ADDRESS        PORTS   AGE
ingressfoo   <none>   ingressfoo.io   192.168.1.100   80      1h

说明Ingress创建成功,修改hosts :

ingressfoo.io 192.168.1.100

验证访问 ingressfoo.io/bar

success

参考

jefffff

Stay hungry. Stay Foolish COOL

Go backend developer

China Amoy