上篇文章介紹了 Contour 分布式架構的工作原理,順便簡單介紹了下 IngressRoute 的使用方式。本文將探討 IngressRoute 更高級的用法,其中級聯功能是重點。
1. IngressRoute 大入門
上篇文章在 examples/example-workload 目錄下創建了一個示例應用,我們來回顧一下它的 IngressRoute 配置:
apiVersion: contour.heptio.com/v1beta1
kind: IngressRoute
metadata:
labels:
app: kuard
name: kuard
namespace: default
spec:
virtualhost:
fqdn: kuard.local
routes:
- match: /
services:
- name: kuard
port: 80
- virtualhost : 該字段是 root IngressRoute,表示此域的頂級入口點。
- fqdn : 該字段指定了完整的域名,可以通過在 HTTP 請求頭中指定
Host:字段來訪問該服務。
這是最簡單是使用方法,看起來沒什么特別的,我們來稍作修改一下:
apiVersion: contour.heptio.com/v1beta1
kind: IngressRoute
metadata:
labels:
app: kuard
name: kuard
namespace: default
spec:
virtualhost:
fqdn: kuard.local
routes:
- match: /test
services:
- name: kuard
port: 80
將 match: / 改為 match: /test,然后重新應用新規則。這時如果你訪問 url kuard.local/test 是不通的,因為 kuard 服務本身並沒有 /test 這個路徑,我們可以強制將路徑重寫為 /:
apiVersion: contour.heptio.com/v1beta1
kind: IngressRoute
metadata:
labels:
app: kuard
name: kuard
namespace: default
spec:
virtualhost:
fqdn: kuard.local
routes:
- match: /test
prefixRewrite: "/"
services:
- name: kuard
port: 80
重新 apply 之后,再次訪問 url kuard.local/test 就通了。
這里可以和標准的 ingress 對象對比一下,IngressRoute 的優勢在於它可以分別對每個路由設置 rewrite 規則,而 Nginx Ingress Controller 只能設置全局的 rewrite 規則,因為它用的是 annotations。雖然可以通過其他手段來實現,但相對來說會比較麻煩。
2. 級聯功能介紹
下面我們來看看 IngressRoute 的級聯功能,這是個非常有特色的功能,你可以通過級聯多個路由規則,上層 IngressRoute 的配置被下層繼承。例如,我們可以將 url 路徑 / 的路由規則級聯到其他的 IngressRoute 中,其他的 IngressRoute 可以來自不同的 namespace。
舉個例子,我們可以先創建一個這樣的 IngressRoute:
$ cat > delegate-from-main.yaml <<EOF
apiVersion: contour.heptio.com/v1beta1
kind: IngressRoute
metadata:
name: delegate-from-main
spec:
routes:
- match: /
services:
- name: kuard
port: 80
EOF
$ kubectl apply -f delegate-from-main.yaml
$ kubectl get ingressroute delegate-from-main -o jsonpath='{.status.currentStatus}'
orphaned
該 IngressRoute 的狀態為 orphaned,因為它沒有包含一個合法的 fqdn。接下來需要創建一個 root IngressRoute 來和它進行級聯:
apiVersion: contour.heptio.com/v1beta1
kind: IngressRoute
metadata:
labels:
app: kuard
name: kuard
namespace: default
spec:
virtualhost:
fqdn: kuard.local
routes:
- match: /
delegate:
name: delegate-from-main
namespace: default
這時如果再檢查 IngressRoute delegate-from-main 的狀態,就會發現它從 orphaned 狀態變成了 valid 狀態,kuard.local 也能夠順利訪問。
了解了級聯功能的用法之后,下面就來看看它的應用場景。
- 場景一:可以使用級聯功能來做藍綠部署和灰度發布,只需要在上層 IngressRoute 中稍作修改,切換到另一個下層 IngressRoute,就可以切換流量的處理規則。
- 場景二:管理員可以利用級聯功能將部分 ingress 的權限放行到其他的
namespace中,在這些 namespace 中,用戶可以自由更新與 root IngressRoute 級聯的相關的 IngressRoute。例如,如果管理員想防止其他用戶配置非法的域名或路徑,可以將該部分的配置權限放到 root IngressRoute 中,其他namespace中的下層 IngressRoute 中只能配置各自的路徑相關信息。
接下來主要探討場景一。
3. 藍綠部署
藍綠部署簡單來講就是在生產環境中有兩套系統:一套是正在提供服務的系統,標記為“綠色”;另一套是准備發布的系統,標記為“藍色”。兩套系統都是功能完善的,並且正在運行的系統,只是系統版本和對外服務情況不同。
最初,沒有任何系統,沒有藍綠之分。
然后,第一套系統開發完成,直接上線,這個過程只有一個系統,也沒有藍綠之分。
后來,開發了新版本,要用新版本替換線上的舊版本,在線上的系統之外,搭建了一個使用新版本代碼的全新系統。 這時候,一共有兩套系統在運行,正在對外提供服務的老系統是綠色系統,新部署的系統是藍色系統。

