kubernetes
istio

Istio envoy 通信

istio とは

こちらを参照してください

envoy 通信

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

スクリーンショット 2017-12-31 0.23.12.png

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

スクリーンショット 2017-12-31 0.23.24.png

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

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

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_OUTPUTISTIO_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 の問い合わせや他サービスへの通信も通常通りのものでした。

スクリーンショット 2017-12-31 0.24.03.png

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