nginx에서 파일을 이용하여 L7 health check (10초 동안 x번 200 리턴 값이 아닌 값이 나오면 l7 binding이 빠지게 하는 방법)하는 방법을 소개한다. 



1. -f을 이용하여 파일을 체크하는 방식이 있다. 

(사실 if가 evil이긴 하지만, 이 방법만큼 심플한 방법이 없었다..)


location = /l7.html {

  if (!-f /usr/local/nginx/off_health_check) {

    return 404; 

  }

  access_log  off;

  allow       all;


  proxy_pass http://service

}



/usr/local/nginx/off_health_check이 파일이 존재하지 않으면, 404을 리턴하여 l7 health check에 실패로 인식하게 한다.

만약 해당 파일이 존재하지 않으면 service 포트로 전달하도록 proxy_pass를 이용한다.


elasticsearch 라면, proxy_pass http://es/_cluster/health; 를 추가하여 elasticsearch의 클러스터 헬쓰 체크를 할 수 있도록 변경할 수 있다. 



참고 #1


nginx 공식 문서에, if (-f 파일명)에 대해서 좋지 않는 것 같다. 대신 try-files를 쓰라고 권고하고 있다.

https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#check-if-file-exists



Check (If) File Exists


Using if to ensure a file exists is horrible. It’s mean. If you have any recent version of NGINX you should look at try_files which just made life much easier.


BAD:


server {

    root /var/www/example.com;

    location / {

        if (!-f $request_filename) {

            break;

        }

    }

    

    






2. 설정 파일에서 읽어 l7 health check를 제어하는 방법이다.

if is evil!(https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/)이 찜찜하지만, 너무 좋은 기능이라 쓸 수 밖에 없다. 



설정 


<conf/l7.conf>

$ cat /usr/local/nginx/conf/l7.conf

set $l7 down;



<conf/vhost.conf 파일>


location /health_check.html {

include l7.conf;

if ($l7 = "down") {

return 404;

}


access_log  off;

        allow       all;


        default_type text/html;

        return 200 "OK";

        }





스크립트를 다음처럼 사용할 수 있다.


$ cat > l7.sh

#!/bin/sh


COMMAND=$1


if [ -z "${COMMAND}" ]; then

  echo 1>&2 "$0: no given command."

  exit 2

fi


echo "set \$l7 ${COMMAND};" > /usr/local/nginx/conf/l7.conf && sudo ./sbin/nginx -s reload && echo "${COMMAND}"




다음처럼 스크립트를 실행하면 l7 health check를 제어할 수 있다.


$ l7.sh up 

up

$ curl -v -XGET http://localhost/health_check.html

..HTTP/1.1 200 OK


$l7.sh down

down

.. HTTP/1.1 404 Not Found

    





* 노트 1

keepalive 모드를 사용하면서, l7.conf를 사용하여 변수 값을 이용하여 l7 health check하는 방법을 사용할 때, 이슈가 발생할 수 있다. nginx -s reload는 graceful하게 할 수 있다고 알려져 있지만, keepalive 모드에서는 tcp 데이터가 전달되면서 동시에 잠깐의 재시작이 일어나면서 패킷 드롭 현상이 발생될 수 있다.

no host exception과 같은 에러를 발견할 수 있다. 


이 문제를 해결하려면, keepalive를 쓰지 않거나, -f을 이용한 파일 체크를 사용하는 방법이 나을 것 같다. 





* 노트 2


keepalive 상태에서 파일을 이용한 l7 health check 방법은 약간의 한계가 있다. 

keepalive이기 때문에 대용량 서비스일 때, tcp 패킷이 계속 들어올 수 있기 때문에 l7 health check에서 200이 아닌 값, 즉 400 에러를 내보내도 계속 tcp 패킷이 들어와서 l7 스위치 바인딩에서 빠지지 않게 된다.


요청량이 아주 많지 않으면 keepalive를 쓰지 않는다. 그러면 파일을 이용한 l7 health check가 아주 유용할 것이다.

keepalive를 사용중이라면, client 쪽에서 여러 번 retry 구조로 변경해야 한다. 



* 노트 3

if (!-f 파일명) 


-f는 파일이 존재하면,

!-f는 파일이 존재하지 않으면 이라는 의미를 가진다.


!-f를 주로 사용하는 것이 추천하고 싶은 이유는 좀 더 유연하게 대처할 수 있을 것 같다. 

nginx를 재시작하기 전에 파일이 없으면 404라는 의미를 주는 것이 더 명쾌하는 것 같다. 



Posted by '김용환'
,