어느날 nginx 의 proxy_pass 에서pending이 걸렸다. (두둥)
어느날 멀쩡히 돌던 front server nginx 의 api proxy 부분에서 pending 이 걸렸다. 우왕 자왕 하다 재기동하니 정상 동작 했다.
주말에 발생한 부분이라 일단 정상동작하니, 주중에출근하면 확인해보려 했지만. 막상 출근해서 로그를 보려했더니 딱히 error 가 보이지 않는다. -_-
고민을 하던중에 프론트엔드팀의 차장님께서 okky 의 글 하나를 알려주셨다.
(이 차장님은 어떤것을 물어보면 척하고 좋은 의견/정보를 알려 주신다.)
이와 관련된 또다른 글
http://tech.kkung.net/blog/nginx-with-elb/
문제는 AWS ELB (복수의 ip가 할당됨, elb는 ec2인스턴스의 집합)는 트래픽 등에 의해 동적으로 ip들이 늘어나거나 줄어드는데.
proxy_pass https://www.test.com
위와 같이 정의 되어있으면 nginx 가 설정파일을 읽는 시점에 도메인의 ip를 resolve 해버리기 때문에 AWS ELB 의 동적인 ip 변경이 일어날 경우
connect() failed (113: No route to host) while connecting to upstream,
위와 같은 문제가 생긴다는 것이다.
여기에 동일한 문제의 답이 있다. okky 글의 원출처.
The answer to this question is that ELBs sometimes change ip adresses and nginx does name resolving during start.To fix this there is always a DNS server in your VPC at 0.2. So if the local ip CIDR is 10.0.0.0/16 the DNS server is at 10.0.0.2.Add this to the nginx config.resolver 10.0.0.2 valid=10s;
The proxy_pass also needs to be defined as a variable otherwise nginx will only resolve it once. So based on the configuration above this is the correct config:server {
listen 3000;
location / {
resolver 10.0.0.2 valid=10s;
set $backend "http://internal-prod732r8-PrivateE-1GJ070M0745TT-348518554.eu-west-1.elb.amazonaws.com:3000"
proxy_pass $backend;
include /etc/nginx/proxy.conf;
}
}
위의 답변과 같이 proxy_pass 에 도메인 직접입력이 아니라 변수로 할당하게 되면
nginx 는 resolver dns를 참조하여 매번 ip를 찾아가기 때문에 문제를 해결할 수 있겠다.
ㅜㅜ 그런데 어떤글은 172.16.0.23 AWS DNS 주소라고 하고
어떤글은 vpc 주소의 XXX.XXX.0.2 가 AWS DNS 주소라고 한다.
뭐가 맞는 말인가.. ㅜㅜ
AWS 문서에 아래와 같은 내용이 있다.
Amazon DNS Server
Amazon provides a DNS server that resolves Amazon-provided IPv4 DNS hostnames to IPv4 addresses. In EC2-Classic, the Amazon DNS server is located at 172.16.0.23
. In EC2-VPC, the Amazon DNS server is located at the base of your VPC network range plus two. For more information, see Amazon DNS Server in the Amazon VPC User Guide.
EC2-Classic 의 DNS 서버는 172.16.0.23 이고
EC2-VPC 의 DNS 서버는 위치한 VPC 네트워크 range +2 에 위치 한다.
VPC 의 IPv4 CIDR 이 172.31.0.0/16 라면 172.31.0.2에 DNS 서버가 있다.
(또는 cat /etc/resolv.conf 확인)
설정은 아래와 같이 하면 되겠다.
resolver 172.31.0.2 valid=5s; #VPC 일때
#resolver 172.16.0.23 valid=5s; #EC2-Classic
set $target "elb.aws-test.com";location / { proxy_pass http://$target;
proxy_set_header Host $target;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
끝…