TheKoguryo's 기술 블로그

 Version 2023.11.20

4.1.4.3 OCI Network Load Balancer 기반 NGINX Ingress Controller에서 클라이언트 IP 얻기

Nginx Ingress Controller를 사용할 때, Pod에 있는 애플리케이션에서 모니터링 등을 위해 실 Client IP를 확인 할 필요가 있습니다. 하지만, 클라이언트의 요청은 Nginx Ingress Controller가 사용하는 OCI Network Load Balancer를 거쳐 오는 경우에도 실제 Client IP를 얻기 위한 방법을 알아봅니다.

기본 설치 상태에서 확인하기

기본 설치 상태에서 애플리케이션 로그 확인하기
  1. 인그레스 주소를 확인하고, 접속합니다.

    $ kubectl get ingress
    NAME                         CLASS   HOSTS                             ADDRESS                      PORTS     AGE
    ingress-path-basic           nginx   *                                 10.0.20.182,152.xx.xxx.xxx   80        10h
    
  2. 웹브라우저에서 관련 사이트를 통해, 자신의 Public IP를 확인합니다.

    image-20230702110312584

  3. 테스트 앱을 브라우저로 접속합니다.

    예) http://152.xx.xxx.xxx/blue

  4. 애플리케이션 로그를 확인합니다.

    예시에서는 클라이언트 주소(X-Forwarded-For)가 14.45.121.214로 앞서 확인한 나의 작업 PC의 Public IP가 나오는 것을 확인할 수 있습니다.

    $ kubectl logs -lapp=nginx-blue -f
    10.244.1.5 - - [02/Jul/2023:01:54:07 +0000] "GET /blue HTTP/1.1" 200 7270 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36" "14.45.121.214"
    
관린설정 확인
  1. Client IP를 보존하기 위해 다음 설정이 필요합니다..

    • Load Balancer 타입을 Network Load Balancer로 설정

      oci.oraclecloud.com/load-balancer-type: "nlb"
      
    • Network Load Balancer의 Client IP 보존 설정

      oci-network-load-balancer.oraclecloud.com/is-preserve-source: "true"
      
    • spec.externalTrafficPolicy을 Local로 지정

        externalTrafficPolicy: Local
      
    • NGINX Ingress Controller 설치시 다운받은 deploy.yaml 파일을 아래와 같이 변경하여 배포하면됩니다.

      ...
      ---
      apiVersion: v1
      kind: Service
      metadata:
        ...
        name: ingress-nginx-controller
        namespace: ingress-nginx
        annotations:
          oci.oraclecloud.com/load-balancer-type: "nlb"
          oci-network-load-balancer.oraclecloud.com/is-preserve-source: "true"
      spec:
        externalTrafficPolicy: Local
      ...
      
  2. Nginx Ingress Controller v1.8.0 버전로 2023년 6월 기준 OKE에 설치시에는 위 설정이 기본 적용되어 있습니다.

    # 설정하지 않더라도 nlb를 사용하는 경우 디폴트가 true임
    oci-network-load-balancer.oraclecloud.com/is-preserve-source: "true"
    
    # Nginx Ingress Controller v1.8.0 설치시 다운받은 deploy.yaml에 기본값이 Local임
    spec:
      externalTrafficPolicy: Local
    

클라이언트 IP가 확인되지 않는 경우

기본 설치 상태에서 애플리케이션 로그 확인하기
  1. 인그레스 주소를 확인하고, 접속합니다.

    $ kubectl get ingress
    NAME                 CLASS    HOSTS   ADDRESS          PORTS   AGE
    ingress-path-basic   <none>   *       146.56.xxx.xxx   80      21m
    
  2. 테스트 앱을 브라우저로 접속합니다.

    예) http://146.56.xxx.xxx/blue

  3. 애플리케이션 로그를 확인합니다.

    예시에서는 클라이언트 주소가 10.0.20.21로 나옵니다.

    • 10.0.20.x는 Quick Create 모드로 OKE 클러스터를 만든 경우 oke-svclbsubnet의 대역으로, Nginx Ingress Controller와 연동된 Load Balancer의 Private IP입니다.
    $ kubectl logs -lapp=nginx-blue -f
    10.244.1.3 - - [02/Sep/2022:12:35:39 +0000] "GET /blue HTTP/1.1" 200 7272 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" "10.0.20.21"
    
  4. 테스트에서 보듯이, 기본 Nginx Ingress Controller 설치상태에서는 애플리케이션 Pod에서 찍히는 Client IP는 실제 클라이언트의 IP가 아님을 알 수 있습니다.

