
Istio 사용 시 장점도 있지만, 없을 경우 대비 비용(지연 추가, 프로세싱 추가, 복잡한 구조 등)이 추가된다. 이스티오가 추가되면 바로 통신이 되는게 아니라 엔보이가 요청을 중간에 가로챈다. 이때 ip 테이블 룰을 변경 한다. 이때 목적지 아이피와 동일하게 사용하면 목적지로 전달이 안되기 때문에 엔보이는 루프백 ip를 사용하고 목적지는 파드 ip를 사용한다. 때문에 목적지로 갈 때 다시 ip테이블을 사용한다.

1) 외부에서 인그레스 게이트웨이를 통해서 접근하는데 이 때 ip가 변경된다. D.IP도 파드의 ip로 변경되며 대신 XFF에 기존 IP를 보관
2) 노드로 요청이 전달되어 파드로 전달
3) 파드로 인입됐을 때 istio-proxy가 요청을 가로채기 위하여 15006으로 포트를 변경
4) 목적지로 전달하기 위하여 소스 ip를 127.0.0.6으로 변경하기 때문에 클라이언트 ip 레벨에서 로그를 수집하면 127.0.0.6으로 표시된다. 더불어 포트를 80으로 변경
5) 클라이언트 ip는 XFF에서 수집하고 내부 ip 테이블에 의해서 바뀐 포트를 인식하고 목적지 어플리케이션으로 도달
6) 리턴 응답 시에는 소스 IP와 데스네이션 IP가 스위칭되어 변경
7) 목적지 ip가 127.0.0.6이 되었기 때문에 istio-proxy가 받게 됨
8) istio-proxy가 리턴할 때는 원래 상태로 돌리기 위해 15006 포트로 변경 한다. 더불어 D.IP는 istio ingress gw로 나가기 위하여 랜덤으로 변경된다. 그리고 envoy upstream이 HTTP에 표시
9) 15006 포트가 80으로 변경되어 istio ingress gw로 전달
10) 클라이언트로 응답을 전달
1️⃣ 클라이언트 요청 -> 파드 인입


1) 외부에서 PREROUTING TABLE로 전달
2) ISTIO INBOUND 채널로 전달
3) ISTIO IN REDIRECT로 전달한다. 이는 APP Container가 직접 받지 않도록 하기 위함이다.
4) tcp 15006으로 엔보이 사이드카 프록시로 전달
5) 엔보이 사이드카 프록시를 빠져 나감 (OUTPUT)
6) ISTIO OUTPUT으로 전달
7) POSTROUTING으로 전달
8) 어플리케이션이 요청을 받음
9) upstream return을 OUTPUT으로 전달
10) ISTIO OUTPUT으로 전달
11) 이스티오 사이드카 프록시로 전달하기 위하여 ISTIO REDIRECT로 전달
12) 이스티오 사이드카 프록시로 전달
13) OUTPUT으로 전달
14) ISTIO OUTPUT으로 전달
15) 클라이언트로 응답 전달
이런 IP TABLE은 Init 컨테이너가 설정한다. 이는 초기화하고 종료가 된다.
# 아래 처럼 'istio-init 컨테이너' 의 로그에 iptables rules 설정을 확인할 수 있습니다.
# 참고로, NAT Tables 만 설정되고, 그외(filter, mangle, raw 등)은 설정하지 않습니다.
(istio-k8s:default) root@k8s-m:~# kubectl logs nginx-pod -c istio-init
* nat
-N ISTIO_INBOUND
-N ISTIO_REDIRECT
-N ISTIO_IN_REDIRECT
-N ISTIO_OUTPUT
-A ISTIO_INBOUND -p tcp --dport 15008 -j RETURN
-A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001
-A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15006
-A PREROUTING -p tcp -j ISTIO_INBOUND
-A ISTIO_INBOUND -p tcp --dport 22 -j RETURN
-A ISTIO_INBOUND -p tcp --dport 15090 -j RETURN
-A ISTIO_INBOUND -p tcp --dport 15021 -j RETURN
-A ISTIO_INBOUND -p tcp --dport 15020 -j RETURN
-A ISTIO_INBOUND -p tcp -j ISTIO_IN_REDIRECT
-A OUTPUT -p tcp -j ISTIO_OUTPUT
-A ISTIO_OUTPUT -o lo -s 127.0.0.6/32 -j RETURN
-A ISTIO_OUTPUT -o lo ! -d 127.0.0.1/32 -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 -o lo ! -d 127.0.0.1/32 -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
COMMIT
✔️ IPTable 적용하여 이스티오 프록시 컨테이너 인입
# 트래픽 인입 시 TCP 경우 모든 트래픽을 15006 으로 리다이렉트한다, 일부 포트는 제외(22, 15008, 15020, 15021, 15090)
c1 iptables -t nat -L -n -v
Chain PREROUTING (policy ACCEPT 44 packets, 2640 bytes)
pkts bytes target prot opt in out source destination
45 2700 ISTIO_INBOUND tcp -- * * 0.0.0.0/0 0.0.0.0/0
Chain ISTIO_INBOUND (1 references)
pkts bytes target prot opt in out source destination
...
1 60 ISTIO_IN_REDIRECT tcp -- * * 0.0.0.0/0 0.0.0.0/0
Chain ISTIO_IN_REDIRECT (3 references)
pkts bytes target prot opt in out source destination
1 60 REDIRECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 redir ports 15006
✔️ 이스티오 프록시 컨테이너에서 IPTables 적용
# 로그 내용 중 출발지 정보(127.0.0.6:50763)를 변경하고 전달하는 것을 알 수 있다
(istio-k8s:default) root@k8s-m:~# kubectl logs nginx-pod -c istio-proxy -f
[2021-12-15T18:05:56.334Z] "GET / HTTP/1.1" 200 - via_upstream - "-" 0 615 0 0 "192.168.10.254" "curl/7.68.0" "0844349b-d290-994b-93b2-da36bf929c62" "www.gasida.dev:30384" "172.16.46.11:80" inbound|80|| 127.0.0.6:50763 172.16.46.11:80 192.168.10.254:0 - default

