Istio Routing 實踐掌握virtualservice/gateway/destinationrule/AB版本發佈/金絲雀發佈

原文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. 建立一個 Kubernetes 集羣並安裝帶有 sidecare 自動注入的 Istio。
  2. 使用您選擇的語言建立 Hellohttp 應用程序,建立 Docker 鏡像並將其推送到公共鏡像倉庫。
  3. 爲你的容器建立 Kubernetes deployment 和 service。
  4. 建立 Gateway 以啓用到羣集的 HTTP(S)流量。
  5. 建立 VirtualService,經過 Gateway 公開 Kubernetes 服務。
  6. (可選)若是要建立多個版本應用程序,請建立 DestinationRule 以定義可從 VirtualService 引用的 subsets。
  7. (可選)若是要在服務網格外部調用其餘外部服務,請建立 ServiceEntry。

我不會在本文中介紹步驟 1 和 2,由於它們不是特定於 Istio 的。 若是您須要有關這些步驟的幫助,能夠查看我在本文末尾提到的文章。 第 3 步也不是 Istio 特定的,但它是其餘一切的先決條件,因此讓咱們從那開始。app

Deployment 和 Service

正如我所提到的,應用程序生命週期由 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 的內容。學習

Gateway

咱們如今能夠開始研究 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

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

測試 V1 版本 APP

咱們準備測試咱們的應用程序了。 咱們須要獲取 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

在某些時候,您但願將應用更新爲新版本。 也許你想分割兩個版本之間的流量。 您須要建立一個 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 版本。

測試AB版本更新

能夠從 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 主機頭匹配,進行版本區分,基礎的金絲雀發佈更新版本就是這樣實現的。

ServiceEntry

我想在 Istio Routing 中提到的最後一件事是 ServiceEntry。 默認狀況下,Istio 中的全部外部流量都被阻止。 若是要啓用外部流量,則須要建立 ServiceEntry 以列出爲外部流量啓用的協議和主機。 我不會在這篇文章中展現一個例子,但你能夠在這裏閱讀更多相關內容。

但願這篇文章對你有用! 若是您想了解更多信息,可使用 codelab 系列如下兩部分,其中全部這些概念和更多內容將在逐步的詳細教程中進行說明:

相關文章
相關標籤/搜索