藍色系統不對外提供服務,用來做啥?
用來做發布前測試,測試過程中發現任何問題,可以直接在藍色系統上修改,不干擾用戶正在使用的系統。(注意,兩套系統沒有耦合的時候才能百分百保證不干擾)
藍色系統經過反復的測試、修改、驗證,確定達到上線標准之后,直接將用戶切換到藍色系統:

切換后的一段時間內,依舊是藍綠兩套系統並存,但是用戶訪問的已經是藍色系統。這段時間內觀察藍色系統(新系統)工作狀態,如果出現問題,直接切換回綠色系統。
當確信對外提供服務的藍色系統工作正常,不對外提供服務的綠色系統已經不再需要的時候,藍色系統正式成為對外提供服務系統,成為新的綠色系統。 原先的綠色系統可以銷毀,將資源釋放出來,用於部署下一個藍色系統。
通過 IngressRoute 的級聯功能可以很方便地實現藍綠部署策略,首先創建一個上層的 root IngressRoute(假設名為 root-blog),然后將域名 yangcs.net/blogs 的路由策略級聯到下層的 IngressRoute(名為 blog)。我們會同時部署”藍色“版本和”綠色“版本的應用,此時只有”綠色“版本接收流量。
---
apiVersion: contour.heptio.com/v1beta1
kind: IngressRoute
metadata:
name: root-blog
namespace: root-ingressroute
spec:
virtualhost:
fqdn: yangcs.net
tls:
secretName: yangcs-net
routes:
- match: /blog
delegate:
name: blog
namespace: marketing
---
apiVersion: contour.heptio.com/v1beta1
kind: IngressRoute
metadata:
name: blog
namespace: marketing
spec:
routes:
- match: /blog
services:
- name: green
port: 80
---
apiVersion: contour.heptio.com/v1beta1
kind: IngressRoute
metadata:
name: blog2
namespace: marketing
spec:
routes:
- match: /blog
services:
- name: blue
port: 80
在對藍色版本進行測試驗證之后,就可以將用戶切換到藍色應用了:
apiVersion: contour.heptio.com/v1beta1
kind: IngressRoute
metadata:
name: root-blog
namespace: root-ingressroute
spec:
virtualhost:
fqdn: yangcs.net
tls:
secretName: yangcs-net
routes:
- match: /blog
delegate:
name: blog2
namespace: marketing
4. 金絲雀發布
金絲雀發布(Canary)也是一種發布策略,和國內常說的灰度發布是同一類策略。它和藍綠有點像,但是它更加規避風險。你可以階段性的進行,而不用一次性從藍色版本切換到綠色版本。
采用金絲雀部署,你可以在生產環境的基礎設施中小范圍的部署新的應用代碼。一旦應用簽署發布,只有少數用戶被路由到它,可以最大限度的降低影響。
如果沒有錯誤發生,把剩余的 V1 版本全部升級為 V2 版本。如果有錯誤發生,則直接回退到老版本,發布失敗。下圖示范了金絲雀部署:

其實金絲雀發布的名稱來源於一個典故。在 17 世紀,英國礦井工人發現,金絲雀對瓦斯這種氣體特別敏感,空氣中哪怕有極其微量的瓦斯,金絲雀也會停止唱歌。當瓦斯含量超過一定限度時,人類毫無察覺,但金絲雀卻會毒發身亡。當時在采礦設備相對簡陋的條件下,工人們每次下井都會帶上一只金絲雀作為”瓦斯檢測指標“,以便在危險情況下緊急撤離。映射到這里就是先發布一小部分來試探整體是否能夠正常運行,如果能正常運行則進行完全部署的發布方式,目前仍然是不少成長型技術組織的主流發布方式。

IngressRoute 可以通過分配權重來實現金絲雀發布,和藍綠部署一樣,首先創建一個上層的 root IngressRoute(名為 root-blog),然后將域名 yangcs.net/blogs 的路由策略級聯到下層的 IngressRoute(名為 blog)。在下層的 IngressRoute 中將流量按不同權重轉發到不同的后端服務。
apiVersion: contour.heptio.com/v1beta1
kind: IngressRoute
metadata:
name: blog
namespace: marketing
spec:
routes:
- match: /blog
services:
- name: green
port: 5
- name: blue
port: 95
如果沒有錯誤發生,就將 green 的權重調整為 100,blue 的權重調整為 0。至此就完成了金絲雀發布。
本文主要介紹了 IngressRoute 級聯功能的用法,探討了如何使用級聯功能來實現藍綠部署和金絲雀發布,后面的文章將會陸續探討其他的流量治理功能。
5. 參考資料
微信公眾號
掃一掃下面的二維碼關注微信公眾號,在公眾號中回復◉加群◉即可加入我們的雲原生交流群,和孫宏亮、張館長、陽明等大佬一起探討雲原生技術

