📚
istio-proxyがどのように通信を仲介しているかを知る
目的
前回、書いた記事で素のKubernetesのネットワークについて少し理解できたのですが、Istioを入れた場合はEnvoyが通信を仲介するのでその仕組みを知りたく調べてみました
環境
- OS: Arch Linux(5.17.9-arch1-1)
- k8sの環境: kind
- https://kind.sigs.k8s.io/
- version 0.14.0
- デフォルトのk8sのバージョンは1.24
クラスタのセットアップ
kindでクラスタ作成
- https://kind.sigs.k8s.io/docs/user/quick-start/#installation を参考にkindをインストールします
-
$ kind create cluster --name kind-iptables --config=kind-config.yaml
- ワーカーを3台用意し、1台をIstio用で2台をアプリ用にしています
- Istioを動かすノードは31039をポートフォワーディングしてます
kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
kubeadmConfigPatches:
- |
kind: JoinConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "istio=true"
extraPortMappings:
- containerPort: 31039
hostPort: 31039
protocol: TCP
- role: worker
kubeadmConfigPatches:
- |
kind: JoinConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "app=true"
- role: worker
kubeadmConfigPatches:
- |
kind: JoinConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "app=true"
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4cbf60373417 kindest/node:v1.24.0 "/usr/local/bin/entr…" 26 hours ago Up 2 hours kind-iptables-worker2
27ba7418c58f kindest/node:v1.24.0 "/usr/local/bin/entr…" 26 hours ago Up 2 hours 0.0.0.0:31039->31039/tcp kind-iptables-worker
6ff6e1602678 kindest/node:v1.24.0 "/usr/local/bin/entr…" 26 hours ago Up 2 hours 127.0.0.1:33099->6443/tcp kind-iptables-control-plane
042b1d4a47f5 kindest/node:v1.24.0 "/usr/local/bin/entr…" 26 hours ago Up 2 hours kind-iptables-worker3
Istioのインストール
- istioctlをインストールします
- asdfは https://asdf-vm.com/
$ asdf plugin add istioctl
$ asdf install istioctl 1.12.7
$ asdf global istioctl 1.12.7
- 用意したクラスタにIstioをインストール
- istio-operator.yamlにクラスタ作成で指定したポートやノードラベルを記述しています
- 今回はログも見たいのでprofileをdemoにしておきます
$ istioctl x precheck
$ istioctl install -f istio-operator.yaml --dry-run
$ istioctl install -f istio-operator.yaml
$ istioctl verify-install -f istio-operator.yaml
$ istioctl tag set stable --revision 1-12-7
istio-operator.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
revision: 1-27-7
profile: demo
components:
ingressGateways:
- name: istio-ingressgateway
enabled: true
k8s:
nodeSelector:
istio: "true"
service:
type: NodePort
ports:
- name: http2
port: 80
targetPort: 8080
nodePort: 31039
pilot:
k8s:
nodeSelector:
istio: "true"
サンプルのリソースをデプロイ
kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- gateway.yaml
- namespace.yaml
- service.yaml
- virtual_service.yaml
namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: nginx
labels:
istio.io/rev: stable
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
nodeSelector:
app: "true"
service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
namespace: nginx
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 8080
targetPort: 80
virtual_service.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: nginx-virtual-service
namespace: nginx
spec:
hosts:
- "*"
gateways:
- nginx-gateway
http:
- match:
- port: 80
route:
- destination:
host: nginx-service.nginx.svc.cluster.local
port:
number: 8080
gateway.yaml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: nginx-gateway
namespace: nginx
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
- 上記ファイルをディレクトリに保存してapply
$ kubectl apply -k nginx
クラスタの情報
- istiodとistio-ingressgatewayがWorkerにあります
$ docker exec -it 27ba7418c58f bash
root@kind-iptables-worker:/# crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID POD
03c9af68b9f13 d30470c3a71e4 2 hours ago Running istio-proxy 1 ece587da5d00b istio-ingressgateway-747b48b769-97sw9
32eb4b7f86960 839c166d0220e 2 hours ago Running discovery 1 e43a4756ff2c0 istiod-1-12-7-6fc7b96bc7-4kjn2
2f00d2479d6f0 6960c0e47829d 2 hours ago Running kube-proxy 1 4b8dd4ea1ca7f kube-proxy-tp2bn
4d4f608ee18ea 6fb66cd78abfe 2 hours ago Running kindnet-cni 1 7b4f7ff831de6 kindnet-q2pm8
- nginxがWorker2にnginxが1つ、Worker3に2つあります。そして、nginxのあるPodにistio-proxyが挿入されていることが確認できます
$ docker exec -it 4cbf60373417 bash
root@kind-iptables-worker2:/# crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID POD
8dc62d326774b d30470c3a71e4 2 hours ago Running istio-proxy 1 6260cc29c02dc nginx-deployment-6d47dbd4d-6jx9p
2149600f4039e 0e901e68141fd 2 hours ago Running nginx 1 6260cc29c02dc nginx-deployment-6d47dbd4d-6jx9p
9abf259b3a839 6960c0e47829d 2 hours ago Running kube-proxy 1 e16f248c190a4 kube-proxy-lq7bx
f5524f5a65ac3 6fb66cd78abfe 2 hours ago Running kindnet-cni 1 284b4c1a554a3 kindnet-29dkd
$ docker exec -it 042b1d4a47f5 bash
root@kind-iptables-worker3:/# crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID POD
0550b2a85117b d30470c3a71e4 2 hours ago Running istio-proxy 1 35f62bf4a3532 nginx-deployment-6d47dbd4d-4p477
511d50f1b85e8 0e901e68141fd 2 hours ago Running nginx 1 35f62bf4a3532 nginx-deployment-6d47dbd4d-4p477
f22ca438e5540 d30470c3a71e4 2 hours ago Running istio-proxy 1 25d6b027a3078 nginx-deployment-6d47dbd4d-zlr62
b74fbff00d282 0e901e68141fd 2 hours ago Running nginx 1 25d6b027a3078 nginx-deployment-6d47dbd4d-zlr62
c31d0698f9dd5 6960c0e47829d 2 hours ago Running kube-proxy 1 9b74410f5c4e9 kube-proxy-kfzlh
e056f7b55fd12 6fb66cd78abfe 2 hours ago Running kindnet-cni 1 17c5b9444ac03 kindnet-krfnh
ネットワーク
- mermaidの使い方が下手で見づらいかもです
Podのiptablesを覗く
- iptablesによってenvoyが通信を仲介するように設定してあるので確認してみます
iptables
-
送信先や宛先を変更できる。他にも色々できる
-
テーブル
- 役割に応じて4種類ありk8s、Istioで利用しているのはnatテーブルで送信元や宛先を変更するのに利用します
-
チェイン
- 実際のルールのリスト
- テーブルの中にチェインがある
- 組み込みのチェイン
- PREROUTING、INPUT、OUTPUT、POSTROUTING
- この順序で適用される
- 今回だとLOCAL_PROCESSがnginx、envoy
- ユーザー定義のチェインもある
- k8sやIstioが用意
- 組み込みのチェインの中にあるルールによってジャンプして適用される
-
iptablesについてはここに一番詳しく書かれていますが情報が膨大なので私は読めてません
iptablesが更新されるタイミング
- envoyが挿入されるタイミングと同じくしてinitContainersでistio-iptablesによって更新されている
$ kubectl get pods nginx-deployment-6d47dbd4d-4p477 -o jsonpath='{.spec.initContainers[*].args[*]}'
istio-iptables -p 15001 -z 15006 -u 1337 -m REDIRECT -i * -x -b * -d 15090,15021,15020
-
https://istio.io/latest/docs/ops/deployment/requirements/#ports-used-by-istio
- 15001がEnvoy outbound
- 15006がEnvoy inbound
- 15090がEnvoy Prometheus telemetry
- 15021がHealth checks
- 15020がMerged Prometheus telemetry from Istio agent, Envoy, and application
iptablesを確認
- iptables -L -t nat
$ docker exec -it 042b1d4a47f5 bash
root@kind-iptables-worker3:/# nsenter -t $(pgrep envoy | sed -n 1p) -n iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
ISTIO_INBOUND tcp -- anywhere anywhere
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ISTIO_OUTPUT tcp -- anywhere anywhere
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
Chain ISTIO_INBOUND (1 references)
target prot opt source destination
RETURN tcp -- anywhere anywhere tcp dpt:15008
RETURN tcp -- anywhere anywhere tcp dpt:ssh
RETURN tcp -- anywhere anywhere tcp dpt:15090
RETURN tcp -- anywhere anywhere tcp dpt:15021
RETURN tcp -- anywhere anywhere tcp dpt:15020
ISTIO_IN_REDIRECT tcp -- anywhere anywhere
Chain ISTIO_IN_REDIRECT (3 references)
target prot opt source destination
REDIRECT tcp -- anywhere anywhere redir ports 15006
Chain ISTIO_OUTPUT (1 references)
target prot opt source destination
RETURN all -- 127.0.0.6 anywhere
ISTIO_IN_REDIRECT all -- anywhere !localhost owner UID match 1337
RETURN all -- anywhere anywhere ! owner UID match 1337
RETURN all -- anywhere anywhere owner UID match 1337
ISTIO_IN_REDIRECT all -- anywhere !localhost owner GID match 1337
RETURN all -- anywhere anywhere ! owner GID match 1337
RETURN all -- anywhere anywhere owner GID match 1337
RETURN all -- anywhere localhost
ISTIO_REDIRECT all -- anywhere anywhere
Chain ISTIO_REDIRECT (1 references)
target prot opt source destination
REDIRECT tcp -- anywhere anywhere redir ports 15001
- iptables -S -t nat
root@kind-iptables-worker3:/# nsenter -t $(pgrep envoy | sed -n 1p) -n iptables -S -t nat
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N ISTIO_INBOUND
-N ISTIO_IN_REDIRECT
-N ISTIO_OUTPUT
-N ISTIO_REDIRECT
-A PREROUTING -p tcp -j ISTIO_INBOUND
-A OUTPUT -p tcp -j ISTIO_OUTPUT
-A ISTIO_INBOUND -p tcp -m tcp --dport 15008 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 22 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15090 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15021 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15020 -j RETURN
-A ISTIO_INBOUND -p tcp -j ISTIO_IN_REDIRECT
-A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15006
-A ISTIO_OUTPUT -s 127.0.0.6/32 -o lo -j RETURN
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -m owner --uid-owner 1337 -j ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -m owner ! --uid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -m owner --uid-owner 1337 -j RETURN
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -m owner --gid-owner 1337 -j ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -m owner ! --gid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -m owner --gid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN
-A ISTIO_OUTPUT -j ISTIO_REDIRECT
-A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001
- ISTIO_INBOUND、ISTIO_IN_REDIRECT、ISTIO_OUTPUT、ISTIO_REDIRECTチェインがIstioによって定義されている
- istio-proxyのuidが1337
root@kind-iptables-worker3:/# crictl exec 0550b2a85117b id
uid=1337(istio-proxy) gid=1337(istio-proxy) groups=1337(istio-proxy)
-
iptablesだけでは順序が分からないのでcurlでリクエストしてistio-proxyのログを確認します
$ curl http://localhost:31039
-
$ kubectl logs nginx-deployment-6d47dbd4d-6jx9p istio-proxy
[2022-06-04T13:36:03.773Z] "- - -" 0 - - - "-" 2583 1548 65091 - "-" "-" "-" "-" "10.244.2.4:80" inbound|80|| 127.0.0.6:49097 10.244.2.4:80 10.244.3.3:44008 outbound_.8080_._.nginx-service.nginx.svc.cluster.local -
- UPSTREAM_HOST
- 10.244.2.4:80
- UPSTREAM_CLUSTER
- inbound|80||
- UPSTREAM_LOCAL_ADDRESS
- 127.0.0.6:49097
- DOWNSTREAM_LOCAL_ADDRESS
- 10.244.2.4:80
- DOWNSTREAM_REMOTE_ADDRESS
- 10.244.3.3:44008
- REQUESTED_SERVER_NAME
- outbound_.8080_._.nginx-service.nginx.svc.cluster.local
- https://istio.io/latest/docs/tasks/observability/logs/access-log/#default-access-log-format
-
envoyへのチェインの適用順
- PREROUTING
- ISTIO_INBOUND tcp -- anywhere anywhere
- ISTIO_IN_REDIRECT tcp -- anywhere anywhere
- REDIRECT tcp -- anywhere anywhere redir ports 15006
-
envoyからnginxへのチェインの適用順
- OUTPUT
- ISTIO_OUTPUT tcp -- anywhere anywhere
- RETURN all -- 127.0.0.6 anywhere
- RETURNは次のチェインでOUTPUTの次はPOSTROUTING
- UPSTREAM_LOCAL_ADDRESSが127.0.0.6:49097
- POSTROUTING
- ルールなしでそのままUPSTREAM_HOSTの10.244.2.4:80
まとめ
istio-proxyの周りしか見れなかったですが、iptablesによって通信を仲介していることが確認できました
雰囲気でIstioと接していたので少し親睦が深められ良かったです
Discussion