다음을 통해 공유


Azure Kubernetes Service 노드에서 SNAT 포트 고갈 문제 해결

이 문서는 SNAT(원본 네트워크 주소 변환) 포트 고갈을 경험하는 AKS(Azure Kubernetes Service) 노드를 찾아서 문제를 해결하는 데 도움이 됩니다.

참고 항목

  • Kubernetes 작업을 실행하는 AKS 클러스터의 AKS 노드에서 SNAT 포트 고갈 문제를 해결하려면 작업이 AKS 노드에서 적극적으로 실행되는 경우에만 다음 단계를 수행합니다.
  • SNAT 포트 및 가상 머신당 할당에 대한 자세한 내용은 SNAT 포트란?을 참조하세요.

1단계: SNAT 포트 고갈이 발생하는 노드 찾기

  1. Azure Portal에서 활성 SNAT 포트 소모가 발생하는 AKS 노드의 IP 주소를 가져옵니다.

    이렇게 하려면 Azure Portal에서 AKS 클러스터로 이동하고 진단 및 문제 해결>연결 문제>SNAT 연결 및 포트 할당을 선택합니다. SNAT 연결 및 포트 할당 탭에는 SNAT 포트 고갈이 발생하는 AKS 노드의 개인 IP 주소가 표시됩니다.

    '문제 진단 및 해결' 창의 스크린샷.

    '연결 문제' 창의 스크린샷.

  2. AKS 클러스터에 연결하고 노드 IP 주소를 사용하여 다음 kubectl 명령을 실행하여 노드 이름을 가져옵니다.

    kubectl get nodes -o wide | grep <node IP>
    

2단계: 높은 아웃바운드 연결이 있는 Linux Pod 찾기

