[Istio] Istio ingress gateway TCP Keep Alive 설정해보기

Dante·2023년 11월 20일
0

Kubernetes

목록 보기
1/1

들어가기 앞서

Keep Alive 대해 알아보자, Keep Alive의 네이버 기준 사전적 의미는 "살아 있다" 또는 "꺼지지 않게 하다" 라는 의미를 가지고 있다.

그럼 Keep Alive는 왜 쓸까?

보통은 Client와 Server 간의 통신을 유지 하려고 keep alive를 적용한다.

위 그림 처럼 Client에서 Server로 데이터 요청을할 때 처리 시간이 약 1분 이상 소요되고 있다면, 해당 연결을 끊거나 유지를 해야 할 필요가 있다.
연결이 강제로 끊긴다면? - 사용자가 요청한 데이터에 대해 원하는 결과를 얻지 못 할 수 있다.
연결을 유지 한다면? - 사용자가 요청한 데이터에 대해 원하는 결과를 얻을 수 있다.

만약 사용자가 요청한 데이터가 오래 걸린다면, Keep Alive를 이용해 Client와 Server간의 연결이 유효한지 계속 확인을 하면서 연결이 끊어지지 않게 요청한 데이터를 응답할 수 있도록 할 수 있다.

이렇게 Wireshark 도구를 사용해 Keep Alive를 통해 TCP 통신이 유지되는 것을 확인할 수 있다.
Keep Alive는 Client가 Server로 또는 Server가 Client로 TCP Keep Alive Packet를 보내서, 이에 대한 Ack 응답이 오면 정상, 응답이 안오면 몇 번 재시도 후 해당 연결을 끊는다.

sudo sysctl -a | grep keepalive
net.ipv4.tcp_keepalive_intvl = 10
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_time = 60

리눅스 시스템 환경에서는 Keep Alive에 대한 커널 파라미터가 기본적으로 설정이 되어있고, 각 운영체제마다 약간 상이하다.
리눅스 Keep Alive에 대한 커널 파라미터 설명은 링크 에서 확인이 가능하다.

Istio ingress gateway Keep Alive 적용 검토

결론은 이걸 왜 적용을 했냐면, Client가 Server로 10분 이상 소요되는 API 호출할 때마다 자꾸 5분 이내로 연결이 종료되는 문제가 있어 Istio ingress gateway에 Envoy Filter를 적용하여 해결을 하였다.

통신 흐름은 Client -> Loadbalance -> Istio ingress gateway -> Service Application 이러한 흐름으로 통신을 하고 있었다.

대강 보면, 15시 2분에 HTTP POST 요청을 받고 5분 뒤인 15시 7분에 연결이 종료됐다.
Client가 TCP 헤더 플래그에 FIN, ACK 설정하여 Server한테 연결 종료
요청을 한 것 이다.

도대체 왜? 라는 생각에 Istio ingress gateway가 올라간 노드에서 tcpdump 도구를 통해 패킷 캡처를 진행했다.

뭔가 이상한 느낌이 들었다. 이건 뭔지..?

Istio ingress gateway에서 패킷 덤프를 뜬 결과를 보고 머리가 복잡해졌다.
Istio ingress gateway로 트래픽이 들어오면, virtual service에 정의 된 Service로 전달을 해주는 역할이라고 이해하고 있었다.

하지만, 해당 어플리케이션의 Sidecar인 istio-proxy 컨테이너가 Istio ingress gateway의 TCP 8080 Port3-way-handshake 요청을 하고, Client가 보낸 HTTP POST 요청을 보냈다.
이 후 Istio ingress gateway는 해당 어플리케이션에 3-way-handshake 요청을 하고, Client가 보낸 HTTP POST 요청을 보냈다.

대략 흐름을 표현하면 이렇고

와이어샤크를 통해 합쳐서 보면 이렇다.
(해당 패킷 플로우를 보면, 10.233.121.64는 어플리케이션이 올라간 노드의 vxlan IP이고, 10.233.91.53은 Istio ingress gateway의 아이피이다.
왜 istio-proxy sidecar 컨테이너의 아이피가 아니라 vxlan IP인지 아직도 생각중이다. 과연 istio-proxy일까..?
istio 심화 내용은 여기서 다시 보자)
무튼, 누가 통신을 끊는지 알겠고 이 사이에 Keep Alive를 적용하면, 10분 이상 소요되는 API 호출할 때 10분 뒤에 정상적으로 응답을 받을 수 있겠구나 라고 생각했다.

적용 하기 전에!

Istio ingress gateway의 EnvoyFilter에 Keep Alive를 적용하기 전에 몇몇 테스트를 해 보았다.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
spec:
  gateways:
    - istio-system/istio-gw
  hosts:
    - test.test.com
  http:
      name: service-application
      route:
        - destination:
            host: service-application
            port:
              number: 8087
       timeout: 10s

Virtual Service에 timeout을 적용하면 어떻게 될까 궁금했다.

