Posted at

Istio envoy 通信

More than 1 year has passed since last update.


istio とは

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


envoy 通信

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

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

各サービスを実現しているコンテナが 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 の問い合わせや他サービスへの通信も通常通りのものでした。

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