Istio envoy 通信

# istio とは
[こちら](https://qiita.com/Ladicle/items/979d59ef0303425752c8)を参照してください

# envoy 通信
istio の bookinfo デモを試しているときに、ふと「どうやって既存のサービス同士の通信を envoy が中継しているの？」という疑問がわきました。

<img width="600" alt="スクリーンショット 2017-12-31 0.23.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/216087/bff24d1a-748e-2280-e363-72ba1431db19.png">

上記が istio 適用前の bookinfo の通信イメージです。これが istio を適用すると下記のようになります。

<img width="998" alt="スクリーンショット 2017-12-31 0.23.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/216087/3ee3d5e3-664f-4bb0-8c74-87e1ee51856f.png">

各サービスを実現しているコンテナが istio-proxy と通信するように変わっていますが、どうやってやっているんだろう、というのが疑問点です。envoy の説明で「 **サービスメッシュのイン/アウトバウントの全てのトラフィックを管理するプロキシサーバで、KubernetesではPodのサイドカーとしてデプロイします。** 」という説明を読んでもイメージがわきません。そこで、図の赤枠で囲んだ productpage pod の中身を確認してみました。

まずは istio-proxy の iptables のルールを見てます。

```bash
istio-proxy@productpage-v1-7c96dc567c-dl6dd:/$ sudo iptables -t nat -n -L -v
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
   12   720 ISTIO_REDIRECT  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* istio/install-istio-prerouting */

Chain INPUT (policy ACCEPT 12 packets, 720 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 7978 packets, 728K bytes)
 pkts bytes target     prot opt in     out     source               destination
  726 43560 ISTIO_OUTPUT  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            /* istio/install-istio-output */

Chain POSTROUTING (policy ACCEPT 7999 packets, 729K bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain ISTIO_OUTPUT (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ISTIO_REDIRECT  all  --  *      lo      0.0.0.0/0           !127.0.0.1            /* istio/redirect-implicit-loopback */
  705 42300 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0            owner UID match 1337 /* istio/bypass-envoy */
    0     0 RETURN     all  --  *      *       0.0.0.0/0            127.0.0.1            /* istio/bypass-explicit-loopback */
   21  1260 ISTIO_REDIRECT  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* istio/redirect-default-outbound */

Chain ISTIO_REDIRECT (3 references)
 pkts bytes target     prot opt in     out     source               destination
   33  1980 REDIRECT   tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            /* istio/redirect-to-envoy-port */ redir ports 15001
```

`ISTIO_OUTPUT` と `ISTIO_REDIRECT` というチェインが追加されています。 `OUTPUT` チェインには tcp 通信はすべて `ISTIO_OUTPUT` にパスされています。そして `ISTIO_OUTPUT` では `UID` が 1337 の通信と `localhost` 宛の通信は `RETURN` つまり評価されないと定義されており、それ以外の通信は `ISTIO_REDIRECT` にパスされています。`ISTIO_REDIRECT` チェインは `PREROUTING` チェインと `ISTIO_OUTPUT` チェインから呼びされており、すべての tcp 通信をポート 15001 で LISTEN しているプロセスに渡しています。

まずは `UID 1337` の確認からします。

```
istio-proxy@productpage-v1-7c96dc567c-dl6dd:/$ id -u istio-proxy
1337
```

istio-proxy が `UID 1337` を持つユーザです。つまり、istio-proxy ユーザが起動しているプロセスの通信は `ISTIO_REDIRECT` にはパスされません。

また、ポート 15001 で LISTEN しているプロセスは下記の通り、envoy であることが確認できます。

```
istio-proxy@productpage-v1-7c96dc567c-dl6dd:/$ netstat -anp | grep 15001
tcp        0      0 0.0.0.0:15001           0.0.0.0:*               LISTEN      436/envoy
```

プロセス一覧を確認して見ます。

```
istio-proxy@productpage-v1-7c96dc567c-dl6dd:/$ ps aux | grep -v bash | grep -v ps
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
istio-p+     1  0.0  0.2 301460 11188 ?        Ssl  00:09   0:00 /usr/local/bin/pilot-agent proxy sidecar -v 2 --configPath /etc/istio/proxy --binaryPath /usr/local/bin/envoy --serviceCluster productpage --drainDuration 45s --parentShutdownDuration 1m0s --discoveryAddress istio-pilot.istio-system:15003 --discoveryRefreshDelay 1s --zipkinAddress zipkin.istio-system:9411 --connectTimeout 10s --statsdUdpAddress istio-mixer.istio-system:9125 --proxyAdminPort 15000 --controlPlaneAuthPolicy MUTUAL_TLS
istio-p+   142  4.5  0.7  86800 31584 ?        Sl   03:22   2:17 /usr/local/bin/envoy -c /etc/istio/proxy/envoy-rev5.json --restart-epoch 5 --drain-time-s 45 --parent-shutdown-time-s 60 --service-cluster productpage --service-node sidecar~172.17.0.14~productpage-v1-7c96dc567c-dl6dd.default~default.svc.cluster.local --max-obj-name-len 189
```

上記の通り envoy は istio-proxy が起動しているプロセスです。

これらの結果から、istio-proxy コンテナの envoy が透過型プロキシであることがわかります。つまり、bookinfo プロセスは従来の通信相手先に通信しているのですが、それを各 pod の istio-proxy が透過型プロキシとして中継することで実際は envoy 同士が通信する構図にできています。実際に tcpdump でパケットを確認しましたが kube-dns の問い合わせや他サービスへの通信も通常通りのものでした。

<img width="896" alt="スクリーンショット 2017-12-31 0.24.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/216087/08d447e4-964e-103b-efa5-8fceb6f3a7bc.png">

上記が productpage pod へのフロント側からの GET リクエストおよび productpage.py から reviews, details サービスへの GET リクエストが iptables によって曲げられて envoy によって処理される様子です。