原文html
在學習像 Istio 這樣的新技術時,看一下示例應用程序老是一個好主意。 Istio repo 有一些示例應用程序,但它們彷佛有各類不足。 文檔中的 BookInfo 是一個很好的示例。 可是,對於我而言,它太冗長,服務太多,並且文檔彷佛專一於管理 BookInfo 應用程序,而不是從頭開始構建。 有一個較小的 hellohttp 例子,但它更多的是關於自動伸縮而不是其餘。shell
在這篇文章中,我想介紹一下基礎知識,並向您展現如何從頭開始構建支持 Istio 的「hellohttp」應用程序。 要記住的一點是,Istio 只管理您應用的流量。 在這種狀況下,應用程序生命週期由底層平臺 Kubernetes 管理。 所以,您須要瞭解容器和 Kubernetes 基礎知識,而且須要瞭解 Istio Routing 原語,例如 Gateway,VirtualService,DestinationRule。 我假設大多數人都知道容器和 Kubernetes 基礎知識。 我將在本文中專一於 Istio Routing。api
如下這些大體就是您須要遵循的,以得到 Istio 的「hellohttp」應用程序的步驟:瀏覽器
我不會在本文中介紹步驟 1 和 2,由於它們不是特定於 Istio 的。 若是您須要有關這些步驟的幫助,能夠查看我在本文末尾提到的文章。 第 3 步也不是 Istio 特定的,但它是其餘一切的先決條件,因此讓咱們從那開始。app
正如我所提到的,應用程序生命週期由 Kubernetes 管理。 所以,您須要從建立 Kubernetes deployment 和 service 開始。 個人狀況以下,我有一個容器化的 ASP.NET 核心應用程序,其鏡像我已經推送到谷歌鏡像倉庫。 讓咱們從建立一個hellohttp-deploy.yaml.yaml
文件開始:負載均衡
apiVersion: v1 kind: Service metadata: name: hellohttp-service labels: app: hellohttp spec: ports: - port: 80 name: http selector: app: hellohttp --- apiVersion: apps/v1 kind: Deployment metadata: name: hellohttp-v1 spec: replicas: 1 selector: matchLabels: app: hellohttp version: v1 template: metadata: labels: app: hellohttp version: v1 spec: containers: - name: hellohttp image: busybox imagePullPolicy: IfNotPresent command: ["/bin/sh", "-c", "echo 'hello httpd v1' > /var/www/index.html; httpd -f -p 80 -h /var/www/"] ports: - containerPort: 80
建立 Deployment 和 Service:ide
$ kubectl apply -f hellohttp-deploy.yaml service "hellohttp-service" created deployment.extensions "hellohttp-v1" created
到目前爲止沒有任何特定的針對 Istio 的內容。學習
咱們如今能夠開始研究 Istio Routing。 首先,咱們須要爲服務網格啓用 HTTP/HTTPS 流量。 爲此,咱們須要建立一個網關。 Gateway 描述了在邊緣運行的負載均衡,用於接收傳入或傳出的 HTTP/TCP 鏈接。測試
讓咱們建立一個hellohttp-gateway.yaml
文件:google
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: hellohttp-gateway spec: selector: istio: ingressgateway # use istio default controller servers: - port: number: 80 name: http protocol: HTTP hosts: - "hellohttp.com"
建立 Gateway:
$ kubectl apply -f hellohttp-gateway.yaml gateway.networking.istio.io "hellohttp-gateway" created
此時,咱們爲集羣啓用了 HTTP 流量。 咱們須要將以前建立的 Kubernetes 服務映射到 Gateway。 咱們將使用 VirtualService 執行此操做。
VirtualService 實際上將 Kubernetes 服務鏈接到 Istio 網關。 它還能夠執行更多操做,例如定義一組流量路由規則,以便在主機被尋址時應用,但咱們不會深刻了解這些細節。
讓咱們建立一個hellohttp-virtualservice.yaml
文件:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: hellohttp-virtualservice spec: hosts: - "hellohttp.com" gateways: - hellohttp-gateway http: - route: - destination: host: hellohttp-service
請注意,VirtualService 與特定網關綁定,並定義引用 Kubernetes 服務的主機。
建立 VirtualService:
$ kubectl apply -f hellohttp-virtualservice.yaml virtualservice.networking.istio.io "hellohttp-virtualservice" created
咱們準備測試咱們的應用程序了。 咱們須要獲取 Istio Ingress Gateway 的 IP 地址:
$ istio-ingressgateway NodePort 10.109.111.38 <none> 15020:32105/TCP,80:30824/TCP,443:32478/TCP,31400:32419/TCP,15443:30884/TCP 4d
當咱們在瀏覽器中打開NodePort-IP
時,咱們應該看到 hellohttp ASP.NET Core 應用程序:
在某些時候,您但願將應用更新爲新版本。 也許你想分割兩個版本之間的流量。 您須要建立一個 DestinationRule 來定義是哪些版本,在 Istio 中稱爲 subset。
首先,更新 hellohttp-deploy.yaml
文件以使用 v2 版本的容器定義 v2 的 deployment:
apiVersion: v1 kind: Service metadata: name: hellohttp-service labels: app: hellohttp spec: ports: - port: 80 name: http selector: app: hellohttp --- apiVersion: apps/v1 kind: Deployment metadata: name: hellohttp-v1 spec: replicas: 1 selector: matchLabels: app: hellohttp version: v1 template: metadata: labels: app: hellohttp version: v1 spec: containers: - name: hellohttp image: busybox imagePullPolicy: IfNotPresent command: ["/bin/sh", "-c", "echo 'hello httpd v1' > /var/www/index.html; httpd -f -p 80 -h /var/www/"] ports: - containerPort: 80 --- apiVersion: apps/v1 kind: Deployment metadata: name: hellohttp-v2 spec: replicas: 1 selector: matchLabels: app: hellohttp version: v2 template: metadata: labels: app: hellohttp version: v2 spec: containers: - name: hellohttp image: busybox imagePullPolicy: IfNotPresent command: ["/bin/sh", "-c", "echo 'hello httpd v2' > /var/www/index.html; httpd -f -p 80 -h /var/www/"] ports: - containerPort: 80
建立新的 Deployment:
$ kubectl apply -f hellohttp-deploy.yaml service "hellohttp-service" unchanged deployment.extensions "hellohttp-v1" unchanged deployment.extensions "hellohttp-v2" created
若是使用 EXTERNAL-IP 刷新瀏覽器,您將看到應用程序的 v1 和 v2 版本交替出現:
這是符合預期的,由於兩個版本都暴露在相同的 Kubernetes 服務以後:hellohttp-service。
若是您想將服務僅指向 v2,該怎麼辦? 這能夠經過在 VirtualService 中指定 subset 來完成,但咱們須要首先在 DestinationRules 中定義這些 subset。 DestinationRule 本質上是將標籤映射到 Istio 的 subset。
建立一個hellohttp-destinationrule.yaml
文件:
apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: hellohttp-destinationrule spec: host: hellohttp-service trafficPolicy: tls: mode: ISTIO_MUTUAL subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2
建立 DestinationRule:
$ kubectl apply -f hellohttp-destinationrule.yaml destinationrule.networking.istio.io "hellohttp-destinationrule" created
如今你能夠從 VirtualService 來引用 v2 subset:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: hellohttp-virtualservice spec: hosts: - "hellohttp.com" gateways: - hellohttp-gateway http: - route: - destination: host: hellohttp-service subset: v2
更新 VirtualService:
$ kubectl apply -f hellohttp-virtualservice.yaml virtualservice.networking.istio.io "hellohttp-virtualservice" configured
若是您如今繼續瀏覽 EXTERNAL-IP,您如今應該只能看到應用程序的 v2 版本。
能夠從 VirtualService 來引用v2 subset和v1 subset
[root@localhost hello-world]# cat hellohttp-virtualservice.yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: hellohttp-virtualservice spec: hosts: - "hellohttp.com" gateways: - hellohttp-gateway http: - route: - destination: host: hellohttp-service subset: v1 weight: 75 - destination: host: hellohttp-service subset: v2 weight: 25
上面的配置就是經過VirtualService 調用DestinationRule 裏面定義的host分類,來進行AB 版本的流量分離,進行AB 版本更新。
對於生產環境裏面的版本更新能夠進行header 主機頭匹配,進行版本區分,基礎的金絲雀發佈更新版本就是這樣實現的。
我想在 Istio Routing 中提到的最後一件事是 ServiceEntry。 默認狀況下,Istio 中的全部外部流量都被阻止。 若是要啓用外部流量,則須要建立 ServiceEntry 以列出爲外部流量啓用的協議和主機。 我不會在這篇文章中展現一個例子,但你能夠在這裏閱讀更多相關內容。
但願這篇文章對你有用! 若是您想了解更多信息,可使用 codelab 系列如下兩部分,其中全部這些概念和更多內容將在逐步的詳細教程中進行說明: