문제 상황
클라이언트에게 서버가 제대로 배포되지 않았다는 메세지를 받았다. 장애 시점은 재배포 직후이다.

배포 서버는 실제로도 제대로 동작하고 있지 않았다.
모니터링 지표를 확인했을때도 유의미한 내용을 확인할 수 없었다.

2025/10/23 15:45:32 [error] 79#79: *1393 connect() failed (111: Connection refused) while connecting to upstream, client: "clientIP", server: "serverDomain",
request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "hostIP", referrer: "http://hostIP/"
원인
빠르게 해결하기

현재 API서버는 Nginx을 통해 Reverse Proxy 형태로 WAS를 가리키고 있다.
배포 환경을 하나씩 체크해보자.
첫번째로는 도커 환경에서 WAS 컨테이너가 제대로 돌아가고 있는지 확인해보자.
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
containerId service/was "java -jar /app/app.…" 21 minutes ago Up 21 minutes 0.0.0.0:8080->8080/tcp was
컨테이너는 제대로 구동하고 있다. WAS 로그에서 비정상적인 흐름은 확인되지 않는다.
따라서 Nginx에서 문제가 발생하고 있다는 것을 유추해볼 수 있다.
service nginx reload
실제로 reload 명령어를 통해 문제를 해결할 수 있었다..
하나씩 이해하기
문제 해결 이후에는 클라이언트단에서는 배포 문제가 더 이상 확인되지 않았지만, 모니터링 관련 인프라 작업중에 간혈적으로 동일한 문제가 확인되었고, 장애 원인을 더 조사해보았다.
TCP Socket
Nginx에서 WAS를 Reverse Proxy로 제대로 가리키 못하고 있는 이유는 WAS의 주소가 변경되고 있었기 때문이였다.

Nginx는 Reverse Proxy로 8080포트를 가리키고 있다. 따라서 요청은 받은 Nginx와 WAS사이에 TCP Socket이 생성 및 연결된다.

TCP Socket은 목적지 IP + Port으로 이루어진 TCP Welcome Socket을 통해출발지 IP + Port, 목적지 IP + Port 으로 이루어져 있는 TCP Socket을 생성할 수 있다. 만약 목적지 IP또는 Port가 달라진다면 새로운 TCP Welcome Socket을 필요로 한다.
현재 Nginx는 도커 서비스 이름으로 WAS를 가리키고 있다. 따라서 기존 TCP Welcome Socket을 Nginx에서 계속 사용하면서 장애가 발생하고 있었다고 예상해볼 수 있었다. 아래와 같은 상황이다.

Nginx는 설정 파일을 로드할때 upstream또는 proxy_pass 설정 값을 읽으면서 DNS 주소를 Nginx Process 단에서 저장해서 사용하기 때문에 변경된 주소를 처리할 수 없다.
다시 보기
문제의 원인을 이해했지만, 하나 더 확인할 부분이 있다. 장애가 “간혈적”으로 발생했다는 것이다. 초기에는 NGINX단에서 DNS를 캐싱하기 때문에 해당 캐싱이 운나쁘게(?) 유지되는 경우에만 장애가 발생해서 “간혈적”인 장애가 발생한다고 판단했지만, 앞써 말했듯이 Nginx는 설정 파일 로드 후에서는 DNS 정보를 계속 유지하고 있다.
CIDR

컨테이너를 생성할때 컨테이너가 사용하게 될 도커 네트워크에서 CIDR에 따라 남은 IP를 해당 컨테이너에서 할당받게 된다. 그림과 같이 bobtory-network0은 172.18.0.1/16 의 CIDR를 가지고 있고, IP주소(172.18.0.0)와 게이트 웨이 주소(172.18.0.1)를 제외한 주소 192.18.0.2를 컨테이너 IP로 할당받게 된다.

기존 배포 환경에서는 WAS 컨테이너만을 삭제 생성을 반복했었기 때문에 새로 생성된 컨테이너도 이전 컨테이너와 동일한 주소를 가져갈 수 있었다. (운이 좋았다)

그러나 모니터링 리소스 컨테이너를 새로 생성하면서 기존 WAS에 사용하던 주소를 모니터링 컨테이너가 점유하게 된다. 그림과 같이 172.18.0.4/16를 WAS 컨테이너가 아닌 모니터링 컨테이너가 할당 받게 되면서, 문제가 되었던 것이다.
DNS Resolver
Nginx에서 DNS resolve 사이클을 통제할 수 있는 옵션을 제공한다.
resolver 127.0.0.53 valid=5s;
resolver_timeout 5s;
코드에서 확인할 수 있듯이 Resolver 5s를 통해 5초간 간격으로 주소를 업데이트할 수 있다. 그러나 해당 설정이 제대로 작동하지 않았다.
https://github.com/nginx/nginx/pull/208
[Upstream: re-resolvable servers by bavshin-f5 · Pull Request #208 · nginx/nginx
v3 of the patchset, previously submitted in https://mailman.nginx.org/pipermail/nginx-devel/2024-July/MYXA5AVMTIMDNEVMA462AN7CRQ546Y7L.html This PR adds to the open-source code DNS re-resolve and s...
github.com](https://github.com/nginx/nginx/pull/208)
https://www.f5.com/company/blog/nginx/dns-service-discovery-nginx-plus
[Using DNS for Service Discovery with NGINX and NGINX Plus
Explore five methods for service discovery in NGINX and NGINX Plus that use DNS records, including SRV records in NGINX Plus R9.
www.f5.com](https://www.f5.com/company/blog/nginx/dns-service-discovery-nginx-plus)
PR에서 확인할 수 있듯이 Resolver 설정은 본래 Nginx Plus에서만 제공했지만, 1.27.3부터 Nginx에서 제공한다는 것을 알 수 있다. 현재 배포서버는 Nginx 1.24.0를 사용하고 있었기 때문에 버전업으로 최종 해결하였다.
resolver 127.0.0.11 valid=5s ipv6=off;
resolver_timeout 5s;
upstream was_upstream {
zone was_upstream_zone 64k;
server was:8080 resolve;
}
레퍼런스
https://stackoverflow.com/questions/67439712/nginx-does-not-re-resolve-dns-names-in-docker
https://blog.nginx.org/blog/dynamic-dns-resolution-open-sourced-in-nginx
'인프라' 카테고리의 다른 글
| [NGINX] Nginx 이해하기 (리버스 프록시) (0) | 2025.05.26 |
|---|---|
| 데이터베이스가 계속 꺼지는 경우 (시스템 용량 초과) (0) | 2024.12.28 |
| [NGINX] CORS, Mixed Content (3) | 2024.07.22 |