참고 항목

  • Tcptracer 는 Linux 노드에 미리 설치된 BCC(BPF 컴파일러 컬렉션) 도구 중 하나입니다. TCP 설정 연결(connect()accept()close())을 추적할 수 있습니다. 이를 사용하여 Pod의 원본 IP 주소 및 네트워크 네임스페이스(netns)에서 높은 아웃바운드 연결을 찾을 수 있습니다.
  • BCC 도구에 액세스하려면 kubectl node-shell 사용합니다.
  • 이 섹션의 다음 명령은 모두 BCC 도구가 설치된 Linux 노드에서 루트 사용자로 실행됩니다.
  1. SNAT 포트 소모가 발생하는 Linux 노드에서 kubectl node-shell을 설치합니다.

    curl -LO https://github.com/kvaps/kubectl-node-shell/raw/master/kubectl-node_shell
    chmod +x ./kubectl-node_shell
    sudo mv ./kubectl-node_shell /usr/local/bin/kubectl-node_shell
    
  2. SSH를 사용하여 SNAT 포트 소모가 발생하는 노드에 연결하고 TCP 설정된 연결을 추적하는 데 사용합니다 tcptracer .

    kubectl node-shell <node name>
    cd /usr/share/bcc/tools
    /usr/share/bcc/tools# python3 tcptracer -t4v
    

    다음은 명령 출력 예제입니다.

    Tracing TCP established connections. Ctrl-C to end.
    TIME(ns)     TYPE         PID   COMM             IP SADDR            DADDR            SPORT  DPORT  NETNS
    0           connect      18627  curl             4  1.2.3.4           5.6.7.8          53746  80     4026532785
    3xxx9       close        18627  curl             4  1.2.3.4           5.6.7.8          53746  80     4026532785
    1xxxx4      connect      18629  curl             4  1.2.3.4           9.10.11.12       35686  80     4026532785
    2xxxx9      close        18629  curl             4  1.2.3.4           9.10.11.12       35686  80     4026532785
    4xxxx5      connect      18631  curl             4  1.2.3.4           9.10.11.12       35688  80     4026532785
    4xxxx8      close        18631  curl             4  1.2.3.4           9.10.11.12       35688  80     4026532785
    7xxxx3      connect      18633  curl             4  1.2.3.4           13.14.15.16      35690  80     4026532785
    9xxxx7      close        18633  curl             4  1.2.3.4           13.14.15.16      35690  80     4026532785
    
  3. 이전 명령 출력을 로그 파일에 쓴 다음 출력을 정렬하여 높은 연결 목록을 검토합니다.

    python3 tcptracer -t4v > log
    head -n +2 log | tail -n 1 | awk '{print "Count",$6,$10}'; awk '{print $6,$10}' log | sort | uniq -c | sort -nrk 1 | column -t
    

    다음은 명령 출력 예제입니다.

    Count SADDR        NETNS
    387   1.2.3.4      4026532785
    8     11.22.33.44  4026532184
    8     55.66.77.88  4026531992
    
  4. IP 주소를 이전 출력의 가장 많은 연결과 Pod에 매핑합니다. 작동하지 않으면 계속할 수 있습니다.

  5. SADDR 이전 출력에서 가장 많은 연결이 있는 값 또는 NETNS 값을 적어두고 다음 lsns 명령을 실행하여 PID에 매핑합니다. Lsns는 네임스페이스를 나열하고 네임스페이스를 Linux 프로세스 트리의 PID에 매핑하는 Linux 도구입니다.

    lsns -t net
    

    다음은 명령 출력 예제입니다.

    NS         TYPE NPROCS PID   USER  COMMAND
    4026532785 net  3      19832 root  bash
    
  6. pstree를 사용하여 이전 PID를 컨테이너된 프로세스에 매핑합니다. Pstree는 가독성을 위해 프로세스를 트리 형식으로 나열하는 Linux 도구입니다.

    pstree -aps 19832
    

    다음은 명령 출력 예제입니다.

    systemd,1
      `-containerd-shim,20946 -namespace k8s.io -id 2xxxf...
    

    명령 출력에 컨테이너된 -id 처음 5자를 확인합니다. 7단계에서 사용됩니다.

  7. crictl을 사용하여 이전 컨테이너 값을 -id POD ID에 매핑합니다. Crictl은 CRI 호환 컨테이너 런타임에 대한 CLI를 제공합니다.

    crictl ps -a
    

    다음은 명령 출력 예제입니다.

    CONTAINER   IMAGE     CREATED      STATE     NAME    ATTEMPT    POD ID        POD
    6b5xxxxb    fbxxxxx1  6 hours ago  Running   ubuntu  0          2xxxxxxxxf    nginx
    

    이전 컨테이너 값 -id 의 처음 5자를 사용하여 POD ID와 일치합니다.

  8. 노드에서 실행되는 모든 Pod를 가져오고 이전 POD ID를 사용하여 명령 출력에서 높은 아웃바운드 연결이 있는 Pod와 일치합니다.

    kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=<nodename>
    

3단계: 애플리케이션에서 만든 모든 아웃바운드 네트워크 연결 찾기

  1. 다음 명령 중 하나를 사용하여 2단계에서 높은 아웃바운드 연결이 있는 것으로 식별되는 Pod로 실행합니다.

    • kubectl exec -it <pod name> -n <namespace> /bin/bash
      
    • kubectl exec -it <pod name> -n <namespace> /bin/sh
      
  2. 다음 명령을 실행하여 Pod에 netstat 명령줄 도구를 설치합니다. Netstat는 관리자만을 위한 네트워크 문제 해결 도구입니다.

    • Debian, Ubuntu 또는 Linux Mint에서

      apt update
      apt install net-tools  
      
    • RHEL, CentOS, Fedora, AlmaLinux 또는 Rocky Linux에서

      yum update
      yum install net-tools      
      
    • Gentoo Linux에서

      emerge -a sys-apps/net-tools  
      
    • Alpine Linux에서

      apk add net-tools    
      
    • Arch Linux에서

      pacman -S net-tools
      
    • OpenSUSE에서

      zypper install net-tools
      
  3. netstat가 Pod에 설치되면 다음 명령을 실행합니다.

    netstat -ptn | grep -i established
    

    다음은 명령 출력 예제입니다.

    tcp        0      0 10.x.x.x:xxxx        20.x.x.x:443       ESTABLISHED xxxxx3/telnet
    

명령 출력에서 로컬 주소는 Pod의 IP 주소이고 외래 주소는 애플리케이션이 연결하는 IP입니다. 상태의 ESTABLISHED 공용 IP 연결은 SNAT를 활용하는 연결입니다. 공용 IP 주소에 ESTABLISHED 대한 상태의 연결만 계산하고 개인 IP 주소에 대한 상태의 ESTABLISHED 모든 연결을 무시해야 합니다.

노드에서 실행되는 다른 모든 Pod에 대해 이 섹션의 단계를 반복합니다. 공용 IP 주소에 대한 상태 연결이 가장 많은 Pod는 노드에서 ESTABLISHED SNAT 포트 소모를 일으키는 애플리케이션을 호스트합니다. 애플리케이션 개발자와 협력하여 연결 효율적인 애플리케이션 디자인에 언급된 권장 사항을 사용하여 향상된 네트워크 성능을 위해 애플리케이션을 조정합니다. 권장 사항을 구현한 후 SNAT 포트 고갈이 더 적게 표시되는지 확인합니다.

도움을 요청하십시오.

질문이 있거나 도움이 필요한 경우 지원 요청을 생성하거나Azure 커뮤니티 지원에 문의하세요. Azure 피드백 커뮤니티에 제품 피드백을 제출할 수도 있습니다.