NLB, Istio 구성에서 curl 을 사용한 통신 과정

2025. 9. 7. 20:10·트러블슈팅

현업에서 네트워크 이슈 딥다이브 중 공부한 curl 을 사용한 통신 과정에 대해 블로그에 정리해둡니다.

curl

  • 명령줄(CLI)에서 다양한 프로토콜을 이용해 데이터를 전송할 수 있는 도구.
  • Client for URL
  • 브라우저의 역할을 GUI 없이 텍스트 기반 명령줄에서 수행해줌.

 

클라이언트 ↔ 서버 통신 과정

네트워크 구성: NLB -> Istio Ingres Gateway -> EKS Pod

 

여기서 클라이언트는 curl, 서버는 NLB, Istio Ingress Gateway Pod, 실제 애플리케이션 Pod

  • curl 로 보낸 요청은 최종 목적지인 애플리케이션 파드로 전달됨. 요청은 여러 단계의 서버(프록시)를 거쳐 전달됩니다.
  1. curl -> NLB
    • DNS 는 도메인을 NLB 의 공인 IP 주소로 알려줌
    • curl 은 이 IP 주소와 TCP 연결을 맺음.
    • NLB 는 Layer 4 장비로, HTTP 요청을 들여다보지 않고 다음 서버(프록시)로 전달
  2. NLB -> Istio Ingress Gateway Pod
    • 현재 구성에서는 NLB 에 ACM 이 등록되어 있어 TLS 협상 대상이 NLB 임.
    • NLB 는 외부 트래픽을 TLS 프로토콜로 받고, 직접 클라이언트와 TLS Handshake 를 수행하여 트래픽을 복호화함.
    • NLB 는 받은 요청을 복호화하여 일반 HTTP 트래픽을 타겟 그룹(istio ingress gateway) 으로 전달함
    • Istio proxy(Istio ingress gateway) 는 전달받은 요청을 등록된 Gateway. Virtualservice 를 보고 요청을 최종 목적지인 내부 서비스로 라우팅함
  3. Istio Ingress Gateway Pod -> application pod
    • 요청이 파드 안에서 실행 중인 애플리케이션 컨테이너로 도착
    • 해당 애플리케이션에서 비즈니스 로직을 수행하고 최종 응답을 생성함.

 [175.41.240.159] [2025-09-02 15:54:46.3N] [REQ-17535] [SUCCESS] [HTTP-200] connect:0.048334 appconnect:0.141238 starttransfer:0.185948 total:0.186507 ver:1.1

 

사용한 스크립트 일부:

# 본문은 버리고(-o /dev/null), -w 로 메트릭만 수집
      metrics=$(curl -o /dev/null -sS \
        --connect-timeout "$TIMEOUT" \
        --max-time "$TIMEOUT" \
        --http1.1 \
        -w "$CURL_FMT" \
        "$API_URL")
      curl_exit_code=$?

      end_ms=$(date +%s%3N)
      actual_duration=$(echo "scale=3; ($end_ms - $start_ms) / 1000" | bc -l)

      # 파싱
      remote_ip=$(awk '{for(i=1;i<=NF;i++) if($i ~ /^remote_ip:/){sub("remote_ip:","",$i); print $i}}' <<< "$metrics")
      http_code=$(awk '{for(i=1;i<=NF;i++) if($i ~ /^http_code:/){sub("http_code:","",$i); print $i}}' <<< "$metrics")
      connect_t=$(awk '{for(i=1;i<=NF;i++) if($i ~ /^connect:/){sub("connect:","",$i); print $i}}' <<< "$metrics")
      appconnect_t=$(awk '{for(i=1;i<=NF;i++) if($i ~ /^appconnect:/){sub("appconnect:","",$i); print $i}}' <<< "$metrics")
      starttransfer_t=$(awk '{for(i=1;i<=NF;i++) if($i ~ /^starttransfer:/){sub("starttransfer:","",$i); print $i}}' <<< "$metrics")
      total_t=$(awk '{for(i=1;i<=NF;i++) if($i ~ /^total:/){sub("total:","",$i); print $i}}' <<< "$metrics")
      http_ver=$(awk '{for(i=1;i<=NF;i++) if($i ~ /^http_version:/){sub("http_version:","",$i); print $i}}' <<< "$metrics")

      # 숫자 보정 및 total 보정
      is_number "$connect_t"       || connect_t=0
      is_number "$appconnect_t"    || appconnect_t=0
      is_number "$starttransfer_t" || starttransfer_t=0
      if ! is_number "$total_t"; then total_t=0; fi
      # -w 가 0/빈값인 경우(특히 TIMEOUT) 실제 측정값으로 대체
      if (( $(echo "$total_t == 0" | bc -l) )); then total_t="$actual_duration"; fi
      [[ -z "$http_code" ]] && http_code=000
      [[ -z "$remote_ip" ]] && remote_ip=""

 

