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_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 の問い合わせや他サービスへの通信も通常通りのものでした。
上記が productpage pod へのフロント側からの GET リクエストおよび productpage.py から reviews, details サービスへの GET リクエストが iptables によって曲げられて envoy によって処理される様子です。