starting with AWS EC2

AWS(Amazon Web Service)를 사용하게 되면 일단 가입한지 일년동안은 AWS Free Usage Tier 로 1년동안 1 Linux Micro Instance, ELB, EBS 10G, S3, SimpleDB, SQS등 무료로 사용이 가능하다. 그러므로 초심자가 접근하는데 너무 걱정을 하지도 않아도 된다.

일단 EC2를 만들기 전에 EC2에서 사용하는 storage 개념부터 이해해야 한다.

AMI(Amazon Machine Images)를 이용해서 서버를 런칭하게 되는데, AMI는 두가지 Storage 종류가 있다. EBS-backed storage device 와 S3-backed storage device인 ephemeral storage 로 두가지다.

보통 micro instance가 아닌 Medium, Large 등으로 돈이 들어 만드는 ami instance에 들어가는 storage는 S3-backed storage를 사용하게 된다. 이 S3-backed storage는 EBS보다 빠르나 instance가 정지(stop)되거나 종료(terminate)되면 storage의 내용은 날라가게 된다.(그 서버는 restart만 가능하게 되는 것이다.) 그러니 일단 그런 storage를 사용하게 되면 주의해야 한다. (단 S3-backed storage로 AMI를 만들게 되면 S3를 이용해서 다른곳으로 이동할수 있다고 한다.)

일단 Free Usage Tier 이므로 Micro Linux Instance + 10G EBS Volume을 사용해 보겠다.

나의 경우에는 ubuntu ami보다 amazon linux ami를 선호하는데, 이유는 ubuntu ami의 경우 가끔씩 리부팅시(극히 낮은 빈도지만, 직접 경험해봤다. aws console에서는 분명 제대로 돌아가고 있는데 ssh 접근이 안된다. 이유가 ubuntu ami라는 확신은 없다.) hang이 걸리기 때문이다.

