• Nginx proxy_pass 설정 이슈 :: 마이구미
    AWS 2023. 11. 25. 14:26
    반응형
    이 글은 직접 겪은 nginx proxy_pass 설정과 관련 있는 이슈를 다룬다.
    본인이 경험한 이슈는 뒤늦게 알았지만... 이미 많은 사람들이 겪어서 관련 글들이 존재한다.
    nginx - https://www.nginx.com/blog/dns-service-discovery-nginx-plus/

     

     

    nginx 의 proxy_pass 설정을 활용하고 있는 서비스가 존재한다.

    간략하게 나타내면, 다음과 같은 구조로 구성되어있다.

     

     

    실제 서비스 도메인은 mygumi.com 으로 구성된다.

    사용자가 만약 mygumi.com/mygumi 경로로 진입한다면, 내부적으로 다른 도메인을 가지고 있는 서비스를 진입하게 된다.

     

    이를 위한 nginx 설정은 다음과 같다.

     

    // nginx.conf
    
    location /mygumi {
      proxy_pass https://proxy-mygumi.com;
    }

     

    이러한 상황에서 어느 순간 /mygumi 경로로 서비스 진입시 간헐적으로 504 에러가 발생하는 현상이 생겨났다.

     

     

    proxy_pass 경로가 아니라면 정상 동작하고 있었고, proxy_pass 에 설정된 경로 진입시에 문제가 발생했다.

    proxy-mygumi.com 로 직접 접근은 가능한 상황이라, 해당 서비스 자체의 문제는 아니였다.

     

    • Nginx 에서 504 Gateway Time-out 에러 발생
    • 프록시 대상이 되는 서비스는 정상적인 상태

     

    2가지 상황에서 추정할 수 있는 건 결국 nginx 쪽에서 프록시 대상과의 통신에 문제가 있다는 것이었다.

    프록시 대상이 되는 서비스는 정상적인데 왜 nginx 는 통신하지 못할까? 라는 것을 이해할 수 없었다.

     

    그러다가 문득 nginx 쪽에서 제대로 된 곳으로 요청하는 건 확실한건가? 라는 의심이 시작되었다.

    nginx 는 /mygumi 경로 진입시에는 prox-mygumi 서비스로 이동시킨다.

    내부적으로 다시 이야기해보면, nginx 는 DNS 서버를 통해 proxy-mygumi.com 의 실제 IP 로 이동시킬 것이다.

    host 명령어를 통해 proxy-mygumi.com 의 IP 를 확인해볼 수 있다.

     

    host proxy-mygumi.com

     

    명령어의 실행 결과는 4개의 IP 주소가 출력될 것이다.

     

    • proxy-mygumi.com has address 54.*.*.1
    • proxy-mygumi.com has address 54.*.*.2
    • proxy-mygumi.com has address 54.*.*.3
    • proxy-mygumi.com has address 54.*.*.4

     

    실제로 proxy-mygumi 서비스는 CloudFront 를 이용하는 서비스로써, 다음과 같은 정책을 가지고 있다.

     

    CloudFront는 배포에 고정 IP 주소를 할당하는 것을 지원하지 않습니다.
    사용자가 CloudFront에서 콘텐츠를 요청하면 DNS는 지연 시간이 가장 짧은 엣지 로케이션의 IP 주소 4개를 반환합니다. 이렇게 하면 콘텐츠를 최상의 성능으로 제공할 수 있습니다. 엣지 로케이션은 서로 다른 IP 주소 세트와 연결되어 있으므로 요청할 때 배포에 대해 동일한 고정 주소를 수신하지 않습니다.

     

    결론적으로 cloudfront 는 고정 IP 를 제공하지 않는다.
    proxy-mygumi.com 서비스의 경우 DNS 는 가장 가까운 엣지 4군데의 IP 를 반환할 것이고, IP 는 동적으로 변경될 수 있다는 것을 의미한다.
    이 상황에서 만약 nginx 는 변경된 IP 가 아니라, 기존 IP 를 바라보고 있다면? 504 응답을 초래할 여지가 있다.
    실제로 로그를 확인해보니 504 시점과 504 해소 시점의 IP 는 다른 상황이라는 것을 알 수 있었다.

     

    ex)

    1. 12:54 분까지의 CloudFront IP 의 54.x 였음
    2. 14:30분 부터 CloudFront IP 는 18.x 변경되었음
    3. nginx 는 그대로 54.x 를 바라보고 있어서 504 에러 발생
    4. 서버 재시작해서 nginx 는 54.x 를 물지 않고 다시 올바른 18.x 바라보게 되어서 해소

     

    nginx 는 proxy_pass 에 설정된 도메인의 IP 를 어떻게 캐시하고 있는지? 얼마나 캐시하고 있는지? 등과 같은 것들을 확인해볼 필요가 있었다.

    여기까지 분석이 되니 상황에 대한 구글링은 수월해지게 되었고, 관련 글들을 찾을 수 있게 되었다.

     


     

    nginx 공식 문서에서는 proxy_pass 에 대해 다음과 같이 설명하고 있다.

     

    nginx 는 proxy_pass 에 도메인을 사용하는 경우에 다시 시작하거나 구성을 다시 로드할때 DNS 서버에 쿼리하여 도메인을 확인한다.

    (nginx 는 어떤 DNS 서버를 선택할지 설정할 수 있는데 이것을 resolver 라고 하고, DNS 서버는 /etc/resolv.conf 를 통해 설정할 수 있다.)

    그리고 쿼리 결과로 반환된 IP 는 TTL 값과는 상관없이 다시 시작하거나 구성을 다시 로드할때까지 캐시된다.

    즉, nginx 는 DNS 서버에 쿼리하는 것이 딱 한번만 이루어지고 더이상 resolver 를 참조하지 않는다는 것을 의미한다.

    https://www.nginx.com/blog/dns-service-discovery-nginx-plus/#domain-name-proxy_pass

     

    NGINX caches the DNS records until the next restart or configuration reload, ignoring the records’ TTL values

     

     

     

    위 내용들을 그대로 주입해보자.

    proxy-mygumi.com 의 IP 는 초기에 캐시되어, 변경되더라도 nginx 는 기존 IP 를 바라보고 있다는 것을 의미한다.

    이러한 상황을 해결하기 위해서는 DNS 서버 쿼리를 주기적으로 요청이 이루어져야만, IP 변경에 대응할 수 있다.

    공식 문서에서는 이러한 이슈를 위한 방안도 제공해주고 있었다.

    변수에 도메인을 설정하여 사용하면, DNS 쿼리 빈도를 제어할 수 있다는 것이다.

     

    When you use a variable to specify the domain name in the proxy_pass directive, NGINX re‑resolves the domain name when its TTL expires.

     

     

    // as-is
    location /mygumi {
      proxy_pass https://proxy-mygumi.com;
    }
    
    // to-be
    location /mygumi {
      set $proxy_app https://proxy-mygumi.com;
      proxy_pass $proxy_app;
    }

     

    위와 같은 설정으로 변경되면, TTL 만료시 resolver 를 참조하여 다시 IP 를 확인하게 된다.

    참고로 TTL 값에 의존하지 않고, resolver 의 valid 설정값으로 제어할 수도 있다.

     

    resolver {DNS_SERVER} valid=10s;

     


     

     

    관련 지식은 부족하여 혹시나 잘못된 내용이 있다면, 댓글로 공유해주시면 감사...

     

    참고 자료

    https://tech.kkung.net/blog/nginx-with-elb/

    https://circlee7.medium.com/nginx-proxy-pass-%EC%9D%98-aws-elb-%EC%97%B0%EA%B2%B0-%EC%84%A4%EC%A0%95-f0c4b792ef71

    반응형

    댓글

Designed by Tistory.