System Compleat.

Nginx + memcached, and balancing

Techs

( younjin.jeong@gmail.com, 정윤진 )




Nginx 는 언젠가부터 급 부상하기 시작한 다용도의-가볍고-사용하기쉬운 웹 서버다. lighttpd 와 같은 시스템 과는 약간 궤를 달리하는데, apache 에서 어플리케이션 서버의 기능을 배제하고, 부가기능에 보다 충실한 서버다 라고 할 수 있겠다. Nginx 에 대한 자세한 설명은 http://wiki.nginx.org 에서 얻을 수 있으므로 그게 무엇이다를 설명하는 것은 스킵하기로 한다. 


다음은 발로 그린 서비스 아키텍쳐이다. 여기에는 내부망과 외부망 사이에서 각 서비스로의 도메인 라우팅 ( aka. 리버스 프락싱 ) 및 로드 밸런싱, 그리고 SSL endpoint 로서의 기능을 하는 서버가 필요하다. 물론 여기에 상용의 밸런서를 넣을 수도 있으며, 아예 밸런서 클라우드로 구성해 버리는 방법도 있다. 하지만 양자 모두 돈이 많이 드니까, 그냥 Nginx 를 쓰기로 했다. 



Diagram #1, Entire system design


다시한번 그림은 발로 그렸음을 강조한다. ( 사실은 인튜오스4에 Sketchbook Express ;;; ) 


구성하고자 하는 것이 Compute cloud 건, Storage cloud 건, 하둡이건, 그도 아니면 태풍을 예보하는 기상용 HPC 클러스터이던 간에 서비스를 구성하는 구성 요소는 대부분 다 엇비슷하다. 멤버들의 스펙이나 연결 방법들은 조금씩 다르긴 하지만. 아무튼 요즘 유행하고 있는 여기건 저기건 무한대로 확장해야 한다 라는 요소를 가미하면, 모든 구간에 확장이 가능해야 하며 여기에는 똥색으로 그려진 밸런서들도 예외가 아니다. 만약 백본의 트래픽이 수십/수백 기가에 달하는 지경이 된다면 서비스의 종류에 따라 내부 트래픽은 훨씬 더 증가 할 가능성이 있으며, 이 트래픽들은 DSR 구조로 연결되어 있지 않다면 모두 밸런서를 통과하게 된다. 


행여 역시 개발로 쓴 영문을 보신 분들이라면 알겠지만, Nginx 는 만능이 아니다. 잘못사용하게 되면 사용하지 않느니만한 결과를 불러오며, 간결하게 만들어진 시스템에 이것저것 붙이다 보면 오히려 최근의 BMW 처럼 된다.  성능과 정비성이 떨어지게 되며, 장애 포인트가 늘어난다. 프락싱이나 밸런싱의 종류에 따라, Varnish / Pound / Apache 등이 좋은 선택이 될 수 있다. 테스트 테스트. 



Simple concept - 발그림 2탄



밸런싱은 기본적으로 Service rack #1 - 5 에 대해서 수행하게 되며, 추가적으로 Log 서버에서 제공하는 웹 페이지와 Redmine 을 운영에 필요한 Issue tracking 으로 사용한다고 치자. 그리고, 이 Nginx 는 SSL payload 를 처리하도록 한다. 물론 어차피 이런 구조라면 밸런서를 각 랙에 넣으면 되지 않냐고 할 수도 있겠지만, 그런 내용은 요기의 주제가 아니므로 패씅. 


요새는 멀티 코어 서버가 유행이므로, 일단 프로세서는 적당한 가격으로 1~2개 정도 넣어준다. 멀티코어에 하이퍼스레딩을 더하면  OS 에서 뻥튀기는 순식간이므로..;;  Nginx 용 서버는 Generic x86_64 로 하고, 편의상 우분투로 한다. 설정을 진행하기 전에, 아래의 내용을 보자. 


root@balancer01:/etc/nginx# openssl engine -t 
(aesni) Intel AES-NI engine
     [ available ]
(dynamic) Dynamic engine loading support
     [ unavailable ]


위의 커맨드는 현재 시스템에서 지원하는 SSL engine 을 확인하는 커맨드 된다. 이제 몇년전에 포스팅에 끄적이고 한번도 올리지 않았던 nginx.conf 의 샘플을 올려본다. 물론, 그대로 가져다 사용하면 문제가 될 수 있으므로 몇몇 포인트는 수정해야 할 수 있겠다. 물론 SSL 에 필요한 crt/key 파일 생성은 사전에 진행 되어야 하겠다. Nginx 설치 역시 여기서 다루지는 않는다. 