✔️ IPTables를 적용하여 어플리케이션 컨테이너로 전달
파드 내에 IPTables 는 전역으로 적용되므로, 'Istio-proxy' 의 인/아웃 시 트래픽 구별이 중요하다. 'Istio-proxy' 를 빠져나올때는 출발지 IP가 127.0.0.6 이므로 ISTIO_OUTPUT 에 적용되어 리턴되어 POSTROUTING 를 통해 nginx 로 도착한다.
# 출발IP가 127.0.0.6 이고, 빠져나오는 인터페이스가(-o lo)에 매칭되어 리턴됨
c1 iptables -v --numeric --table nat --list ISTIO_OUTPUT
Chain ISTIO_OUTPUT (1 references)
pkts bytes target prot opt in out source destination
2 120 RETURN all -- * lo 127.0.0.6 0.0.0.0/0
# POSTROUTING 은 특별한 rule 이 없으니 통과!
Chain POSTROUTING (policy ACCEPT 144 packets, 12545 bytes)
pkts bytes target prot opt in out source destination
최종적으로 nginx 컨테이너에 클라이언트의 요청 트래픽이 도착한다.
# nginx 웹 데몬에 도착하여 액세스 로그 기록되고, 이후 200ok 리턴되며, XFF 헤더에서 클라이언트의 IP를 확인 할 수 있다
(istio-k8s:default) root@k8s-m:~# kubectl logs nginx-pod -f
127.0.0.6 - - [15/Dec/2021:18:37:38 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.68.0" "192.168.10.254"
127.0.0.6 - - [15/Dec/2021:18:40:52 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.68.0" "192.168.10.254"
...
2️⃣ 클라이언트로 파드 리턴 트래픽

c1 conntrack -L --dst-nat
tcp 6 430172 ESTABLISHED src=172.16.228.76 dst=172.16.46.11 sport=40882 dport=80 src=172.16.46.11 dst=172.16.228.76 sport=15006 dport=40882 [ASSURED] mark=0 use=1
src=172.16.228.76 dst=172.16.46.11 sport=40882 dport=80 # 3번 과정 직전(IPTables 적용 전)의 IP/Port 정보
src=172.16.46.11 dst=172.16.228.76 sport=15006 dport=40882 # 8번 과정 의 IP/Port 정보, 특히 출발지 포트가 15006 으로, 'istio-proxy' 경유를 했음을 알 수 있다
3️⃣ 파드에서 외부 웹서버로

1) 출발지가 파드의 IP
2) IPTables Rule을 적용해서 127.0.0.1:15001로 변경하여 엔보이 이스티오 프록시로 전달
3) 다시 파드 IP로 변경
4) 외부로 나가서 응답

