IstioのIngress通信に何が関わるのかをざっくり解説します

# 概要

KubernetesにIstioを導入し、外部からメッシュ内のPodにアクセスするまでに
何のリソースが関連しているかをざっくり調べてみましたので画像を交えて説明します。
また、例として記載するyamlファイルは一部を抜粋しています。

※私個人の解釈が多く混じっているので別の観点から捉えてみると理解しやすいかもしれません。

# 代表的なIstioリソースは3つ

![スクリーンショット 2020-07-07 6.54.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447425/d9ea2edc-4c7b-548d-b507-2c5a224a95cd.png)

- IngressGateway(Service/Pod)
- Gateway(Resource)
- Virtual Service(Resource)

これらのIstioリソースを定義することで最低限のアクセスは可能となります。
DestinationRuleはKubernetesリソースのServiceに対し、同時コネクション数やHTTPリクエスト数の制限、コネクションのアイドル時間の制限といったあらゆる制限を付加することができますが、外部からメッシュ内のPodにとりあえずアクセスしたい場合には必須ではなく、おまけ程度の認識です。


## IngressGateway

IngressGatewayは上記画像のようにKubernetesのServiceとDeployment(Pod）で構成します。
ServiceはKubernetesリソースをそのまま使っているだけなので、単純にNodePortと同じ動作をしているように見受けられます。

Podが一番重要な働きをしているように見えていて、Podで受けたトラフィックは後述のIstioリソースに従いトラフィックをコントロールします。

![スクリーンショット 2020-07-07 7.13.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447425/ff2ce6ae-8deb-5a85-3e48-3cfc2777224f.png)

例として`istio-system`Namespaceに対しGatewayリソースをデプロイするとIngressGateway Podに反映されることが確認できます。
確認方法は次のコマンドでPod(Envoy)のconfig_dumpをcurlコマンドでGETし、デプロイ前後で比較します。
`kubectl exec [IngressGatewayPodName] -n istio-system -- curl localhost:15000/config_dump`

## Gateway

![スクリーンショット 2020-07-07 7.19.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447425/d839dda4-db75-de6c-982a-c2f77364a249.png)

トラフィックを受信するとIngressGateway Podは`Gateway`リソースを確認します。
トラフィックの`FQDN、ポート番号、プロトコル`に一致すると`VirtualService`リソースでトラフィックをコントロールすることが可能になります。
この時点でのトラフィックの位置はまだIngressGateway Podの中です。

## VirtualService
![スクリーンショット 2020-07-07 7.34.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447425/e4af7488-1c4c-e186-c5e5-160a2ec08814.png)

`Gateway`の次は`VirtualService`リソースに基づきトラフィックをコントロールしていきます。
画像の`VirtualService`は特定の`Gateway`のルールに一致したトラフィックだけを扱うことを明示しています。
`http:`以降ではリクエストURIのプレフィックス`/hogehoge`に一致した場合に、KubernetesリソースのServiceである`serviceA`の`8080ポート`にルーティングします。

ここでやっと`IngressGateway Pod`から`Service`にトラフィックが流れ、その後`Service`から`Pod`に流れていきます。
Pod内にはサイドカーとしてインジェクションされている`Envoy-Proxy`があり、トラフィックを一旦受け取ってからアップストリーム（バックエンド）の`Application`コンテナにトラフィックが渡されます。

## 外からアクセスができない！どこを調べれば良いの！？

今のトラフィックの流れを見ると
`IngressGateway Service` -> `IngressGateway Pod` -> 
`serviceA` -> `Pod(Envoy-Proxy)` -> `Pod(Application)`
といったフローになります。

まずは、外部からアクセスした際に`IngressGateway Pod`までトラフィックが来ているのかを確認します。
`kubectl logs -f [IngressGatewayPodName] -n istio-system`でtail -fモードを使用し、ログをリアルタイムで確認できる状態にします。
次にブラウザやcurlコマンドで外部からアクセスしてみます。
その時にログとして確認できれば`IngressGateway`としては正常に動いています。
しかし、そこから`Service`までの経路が繋がっていない可能性があるため、`Gateway`や`VirtualService`が正しく設定されているか見直してみます。

逆に`IngressGateway Pod`のログからトラフィックを確認できない場合は、`IngressGateway Service`の設定に問題があるか、そもそもワーカーノードのポートまでたどり着けていない可能性がありますので、外部LBのフォワーディング設定やELBのターゲットグループ設定を確認してみると良いかもしれません。

## そもそもアクセスログが出力されないのですが？？？

Istio導入直後は`kubectl logs`でアクセスログを確認できません。
`kubectl edit configmap istio -n istio-system`を実行し、`AccessLogFile`の値を`/dev/stdout`に変更します。
詳細についてはこちらのページで解説しています。
[istio-proxy(Envoy)を通過するhttp accessログを出力させる(Pod個別設定)](https://qiita.com/Takagi_/items/75ae32d864fee9bc47fc)
 
# ここまでざっくりとIngress通信について解説しましたが

「これは違うんじゃないのかな〜？」「私はこう解釈してるよ」といったコメント頂けると本当に嬉しいです。
そもそも私の解釈が全て正解だとは思っていないので他の方の意見も聞いてみたいというのが本音です。