UZABASE Tech Blog

〜迷ったら挑戦する道を選ぶ〜 株式会社ユーザベースの技術チームブログです。

Kubernetes + Istioでblue-green deploymentを実現する

こんにちは、SPEEDAのSREチームの阿南です。最近Kubernetes界隈が盛り上がっていますね。ここ一年で、各企業での利用事例やKubernetesを解説している書籍等もかなり増え、活用の仕方も徐々に確立されて来ているのではないでしょうか。一方Istioについては、色々できそうということはわかったんだけど、利用事例も少ないためどう使えばいいかわからない、本番運用しているという企業もまだあまり聞かないし導入に踏み切れない、という方も多いかと思います。弊社ではまだ2つのnamespaceのみですが、Istioで運用を開始しております。今回は、Istioで実現できることはなんとなく知っているが、具体的な設定方法がよくわからない方向けにblue-green deployの設定を参考に説明してみたいと思います。

Istioの通信について知りたい方はこちら

環境

GKE 1.9.7-gke.11 ,Istio1.0.2 を利用しています。

IstioのRouting Rule

IstioのRouting Ruleには大きく4つのリソースがあります。

resource 説明
Gateway HTTP/TCPのリクエストを受付. どのHost or Portのアクセスを許可するかのルールを記載。 Ingress / Egress のルールを適用できる
VirtualService ルールにマッチしたリクエストをKubernetesのサービスにルーティングする. weightやheaderの情報を利用した振り分けを定義でき、Istioの設定の要とも言える
DestinationRule trafficの振り分けルールを設定. (例: round robin, least connection 等)
ServiceEntry 外部サービスを登録. 例えば、Kubernetes(Istio)の外側にあるDBの接続先等

この4つが適用された通信のイメージを手書きして見ました。まず、クラスター外部から内部への通信です。

f:id:tanan55:20181118130152p:plain

Gatewayを通ったリクエストがVirtualServiceのルールに基づいて各サービスにルーティングされます。その際に、DestinationRuleに基づき最終的にリクエストが送られるpodが決まります。(DestinationRuleでsubsetが設定されていない場合は、RoundRobinで均等に分散される)

続いて、クラスター内部から外部への通信です。

f:id:tanan55:20181118132321p:plain

コンテナから外向きに通信が発生した後、ServiceEntryのルールに基づきRequestを許可するかどうか判断します。ルール次第で、Egressgatewayを通る場合とそうでない場合の2種類があります。個人的には、まだEgressgatewayを使ってないので、外部のエンドポイントを登録する際はServiceEntryに毎回登録しています。

blue-green deploymentの設定

まずは、Kubernetes のPodをサービスとして稼働させるためのリソースを作成します。

  • namespace

gist.github.com

Namespaceを作成する際に istio-injection: enabled を設定しておきます。この設定で自動的にistio-proxyがサイドカーコンテナとして起動するようになります。

  • deployment

gist.github.com

Deploymentでは、 version: blueversion: green の2つnginxを稼働させます。Istioの設定を行う際に、このlabelを元にBlue-Greenができるように設定します。

  • service

gist.github.com

serviceでは、port: 40001で待ち受け、app: nginxtargetPort: 80番へフォワードします。

続いて、Istioのリソースです。Istioのリソースについては、istioをインストールした際にCRDに登録されていますので、kubectl コマンドを利用して設定の反映が可能です。

  • gateway

gist.github.com

gatewayには許容するHostを指定します。正規表現も可能です。 今回は sample.hoge.com を登録します。

  • virtualservice

gist.github.com

gatewayのルールにマッチした通信が、virtualserviceのルールに基づいてkubernetesのServiceへルーティングされます。ポイントとして、headerに x-version: blue とあれば、subset: blue のdestinationruleが適用されるようにしています。このほかの通信については全てgreenにアクセスされます。この設定を利用してblue-greenの切り替え前にblue環境のテストに利用が可能です。

  • destinationrule

gist.github.com

subsetがblueであれば、version: blue のラベルを付与し、subsetがgreenであれば、 version: green のラベルを付与します。これによって、どのPodにアクセスが振り分けられるかが決まります。以上で、設定が完了です。設定を確認するには下記のコマンドを実行します。

$ kubectl get gateway
$ kubectl get virtualservice
$ kubectl get destinationrule

今回構築した環境のイメージは下記の通りです。

f:id:tanan55:20181118230108p:plain

では、実際にアクセスしてみます。今回は、nginxコンテナに出力されたログを見ることにより、どちらのPodにアクセスされたかを確認します。 下記のコマンドでコンテナのログをtailしておきます。

$ kubectl logs -f -n sample-ns $(kubectl get pod -n sample-ns | grep blue | cut -d' ' -f1) -c nginx
$ kubectl logs -f -n sample-ns $(kubectl get pod -n sample-ns | grep green | cut -d' ' -f1) -c nginx

まずは、headerにx-versionを記載せずアクセスします。

$ kubectl get svc istio-ingressgateway -n istio-system
// EXTERNAL-IP を確認
$ curl -XGET -H 'Host: sample.hoge.com' http://<EXTERNAL-IP>/

f:id:tanan55:20181119223402p:plain

最初にアクセスした際は、全てのリクエストがblueのPodにしかリクエストが送られません。

ここで、headerにx-version: green を付けてアクセスします。

$ curl -XGET -H 'Host: sample.hoge.com' -H 'x-version: green' http://<EXTERNAL-IP>/

f:id:tanan55:20181119223549p:plain

特別なheaderをつけることで、特定のリクエストのみを新規にリリースしたgreenに送ることができます。greenが正常なことを確認できたら、blueとgreenを切り替えます。切り替えの方法は、先ほど設定したvirtualserviceのsubsetのblue-greenを逆転させるだけです。

gist.github.com

上記のyamlを適用後、アクセスすると、blueとgreenが入れ替わり、Blue-Green Deploymentが出来ます。

Istioを使い始めてこれはいい!と思ったポイントとしては、本番環境と全く同じ環境でテストができるということです。検証環境と本番環境で差分があってリリースがうまく行かないというのはよくあることだと思いますが、Istioを使うことで、テストができている状態のPodにアクセスを切り替えることが簡単に実現できます。さらにこれを応用して、特定の割合を振り分けたり、社内ユーザのみに新しい環境にアクセスしたりといったことをPodに変更を加えることなく実現できるようになります。 今回は紹介していませんが、gateway や istio-proxy で telemetryを収集でき、grafana / jaeger 等でリクエストのトレースやレスポンス速度を簡単に可視化できるのでこの辺りをフルスタックで揃えているIstioには最初感動しました。ただし、ハマりどころの多さ(本当に多い)や安定性といった面ではまだまだ成熟していない(バグ結構ある)ので、まずは影響の少ないnamespaceから、かつ、メイン機能となるルーティング周りからIstioを使い始めて、運用ノウハウを貯めていくのがいいかなと個人的には思っています。

仲間募集!!

ユーザベースのSPEEDA SREチームは、 「No Challenge, No SRE, No SPEEDA」 を掲げて業務に取り組んでいます。

「挑戦しなければ、SREではないし、SREがなければ、SPEEDAもない」という意識の元、ユーザベースのミッションである 「経済情報で、世界をかえる」 の実現に向けて、日々邁進しています。

IstioやKubernetes以外にも様々なことにチャレンジしてますので少しでも興味を持ってくださった方はこちらまで!