OUTPUT은 어플리케이션을 빠져나갈 때와 엔보이 이스티오 프록시를 빠져나갈 때 모두 사용한다. 이것을 구분하는 것이 중요하다. 이건 유저 id를 통해서 구분한다. (1339)
✔️ 파드 내부 IPTables를 통해 Istio-proxy 컨테이너로 전달
# nginx 파드에서 TCP 트래픽 요청으로 인입 시, ISTIO_REDIRECT 에서 redir ports 15001 되어 'Istio-proxy 컨테이너'로 인입됩니다.
c1 iptables -t nat -L -n -v
Chain OUTPUT (policy ACCEPT 5 packets, 455 bytes)
pkts bytes target prot opt in out source destination
0 0 ISTIO_OUTPUT tcp -- * * 0.0.0.0/0 0.0.0.0/0
Chain ISTIO_OUTPUT (1 references)
pkts bytes target prot opt in out source destination
...
0 0 ISTIO_REDIRECT all -- * * 0.0.0.0/0 0.0.0.0/0
Chain ISTIO_REDIRECT (1 references)
pkts bytes target prot opt in out source destination
0 0 REDIRECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 redir ports 15001

✔️ 파드 내부 Istio-proxy 컨테이너에서 노드의 호스트 네임스페이스
'Istio-proxy 컨테이너' 는 대리인(Proxy) 역할로, 출발지 포트를 변경(+2개) 후 외부 웹서버에 연결을 한다.
(istio-k8s:default) root@k8s-m:~# kubectl logs nginx-pod -c istio-proxy -f
[2021-12-15T21:13:34.787Z] "GET /loc HTTP/1.1" 200 - via_upstream - "-" 0 17 187 187 "-" "curl/7.74.0" "d86b9c0b-9519-9c96-9b06-17938fa6ed3b" "ipinfo.io" "34.117.59.81:80" PassthroughCluster 172.16.46.11:36198 34.117.59.81:80 172.16.46.11:36196 - allow_any

파드를 빠져나가기 전, 다시 한번 더 IPTables 적용 된다. 이때, 이전 트래픽과 매칭되는 Rule 이 다른 것은 UID 1337 때문이다.
# iptables 확인
c1 iptables -t nat --zero # 패킷 카운트 초기화
# 아래 처럼 Istio-proxy(15001)에서 빠져나온 부분은 UID 1337 매칭되어서 RETURN 되어 파드를 빠져나오게 됩니다!
c1 iptables -t nat -L -n -v
Chain ISTIO_OUTPUT (1 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- * lo 127.0.0.6 0.0.0.0/0
0 0 ISTIO_IN_REDIRECT all -- * lo 0.0.0.0/0 !127.0.0.1 owner UID match 1337
0 0 RETURN all -- * lo 0.0.0.0/0 0.0.0.0/0 ! owner UID match 1337
2 120 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0 owner UID match 1337
0 0 ISTIO_IN_REDIRECT all -- * lo 0.0.0.0/0 !127.0.0.1 owner GID match 1337
0 0 RETURN all -- * lo 0.0.0.0/0 0.0.0.0/0 ! owner GID match 1337
0 0 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0 owner GID match 1337
0 0 RETURN all -- * * 0.0.0.0/0 127.0.0.1
2 120 ISTIO_REDIRECT all -- * * 0.0.0.0/0 0.0.0.0/0
'Istio' 카테고리의 다른 글
| Ambient Mesh (2) (3) | 2025.06.05 |
|---|---|
| Ambient Mesh (1) (4) | 2025.06.05 |
| DNS 프록시 이해 (0) | 2025.05.31 |
| 가상 머신 프로비저닝 (0) | 2025.05.31 |
| 가상머신 인프라 준비하기 (AWS EC2 K3S) (0) | 2025.05.31 |