こんにちは、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つが適用された通信のイメージを手書きして見ました。まず、クラスター外部から内部への通信です。
Gatewayを通ったリクエストがVirtualServiceのルールに基づいて各サービスにルーティングされます。その際に、DestinationRuleに基づき最終的にリクエストが送られるpodが決まります。(DestinationRuleでsubsetが設定されていない場合は、RoundRobinで均等に分散される)
続いて、クラスター内部から外部への通信です。
コンテナから外向きに通信が発生した後、ServiceEntryのルールに基づきRequestを許可するかどうか判断します。ルール次第で、Egressgatewayを通る場合とそうでない場合の2種類があります。個人的には、まだEgressgatewayを使ってないので、外部のエンドポイントを登録する際はServiceEntryに毎回登録しています。
blue-green deploymentの設定
まずは、Kubernetes のPodをサービスとして稼働させるためのリソースを作成します。
- namespace
Namespaceを作成する際に istio-injection: enabled
を設定しておきます。この設定で自動的にistio-proxyがサイドカーコンテナとして起動するようになります。
- deployment
Deploymentでは、 version: blue
と version: green
の2つnginxを稼働させます。Istioの設定を行う際に、このlabelを元にBlue-Greenができるように設定します。
- service
serviceでは、port: 40001
で待ち受け、app: nginx
の targetPort: 80
番へフォワードします。
続いて、Istioのリソースです。Istioのリソースについては、istioをインストールした際にCRDに登録されていますので、kubectl コマンドを利用して設定の反映が可能です。
- gateway
gatewayには許容するHostを指定します。正規表現も可能です。 今回は sample.hoge.com
を登録します。
- virtualservice
gatewayのルールにマッチした通信が、virtualserviceのルールに基づいてkubernetesのServiceへルーティングされます。ポイントとして、headerに x-version: blue
とあれば、subset: blue
のdestinationruleが適用されるようにしています。このほかの通信については全てgreenにアクセスされます。この設定を利用してblue-greenの切り替え前にblue環境のテストに利用が可能です。
- destinationrule
subsetがblueであれば、version: blue
のラベルを付与し、subsetがgreenであれば、 version: green
のラベルを付与します。これによって、どのPodにアクセスが振り分けられるかが決まります。以上で、設定が完了です。設定を確認するには下記のコマンドを実行します。
$ kubectl get gateway $ kubectl get virtualservice $ kubectl get destinationrule
今回構築した環境のイメージは下記の通りです。
では、実際にアクセスしてみます。今回は、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>/
最初にアクセスした際は、全てのリクエストがblueのPodにしかリクエストが送られません。
ここで、headerにx-version: green
を付けてアクセスします。
$ curl -XGET -H 'Host: sample.hoge.com' -H 'x-version: green' http://<EXTERNAL-IP>/
特別なheaderをつけることで、特定のリクエストのみを新規にリリースしたgreenに送ることができます。greenが正常なことを確認できたら、blueとgreenを切り替えます。切り替えの方法は、先ほど設定したvirtualserviceのsubsetのblue-greenを逆転させるだけです。
上記の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以外にも様々なことにチャレンジしてますので少しでも興味を持ってくださった方はこちらまで!