트래픽 흐름
- Istio 통신 : 호스트의 tcp/ip 와 iptables 과 파드 내에 iptables 와 envoy 를 경유
- 달리기에 비유하자면, Istio 가 없을 경우를 운동장 한바퀴라면, istio 사용 시 대략 운동장 세바퀴라고 볼 수 있습니다.
- Istio 사용 시 장점도 있지만, 없을 경우 대비 **비용(지연 추가, 프로세싱 추가, 복잡한 구조 등)**이 추가됩니다.
실습
배포
cat <<EOF | k apply -f -
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx-app
spec:
terminationGracePeriodSeconds: 0
containers:
- name: nginx-container
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: svc-nginx
spec:
ports:
- name: svc-nginx
port: 80
targetPort: 80
selector:
app: nginx-app
type: ClusterIP
---
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: test-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: nginx-service
spec:
hosts:
- "*"
gateways:
- test-gateway
http:
- route:
- destination:
host: svc-nginx
port:
number: 80
---
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: "example-workload-policy"
spec:
selector:
matchLabels:
app: nginx-app
portLevelMtls:
80:
mode: DISABLE
EOF
Client PC -> Istio IngressGateway 구간
해당 부부은 기본 배포 후 접속 상태이다.

Istio IngressGateway POD 구간
- Istio IngressGateway(envoy) 파드를 경유하여 웹 서버 파드가 있는 노드로 인입
- Istio IngressGateway(envoy) 파드는 클라이언트 PC의 IP를 HTTP
XFF
(X-Forwarded-for) 헤더에 담아서 전달합니다. - Istio IngressGateway(envoy) 파드 x-envoy-Y 헤더를 추가해서 전달합니다.
- Istio IngressGateway(envoy) 파드는 클라이언트 PC의 IP를 HTTP
Pod 내부의 IPTables 적용 -> instio-proxy 인입
‘PAUSE 컨테이너'가 파드 네트워크 네임스페이스를 생성하여 제공하며, ‘Init 컨테이너'는 Istio-proxy가 트래픽을 가로챌 수 있게 파드 내에 iptables rules 설정을 완료한다.

