ngx_mruby와 docker로 blue-green deployment

목적



ngx_mruby를 사용하여 백엔드 컨테이너를 전환할 수 있는지 살펴보았습니다.
docker를 사용하고 싶지만 가동 중지 시간없이 deploy하려면 이렇게해야합니다.
라는 간단한 방법이없는 것 같습니다. 이 방법은 범용적으로 사용할 수 있지 않을까 생각합니다.

샘플 이동



세트를 Github( htps : // 기주 b. 코 m / 무 k 아이 / 레 st 아피 )에 넣었습니다.
network 기능을 사용하므로 docker >= 1.10, docker-compose >= 1.6 으로 사용해 보세요.
git clone https://github.com/muk-ai/rest-api.git
cd rest-api/
git checkout 1f978500008e2126fdce2b31b1d4e189520e069b

docker-compose build
docker-compose up -d

브라우저에서 port 80에 액세스하면 {"messages": "hello, world"}가 표시됩니다.
여기에서 deploy.sh에서 컨테이너를 바꿉니다.
sh deploy.sh mukai/rest-api:goodbye

port 80에 액세스하면 {"messages": "goodbye, world"} 가 표시됩니다.
nginx의 전달 대상 컨테이너가 전환되었기 때문입니다.
롤백도 컨테이너 전환으로 할 수 있습니다.
sh deploy.sh restapi_falcon

롤백은 컨테이너 이미지를 pull 할 시간이 없기 때문에 빠릅니다.

가동 중지 시간이 있습니까?



wrk로 액세스를 하면서 백엔드 컨테이너의 stop/start를 걸었을 경우
$ ./wrk -c300 -d10s -H"User-Agent: strees-test" --latency --timeout 10 http://172.31.26.80/
Running 10s test @ http://172.31.26.80/
  2 threads and 300 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   738.10ms    1.37s    7.88s    87.79%
    Req/Sec   796.77    221.40     1.35k    81.82%
  Latency Distribution
     50%   64.22ms
     75%  832.17ms
     90%    2.57s
     99%    6.44s
  14137 requests in 10.01s, 2.70MB read
  Non-2xx or 3xx responses: 315
Requests/sec:   1412.04
Transfer/sec:    275.74KB

315번의 에러(Non-2xx or 3xx responses)가 나왔습니다.
그런 다음 wrk로 액세스하는 동안 deploy.sh에서 컨테이너를 전환하는 경우.
$ ./wrk -c300 -d10s -H"User-Agent: strees-test" --latency --timeout 10 http://172.31.26.80/
Running 10s test @ http://172.31.26.80/
  2 threads and 300 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   629.61ms    1.38s    9.43s    90.19%
    Req/Sec   792.55    196.76     1.34k    63.32%
  Latency Distribution
     50%   66.83ms
     75%  472.64ms
     90%    1.91s
     99%    6.90s
  15750 requests in 10.01s, 2.97MB read
Requests/sec:   1573.40
Transfer/sec:    303.44KB

오류가 발생하지 않았습니다. ( ̄- ̄) 니리

요소 (nginx.conf) 설명



ngx-mruby/docker/conf/nginx.conf
        location / {
            resolver 127.0.0.11 valid=2s;
            mruby_set_code $backend '
              cache = Cache.new :namespace => "nginx"
              cache["proxy_dest"]
            ';
            proxy_pass http://$backend:3031;
        }

해석기 지정이 127.0.0.11 인 이유는 docker 네트워크의 다른 컨테이너 이름 확인 때문입니다.
(깜박이지만 127.0.0.1 이외의 루프백 주소로 DNS를 빼면 컨테이너 이름 확인이 가능합니다.)cache["proxy_dest"] 안에 백엔드 서버를 넣습니다.
이 변수는 ↓와 같이 초기화됩니다.

ngx-mruby/docker/conf/nginx.conf
    mruby_init_code '
      # mruby-cache
      cache = Cache.new :namespace => "nginx"
      cache["proxy_dest"] = "falcon"
    ';

Cache 클래스를 사용하는 것은 nginx 프로세스 전체에서 값을 공유하고 싶기 때문입니다.falcon는 응용 프로그램 컨테이너의 이름입니다.
이 이름을 127.0.0.11에 문의하면 IP가 반환됩니다.

ngx-mruby/docker/conf/nginx.conf
        location /container/switchover {
            allow 172.16.0.0/12;
            deny all;

            mruby_content_handler_code '
              v = Nginx::Var.new
              if v.arg_dest.nil?
                Nginx.errlogger Nginx::LOG_ERR, "Invalid parameter #{v.arg_dest}"
                Nginx.return Nginx::HTTP_BAD_REQUEST
              end
              cache = Cache.new :namespace => "nginx"
              cache["proxy_dest"] = v.arg_dest
              Nginx.echo "ack"
            ';
        }
/container/switchover라는 경로를 사용하여 대상 컨테이너를 제어합니다.
v.arg_dest에서 dest 요청 매개 변수를 가져오고 해당 값으로 cache["proxy_dest"]를 업데이트합니다.
curl http://localhost/container/switchover?dest=$container_id

와 같이 nginx의 방향을 전환합니다.
deploy.sh에서는 다음을 수행합니다.
① 컨테이너 이미지 pull
② 컨테이너의 기동과 컨테이너 ID의 취득
/container/switchover을 두드려 컨테이너 전환

알려진 문제



  • nginx가 뚱뚱하다 (critical)
  • 이전 컨테이너 폐기 처리 없음

  • nginx가 뚱뚱한 것은 mruby를 쓰는 방법에 문제가 있다고 생각합니다. 부하 테스트에 걸면 마루마루와 뚱뚱해집니다.
    wrk를 대체로 30초 정도 걸리면 1GB 있던 메모리가 다합니다. 식자의 분, 어드바이스 받을 수 있으면 다행입니다・・・.
    또, 구 컨테이너를 그대로 하고 있기 때문에 deploy 때마다 컨테이너가 증가해 가고 그 중 파탄이라고 생각합니다.

    추가



    2016/04/11



    @matsumotory 님이 조언을 받고 Nginx의 메모리 누수를 해결했습니다.
    htps : // 기주 b. 코 m / 무 k 아이 / 레 st 아피 / 푸 l / 10 / 후 ぇ s
    고마워요. m(__)m

    그런데, wrk를 장시간 걸릴 수 있게 되어, 또 다른 문제(고부하시에 잠시 패킷이 떨어진다)가 발견되었습니다.
    docker network의 문제인지 uwsgi의 문제인지 아직 잘라내지 못하고 있습니다.
    → 이 문제는 nginx와 uwsgi 사이를 http로 연결하는 것을 그만둔 곳 보지 않게 되었기 때문에, 쫓는 것을 그만두었습니다.

    좋은 웹페이지 즐겨찾기