圖片來源:https://unsplash.com/photos/y9JdGEU7b5Icss
因爲 nginx 的優秀性能表現,因此不少企業在 Kubernetes 中選擇 Ingress Controller 的時候依然會選擇基於 nginx 的 ingress-nginx(https://kubernetes.github.io/ingress-nginx),前面文章中咱們更多的是介紹更加雲原生配置更加靈活的 Traefik,特別是 Traefik 2.0 版本新增中間件概念之後,在配置上就更加方便了,各類需求均可以經過中間件來實現,對於 ingress-nginx 來講配置就稍微麻煩一點,一些複雜的需求須要經過 Ingress 的 annotation 來實現,好比咱們如今須要實現一個 url rewrite 的功能,簡單來講就是咱們以前的應用在 todo.qikqiak.com 下面,如今咱們須要經過 todo.qikqiak.com/app/ 來進行訪問。nginx
本次測試使用的集羣爲 Kubernetes v1.16.2,ingess-nginx 鏡像版本爲 0.26.1
最原始的 Ingress 對象以下所示:git
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: fe namespace: default annotations: kubernetes.io/ingress.class: "nginx" spec: rules: - host: todo.qikqiak.com http: paths: - backend: serviceName: fe servicePort: 3000 path: /
就是一個很常規的 Ingress 對象,部署該對象後,將域名解析後就能夠正常訪問到應用:github
按照需求咱們須要對訪問的 URL 路徑作一個 Rewrite,在 ingress-nginx 官方文檔中也給出了說明:正則表達式
按照要求咱們須要在 path 中匹配前綴 app,而後經過 rewrite-target 指定目標,修改後的 Ingress 對象以下所示:後端
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: fe namespace: default annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: rules: - host: todo.qikqiak.com http: paths: - backend: serviceName: fe servicePort: 3000 path: /app(/|$)(.*)
更新後,咱們能夠碰見到直接訪問域名確定是不行了,由於咱們沒有匹配 / 的 path 路徑:
可是咱們帶上 app 的前綴再去訪問:api
咱們能夠看到已經能夠訪問到頁面內容了,這是由於咱們在 path 中經過正則表達式 /app(/|$)(.*) 將匹配的路徑設置成了 rewrite-target 的目標路徑了,因此咱們訪問 todo.qikqiak.com/app 的時候實際上至關於訪問的就是後端服務的 / 路徑,可是咱們也能夠發現如今頁面的樣式沒有了:app
這是由於應用的靜態資源路徑是在 /stylesheets 路徑下面的,如今咱們作了 url rewrite 事後,要正常訪問也須要帶上前綴才能夠:http://todo.qikqiak.com/stylesheets/screen.css,對於圖片或者其餘靜態資源也是如此,固然咱們去更改頁面引入靜態資源的方式爲相對路徑也是能夠的,可是畢竟要修改代碼,這個時候咱們能夠藉助 ingress-nginx 中的 configuration-snippet 來對靜態資源作一次跳轉,以下所示:ide
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: fe namespace: default annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/rewrite-target: /$2 nginx.ingress.kubernetes.io/configuration-snippet: | rewrite ^/stylesheets/(.*)$ /app/stylesheets/$1 redirect; # 添加 /app 前綴 rewrite ^/images/(.*)$ /app/images/$1 redirect; # 添加 /app 前綴 spec: rules: - host: todo.qikqiak.com http: paths: - backend: serviceName: fe servicePort: 3000 path: /app(/|$)(.*)
更新 Ingress 對象後,這個時候咱們刷新頁面能夠看到已經正常了:性能
要解決咱們訪問主域名出現 404 的問題,咱們能夠給應用設置一個 app-root 的註解,這樣當咱們訪問主域名的時候會自動跳轉到咱們指定的 app-root 目錄下面,以下所示:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: fe namespace: default annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/app-root: /app/ nginx.ingress.kubernetes.io/rewrite-target: /$2 nginx.ingress.kubernetes.io/configuration-snippet: | rewrite ^/stylesheets/(.*)$ /app/stylesheets/$1 redirect; # 添加 /app 前綴 rewrite ^/images/(.*)$ /app/images/$1 redirect; # 添加 /app 前綴 spec: rules: - host: todo.qikqiak.com http: paths: - backend: serviceName: fe servicePort: 3000 path: /app(/|$)(.*)
這個時候咱們更新應用後訪問主域名 http://todo.qikqiak.com 就會自動跳轉到 http://todo.qikqiak.com/app/ 路徑下面去了。可是還有一個問題是咱們的 path 路徑其實也匹配了 /app 這樣的路徑,可能咱們更加但願咱們的應用在最後添加一個 / 這樣的 slash,一樣咱們能夠經過 configuration-snippet 配置來完成,以下 Ingress 對象:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: fe namespace: default annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/app-root: /app/ nginx.ingress.kubernetes.io/rewrite-target: /$2 nginx.ingress.kubernetes.io/configuration-snippet: | rewrite ^(/app)$ $1/ redirect; rewrite ^/stylesheets/(.*)$ /app/stylesheets/$1 redirect; rewrite ^/images/(.*)$ /app/images/$1 redirect; spec: rules: - host: todo.qikqiak.com http: paths: - backend: serviceName: fe servicePort: 3000 path: /app(/|$)(.*)
更新後咱們的應用就都會以 / 這樣的 slash 結尾了。這樣就完成了咱們的需求,若是你本來對 nginx 的配置就很是熟悉的話應該能夠很快就能理解這種配置方式了,固然若是你仍是喜歡更加簡單明瞭的方式的話能夠推薦使用 Traefik 。