AWS(http://aws.amazon.com/)에 접속해서 계정을 만들어라. 신용카드 사용에 대한 좀 복잡한 과정등있으니, 하나하나 다 읽어본 후 계정 만들기를 완료한다.

그리고 AWS Management Console (https://console.aws.amazon.com) 들어가 [EC2] 탭으로 들어간다. [Launch Instance]를 눌러서 Basic 32-bit(or 64-bit) Amazon Linux AMI를 선택해서 일단 생성한다.

일단 Unix 콘솔이 있다면 다음과 같이 로그인 한다.

ssh -i xxxx.pem ec2-user@xxx.xxx.xxx.xxx

xxxx.pem은 key pair 생성과정에서 저장한 개인키이다.  xxx.xxx.xxx.xxx 는 생성한 instance의 public dns 주소다. 접속한 다음 최신 버젼으로 업데이트 하면 일단 서버 하나를 사용하기 위한 기본작업이 완료된다. (이와 더불어 [elastic IPs]를 클릭해서 ip를 할당해주고 서버에 연결해도 좋다.)

sudo yum update;sudo reboot

AWS 웹콘솔로 가서 [Volumes]을 클릭한후 [Create Volume]으로 10G의 하드 디스크를 만들어주고(Availability Zone에 주의, 서버과 같은 zone에 만든다.) 새로 만든 서버에 만든 볼륨을 attach 한다. 다시 서버 터미널에 접속한후

sudo yum install xfsprogs
grep -q xfs /proc/filesystems || sudo modprobe xfs
sudo mkfs.xfs /dev/sdf

echo "/dev/sdf /mnt xfs noatime 0 0" | sudo tee -a /etc/fstab
sudo mount /mnt

해주면 10G 하드디스크가 /mnt 마운트 된다.

이 같은 작업으로 8+10G micro서버를 1년동안 무료로 사용할수 있게 되는 것이다. 1년 이후로 좀더 오래 사용한다면, reserved instance 3 year, Medium Utilization, tokyo로 결재를 하면 싸게 사용할수 있다.

3년 예약 비용 : $86(하루에 $0.0785)
3년 예약 일때 하루 사용비용이 $0.264(1 hour $0.011)
10G EBS : 한달에 $1~1.5
대략 micro instance 사용으로 한달 30일로 치면 $11~12 선에서 서버를 사용할수 있다. 국내 다른 클라우드 서버(5000원 하는데도 있으니)에 비하면 싼편은 아니지만 AWS의 다른 기능까지 사용해 본다면 그리 비싼편은 아니다.

using SimpleDB CLI

case : amazon linux ami

http://aws.amazon.com/code/1136
http://code.google.com/p/amazon-simpledb-cli/

sudo yum install autoconf automake libtool make
sudo yum install perl-CPAN perl-YAML
sudo yum install openssl-devel
sudo yum install perl-Digest-SHA perl-XML-Simple perl-Digest-SHA1 perl-Digest-HMAC perl-Time-HiRes
sudo perl -MCPAN -e 'install Bundle::LWP'

wget http://aws-libraries.s3.amazonaws.com/perl/AmazonSimpleDB/2009-04-15/AmazonSimpleDB-2009-04-15-perl-library.zip
unzip AmazonSimpleDB-2009-04-15-perl-library.zip
sitelib=$(perl -MConfig -le 'print $Config{sitelib}')
sudo scp -r AmazonSimpleDB-*-perl-library/src/Amazon $sitelib

sudo curl -Lo /usr/local/bin/simpledb http://simpledb-cli.notlong.com
sudo chmod +x /usr/local/bin/simpledb

몇가지 테스트를 해보자

simpledb create-domain snapshot
simpledb list-domains
simpledb put snapshot test test='abc'
simpledb select "SELECT * FROM snapshot"
simpledb delete snapshot test
simpledb select "SELECT * FROM snapshot"

install mercurial with nginx

개발을 할때면 간단히 형상관리를 할수 있는 개인만의 repository를 가지고 싶어지는데, AWS 상에서 nginx서버를 이용해서 간단한 mercurial web repository 를 구성해보았다.

soruce url : http://geeksharp.com/2010/01/20/mercurial-web-with-fastcgi-nginx/ http://mercurial.selenic.com/wiki/HgWebDirStepByStep

case : ubuntu(on aws)

apt-get install nginx mercurial python-flup spawn-fcgi
mkdir /var/www/hg
chown ubuntu:www-data /var/www/hg

case : amazon linux ami(on aws)

sudo yum install nginx spawn-fcgi mercurial
sudo easy_install flup
mkdir /var/www/hg
chown ec2-user:nginx /var/www/hg

nginx를 ubuntu, yum 기본패키지를 깔수도 있고, 최신 stable 버젼으로 깔수도(http://wiki.nginx.org/Install) 있다.

vi /var/www/hg/hgwebdir.fcgi

#!/usr/bin/env python
#
# An example CGI script to export multiple hgweb repos, edit as necessary

# adjust python path if not a system-wide install:
#import sys
#sys.path.insert(0, "/path/to/python/lib")

# enable demandloading to reduce startup time
from mercurial import demandimport; demandimport.enable()

# Uncomment to send python tracebacks to the browser if an error occurs:
#import cgitb
#cgitb.enable()

# If you'd like to serve pages with UTF-8 instead of your default
# locale charset, you can do so by uncommenting the following lines.
# Note that this will cause your .hgrc files to be interpreted in
# UTF-8 and all your repo files to be displayed using UTF-8.
#
import os
os.environ["HGENCODING"] = "UTF-8"

from mercurial.hgweb.hgwebdir_mod import hgwebdir
from flup.server.fcgi import WSGIServer

# The config file looks like this. You can have paths to individual
# repos, collections of repos in a directory tree, or both.
#
# [paths]
# virtual/path1 = /real/path1
# virtual/path2 = /real/path2
# virtual/root = /real/root/*
# / = /real/root2/*
#
# [collections]
# /prefix/to/strip/off = /root/of/tree/full/of/repos
#
# paths example:
#
# * First two lines mount one repository into one virtual path, like
# '/real/path1' into 'virtual/path1'.
#
# * The third entry tells every mercurial repository found in
# '/real/root', recursively, should be mounted in 'virtual/root'. This
# format is preferred over the [collections] one, using absolute paths
# as configuration keys is not supported on every platform (including
# Windows).
#
# * The last entry is a special case mounting all repositories in
# '/real/root2' in the root of the virtual directory.
#
# collections example: say directory tree /foo contains repos /foo/bar,
# /foo/quux/baz. Give this config section:
# [collections]
# /foo = /foo
# Then repos will list as bar and quux/baz.
#
# Alternatively you can pass a list of ('virtual/path', '/real/path') tuples
# or use a dictionary with entries like 'virtual/path': '/real/path'

WSGIServer(hgwebdir('/var/www/hg/hgweb.config')).run()
sudo chmod ug+x /var/www/hg/hgwebdir.fcgi

WSGI 서버를 만들수 있도록 한다.

vi /var/www/hg/hgweb.config

[web]
baseurl = /
allow_push = *
push_ssl = false

[paths]
/ = /var/www/hg/*

WSGI 서버에서 레포지토리 연결할수 있도록 설정 파일을 설정해준다.

perl -le 'print crypt("[your-password]", "salt-hash")'
vi /var/www/hg/hgusers.config

username:encrypted-password:comment

접근 암호도 설정해준다.

vi /etc/init.d/fcgi-hg

#! /bin/sh
#
# fcgi-hg Startup script for the nginx HTTP Server
#
# chkconfig: - 84 15
# description: Loading php-cgi using spawn-cgi
# HTML files and CGI.
#
# Author: Ryan Norbauer
# Modified: Geoffrey Grosenbach http://topfunky.com
# Modified: David Krmpotic http://davidhq.com
# Modified: Kun Xi http://kunxi.org
PATH=/opt/python/bin:$PATH
DAEMON=/usr/bin/spawn-fcgi
FCGIHOST=127.0.0.1
FCGIPORT=9003
FCGIUSER=nginx # ubuntu www-data
FCGIGROUP=nginx
FCGIAPP=/var/www/hg/hgwebdir.fcgi
PIDFILE=/var/run/fcgi-hg.pid
DESC="HG in FastCGI mode"

# Gracefully exit if the package has been removed.
test -x $DAEMON || exit 0
test -x $FCGIAPP || exit 0

start() {
$DAEMON -a $FCGIHOST -p $FCGIPORT -u $FCGIUSER -g $FCGIGROUP -f $FCGIAPP -P $PIDFILE 2> /dev/null || echo -en "\n already running"
}

stop() {
kill -QUIT `cat $PIDFILE` || echo -en "\n not running"
}

restart() {
kill -HUP `cat $PIDFILE` || echo -en "\n can't reload"
}

case "$1" in
start)
echo -n "Starting $DESC: "
start
;;
stop)
echo -n "Stopping $DESC: "
stop
;;
restart|reload)
echo -n "Restarting $DESC: "
stop
# One second might not be time enough for a daemon to stop,
# if this happens, d_start will fail (and dpkg will break if
# the package is being upgraded). Change the timeout if needed
# be, or change d_stop to have start-stop-daemon use --retry.
# Notice that using --retry slows down the shutdown process somewhat.
sleep 1
start
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart|reload}" >&2
exit 3
;;
esac

exit $?

서버 실행시 서비스 등록을 해준다.

sudo chkconfig fcgi-hg on		# case amazon linux ami or centos
sudo update-rc.d fcgi-hg defaults		# case ubuntu

fcgi-hg 에 대한 init script를 만들어주고 등록한다.

vi /etc/nginx/host.d/xxxxx

server {
	listen 80;
	server_name test.abc.com;
	root /var/www/hg/;
	gzip on;

	location / {
		include fastcgi_params;
		fastcgi_pass 127.0.0.1:9003;
		fastcgi_split_path_info ^(/)(.*)$;
		fastcgi_param  SCRIPT_NAME      $fastcgi_script_name;
		fastcgi_param  PATH_INFO        $fastcgi_path_info;
		fastcgi_param  AUTH_USER        $remote_user;
		fastcgi_param  REMOTE_USER      $remote_user;
		fastcgi_intercept_errors        off;
		limit_except GET HEAD {
			auth_basic  'Geek\'s Repositories';
			auth_basic_user_file /var/www/hg/hgusers.config;
		}
	}
	location /static/ {
		rewrite /static/(.*) /$1 break;
		root /usr/lib/python2.6/site-packages/mercurial/templates/static;
		expires 30d;
	}
}

nginx 웹설정 파일을 수정해주고 nginx를 restart 를 하면 해당 도메인으로 mercurial web repository가 뜨는 것을 볼 수 있다.

hg init /var/www/hg/[project_name]
sudo chgrp -R nginx /var/www/hg/[project_name]	# case centos
sudo chgrp -R www-data /var/www/hg/[project_name]	# case ubuntu

[project_name]의 이름의 프로젝트를 위와 같이 추가하면 각각의 프로젝트에 대해 repository 가 생기는 것을 볼수 있다.