Istio入門 その3 -Blue/Greenデプロイメントによるカナリアリリース-


はじめに

ついに第三弾
前回までのあらすじを簡単に説明すると、はじめにIstioのコンセプトとアーキテクチャを把握し、それを踏まえてIstioの構築とアプリケーションの組み込みを実践するという展開でした。
今回は、Istioを使った柔軟なルーティングについてみていきます。

Istio入門

Blue/Greenデプロイメントによるカナリアリリース

サービスのデプロイ方式はいくつかの種類がありますが、クラウドと共に流行りだしたのがBlue/Greenデプロイメント1です。
これは、Blue(現在動いているバージョン)とGreen(新しいバージョン)の2環境を用意されている場合、ロードバランサの向き先を変えるだけで新バージョンへのアップグレードロールバックも最小のダウンタイムで実現できるというものです。

単純に全てのアクセスをGreenに切り替えるという方法もありますが、新しいバージョンにバグがあった場合にユーザへ大きな影響を与えてしまいます。そのため、一度に新しいバージョンに切り替えるのではなく、先行して一部のみを切り替え、問題がなければ新バージョンの割合を徐々に増やしていく手法が考えられました。このように、バグによるユーザ影響を狭める手法をカナリア・リリース2といいます。

Istioではアクセスの何%だけルーティング先を変えたいということが簡単にできるので、これを使ってカナリア・リリースを実現することができます。今回も、引き続きBookInfoを使ってこの動作を確認していきます。まだIstioとBookInfoの構築が終わっていない方は、[前回の記事][istio2]をご参照ください。

バージョンを固定する

前回のBookInfoの構築では、各バージョンのレビューコンポーネントに対して、ラウンドロビンでアクセスするようになっていました。このままではカナリア・リリースによるバージョンアップを試すことができないので、バージョン1に固定します。

  1. まずは、前回ダウンロードしたistioのディレクトリに移動します
  2. 次に、route-rule-all-v1.yamlを適用します

    $ kubectl create -f samples/bookinfo/kube/route-rule-all-v1.yaml
    routerule "productpage-default" created
    routerule "ingress-deny-all" created
    routerule "ingress-products-api" created
    routerule "ingress-productpage-logout" created
    routerule "ingress-productpage-login" created
    routerule "ingress-productpage-landing" created
    routerule "reviews-default" created
    routerule "ratings-default" created
    routerule "details-default" created
    

    本来は、istictlのManifestのバリデーション機能を活用することをお勧めしたいのですが、現在バリデーション[^3]エラーで弾かれてしまうためkubectlを利用しています。

  3. kubectlから、実際にリソースが作成されたことを確認します

    $ kubectl get routerules
    NAME                          AGE
    details-default               5m
    ingress-deny-all              5m
    ingress-productpage-landing   5m
    ingress-productpage-login     5m
    ingress-productpage-logout    5m
    ingress-products-api          5m
    productpage-default           5m
    ratings-default               5m
    reviews-default               5m
    

    ルーティング設定は非同期に設定されるので、全て適用されるまでには数秒程度かかることがあります。

  4. ブラウザからもアクセスし、何度リロードしてもバージョン1が表示されることを確認します

    $ export GATEWAY_URL=$(kubectl get po -n istio-system -l istio=ingress -o 'jsonpath={.items[0].status.hostIP}'):$(kubectl get svc istio-ingress -n istio-system -o 'jsonpath={.spec.ports[0].nodePort}')
    $ open $GATEWAY_URL/productpage
    

[^3]: Istio#1375 参照

20%のアクセスを新バージョンへルーティングする

バージョンが固定できたところで、実際にカナリア・リリースを試してみましょう。まずはカナリアとして20%のアクセスだけバージョン2にルーティングされるように変更してみます。

  1. 以下のようなルーティングManifestを作成してください

    canary-release-test.yaml
    apiVersion: config.istio.io/v1alpha2
    kind: RouteRule
    metadata:
    name: canary-release-test
    spec:
    destination:
    name: reviews
    precedence: 2
    route:
    - labels:
      version: v1
    weight: 80
    - labels:
      version: v2
    weight: 20
    

    先ほどバージョン1に固定するために適用したManifestにもこのRouteRuleが定義されていました。このカスタムリソースの定義についてはこちらをご参照ください

  2. 作成したManifestを適用します

    $ kubectl create -f canary-release-test.yaml
    routerule "canary-release-test" created
    
  3. ブラウザから何度もリロードしてみてください。数回に一度、バージョン2にルーティングされるようになったかと思います。

  4. 問題がなければ、先ほどのファイルを編集して徐々に割合を変えて適用してみてください。ブラウザからアクセスして見ると実際に割合が変わることを実感できると思います

このように、カナリアリリースによる緩やかなアップグレードが実現できることが分かりました。このようなフローを手動でやり続けるのは辛いので、モニタリングツールと連動したアップグレードとロールバックフローを自動化するのもよいかもしれません。

βテスター専用ページ

サービスのテストのために、特定のユーザだけ新しいバージョンを表示させたいと思う事があるかもしれません。ここでは、Cookieの中に入っているユーザ情報を使って、テスターのjasonさんのみバージョン3にを表示させる方法を見ていきます。

  1. 以下のようなルーティングManifestを作成してください

    add-tester.yaml
    apiVersion: config.istio.io/v1alpha2
    kind: RouteRule
    metadata:
    name: add-tester
    spec:
    destination:
    name: reviews
    precedence: 3
    match:
    request:
      headers:
        cookie:
          regex: "^(.*?;)?(user=jason)(;.*)?$"
    route:
    - labels:
      version: v3
    

    ちなみに、このリソースはKubernetesのCustomResourceDefinitionを利用して定義されています。この定義ファイルは、前回のIstio構築時に適用したManifestに含まれています。気になった方はPilotのコードと合わせて見ると面白いかと思います。

  2. 作成したManifestを適用します

    $ kubectl create -f add-tester.yaml
    routerule "add-tester" created
    
  3. Sign inボタンからjasonさんとしてログインします(パスワードは不要です)

  4. ブラウザから何度もリロードしてみてください。バージョン3のみにルーティングされるかと思います

今回はCookieのユーザ名でルーティング先を振り分けましたが、HTTPヘッダの中身であれば何でも条件を設定できます。例えば、User-agentを見てAndroidとiPhoneで表示するページを変えるということもできます。

おわりに

今回は、Istioを使って重みやHTTPヘッダに応じたルーティング先の変更を試していきました。他にもやChaos Engineeringのための障害発生機能があります。これらについては気が向いたら続きを書こうと思います。

明日は、@hatotakaさんによる「RaspberryPiとkubeadmで自宅Kubernetesクラスタを構築する」お話です。それでは引き続きZ Lab Advent Calendar 2017をお楽しみください。

[istio1]: https://qiita.com/Ladicle/items/979d59ef0303425752c8
[istio2]: https://qiita.com/Ladicle/items/e949b0f68ac18b7a95d8


  1. 詳しくはMartin Fowler氏によるBlueGreenDeployment参照 

  2. 一酸化炭素を検出するために鉱山へカナリアを連れて行ったことから、異常を検知するために先行して動作させるものをカナリアと呼ぶ