KANS3 - Service Mesh : Istio-Mode(Sidecar, Ambient) - 03/03

트래픽 흐름

  • Istio 통신 : 호스트의 tcp/ip 와 iptables파드 내에 iptablesenvoy경유
    • 달리기에 비유하자면, 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) 파드는 클라이언트 PCIP를 HTTP XFF(X-Forwarded-for) 헤더에 담아서 전달합니다.
    • Istio IngressGateway(envoy) 파드 x-envoy-Y 헤더를 추가해서 전달합니다.
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회정도 남았는데, 끝까지 잘 배웠으면 합니다.