Istio-proxy -> IPtables 적용
‘Istio-proxy 컨테이너’ 는 대리인(Proxy) 역할로, 출발지 IP를 127.0.0.6 으로 변경하여 ‘Nginx 컨테이너'와 연결을 한다
proxy내 정보 확인
istioctl proxy-config route nginx-pod --name 80
NAME VHOST NAME DOMAINS MATCH VIRTUAL SERVICE
80 istio-ingressgateway.istio-system.svc.cluster.local:80 istio-ingressgateway.istio-system, 10.200.1.162 /*
80 svc-nginx.default.svc.cluster.local:80 svc-nginx, svc-nginx.default + 1 more... /*
80 tracing.istio-system.svc.cluster.local:80 tracing.istio-system, 10.200.1.146 /*
nginx-pod의 endpoint 확인
istioctl proxy-config endpoint nginx-pod --cluster "outbound|80||svc-nginx.default.svc.cluster.local" -o json
[
{
"name": "outbound|80||svc-nginx.default.svc.cluster.local",
"addedViaApi": true,
"hostStatuses": [
{
"address": {
"socketAddress": {
"address": "10.10.0.23",
"portValue": 80
}
},
"stats": [
{
"name": "cx_connect_fail"
},
{
"name": "cx_total"
},
{
"name": "rq_error"
},
{
Iptables -> Nginx 컨테이너로의 전달
iptables -t nat -L -n -v
Chain ISTIO_OUTPUT (1 references)
pkts bytes target prot opt in out source destination
Nginx -> Client
- nginx (웹 서버)컨테이너에서 리턴 트래픽(응답, 200 OK)를 클라이언트에 전달한다.
- IPTables CT(Connection Table)에 정보를 참고해서 역변환 등이 적용되어 전달된다.
Nginx -> Outbound Webserver
외부로의 호출 걸어놓기
while true; do kubectl exec -it nginx-pod -c nginx-container -- curl -s http://ipinfo.io/city; date "+%Y-%m-%d %H:%M:%S" ; echo "--------------" ; sleep 3; done
Nginx -> iptables -> envoy
iptables -t nat -L -n -v
Chain PREROUTING (policy ACCEPT 137 packets, 8220 bytes)
pkts bytes target prot opt in out source destination
139 8340 ISTIO_INBOUND 6 -- * * 0.0.0.0/0 0.0.0.0/0
Chain INPUT (policy ACCEPT 139 packets, 8340 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 94 packets, 6846 bytes)
pkts bytes target prot opt in out source destination
38 2280 ISTIO_OUTPUT 6 -- * * 0.0.0.0/0 0.0.0.0/0
Chain POSTROUTING (policy ACCEPT 106 packets, 7566 bytes)
pkts bytes target prot opt in out source destination
Chain ISTIO_INBOUND (1 references)
pkts bytes target prot opt in out source destination
0 0 RETURN 6 -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:15008
0 0 RETURN 6 -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:15090
136 8160 RETURN 6 -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:15021
1 60 RETURN 6 -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:15020
2 120 ISTIO_IN_REDIRECT 6 -- * * 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
2 120 REDIRECT 6 -- * * 0.0.0.0/0 0.0.0.0/0 redir ports 15006
Chain ISTIO_OUTPUT (1 references)
pkts bytes target prot opt in out source destination
2 120 RETURN 0 -- * lo 127.0.0.6 0.0.0.0/0
0 0 ISTIO_IN_REDIRECT 6 -- * lo 0.0.0.0/0 !127.0.0.1 tcp dpt:!15008 owner UID match 1337
11 660 RETURN 0 -- * lo 0.0.0.0/0 0.0.0.0/0 ! owner UID match 1337
13 780 RETURN 0 -- * * 0.0.0.0/0 0.0.0.0/0 owner UID match 1337
0 0 ISTIO_IN_REDIRECT 6 -- * lo 0.0.0.0/0 !127.0.0.1 tcp dpt:!15008 owner GID match 1337
0 0 RETURN 0 -- * lo 0.0.0.0/0 0.0.0.0/0 ! owner GID match 1337
0 0 RETURN 0 -- * * 0.0.0.0/0 0.0.0.0/0 owner GID match 1337
0 0 RETURN 0 -- * * 0.0.0.0/0 127.0.0.1
12 720 ISTIO_REDIRECT 0 -- * * 0.0.0.0/0 0.0.0.0/0
Chain ISTIO_REDIRECT (1 references)
pkts bytes target prot opt in out source destination
12 720 REDIRECT 6 -- * * 0.0.0.0/0 0.0.0.0/0 redir ports 15001
lo 인터페이스도 값이 증가한다.
ifconfig lo
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 4717 bytes 28326204 (27.0 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 4717 bytes 28326204 (27.0 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
envoy -> outbound
‘Istio-proxy 컨테이너’ 는 대리인(Proxy) 역할로, 출발지 포트를 변경(+2) 후 외부 웹서버에 연결을 한다 노드에 SNAT(masquerading) 설정이 되어 있을 경우, 출발지 IP 를 노드의 NIC IP로 변환하여 외부 웹서버에 요청을 전달한다.
outbound -> nginx return
웹 서버에서 리턴 트래픽이 파드에 돌아오는 과정은 **1.**2 에서 알아본 흐름과 유사하다
다만, 파드 내로 인입 시 목적지 포트(+2) 이므로, ‘Nginx 컨테이너’ 로 바로 가지 않고, ‘Istio-proxy 컨테이너’ 로 먼저 가게 된다.
후기
이번편은 그동안 관심있어 하던 항목이었습니다. 보안요건등이 그리 강하지 않아 아직은 Kong을 사용하고 있지만, Istio 혹은 Anthos(Google Cloud Istio Managed Service)를 사용하고자 했었기 때문입니다. 아니면 Istio의 경우 기존에 kubeflow를 구축할때 필수였기 때문에 구축하면서 가볍게 만져본게 다였기 때문에 더 공부하고 싶었을지도 모릅니다.
이번에 스터디하면서 보니, 생각보다 좋은 Service Mesh 이지만, Ambient mode가 GA 및 일정부분 패치가 되기 전까지는 고민을 해야겠다는 생각도 들었습니다.
이제 스터디가 2회정도 남았는데, 끝까지 잘 배웠으면 합니다.