클라이언트 IP를 얻기 위해 관련 설정하기
  1. NGINX Ingress Controller 설치 파일을 다운로드 합니다.

    wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.3/deploy/static/provider/cloud/deploy.yaml
    
  2. Client IP를 보존하기 위해 다음 설정을 합니다.

    • Load Balancer 타입을 Network Load Balancer로 설정합니다.

      oci.oraclecloud.com/load-balancer-type: "nlb"
      
    • Network Load Balancer의 Client IP 보존 설정을 합니다.

      oci-network-load-balancer.oraclecloud.com/is-preserve-source: "true"
      
    • spec.externalTrafficPolicy을 Local로 지정합니다.

        externalTrafficPolicy: Local
      
    • 다운받은 NGINX Ingress Controller 설치 파일 변경 예시

      ...
      ---
      apiVersion: v1
      kind: Service
      metadata:
        ...
        name: ingress-nginx-controller
        namespace: ingress-nginx
        annotations:
          oci.oraclecloud.com/load-balancer-type: "nlb"
          oci-network-load-balancer.oraclecloud.com/is-preserve-source: "true"
      spec:
        externalTrafficPolicy: Local
      ...
      
  3. 변경한 설정파일로 NGINX Ingress Controller을 배포합니다.

    kubectl apply -f deploy.yaml
    
    • 기존 NGINX Ingress Controller가 있는 경우 삭제 후 재배포합니다. 또한 기존 Nginx Ingress Controller의 Public IP를 그대로 사용하려는 경우 다음을 참조하여 loadBalancerIP 값을 설정합니다.

      • Specifying Reserved Public IP Addresses

        apiVersion: v1
        kind: Service
        metadata:
          ...
          annotations:
            oci.oraclecloud.com/load-balancer-type: "nlb"
        spec:
          loadBalancerIP: 146.56.xx.xxx
          type: LoadBalancer
          ...
        
  4. Security Rule을 설정합니다.

    • Load Balancer에서 Worker Node(10.0.10.0/24)으로 접근할 수 있도록 Service Subnet의 Security List에 다음 규칙을 추가합니다.

      • Security List 이름: 예) oke-svclbseclist-quick-~~~~

      • 추가할 Egress Rule

        StatelessDestinationIP ProtocolSource Port RangeDestination Port RangeType and CodeAllowsDescription
        No10.0.10.0/24TCPAll30000-32767TCP traffic for ports: 30000-32767
    • Worker Node(10.0.10.0/24)에서 Load Balancer를 통해 들어오는 요청을, 클라이언트 IP로 접근할 수 있도록 Worker Node Subnet의 Security List에 다음 규칙을 추가합니다.

      • Security List 이름: 예) oke-nodeseclist-quick-~~~~

      • 추가할 Ingress Rule

        StatelessSourceIP ProtocolSource Port RangeDestination Port RangeType and CodeAllowsDescription
        No0.0.0.0/0TCPAll30000-32767TCP traffic for ports: 30000-32767
  5. 웹브라우저에서 관련 사이트를 통해, 자신의 Public IP를 확인합니다.

    image-20220902230229865

  6. 테스트 앱을 브라우저로 접속합니다.

    예) http://146.56.xxx.xxx/blue

    image-20220902230453550

  7. 애플리케이션 로그를 확인합니다.

    예시에서는 클라이언트 주소(X-Forwarded-For)가 220.117.xxx.x로 앞서 확인한 나의 작업 PC의 Public IP가 나오는 것을 확인할 수 있습니다.

    $ kubectl logs -lapp=nginx-blue -f
    10.244.1.4 - - [02/Sep/2022:14:03:35 +0000] "GET /blue HTTP/1.1" 200 7272 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" "220.117.xxx.x"
    
  8. 테스트 결과와 같이 OCI 문서에 따라 Client IP를 보존하기 위한 관련 설정을 하면, 애플리케이션 Pod에서 실제 Client IP을 확인할 수 있습니다.



이 글은 개인으로서, 개인의 시간을 할애하여 작성된 글입니다. 글의 내용에 오류가 있을 수 있으며, 글 속의 의견은 개인적인 의견입니다.

Last updated on 2 Sep 2022