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
을 두드려 컨테이너 전환
알려진 문제
세트를 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
을 두드려 컨테이너 전환
알려진 문제
$ ./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
$ ./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
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로 연결하는 것을 그만둔 곳 보지 않게 되었기 때문에, 쫓는 것을 그만두었습니다.
Reference
이 문제에 관하여(ngx_mruby와 docker로 blue-green deployment), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/muk-ai/items/c9e540a89f916f4c8377
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(ngx_mruby와 docker로 blue-green deployment), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/muk-ai/items/c9e540a89f916f4c8377텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)