connect ( curl <-> NLB )

  • TCP 연결 수립 단계
  • 클라이언트와 서버가 통신을 시작하기 위해 TCP 3-way Handshake 를 맺는 데 걸린 시간.

appconnect ( curl <-> NLB )

  • TLS 보안 연결 단계. 아래 과정이 끝나야 안전한 보안 채널이 완성됨.
  • TCP 연결이 수립된 후, 데이터를 암호화하기 위한 보안 연결(TLS Handshake) 를 맺는 데까지 걸린 시간.
  • 1단계 (Client Hello)
    • client 가 server 에게 client 가 사용 가능한 암호화 방식 목록 전달 및 SSL/TLS 인증서 요구
    • ALPN(Application-Layer Protocol Negotiation) 목록을 보냄
      • 어떤 애플리케이션 프로토콜(ex. HTTP/2 HTTP/1.1) 로 대화할지 미리 협상하는 기능
  • 2단계 (server Hello)
    • Server 가 Client 와 사용할 암호화 방식과 SSL/TLS 인증서 전달 (cipher suite )
  • 3단계 (키 교환 및 완료)
    • 양측이 인증서와 키를 확인하고, 앞으로의 모든 대화를 암호화할 방법을 합의 완료
      • client 는 인증서를 확인하여 공개키를 획득하고, 공개키로 대칭키를 암호화하여 서버에 전달
      • 서버는 암호화된 대칭키를 개인키로 복호화하여 대칭키를 획득
      • 대칭키를 활용하여 데이터를 주고 받음
    • handshake 가 끝나면 지연없이 선택한 Application-Layer Protocol 을 사용하여 통신을 시작함.

→ HTTPS 통신을 위해 클라이언트와 서버가 서로를 확인하고, 암호화할 비밀 키를 교환함.

starttransfer (Time To First Byte)

  • 보안 채널 준비된 후, 실제 요청을 보내고 서버가 응답 데이터의 첫 조각을 보내주기까지 걸린 시간. 요청 전송 시간 + 서버 처리 시간 + 응답 시작 시간
    • 이 시간이 길다면, 보통 서버 내부의 작업이 오래 걸리는 것.
  • 서버의 성능을 직접적으로 보여줌
  • 1단계 (HTTP Request)
    • client 가 HTTP 요청을 보냄
  • 2단계 (Server Processing)
    • 서버는 요청을 받고 내용을 분석함.
  • 3단계 (First Byte Response)
    • 서버가 모든 준비를 마치고 응답 데이터의 첫번째 바이트를 client 에게 보내기 시작함.

 


curl 을 사용한 부하테스트 진행 시 주의사항 - keepalive 의 한계점

 

서로 다른 curl 프로세스는 네트워크 연결을 공유하지 않음


  • 운영체제는 각 프로세스를 독립적인 메모리 공간과 자원을 가진 격리된 단위로 취급하기 때문에, 1번 curl 이 열어놓은 네트워크 소켓(연결 정보)를 2번 curl 이 사용할 수 없는 것.
  • 따라서 쉘 스크립트로 단순히 curl 을 반복하는 것은 연결을 재사용하는 것이 아닌 설정한 요청의 개수만큼 프로세스를 생성하는 것. TCP 연결을 재사용(keep alive) 하지 않음.

 

# O: 이렇게 하나의 명령어로 실행해야 연결이 재사용됩니다.
curl http://example.com/page1 http://example.com/page2

# X: 이렇게 여러 명령어로 분리하면 연결 재사용이 불가능합니다.
curl http://example.com/page1
curl http://example.com/page2

 

 

이미지 레퍼런스 

'트러블슈팅' 카테고리의 다른 글

Kubernetes 트러블슈팅 가이드: 파드부터 커널 레벨까지.  (1) 2025.10.18
EKS에서 nginx의 EBS 볼륨 Permission Denied  (0) 2025.10.18
EKS 기반 대규모 부하 테스트: NLB, KeepAlive, 커널 파라미터 튜닝  (0) 2025.05.18
'트러블슈팅' 카테고리의 다른 글
  • Kubernetes 트러블슈팅 가이드: 파드부터 커널 레벨까지.
  • EKS에서 nginx의 EBS 볼륨 Permission Denied
  • EKS 기반 대규모 부하 테스트: NLB, KeepAlive, 커널 파라미터 튜닝
HH_g
HH_g
  • HH_g
    HH_Techlog
    HH_g
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 코딩 테스트
      • 프로젝트
        • 식선생
      • K8S
        • 주요 개념
        • Scheduling
        • Cluste Maintenance
        • Application Lifecylcle Mana..
      • NCloud
      • AWS
      • 트러블슈팅
      • Observability
      • 후기
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    로드테스트
    EKS
    스택
    ㅐ
    백준
    10828
    시뮬레이션
    coredns
    파이썬
    8911
    kube-dns
    k8s
    volumemodificationfeature
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
HH_g
NLB, Istio 구성에서 curl 을 사용한 통신 과정
상단으로

티스토리툴바