time curl -X POST test.test.com/~~~ 이렇게 테스트 해보니 10초되자 마자 504 Gateway Timeout 메시지를 받았다.
Virtual Service에 시간을 아무리 오래 줘도 어차피 5분 뒤에 끊기는건 동일하다고 생각했다.

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
spec:
  host: service-application
  subsets:
    - labels:
        app: service-application
      name: service-application
  trafficPolicy:
    connectionPool:
      tcp:
        connectTimeout: 30ms
        tcpKeepalive:
          interval: 75s
          time: 3600s
    tls:
      mode: DISABLE

Destination Rule에 Keep Alive를 적용하면 어떻게 될까 궁금했다.
하지만, Keep Alive 패킷을 볼 수 없었다.

Istio ingress gateway Keep Alive 적용하기

돌고돌아 Istio ingress gateway에 Keep Alive를 적용해야했다. 하지만, 어떻게 설정을 해야 좋을지 막막했다.
다행히 구글 검색 하다 F5의 글을 볼 수 있었고 여기에 해답이 있었다.
K00026550: Istio Ingress Gateway TCP keepalive
내용은 Envoyfilter에 Istio ingress proxy 컨테이너가 리눅스 커널 파라미터에 정의 된 Keep Alive를 사용할 수 있게 설정 해줘야 한다는 것 이다.

istioctl dashboard envoy -n istio-system istio-ingressgateway-68fd8758d4-95lrj

istioctl 도구를 이용해 현재 envoy에 대한 설정을 확인해볼 수 있다.

nsenter -n -t 19495 -- sudo netstat -antp --timer | grep 8080
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      19495/envoy          off (0.00/0/0)
tcp        0      0 10.233.116.242:8080     10.233.115.0:4534       ESTABLISHED 19495/envoy          off (0.00/0/0)

Envoyfilter 적용 전에 Istio ingress gateway가 올라간 노드에서 istio-ingress의 PID를 찾고, 해당 컨테이너의 network Namespace에 동작하고 있는 envoy 프로세스의 Keep Alive가 off로 되어있는 것을 확인할 수 있다.

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
spec:
  configPatches:
    - applyTo: LISTENER
      match:
        context: GATEWAY
        listener:
          name: 0.0.0.0_8080
          portNumber: 8080
      patch:
        operation: MERGE
        value:
          socket_options:
            - description: enable keep-alive
              int_value: 1
              level: 1
              name: 9
              state: STATE_PREBIND
            - description: idle time before first keep-alive probe is sent
              int_value: 7
              level: 6
              name: 4
              state: STATE_PREBIND
            - description: keep-alive interval
              int_value: 5
              level: 6
              name: 5
              state: STATE_PREBIND
            - description: keep-alive probes count
              int_value: 2
              level: 6
              name: 6
              state: STATE_PREBIND

Envoyfilter 적용 후 Istio ingress gateway Pod를 재시작 해야한다.

해당 설정은 istio-ingress의 HTTP 프로토콜 통신에 설정에 적용이 된다.
만약 istio-ingress에서 HTTPS 프로토콜 통신일 경우 8080이 아닌 8443으로 설정을 해야한다.

istioctl dashboard envoy -n istio-system istio-ingressgateway-546cc9d9f6-6wzt9

OR

istioctl pc listener -n istio-system istio-ingressgateway-546cc9d9f6-6wzt9 --port 8080 -oyaml

다시 istioctl 도구를 이용해 Istio ingress gateway에 Envoyfilter가 적용됐는지 확인한다.

       "socket_options": [
        {
         "description": "enable keep-alive",
         "level": "1",
         "name": "9",
         "int_value": "1"
        },
        {
         "description": "idle time before first keep-alive probe is sent",
         "level": "6",
         "name": "4",
         "int_value": "7"
        },
        {
         "description": "keep-alive interval",
         "level": "6",
         "name": "5",
         "int_value": "5"
        },
        {
         "description": "keep-alive probes count",
         "level": "6",
         "name": "6",
         "int_value": "2"
        }
       ],

이렇게 Keep Alive가 정상적으로 적용 됐고,

netstat -antp --timer | grep 8080 | grep keep
tcp        0      0 10.233.121.77:8080      10.233.91.0:23687       ESTABLISHED 19/envoy             keepalive (1.46/0/0)
tcp        0      0 10.233.121.77:8080      10.233.90.192:19032     ESTABLISHED 19/envoy             keepalive (3.07/0/0)

Istio ingress gateway의 envoy 프로세스 또한 Keep Alive time이 표출되고 있다.

확인

22:53:03 에 Client는 Server로 10분이 걸리는 API를 보내고,중간중간에 TCP Keep Alive 패킷을 보내면서 양간의 통신 상태가 정상인지 확인하며,
마침내, 10분 뒤에 Server로 부터 응답을 받을 수 있게되었다.

참조 링크

profile
it's me.

0개의 댓글