Envoy (Envoy proxy)、Istio とは？

[Microservices Advent Calendar 2017](https://qiita.com/advent-calendar/2017/microservices) 14日目の記事です。

今回は、EnvoyとIstioという、microservicesの文脈でよく出てくるツールの紹介です。
https://www.envoyproxy.io/
https://istio.io/

どちらも立派な公式ページ/ドキュメントがあり、紹介も何もあったもんじゃないと思われるかもしれませんが、公式ドキュメント上では、とてもたくさんの概念と機能が紹介されていて、私にはこの２つが一体何物なのか中々掴めなかったので、私なりの理解での言葉に置き換えて説明したいと思います。

# tl;dr
- Envoyはmicroservicesなシステムを作るときに必要な機能を提供してくれるside-car proxy。
- Istioはenvoyをkubernetes上で使うのを助けてくれるツール。(将来的にはkubernetes以外とのツールの連携も目指しているらしい)

# Envoy、Istioとは？
このアドベントカレンダーの７日目に、["Building Fault Tolerant Microservices" というプレゼンがとても良かった話](https://qiita.com/seikoudoku2000/items/01450d9c413a0c487b8f)という記事を書きました。
このプレゼンは、microservicesなシステムを運用していく中で不可欠な、`Circuit Breaker`, `BulkHeads`などの概念を具体例を交えながら分かりやすく説明してくれるものでした。そして、最後のQAで、「今回のサンプルコードはjavaのものだったが、例えば複数のプログラミング言語使っているならば、その言語毎にこういったクライアントの実装したり、ライブラリを選定しなければならないのか？？　言語を跨いで、１つの方法で解決するようなbrilliantなアイデアはないのか？」 という質問があり、それに対して、「そんなbrilliantなアイデアはないなー」というやり取りがあったのですが、、、、
そのbrilliantなアイデアを実現したものが、Envoy。そして、このEnvoyをkubernetesというスタンダードとなりつつあるコンテナマネジメントシステムで動かすのをサポートしてくれるのがIstio。

# Envoy
https://www.slideshare.net/datawire/lyfts-envoy-from-monolith-to-service-mesh-matt-klein-lyft/13
<img width="626" alt="envoy_1.png" src="https://qiita-image-store.s3.amazonaws.com/0/91324/fd402b96-b906-d687-a030-c16518f9ce9d.png">

プログラミング言語/バージョン/フレームワークがバラバラな各Serviceの中に、それぞれCircuit Breakerなどの機能を持たせるのではなく、各ServiceのSidecarとしてproxyを立てて、そこにそういった機能を持たせればいいじゃん！というのが基本となる考え方。
そもそもSidecarって何？という人もいるかと思いますが、アプリケーションサーバの入り口にキャッシュやアクセス制限用にnginx立てるってのが、多くの人が経験ある一番分かりやすい例かなと思います。
https://aws.amazon.com/jp/blogs/compute/nginx-reverse-proxy-sidecar-container-on-amazon-ecs/
キャッシュやアクセス制限は各アプリケーションで実装することも可能だけど、それって色んなアプリケーションで共通してることなんだから、上手く抽象化してできれば、nginx + アプリケーション(ここはプログラミング言語/フレームワーク問わない) という形で使い回せるよねと。

nginxがhttpアプリケーション必要機能集sidecarとするならば、EnvoyはMicroServices必要機能集sidecar。
実際、envoyにcacheを持たせようとか、
https://github.com/envoyproxy/envoy/issues/868
envoyの代わりにnginx使えないの？
https://github.com/istio/proxy/issues/599
みたいな議論もあり、nginxとenvoyはとても似た者同士なレイヤーであることが分かります。

一般的なnginxの使い方とEnvoyが一つ大きく違うのは、outgoingなリクエストも処理することが前提なので、service discovery、http header等による向き先の切り替え、分散トレーシングなど、microservicesをやっていると、いずれ欲しくなる様々な機能も、最初からサポートしてくれているという点がありそうです。

# LyftでのEnvoyの使い方
https://www.slideshare.net/datawire/lyfts-envoy-from-monolith-to-service-mesh-matt-klein-lyft/15
<img width="627" alt="スクリーンショット 2017-12-13 23.43.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/91324/36669942-763a-194a-ea1b-d39016cb28be.png">
オシャレですね！
真ん中上段にLegacy monolithとありますが、sidecarとして提供することで、アプリケーション自体に大きく手を入れづらい箇所にも、サクッと適用できるってのがEnvoyの良い所。
また、ここまでは所謂Service間のやり取りの話が中心でしたが、Lyftでは、データベースへのアクセスもEnvoyをかまして行なっているそうです。これにより、DBが応答しなくなった時に、DBをさらに過負荷にすることを防げたり、素早くエラーを返すことでthreadが枯渇してサービス自体が応答できなくなるといった事態を防ぐことができるそうです。

# Istio
こちらの資料から図を引用してます
https://github.com/kprabhak/Talks/blob/master/Kubernetes-NYC-Meetup-June2017/Calico-Istio-Envoy.pdf

<img width="978" alt="スクリーンショット 2017-12-14 0.02.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/91324/831be0c7-2e81-58b1-d813-d9d8e5f6dab9.png">
Envoyとのやり取りを司るコンポーネント。kubernetesを使っていて、Envoyをsidecarとして全サービスに乗っけるのならば、各サービス毎に定義を書くんじゃなくて、Envoy自体を操作するための仕組みをkubernetesに被せてあげましょうという感じ。
大きく、**Istio-Pilot**, **Mixer**, **Istio-Auth**の３つのコンポーネントに分けられる。

***2018/06/08 追記***
-----
`Envoy自体を操作するための仕組みをkubernetesに被せてあげましょうという感じ。` という表現は、当時の私の理解が足りておらず、正確な表現ではありませんでした。Envoyはdata plane、Istioはcontrol planeで、control planeとしてのIstioの特色としてkubernetesと連携させやすい、っていうのがより正確な表現になるかと思います。control plane, data planeとは？ の話に関して、以下にまとめていますので、ご興味ある方はご覧いただければと。
https://qiita.com/seikoudoku2000/items/d4c6b41337f03df0e005
https://qiita.com/seikoudoku2000/items/2197f9e4936e0e70b565

***追記ここまで***


## Istio-Pilot
<img width="977" alt="スクリーンショット 2017-12-14 0.14.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/91324/f7e1193f-5cf4-75e2-531a-fb9994361dfd.png">
今はkubernetesが前提になっているけど、将来的には、kubernetesのレイヤーを抽象化してMesosやCloudFoundryを使っても、そのままEnvoyの設定ができるようになっていく予定。

## Istio-Mixer
<img width="974" alt="スクリーンショット 2017-12-14 0.12.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/91324/11781b04-4d3a-b1f2-4e1b-865ee2ad9c4e.png">
例えば、分散トレーシングではEnvoyからどこかにデータを送るというようなことが必要になるが、Mixerの中に設定を集約することで、設定の一元管理が可能となる。また、Mixerはpluggableな作りになっているので、自分たちに必要なカスタマイズを施すことも可能。

# 参考資料
- Lyft's Envoy: From Monolith to Service Mesh
    - 動画: https://www.youtube.com/watch?v=RVZX4CwKhGE
    - 資料: https://www.slideshare.net/datawire/lyfts-envoy-from-monolith-to-service-mesh-matt-klein-lyft

EnvoyはLyftが発祥なのですが、Lyftの中の人の、かつEnvoy開発のど真ん中にいるっぽい人のプレゼン。スライドは文字が多くてオシャレとは言い難いですがw、この人がこれまでのmicroservicesの問題点を話す時の口調からは経験から出る苦しさが滲み出ていて、規模は違えど、同じような経験はあったので、そこからEnvoyの説明に入ったときに、これが欲しかったんだよー！と心を撃ち抜かれました。


- Istio & Lyft's Envoy - Karthik Prabhakar, Tigera
    - 動画: https://www.youtube.com/watch?v=bpZJGqscm-4
    - 資料: https://github.com/kprabhak/Talks/blob/master/Kubernetes-NYC-Meetup-June2017/Calico-Istio-Envoy.pdf

正直、Istioに関してはこれだ！っていうのは見つけられなかったのですが、私が見た中では、これが一番分かりやすかったかなーと。そもそも、kubernetesという最初のハードルが高目なオーケストレーションツールの上で、Envoyというこれまた小難しいツールを使おうというものなので、実際に使い込まずに、理解しようという考えが甘い気がします。

ちなみに、先日、Austinで開催されていたkubeconでもIstioに関する発表があったようなので、そちらも期待ですね！

<br>
*12/23 追記： 22日目の記事ではLinkerdのことを書きました。*
https://qiita.com/seikoudoku2000/items/25081212dd89a26033a7