APISIX Ingress 高级使用之 Url Rewrite

运维 系统运维
前面我们了解了 APISIX Ingress 的基本使用,同样我们来介绍下如何使用 APISIX 来实现 URL Rewrite 操作,还是以前面测试用过的 Nexus 应用为例进行说明,通过 ApisixRoute 对象来配置服务路由.

前面我们了解了 APISIX Ingress 的基本使用,同样我们来介绍下如何使用 APISIX 来实现 URL Rewrite 操作,还是以前面测试用过的 Nexus 应用为例进行说明,通过 ApisixRoute 对象来配置服务路由,对应的资源清单如下所示:

  1. # nexus.yaml 
  2. apiVersion: apps/v1 
  3. kind: Deployment 
  4. metadata: 
  5.   name: nexus 
  6.   labels: 
  7.     app: nexus 
  8. spec: 
  9.   selector: 
  10.     matchLabels: 
  11.       app: nexus 
  12.   template: 
  13.     metadata: 
  14.       labels: 
  15.         app: nexus 
  16.     spec: 
  17.       containers: 
  18.       - image: cnych/nexus:3.20.1 
  19.         imagePullPolicy: IfNotPresent 
  20.         name: nexus 
  21.         ports: 
  22.         - containerPort: 8081 
  23. --- 
  24. apiVersion: v1 
  25. kind: Service 
  26. metadata: 
  27.   labels: 
  28.     app: nexus 
  29.   name: nexus 
  30. spec: 
  31.   ports: 
  32.   - name: nexusport 
  33.     port: 8081 
  34.     targetPort: 8081 
  35.   selector: 
  36.     app: nexus 
  37. --- 
  38. apiVersion: apisix.apache.org/v2beta2 
  39. kind: ApisixRoute 
  40. metadata: 
  41.   name: nexus 
  42.   namespace: default 
  43. spec: 
  44.   http: 
  45.     - name: root 
  46.       match: 
  47.         hosts: 
  48.           - ops.qikqiak.com 
  49.         paths: 
  50.           - "/*" 
  51.       backends: 
  52.       - serviceName: nexus 
  53.         servicePort: 8081 

直接创建上面的资源对象即可:

  1. ➜ kubectl apply -f nexus.yaml 
  2. ➜ kubectl get apisixroute 
  3. NAME    HOSTS                   URIS     AGE 
  4. nexus   ["ops.qikqiak.com"]   ["/*"]   39s 
  5. ➜ kubectl get pods -l app=nexus 
  6. NAME                     READY   STATUS    RESTARTS   AGE 
  7. nexus-6f78b79d4c-b79r4   1/1     Running   0          48s 
  8. ➜ kubectl get svc -l app=nexus 
  9. NAME    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE 
  10. nexus   ClusterIP   10.102.53.243   <none>        8081/TCP   58s 

部署完成后,我们根据 ApisixRoute 对象中的配置,只需要将域名 ops.qikqiak.com 解析到 node2 节点(上面通过 port-forward 暴露了 80 端口)即可访问:

url rewrite

同样如果现在需要通过一个子路径来访问 Nexus 应用的话又应该怎么来实现呢?比如通过 http://ops.qikqiak.com/nexus 来访问我们的应用,首先我们肯定需要修改 ApisixRoute 对象中匹配的 paths 路径,将其修改为 /nexus:

  1. apiVersion: apisix.apache.org/v2beta2 
  2. kind: ApisixRoute 
  3. metadata: 
  4.   name: nexus 
  5.   namespace: default 
  6. spec: 
  7.   http: 
  8.     - name: root 
  9.       match: 
  10.         hosts: 
  11.           - ops.qikqiak.com 
  12.         paths: 
  13.           - "/nexus*" 
  14.       backends: 
  15.       - serviceName: nexus 
  16.         servicePort: 8081 

更新后我们可以通过 http://ops.qikqiak.com/nexus 访问应用:

仔细分析发现很多静态资源404了,这是因为现在我们只匹配了 /nexus 的请求,而我们的静态资源是 /static 路径开头的,当然就匹配不到了,所以就出现了404,所以我们只需要加上这个 /static 路径的匹配就可以了,同样更新 ApisixRoute 对象,新增 /static/* 路径支持:

  1. apiVersion: apisix.apache.org/v2beta2 
  2. kind: ApisixRoute 
  3. metadata: 
  4.   name: nexus 
  5.   namespace: default 
  6. spec: 
  7.   http: 
  8.     - name: root 
  9.       match: 
  10.         hosts: 
  11.           - ops.qikqiak.com 
  12.         paths: 
  13.           - "/nexus*" 
  14.           - "/static/*" 
  15.       backends: 
  16.       - serviceName: nexus 
  17.         servicePort: 8081 

更新后发现虽然静态资源可以正常访问了,但是当我们访问 http://ops.qikqiak.com/nexus 的时候依然会出现 404 错误。

这是因为我们这里是将 /nexus 路径的请求直接路由到后端服务去了,而后端服务没有对该路径做任何处理,所以也就是404的响应了,在之前 ingress-nginx 或者 traefik 中我们是通过 url 重写来实现的,而在 APISIX 中同样可以实现这个处理,相当于在请求在真正到达上游服务之前将请求的 url 重写到根目录就可以了,这里我们需要用到 proxy-rewrite 这个插件(需要确保在安装的时候已经包含了该插件),proxy-rewrite 是上游代理信息重写插件,支持对 scheme、uri、host 等信息的重写,该插件可配置的属性如下表所示:

我们现在的需求是希望将所有 /nexus 下面的请求都重写到根路径 / 下面去,所以我们应该使用 regex_uri 属性,转发到上游的新 uri 地址, 使用正则表达式匹配来自客户端的 uri,当匹配成功后使用模板替换转发到上游的 uri, 未匹配成功时将客户端请求的uri 转发至上游,重新修改后的 ApisixRoute 对象如下所示,新增 plugins 属性来配置插件:

  1. apiVersion: apisix.apache.org/v2beta2 
  2. kind: ApisixRoute 
  3. metadata: 
  4.   name: nexus 
  5.   namespace: default 
  6. spec: 
  7.   http: 
  8.     - name: root 
  9.       match: 
  10.         hosts: 
  11.           - ops.qikqiak.com 
  12.         paths: 
  13.           - "/nexus*" 
  14.           - "/static/*" 
  15.       plugins: 
  16.       - name: proxy-rewrite 
  17.         enable: true 
  18.         config: 
  19.           regex_uri: ["^/nexus(/|$)(.*)""/$2"
  20.       backends: 
  21.       - serviceName: nexus 
  22.         servicePort: 8081 

这里我们启用一个 proxy-rewrite 插件,并且将所有 /nexus 路径的请求都重写到了 / 跟路径下,重新更新后再次访问 http://ops.qikqiak.com/nexus 应该就可以正常访问了:

只有最后一个小问题了,从浏览器网络请求中可以看出我们没有去匹配 /service 这个路径的请求,只需要配置上该路径即可,如下所示:

  1. apiVersion: apisix.apache.org/v2beta2 
  2. kind: ApisixRoute 
  3. metadata: 
  4.   name: nexus 
  5.   namespace: default 
  6. spec: 
  7.   http: 
  8.     - name: root 
  9.       match: 
  10.         hosts: 
  11.           - ops.qikqiak.com 
  12.         paths: 
  13.           - "/nexus*" 
  14.           - "/static/*" 
  15.           - "/service/*" 
  16.       plugins: 
  17.       - name: proxy-rewrite 
  18.         enable: true 
  19.         config: 
  20.           regex_uri: ["^/nexus(/|$)(.*)""/$2"
  21.       backends: 
  22.       - serviceName: nexus 
  23.         servicePort: 8081 

现在重新访问子路径就完成正常了:

redirect

现在当我们访问 http://ops.qikqiak.com/nexus 或者 http://ops.qikqiak.com/nexus/ 的时候都可以得到正常的结果,一般来说我们可能希望能够统一访问路径,比如访问 /nexus 子路径的时候可以自动跳转到 /nexus/ 以 Splash 结尾的路径上去。同样要实现该需求我们只需要使用一个名为 redirect 的插件即可,该插件是 URI 重定向插件,可配置的属性如下所示:

要实现我们的需求直接使用 regex_uri 这个属性即可,只需要去匹配 /nexus 的请求,然后进行跳转即可,更新 ApisixRoute 对象:

  1. apiVersion: apisix.apache.org/v2beta2 
  2. kind: ApisixRoute 
  3. metadata: 
  4.   name: nexus 
  5.   namespace: default 
  6. spec: 
  7.   http: 
  8.     - name: root 
  9.       match: 
  10.         hosts: 
  11.           - ops.qikqiak.com 
  12.         paths: 
  13.           - "/nexus*" 
  14.           - "/static/*" 
  15.           - "/service/*" 
  16.       plugins: 
  17.       - name: proxy-rewrite 
  18.         enable: true 
  19.         config: 
  20.           regex_uri: ["^/nexus(/|$)(.*)""/$2"
  21.       - name: redirect 
  22.         enable: true 
  23.         config: 
  24.           regex_uri: ["^(/nexus)$""$1/"
  25.       backends: 
  26.       - serviceName: nexus 
  27.         servicePort: 8081 

我们新启用了一个 redirect 插件,并配置 regex_uri: ["^(/nexus)$", "$1/"],这样当访问 /nexus 的时候会自动跳转到 /nexus/ 路径下面去。

同样如果我们想要重定向到 https,只需要在该插件下面设置 config.http_to_https=true 即可:

  1. # ... 其他部分省略 
  2. name: redirect 
  3.   enable: true 
  4.   config: 
  5.     http_to_https: true 

tls

通过使用上面的 redirect 插件配置 http_to_https 可以将请求重定向到 https 上去,但是我们现在并没有对我们的 ops.qikqiak.com 配置 https 证书,这里我们就需要使用 ApisixTls 对象来进行证书管理。

我们先使用 openssl 创建一个自签名的证书,当然你有正规 CA 机构购买的证书的话直接将证书下载下来使用即可:

  1. ➜ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=ops.qikqiak.com" 

然后通过 Secret 对象来引用上面创建的证书文件:

  1. # 要注意证书文件名称必须是 tls.crt 和 tls.key 
  2. ➜ kubectl create secret tls ops-tls --cert=tls.crt --key=tls.key 

然后就可以创建一个 ApisixTls 资源对象,引用上面的 Secret 即可:

  1. apiVersion: apisix.apache.org/v1 
  2. kind: ApisixTls 
  3. metadata: 
  4.   name: ops-tls 
  5. spec: 
  6.   hosts: 
  7.     - ops.qikqiak.com 
  8.   secret: 
  9.     name: ops-tls 
  10.     namespace: default 

同时 APISIX TLS 还可以配置 spec.client,用于进行 mTLS 双向认证的配置。上面的资源对象创建完成后,即可访问 https 服务了(chrome 浏览器默认会限制不安全的证书,只需要在页面上输入 thisisunsafe 即可访问了):

而且当访问 http 的时候也会自动跳转到 https 上面去,此外我们还可以结合 cert-manager 来实现自动化的 https。

完整的资源对象如下所示:

  1. apiVersion: apisix.apache.org/v2beta2 
  2. kind: ApisixRoute 
  3. metadata: 
  4.   name: nexus 
  5.   namespace: default 
  6. spec: 
  7.   http: 
  8.     - name: root 
  9.       match: 
  10.         hosts: 
  11.           - ops.qikqiak.com 
  12.         paths: 
  13.           - "/nexus*" 
  14.           - "/static/*" 
  15.           - "/service/*" 
  16.       plugins: 
  17.       - name: proxy-rewrite 
  18.         enable: true 
  19.         config: 
  20.           regex_uri: ["^/nexus(/|$)(.*)""/$2"
  21.       - name: redirect 
  22.         enable: true 
  23.         config: 
  24.           regex_uri: ["^(/nexus)$""$1/"
  25.       - name: redirect 
  26.         enable: true 
  27.         config: 
  28.           http_to_https: true 
  29.       backends: 
  30.       - serviceName: nexus 
  31.         servicePort: 8081 
  32. --- 
  33. apiVersion: apisix.apache.org/v1 
  34. kind: ApisixTls 
  35. metadata: 
  36.   name: ops-tls 
  37. spec: 
  38.   hosts: 
  39.     - ops.qikqiak.com 
  40.   secret: 
  41.     name: ops-tls 
  42.     namespace: default 

关于 APISIX Ingress 更多高级用法请继续关注后续文章。

 

责任编辑:姜华 来源: k8s技术圈
相关推荐

2022-01-19 22:14:36

Apache APIAPI 网关插件

2021-01-29 09:58:10

ACKKubernetes模块

2023-08-21 11:09:38

IngressNginxApache

2009-07-27 17:15:51

URL RewriteASP.NET

2022-02-23 21:10:53

LonghornKubernetes快照

2009-07-22 14:23:39

URL RewriteASP.NET

2009-07-16 17:40:48

iBATIS高级查询iBATIS使用

2009-01-04 13:27:10

URL RewriteIISASP.NET

2022-01-14 09:17:13

PythonAPISIX插件

2021-09-26 07:43:08

KongKongaK8s

2009-09-24 09:26:22

ASP.NET MVC

2009-07-15 09:42:56

MyEclipse使用

2009-07-15 09:59:36

MyEclipse使用

2009-07-15 09:59:36

MyEclipse使用

2009-07-09 09:38:43

JDK使用图解

2010-07-20 16:30:44

MySQL内存

2010-07-20 16:34:54

MySQL内存

2021-07-15 09:57:39

Wireshark数据包长度

2021-12-22 07:47:42

Kubernetes 运维开源

2011-08-03 14:13:45

Xcode 4 Interface
点赞
收藏

51CTO技术栈公众号