前面我們了解了 APISIX Ingress 的基本使用,同樣我們來介紹下如何使用 APISIX 來實(shí)現(xiàn) URL Rewrite 操作,還是以前面測試用過的 Nexus 應(yīng)用為例進(jìn)行說明,通過 ApisixRoute 對象來配置服務(wù)路由,對應(yīng)的資源清單如下所示:
- # nexus.yaml
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: nexus
- labels:
- app: nexus
- spec:
- selector:
- matchLabels:
- app: nexus
- template:
- metadata:
- labels:
- app: nexus
- spec:
- containers:
- - image: cnych/nexus:3.20.1
- imagePullPolicy: IfNotPresent
- name: nexus
- ports:
- - containerPort: 8081
- ---
- apiVersion: v1
- kind: Service
- metadata:
- labels:
- app: nexus
- name: nexus
- spec:
- ports:
- - name: nexusport
- port: 8081
- targetPort: 8081
- selector:
- app: nexus
- ---
- apiVersion: apisix.apache.org/v2beta2
- kind: ApisixRoute
- metadata:
- name: nexus
- namespace: default
- spec:
- http:
- - name: root
- match:
- hosts:
- - ops.qikqiak.com
- paths:
- - "/*"
- backends:
- - serviceName: nexus
- servicePort: 8081
直接創(chuàng)建上面的資源對象即可:
- ? kubectl apply -f nexus.yaml
- ? kubectl get apisixroute
- NAME HOSTS URIS AGE
- nexus ["ops.qikqiak.com"] ["/*"] 39s
- ? kubectl get pods -l app=nexus
- NAME READY STATUS RESTARTS AGE
- nexus-6f78b79d4c-b79r4 1/1 Running 0 48s
- ? kubectl get svc -l app=nexus
- NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
- nexus ClusterIP 10.102.53.243 <none> 8081/TCP 58s
部署完成后,我們根據(jù) ApisixRoute 對象中的配置,只需要將域名 ops.qikqiak.com 解析到 node2 節(jié)點(diǎn)(上面通過 port-forward 暴露了 80 端口)即可訪問:
url rewrite
同樣如果現(xiàn)在需要通過一個(gè)子路徑來訪問 Nexus 應(yīng)用的話又應(yīng)該怎么來實(shí)現(xiàn)呢?比如通過 http://ops.qikqiak.com/nexus 來訪問我們的應(yīng)用,首先我們肯定需要修改 ApisixRoute 對象中匹配的 paths 路徑,將其修改為 /nexus:
- apiVersion: apisix.apache.org/v2beta2
- kind: ApisixRoute
- metadata:
- name: nexus
- namespace: default
- spec:
- http:
- - name: root
- match:
- hosts:
- - ops.qikqiak.com
- paths:
- - "/nexus*"
- backends:
- - serviceName: nexus
- servicePort: 8081
更新后我們可以通過 http://ops.qikqiak.com/nexus 訪問應(yīng)用:
仔細(xì)分析發(fā)現(xiàn)很多靜態(tài)資源404了,這是因?yàn)楝F(xiàn)在我們只匹配了 /nexus 的請求,而我們的靜態(tài)資源是 /static 路徑開頭的,當(dāng)然就匹配不到了,所以就出現(xiàn)了404,所以我們只需要加上這個(gè) /static 路徑的匹配就可以了,同樣更新 ApisixRoute 對象,新增 /static/* 路徑支持:
- apiVersion: apisix.apache.org/v2beta2
- kind: ApisixRoute
- metadata:
- name: nexus
- namespace: default
- spec:
- http:
- - name: root
- match:
- hosts:
- - ops.qikqiak.com
- paths:
- - "/nexus*"
- - "/static/*"
- backends:
- - serviceName: nexus
- servicePort: 8081
更新后發(fā)現(xiàn)雖然靜態(tài)資源可以正常訪問了,但是當(dāng)我們訪問 http://ops.qikqiak.com/nexus 的時(shí)候依然會(huì)出現(xiàn) 404 錯(cuò)誤。
這是因?yàn)槲覀冞@里是將 /nexus 路徑的請求直接路由到后端服務(wù)去了,而后端服務(wù)沒有對該路徑做任何處理,所以也就是404的響應(yīng)了,在之前 ingress-nginx 或者 traefik 中我們是通過 url 重寫來實(shí)現(xiàn)的,而在 APISIX 中同樣可以實(shí)現(xiàn)這個(gè)處理,相當(dāng)于在請求在真正到達(dá)上游服務(wù)之前將請求的 url 重寫到根目錄就可以了,這里我們需要用到 proxy-rewrite 這個(gè)插件(需要確保在安裝的時(shí)候已經(jīng)包含了該插件),proxy-rewrite 是上游代理信息重寫插件,支持對 scheme、uri、host 等信息的重寫,該插件可配置的屬性如下表所示:
我們現(xiàn)在的需求是希望將所有 /nexus 下面的請求都重寫到根路徑 / 下面去,所以我們應(yīng)該使用 regex_uri 屬性,轉(zhuǎn)發(fā)到上游的新 uri 地址, 使用正則表達(dá)式匹配來自客戶端的 uri,當(dāng)匹配成功后使用模板替換轉(zhuǎn)發(fā)到上游的 uri, 未匹配成功時(shí)將客戶端請求的uri 轉(zhuǎn)發(fā)至上游,重新修改后的 ApisixRoute 對象如下所示,新增 plugins 屬性來配置插件:
- apiVersion: apisix.apache.org/v2beta2
- kind: ApisixRoute
- metadata:
- name: nexus
- namespace: default
- spec:
- http:
- - name: root
- match:
- hosts:
- - ops.qikqiak.com
- paths:
- - "/nexus*"
- - "/static/*"
- plugins:
- - name: proxy-rewrite
- enable: true
- config:
- regex_uri: ["^/nexus(/|$)(.*)", "/$2"]
- backends:
- - serviceName: nexus
- servicePort: 8081
這里我們啟用一個(gè) proxy-rewrite 插件,并且將所有 /nexus 路徑的請求都重寫到了 / 跟路徑下,重新更新后再次訪問 http://ops.qikqiak.com/nexus 應(yīng)該就可以正常訪問了:
只有最后一個(gè)小問題了,從瀏覽器網(wǎng)絡(luò)請求中可以看出我們沒有去匹配 /service 這個(gè)路徑的請求,只需要配置上該路徑即可,如下所示:
- apiVersion: apisix.apache.org/v2beta2
- kind: ApisixRoute
- metadata:
- name: nexus
- namespace: default
- spec:
- http:
- - name: root
- match:
- hosts:
- - ops.qikqiak.com
- paths:
- - "/nexus*"
- - "/static/*"
- - "/service/*"
- plugins:
- - name: proxy-rewrite
- enable: true
- config:
- regex_uri: ["^/nexus(/|$)(.*)", "/$2"]
- backends:
- - serviceName: nexus
- servicePort: 8081
現(xiàn)在重新訪問子路徑就完成正常了:
redirect
現(xiàn)在當(dāng)我們訪問 http://ops.qikqiak.com/nexus 或者 http://ops.qikqiak.com/nexus/ 的時(shí)候都可以得到正常的結(jié)果,一般來說我們可能希望能夠統(tǒng)一訪問路徑,比如訪問 /nexus 子路徑的時(shí)候可以自動(dòng)跳轉(zhuǎn)到 /nexus/ 以 Splash 結(jié)尾的路徑上去。同樣要實(shí)現(xiàn)該需求我們只需要使用一個(gè)名為 redirect 的插件即可,該插件是 URI 重定向插件,可配置的屬性如下所示:
要實(shí)現(xiàn)我們的需求直接使用 regex_uri 這個(gè)屬性即可,只需要去匹配 /nexus 的請求,然后進(jìn)行跳轉(zhuǎn)即可,更新 ApisixRoute 對象:
- apiVersion: apisix.apache.org/v2beta2
- kind: ApisixRoute
- metadata:
- name: nexus
- namespace: default
- spec:
- http:
- - name: root
- match:
- hosts:
- - ops.qikqiak.com
- paths:
- - "/nexus*"
- - "/static/*"
- - "/service/*"
- plugins:
- - name: proxy-rewrite
- enable: true
- config:
- regex_uri: ["^/nexus(/|$)(.*)", "/$2"]
- - name: redirect
- enable: true
- config:
- regex_uri: ["^(/nexus)$", "$1/"]
- backends:
- - serviceName: nexus
- servicePort: 8081
我們新啟用了一個(gè) redirect 插件,并配置 regex_uri: ["^(/nexus)$", "$1/"],這樣當(dāng)訪問 /nexus 的時(shí)候會(huì)自動(dòng)跳轉(zhuǎn)到 /nexus/ 路徑下面去。
同樣如果我們想要重定向到 https,只需要在該插件下面設(shè)置 config.http_to_https=true 即可:
- # ... 其他部分省略
- - name: redirect
- enable: true
- config:
- http_to_https: true
tls
通過使用上面的 redirect 插件配置 http_to_https 可以將請求重定向到 https 上去,但是我們現(xiàn)在并沒有對我們的 ops.qikqiak.com 配置 https 證書,這里我們就需要使用 ApisixTls 對象來進(jìn)行證書管理。
我們先使用 openssl 創(chuàng)建一個(gè)自簽名的證書,當(dāng)然你有正規(guī) CA 機(jī)構(gòu)購買的證書的話直接將證書下載下來使用即可:
- ? openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=ops.qikqiak.com"
然后通過 Secret 對象來引用上面創(chuàng)建的證書文件:
- # 要注意證書文件名稱必須是 tls.crt 和 tls.key
- ? kubectl create secret tls ops-tls --cert=tls.crt --key=tls.key
然后就可以創(chuàng)建一個(gè) ApisixTls 資源對象,引用上面的 Secret 即可:
- apiVersion: apisix.apache.org/v1
- kind: ApisixTls
- metadata:
- name: ops-tls
- spec:
- hosts:
- - ops.qikqiak.com
- secret:
- name: ops-tls
- namespace: default
同時(shí) APISIX TLS 還可以配置 spec.client,用于進(jìn)行 mTLS 雙向認(rèn)證的配置。上面的資源對象創(chuàng)建完成后,即可訪問 https 服務(wù)了(chrome 瀏覽器默認(rèn)會(huì)限制不安全的證書,只需要在頁面上輸入 thisisunsafe 即可訪問了):
而且當(dāng)訪問 http 的時(shí)候也會(huì)自動(dòng)跳轉(zhuǎn)到 https 上面去,此外我們還可以結(jié)合 cert-manager 來實(shí)現(xiàn)自動(dòng)化的 https。
完整的資源對象如下所示:
- apiVersion: apisix.apache.org/v2beta2
- kind: ApisixRoute
- metadata:
- name: nexus
- namespace: default
- spec:
- http:
- - name: root
- match:
- hosts:
- - ops.qikqiak.com
- paths:
- - "/nexus*"
- - "/static/*"
- - "/service/*"
- plugins:
- - name: proxy-rewrite
- enable: true
- config:
- regex_uri: ["^/nexus(/|$)(.*)", "/$2"]
- - name: redirect
- enable: true
- config:
- regex_uri: ["^(/nexus)$", "$1/"]
- - name: redirect
- enable: true
- config:
- http_to_https: true
- backends:
- - serviceName: nexus
- servicePort: 8081
- ---
- apiVersion: apisix.apache.org/v1
- kind: ApisixTls
- metadata:
- name: ops-tls
- spec:
- hosts:
- - ops.qikqiak.com
- secret:
- name: ops-tls
- namespace: default
關(guān)于 APISIX Ingress 更多高級用法請繼續(xù)關(guān)注后續(xù)文章。
原文鏈接:https://mp.weixin.qq.com/s/P6I_27d3rjmN0Ls_aZMHUA