user www-data; worker_process 16; worker_cpu_affinity 0001 0001 0011 0111 1111 1100 1110 1001 1101 1011 1010 0010 0100 1000 1111 0110; worker_rlimit_nofile 8192; ssl_engine aesni; error_log /var/log/nginx/error.log; pid /var/run/nginx.pid; events { worker_connections 1024; multi_accept on; } http { upstream redmine { server 192.168.1.240:3000; } upstream splunk { server 192.168.1.241:8000; } upstream image { ip_hash; server 192.168.1.101:80 max_fails=3 fail_timeout=10s; server 192.168.1.102:80 max_fails=3 fail_timeout=10s; } upstream sharebox { least_conn; server 192.168.1.1:80 max_fails=3 fail_timeout=10s; server 192.168.1.2:80 max_fails=3 fail_timeout=10s; server 192.168.1.3:80 max_fails=3 fail_timeout=10s; server 192.168.1.4:80 max_fails=3 fail_timeout=10s; server 192.168.1.5:80 max_fails=3 fail_timeout=10s; } server { listen 0.0.0.0:443; ssl on; ssl_certificate /etc/nginx/ssl/cert.crt; ssl_certificate_key /etc/nginx/ssl/cert.key; server_name sharebox.mydomainname.com; sendfile on; client_max_body_size 4096m; client_body_buffer_size 128k; location / { set $memcached_key $request_url; default_type application/x-www-urlencoded; memcached_pass 127.0.0.1:11211; if ($request_method = POST) { proxy_pass http://sharebox; break; } proxy_intercept_errors on; error_page 404 502 = /fallback$uri; } location /fallback { internal; proxy_redirect off; proxy_pass http://sharebox; } } server { listen 0.0.0.0:80; server_name redmine.mydomainname.com; root /var/lib/redmine/; proxy_redirect off; sendfile_on; client_max_body_size 50m; client_body_buffer_size 128k; localtion / { proxy_pass http://redmine; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Photo $scheme; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffer_size 64k; proxy_temp_file_write_size 64k; } } server { listen 0.0.0.0:80; server_name image.mydomainname.com; location / { valid_referes none blocked *.mydomainname.com; if ($invalid_referer) { return 403; } proxy_pass http://image; } } } include tuning/*.conf;


서버는 단순 이미지 파일을 제공하는 image 서버, redmine 서버로의 프락싱, 그리고 무언가 서비스를 돌리고 있는 내부 시스템의 웹 서버로 밸런생+프락싱의 세가지 기능을 한다. 추가적으로 memcached 가 일부 서비스에서 엮여 있는데, 이는 테스트용이므로 참고 해도 좋고 아니어도 좋다. 


Nginx 서비스를 시작하고 다음의 커맨드를 넣으면 보다 디테일한 정보를 볼 수 있다. 


root@redmine:/etc/nginx# nginx -V
nginx: nginx version: nginx/1.0.5
nginx: TLS SNI support enabled
nginx: configure arguments: --prefix=/etc/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-log-path=/var/log/nginx/access.log --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --lock-path=/var/lock/nginx.lock --pid-path=/var/run/nginx.pid --with-debug --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_realip_module --with-http_stub_status_module --with-http_ssl_module --with-http_sub_module --with-http_xslt_module --with-ipv6 --with-sha1=/usr/include/openssl --with-md5=/usr/include/openssl --with-mail --with-mail_ssl_module --add-module=/build/buildd/nginx-1.0.5/debian/modules/nginx-echo --add-module=/build/buildd/nginx-1.0.5/debian/modules/nginx-upstream-fair


로그 서버인 Splunk 는 upstream 에는 등록이 되었지만, 실제로 사용하지는 않았다. 다이어그램에는 Sumo Logic 인데 웬 Splunk 하시는 분들도 계실지 모르겠다. 그렇다. 아무 상관 없다. @_@  음, Sumo Logic 은 클라우드 로그 솔루션이다. 데모 어카운트를 받아서 해봤는데, 검색기능도 강력하고 무엇보다 골치아픈 로그 서버를 내부에서 관리 하지 않아도 된다는 특장점이 있다. 물론 이 특장점은 로그를 외부로 유출 할 수 없는 시스템에서는 고민거리로 탈바꿈 하지만. 


upstream 에 least_conn; 을 적용하려면 nginx 버전이 1.3.1 / 1.2.2 이 되어야 한다. 물론 keepalive 값을 주는 것도 가능. 

upstream 과 밸런싱에 대한 자세한 내용은 요기 http://nginx.org/en/docs/http/ngx_http_upstream_module.html


default_type 은 보통 text 를 할당하는데, 이미지 캐싱을 위해서 한번 바꿔봤다. 이미지가 로컬에 있지 않고 REST 기반의 시스템에 토큰이 포함된 주소를 던져야 뱉어주는데, 좀 빨라질까 싶어서 테스트 중. 


아, 그리고 memcached 최신의 버전에서는, -I (대문자임) 옵션을 사용하여 value 로 사용할 저장소의 크기를 1m 이상을 사용 할 수 있다. 물론 크게 잡으면 크게 잡을수록 키 하나가 먹는 메모리 사이즈가 증가하므로 별로 바람직하지 않을 수 있겠다. 위의 설정 파일에서는 키를 request_url 로 잡았음을 확인 할 수 있다. 또한 캐시 서버가 없거나 죽은 경우에는 바로 내부 서버로 던지므로 서비스 동작에는 문제가 없다. /etc/memcached.conf 를 서비스로 추가한다. 


# 2003 - Jay Bonci 
# This configuration file is read by the start-memcached script provided as
# part of the Debian GNU/Linux distribution. 

# Run memcached as a daemon. This command is implied, and is not needed for the
# daemon to run. See the README.Debian that comes with this package for more
# information.
-d

# Log memcached's output to /var/log/memcached
logfile /var/log/memcached.log

# Be verbose
# -v

# Be even more verbose (print client commands as well)
# -vv

# Start with a cap of 64 megs of memory. It's reasonable, and the daemon default
# Note that the daemon will grow to this size, but does not start out holding this much
# memory
-m 4096

# Default connection port is 11211
-p 11211 

# Run the daemon as root. The start-memcached will default to running as root if no
# -u command is present in this config file
-u memcache

# Specify which IP address to listen on. The default is to listen on all IP addresses
# This parameter is one of the only security measures that memcached has, so make sure
# it's listening on a firewalled interface.
-l 127.0.0.1

# Limit the number of simultaneous incoming connections. The daemon default is 1024
-c 10240

# Lock down all paged memory. Consult with the README and homepage before you do this
# -k

# Return error when memory is exhausted (rather than removing items)
# -M

# Maximize core file limit
# -r

# Increate allocation size limit of value per key to 5 Mega
-I 5m

무슨 메모리를 저리 무식하게 할당 했는가 할 수 있겠는데, 서버가 메모리가 48기가가 있어서 그랬다. 음.. 용서를. 


밸런서가 여러대 있는데 이건 또 어떻게 밸런싱 하나 뭐 그럴 수도 있겠는데, 그건 일단 그림에 PowerDNS 를 쑤셔박는걸로 회피했다. 또한, 당연히 성능에 대해서 이런 저런 의견이 있을 수 있겠지만, 어쨌든 서버만 있으면 오픈소스로 엮어서 돌릴 수는 있다. 가성비에 대해서는 추가적인 비교가 필요하지만, 이건 간단한 소개 정도이므로 여기서 종료. 


원래는 Quagga 까지 함께 엮어서 내부 망에 iBGP / eBGP 및 OSPF 등으로 L3 스위치와 엮는 설정을 함께 적으려 했는데, 아직 Quagaa 가 BGP에 대해 maximum-path ( ECMP ) 를 지원하지 않아서 스킵은 핑계. 아, OSPF 에 대해서는 지원한다. 



뭔가 거창하게 시작했는데 괴발개발 그림 그리다 날 샜다. 다시 업장으로 컴백 고고 하기 전에, naver.com 을 대상으로 reverse-proxy 를 수행 한 모습. 다음에도 해봤는데 아마도 피싱 방지 목적용인지 무조건 http://www.daum.net 으로 리다이렉션 시켜버린다. 네이버에는 몇년 전에도 해봤는데 이번에 해도 잘 나오네. 



user root;
worker_processes  16;
worker_cpu_affinity 0001 0001 0011 0111 1111 1100 1110 1001 1101 1011 1010 0010 0100 1000 1111 0110;
ssl_engine aesni;

error_log  /var/log/nginx/error.log;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
    multi_accept on;
}

http {
	upstream naver {
	server naver.com:80;
	}
	upstream daum {
	server daum.net:80;
	}

	server {
		listen 0.0.0.0:80;
		server_name naver.yourdomainname.com;
                sendfile on;
                client_max_body_size       4096m;
                client_body_buffer_size    512k;
		location / {
			set $memcached_key $request_uri;
			default_type application/octet-stream;
			memcached_pass	127.0.0.1:11211;
			if ($request_method = POST) {
				proxy_pass http://naver;
				break;
			}
			proxy_intercept_errors on;
			error_page 404 502 = /fallback$uri;
		}
		location /fallback {	
			internal;
			proxy_redirect off;
			proxy_pass http://naver;
		}
	}
	server {
		listen 0.0.0.0:80;
		server_name daum.yourdomainname.com;
                sendfile on;
                client_max_body_size       4096m;
                client_body_buffer_size    512k;
		location / {
			set $memcached_key $request_uri;
			default_type application/x-www-urlencoded;
			memcached_pass	127.0.0.1:11211;
			if ($request_method = POST) {
				proxy_pass http://daum;
				break;
			}
			proxy_intercept_errors on;
			error_page 404 502 = /fallback$uri;
		}
		location /fallback {	
			internal;
			proxy_redirect off;
			proxy_pass http://daum;
		}
	}
}


위와 같이 설정한 후, 브라우저에서 naver.yourdomainname.com 으로 접근하면 네이버 페이지가 나온다. 성실하게 작업하면 구멍 없이 리다이렉션을 걸어 줄 수 있을 듯. 뭐, 별로 할 필요는 없지만. 



Reverse-proxy to naver.com



네이버가 이뻐서 스크린샷까지 찍어 준 것은 아님. +ㅁ+ 


( younjin.jeong@gmail.com, 정윤진 ) 


SSL Certificates on Nginx & Windows

Techs
( younjin.jeong@gmail.com , 정윤진 )

최근, 인증서 관련 이슈가 있어 간략하게 인증서를 다루는 법에 대해 소개하려고 한다.
이슈는,

1. nginx 에서 Intermediary SSL 을 설치하는 방법.
2. Windows 에서 certutil 을 사용하는 방법.

의 2가지 이다.

2가지 내용 모두 다음의 내용을 참고 하였다.
1. 이슈 : http://rubypond.com/blog/nginx-intermediary-ssl-certificates-and-passphrases
2. 이슈 : http://blogs.microsoft.co.il/blogs/applisec/archive/2008/04/08/creating-x-509-certificates-using-makecert-exe.aspx

급하신 분들은 위의 내용을 직접 참고 하셔도 되겠다.


1.  Nginx Intermediary SSL Certificates and Passphrases

Merging the site and intermediary SSL certificates

발급받은 사이트 인증서와 중개기관 인증서를 병합해야 한다.  아파치 및 IIS 에서는 두개의 인증서를 따로 지정하거나 별도로 설치가 가능하지만, nginx 는 무조건 1개의 파일로 설정해야 한다.  따라서, 다음과 같이 병합한다.

cat yourdomain.com.crt >> yourdomain.com.crt.merged
cat intermediate_bundle.crt >> yourdomain.com.crt.merged

Removing SSL Passpharse

다음단계는, key 파일에 걸려있는 암호를 제거해야 한다.  물론 남겨두는게 좋지만, 남겨두게 되면 오퍼레이터가 항상 재시작 할때마다 키를 넣어주어야 하기 때문에 자동으로 재시작이 불가능하다.  따라서, 백업을 먼저하고 다음과 같이 진행한다.

mv yourdomain.com.key  yourdomain.com.passphrased
openssl rsa -in yourdomain.key.passphrased -out yourdomain.key


Configuring Nginx to use your new SSL certificate

다음과 비슷한 모양으로 설정한다.

server {
  listen 443;
  server_name myserver.com; 

  ssl on;
  ssl_certificate /etc/nginx/certs/yourdomain.com.crt.merged;
  ssl_certificate_key /etc/nginx/certs/yourdomain.key ;

  # put the rest of your server configuration here.

  location / {
     proxy_set_header X-FORWARDED_PROTO https;
     # put your config here
  }
}

nginx 를 재시작 하면 된다.

2008 년 여름, 일본에서 서비스를 오픈다하가 이 문제로 인해 한참을 구글링 한 적이 있다.
날짜의 압박속에서, Reverse proxy 로 동작하는 nginx 에 키가 제대로 설치되지 않으면, 503 Bad Gateway 메세지를 떨구기 때문에, 반드시 처리 해야만 했던.

아무튼, 필요하신 분에게 좋은 도음이 되었으면 한다.


2. Creating X.509 Certificates using makecert.exe

x.509 인증서 생성은 매우 빈번한 작업이지만, 어떻게 하는 것인지 모르는경우가 종종 있다.
실제로는 신뢰된 인증기관을 통해서 구매해야 하지만, 다음의 툴로 혼자만의 Cert의 생성이 가능하다.
MakeCert.exe

다운로드 후에는, 다음의 진행을 따른다.


Creating a Root Certificate Authority  ( Root 인증서 생성 )
makecert.exe -n "CN=My Root CA,O=Organization,OU=Org Unit,L=San Diego,S=CA,C=US" -pe -ss my -sr LocalMachine -sky exchange -m 96 -a sha1 -len 2048 -r My_Root_CA.cer

Import Root Certificate Authority Certificate into Trusted Root Store ( 생성된 인증서를 Root 저장소로 Import )
certutil.exe -f -addstore Root My_Root_CA.cer

Create Backup (Export) PFX file of Root Certificate Authority Certificate ( 생성된 인증서를 pfx 로 백업 )
certutil.exe -privatekey -exportpfx "My Root CA" My_Root_CA.pfx

Create a Server Certificate issued from the previously created Certificate Authority  ( 기존에 생성된 인증을 바탕으로 서버 인증서 생성 )
makecert.exe -n "CN=Server" -pe -ss my -sr LocalMachine -sky exchange -m 96 -in "My Root CA" -is my -ir LocalMachine -a sha1 -eku 1.3.6.1.5.5.7.3.1,1.3.6.1.5.5.7.3.2 Server.cer

Create Backup (Export) PFX file of Server Certificate ( 생성된 서버 키를 pfx 로 백업 )
certutil.exe -privatekey -exportpfx "Server" Server.pfx

Create a Computer certificate issued from the previously created Certificate Authority ( 기존 생성된 인증을 바탕으로 "Computer" 인증서 생성 )
makecert.exe -n "CN=Computer" -pe -ss my -sr Localmachine -sky exchange -m 96 -in "My Root CA" -is my -ir LocalMachine -a sha1 -eku 1.3.6.1.5.5.7.3.2 Computer.cer

Create Backup (Export) PFX file of Computer Certificate ( 기존에 생성된 "Computer" 키를 pfx 로 백업 )
certutil.exe -privatekey -exportpfx "Computer" Computer.pfx

OID Reference

Encrypting File System (1.3.6.1.4.1.311.10.3.4)
Secure Email (1.3.6.1.5.5.7.3.4)
Smart Card Logon (1.3.6.1.4.1.311.20.2.2)
Client Authentication (1.3.6.1.5.5.7.3.2)
Server Authentication (1.3.6.1.5.5.7.3.1)
IP security IKE intermediate (1.3.6.1.5.5.8.2.2)



써놓고 보니 거의 날로먹은 포스팅..   미안하니까 몇가지 쓸모있는 URL 링크.

인증서 웹 변환 툴
https://www.sslshopper.com/ssl-converter.html

csr ( private key ) 및 certificate 비교
https://www.sslshopper.com/certificate-key-matcher.html

Verisign 의 Intermediate Certificate
https://www.verisign.co.jp/repository/intermediate/server/c3SecureServerCA_1024.html



( younjin.jeong@gmail.com , 정윤진 )

시스템 관리자의 실패, 그리고 서비스.

Techs
( 정윤진, bluebird_dba@naver.com )


웹 서비스를 하는 많은 시스템에서, 사업의 성공과 함께 고객이 증가함에 따라 발생하는 많은 문제들이 있다.  보다 많은 고객에게 무정지 서비스를 하기위한 각 서비스 구성 요소의 이중화 부터, 서버의 추가에 따른 네트워크 장치의 추가, 대역폭의 확장 등 비용 들어가는 요소가 한두가지가 아니게 된다.

물론 이런 비용의 문제가 있다면 자연히 저렴하고 성능좋은 오픈소스 솔루션으로 눈을 돌리게 마련인데, 이 오픈소스 솔루션이라는게 그 좋은 성능만큼 손도 많이가고, 기본적으로 설치되는 패키지 들이 감당 해 낼 수 없는 어떤 한계 상황에 이르게 되면 소소한 튜닝 하나에 서비스의 명암이 엇갈리기도 한다.

여기 블로그에 내가 직접 설치해 보고, 또  그 성능을 온몸으로 확인했던 여러가지 툴 및 어플리케이션들이 '당연하게'  '잘' 동작 한다는 믿음에는 변함이 없지만, 이들과 맞물리는 요소에 따라 실패하게 될 수도 있다는 사실을 최근 뼈저리게 깨닫게 되었다.

사용자 삽입 이미지

BOTTLENECK a image from finsolinc.com





문제의 발단은 고객 서비스 규모의 증가에 따라 상거래 사이트의 특징상 수많은 이미지를 서비스하게 되는데, 이 감당하기 힘든 이미지의 규모 때문에 nginx 를 사용한 이미지 분리를 시도 하였는데, 결과는 참패였다.  참패의 원인은 몇가지가 있는데, 그중에서도 가장 주요한 부분이 바로 아파치의 mod_expire 였다.

HTTP 의 헤더를 조작하는 것이 많은 비용이 들어가는 일이라는 것은 평소에도 잘 알고있었지만, 이 헤더의 조작이 NFS 의 getattr() 호출의 빈번함과 함께 아파치의 Sending Reply 를 지연시켜 결국 사용 가능한 모든 소켓을 불태워 버림에 따라 nginx 는 nginx 대로, 아파치는 아파치 대로 부하상황에 사이트가 정상동작 하지 않게 되어버렸다.  스레드 기반에서의 ( mpm이 워커였다. 물론 prefork 도 동일한 설정에 상황은 마찬가지. ) locking 및 pending 의 무서움을 절실히 깨달았달까.

결국 문제는 찾아 내게 되었지만, 그 주범이 mod_expire 라는 사실에 허무하기 그지 없다. 고객의 사용 패턴에 따라 mod_expire 는 득이 될 수도, 실이 될 수도 있다.


아무리 간단한 서비스 구성에도 많은 요소들이 존재한다.  부하가 없을때에는 당연히 동작해 주는 그것들.  하지만 극한 상황이 되면 아주 작은 파라메터 하나, config 하나, sql 문장 하나가 서버를 멈추게 하고, DB를 멈추게 하는 무서운 적이 될 수 있음을 항상 기억해야 한다.

구성에 관한한 어지간해서는 실패한 경험이 별로 없는데, 이번건은 나에게 매우 큰 정신적 충격이었고,  역시 항상 장애에 대해 트레이닝 하지 않으면 당황하게 되는걸 보니 아직 많이 부족하다 싶다.  그렇게 당연한 인과 관계를 찾아내지 못했던게 참 ... 씁쓸하다고만 하기에는 부족한.


결국, 아파치의 체중조절에 들어갔다.  꼭 필요한 모듈만 올려서 경량화, ServerLimit 조절 같은 기본 구성부터  이미지 서버의 이벤트 폴링,  aio 및 sendfile 의 적용 등.

이제, 쓴맛을 볼만큼 봤으니 단맛을 찾아 내야 겠다.
2만 세션을 커버했다면, 이제 빡시게 준비해서 5만 세션 이상은 버티게 해야지.

대역폭을 병목구간으로 만들어 버리는, 그런 구조를 향하여.



( 정윤진,  bluebird_dba@naver.com )

P.S.

1.
nfs 의 마운트 옵션은 기억해 둘 만 하다.  getattr 비율이 40 또는 60% 이상이라면 서버의 로컬 캐시 타임을 늘리는 방법을 강구해 보도록 하자.

nfsstat -c
nfsstat -m


2.
apache2 구동중인 시스템에서 비교적 성능이 출중한 서버인경우에 위와 같은 상황에서
iowait 나 vmstat 에서 특이할 만한 값은 떨어지지 않는다.
server-status 를 적극 사용 하도록 하고, 리눅스라면 ps -eo wchan 을 참고 하도록 하자.

3.
nginx 는 꼬진 서버가 아니다.
다만 nginx 를 꼭 써야한다면, 기존의 웹서버 설정을 매우 디테일하게 살펴야 할 것이다.

NginX on Ubuntu-9.0.4-server

Techs
( 정윤진, bluebird_dba@naver.com )


오늘은, nginx 의 우분투 설치에 대해 한번 전체 과정을 쭈욱 적어 보려 한다.
우분투에서의 설치 과정은 대체로 다음과 같다.

1. OS 설치.
2. 필요 package 설치
3. nginx source download
4. Additional Module download
5. configure / make / make install
6. Setup
7. Run!!

물론,  2 ~ 5번을 건너 뛰고  apt-get install nginx 해도 된다.  ㅋ
어쨌든 우분투 인스톨이 끝나로 root 계정 세팅을 완료 하였다면 필요한 패키지 인스톨을 시작한다.

Package Install

apt-get update
apt-get dist-upgrade
apt-get install build-essential libpthread-stubs0 libpthread-stubs0-dev libgd2-xpm libgd2-xpm-dev libgeoip-dev libgeoip1 sysvinit openssl libssl-dev libpcre3-dev  libgcrypt11-dev


nginx download

NginX 는, 아직 메이저 버전 넘버가 1 이 채 못되었다.  그렇다고 unstable 한 것은 아니지만, 다음의 버전 넘버링을 참고 하도록 한다.

0.6  -> Legacy 버전  ( 통상 apt-get 으로 install 되는 버전. 3rd party 모듈이 잘 설치되며, 안정적으로 동작한다 )

0.7  -> Stable 버전.

0.8  -> Develop 버전  ( 3rd party 모듈은 포기하는게 좋다.  다만, 기존 3rd party 로 제공되던 모듈이 nginx 에 포함되어  --with 옵션으로 설치 되는 모듈이 많아졌다. )

wget http://sysoev.ru/nginx/nginx-0.6.38.tar.gz
바빠서 그런건지, sysoev.ru 사이트가 종종 먹통일 때가 있다.

google 에서 해당 버전의 파일명을 검색하면 서비스 하는 사이트가 많으니 신뢰할 만한 페이지에서 받아서 사용하도록 한다.

openssl 소스 다운로드
nginx 의 compile 시에 openssl 의 소스코드를 요구한다.

wget http://www.openssl.org/source/openssl-0.9.8k.tar.gz
사이즈에 비해 제법 느리니 커피한잔 마셔 준다. ㅋ



additional module download

http://wiki.nginx.org 의 Module 페이지에 가면 기본적으로 nginx 에서 제공하는 모듈 이외에 3rd party 모듈들의 링크를 제공한다.  필요한게 있다면 추가 하도록 한다.

GeoIP Extension
wget http://wiki.nginx.org/images/9/99/Nginx-geoip-0.1.tar.gz

NCache
wget http://ncache.googlecode.com/files/ncache-2.3_release.tar.gz

다른건 잘 안되서 추적하기도 귀찮고 해서 올리지 않았다.
통상 Upload Module 도 많이 사용 하는듯.

다운로드 받은 모듈은 configure 시에 옵션으로 써 주기 편한 디렉토리에 압축을 풀어 놓도록 한다.  난  $SRCDIR/nginx-0.6.38/modules  에 압축을 풀었다.


Configure && make && make install

일반적인 xNix 어플리케이션의 compile 과 비슷하다.

./configure --add-module=./modules/ncache-2.3 --add-module=./modules/nginx-geoip-0.1/  --with-google_perftools_module --with-poll_module --with-http_ssl_module  --with-http_realip_module  --with-http_gzip_static_module  --with-http_stub_status_module --prefix=/opt/nginx --with-openssl=/usr/src/binaries/openssl-0.9.8k

더 필요한게 있다면 붙여도 된다.

위의 apt-get install 만으로는 빠져있는 것들이 있을 것이다.  configure 과정에서 뭔가 누락된게 있다고 징징대면  apt-cache search 다음에 apt-get 으로 인스톨 해 주면 된다.

configure 가 끝나면 make , make install

configure 는 이상없이 끝났는데,  make 과정에서 error 를 토해내면서 중지하면,  error 부분을 조치해 주고 다시 make 를 시도한다.  통상 openssl 소스를 추가적으로 --with 옵션에 넣어준 경우,  make clean 시에 rm -f 로 디렉토리를 지우려는 멍청한 짓을 가끔 해서 make 파일을 수정하는 세련된 짓은 하지 않고, 그냥 rm -fR ../openssl-0.9.8k 해서 지웠다.
당연히, 지운다음에 다시 압축을 풀어줘야지.


nginx.conf &&  RUN!!!!

 정상적으로 설치가 완료 되었다면,  --prefix 로 지정한 디렉토리에 nginx 가 이쁘게 컴파일되어 설치된 모습을 볼 수 있다.  실행 바이너리는 ./sbin 에 , conf 는 ./conf 디렉토리 안에 있다.

nginx.conf 에서는, 다음의 몇가지가 기본적인 설정이다.  뭐 wiki 참조하시면 엄청 잘 나와있으므로, 모자란 부분은 거기서 추가 하시도록 한다.

몇몇 주요한 conf 는,

worker_process
sendfile

upstream  httpservice {
    ip_hash;
    server x.x.x.x:80;
}

location / {
      set $memcached_key $uri;
      memcached_pass     x.x.x.x:11211;
      ....
      ..
      Default nginx.conf 참조
}

rewrite 및 기타 virtual host 설정등도 함께 제공하므로, wiki.nginx.org 에서 참조 하도록 한다.

nginx 를 구동하기 위해서는, 적절한 계정이 있어야 한다.
groupadd -g 81 apache
useradd -g 81 apache

난 apache 로 돌렸다.  ( 사실 이건 예전에 AJ 가 쓰던거지만. )


어쨌든, 다 설정 되었으면 구동한다.

./sbin/nginx  ( & 안해도 된다  알아서 한다 )

지정한 process 만큼 떠 있는 모습이 확인 가능하다.



음.. 뭐 이런 매뉴얼 스러운 글은 원래 잘 쓰지 않는 편이지만,  나도 돌머리라 자주 잃어버려서 정리 겸 해서 쓴다.  뭐 사실 잃어버려도 다시 삽질 하면 되지만, 점점 삽질 하는 시간이 웬지 아까워 진다고 할까나...


그냥 wiki.nginx.org 를 번역하는게 나을지도..  그러고 보니 한글 페이지를 봤던것 같은 기억도;;;  varnish 가 더 희소성이 높으려나.. ㅋㅋㅋ


( 정윤진, bluebird_dba@naver.com )



Blog 를 굴리면서.

Stories
( 정윤진, yjjeong@rsupport.com )

최근 블로그를 그냥 장난처럼 운영 하면서 보면, 어제 오늘 블로그에 유입되는 경로의 대부분이 nginx 의 검색어를 기반으로 네이버의 상위에 랭크되어 넘어 오시는 분들이 많은 듯 하다.

아마 최근의 DDoS 공격과 관련하여 Reverse-Proxy 의 구성에 대해 어디선가 알아보고 오신듯 하다.  

DDoS 는, 그 방어에 대한 준비가 기술적인 요인 뿐만 아니라 경영진의 이해도 함께 필요하기 때문에, 통상은 공격 당하기 전에 준비한다기 보다는, 일단 일이 터져서 서비스가 불가능해져 그 위기감을 경영진이 느끼게 되었을 때 부랴부랴 준비하는 경향이 많지 않나 싶다.

언제나 사전에 경고하게 되더라도, 결국엔 비용앞에 무너지는 직업이다 보니 이제는 그러려니, 하면서 일 터질때는 이렇게 저렇게 하자 하고 혼자 마음속으로만 준비하곤 한다.

뜬금 없지만, Nginx 도 있지만 Varnish 도 좋다고 웬지 조심스럽게 말해보고 싶다는.. ㅋ

사용자 삽입 이미지

Going home, Winstorm.

* 위의 사진은 내용과는 큰 관계가 없..;;


여러가지의 방어 기법들이 있겠지만, 결국 많은 가능성을 함께 생각하여 보아야 그 대비가 가능 해 질 것도 같고, 이번처럼 대규모의 공격이 간단히 도메인을 변경해서 처리가 가능했다고 하는 걸 보면 내가 보았던 통상적인 공격들과는 좀 다른가 보다.

어쨌든, 복잡한 서비스에서 하나의 메인 페이지와 그 내부의 컨텐츠 들이 모두 동일한 도메인과 uri 에서 서비스 되고 있다면, 페이지의 구조상 선택 가능한 방법이 매우 줄어드는 것도 사실인 듯 하고.  아파치를 굴리는 서비스에서 mod_expires 정도는 설치 해 두어야 CC 공격 ( Command Center 아님 ㅋ) 을 제외한 많은 공격에서 보다 자유로워 질 수도 있다.

특별한 구조는 없으며, 몇년전에 Dos 에 대한 방어로 이슈가 되었던 Null Zero Routing 이라던가 하는 방법도 필요에 따라선 쓰일 수도 있고, reverse-proxy, 도메인의 동적인 분리 또는 A 레코드 변경을 위한 짧은 TTL 로의 수정 등, 방법들은 이미 많이 알려졌다.
공격 형태가 다양 할 뿐.


뭐 어쨌든, 위의 이미지는 내용과는 별로 상관 없지만 또 그게 재미니깐.  집에 가는 길에 회사의 과장님 차에 신세 지고 이런 저런 이야기를 나누다가 한컷 했다.

또 다른 유입 경로를 보자면, '잘 지내나요 청춘' 에 대한 검색도 있기도 하고, 별로 없을 것 같던 ARC GIS 에 대한 64비트에서의 설치도 제법 된다.

일본에서 본의 아니게 욕먹은 것도 있기는 하지만 그것도 나름 재미있는 사건이었고.

사용자 삽입 이미지

Office View


비오는 날은 참 공기가 신선하고 좋다. 비가 주륵 주륵 내리고 있는 것을 보자면, 어떤 분들은 근심이 더 많을 수도 있지만 뭔가 마음속에서 씻겨 내려가는 듯한 기분이 들고,
음악 틀고 커피 한잔의 여유 속에 비가 그쳐 갈 때 쯤 어딘가에서 나는 풀냄새도 좋다.

다만 어떤 동네에서는 비린내가 나는 경우도... 쿨럭.;;


어떤 마음으로 블로그질 하자는 것도 없이, 그냥 시스템에서 나오는 이슈나 살면서 찍는 사진들에 대해 간단히 아무데서나 보자는 목적에서 시작한 블로그 질이지만,  준호형 처럼 HTML 이나 JS 를 예술로 써서 멋들어진 페이지를 만들 수도 없는 일이고. 

졸리니깐 글도 두서도 없고 뭐 재미도 별로 읍고 ㅋ 
비오면 이래 되는 듯.

사용자 삽입 이미지

Surisan Station, 4th Line



집에 와서는 또 현희형과 한참 서비스에 대해서 이런 저런 이야기를 많이 했는데
이렇게 즐거울 수가 없는 듯. 
무언가를 이야기 했을 때 받아주는 사람이 있고, 또 그 이야기를 들으면서 그 타당성에 대해서 생각 해 보고.  내가 맞다고 생각하는 것과 또 현희형이 맞다고 생각 하는 것에 대해 언뜻 우리는 무한 루프를 잠깐 돌았던 것 같지만, 결국은 같은 이야기를 하고 있었고 그게 또 좋은 서비스의, 또 현희형은 잘 모르겠고 나의 생각의 틀을 넓히는 것 같아서.

어디서 또 이런 분을 만날 수 있을까 싶은 생각.



주저리 주저리 썼지만,
뭔가 오늘 하루를 정리 하고 싶었더랬지만,
결국 정리 한 건 별로 없는 듯 하고

청춘이라기에는 쬐끔 민망한
또 하루가 지난다.

김광석의 서른 즈음에 보다는
박정현의 'No Break' 가 더 흥얼거려지는 요즘


이러고 있다.. ㅋ

( 정윤진,  bluebird_dba@naver.com )