最近知ったのですが、EC2にS3のバケットをマウントすることが出来るようです。
つまり、S3にRDBMSのファイルを置いて、そこに対してシステムがアクセスするようにすればRDSを利用せずに永続化したデータを利用することが出来るようになります。
S3をマウントする
s3fs-fuseというライブラリを利用することで、S3のバケットをEC2にマウントすることが出来るようになります。
ubuntu14.04を対象にインストールからセットアップの手順を記載します。
(GithubのReadmeの内容がほぼそのまま書いているだけです。)
インストール
sudo su root
apt-get update
apt-get install automake autotools-dev g++ git libcurl4-gnutls-dev libfuse-dev libssl-dev libxml2-dev make pkg-config
cd /usr/local/src
git clone https://github.com/s3fs-fuse/s3fs-fuse.git
cd s3fs-fuse
./autogen.sh
./configure
make
sudo make install
セットアップ
S3上に、__s3-mount__という名前のバケットを作成してあること、
バケットの下に__test__というフォルダが作成してあること、
また、IAMユーザーでS3にのみアクセス出来るユーザーを作成し、アクセストークンとシークレットキーを取得していることを前提とします。
sudo su root
echo '[AWS_ACCESS_TOKEN]:[AWS_ACCESS_SECRET]' > /etc/passwd-s3fs
mkdir -p /mnt/s3fs
s3fs s3-mount:/test /mnt/s3fs -o allow_other
ここまで、行えばs3のバケットをマウントできているはずです。
df -h |grep s3fs
s3fs 256T 0 256T 0% /mnt/s3fs
256TBもある!
DBをS3に作成して、アプリケーションから接続する
sqlite3でDB作成
MySQLやPostgresqlでもdataを置く場所をS3にしておけば動くんじゃないかなぁと思いますが、試してはいません。
今回は、簡単に利用出来るsqlite3でDBを作成しました。
# インストール
sudo apt-get install sqlite3
# DB、テーブル作成
sqlite3 /mnt/s3fs/sample.db
sqlite> create table users(name text, age integer);
sqlite> .table
users
sqlite> .exit
sinatraで簡易的なWEBアプリケーションを作成
rubyのインストールについては割愛します。
# 利用するgemをインストール
gem install sinatra unicorn sqlite3 slim --no-ri --no-rdoc
アプリケーションのディレクトリ構成は下記のようにしました。
アプリケーションサーバーには安定性重視で、1プロセスが1リクエストしか対応しないUnicornを選んでいます。
/var/www/app
logs/
pids/
sockets/
config.ru
unicorn.rb
main.rb
worker_processes 1
timeout 180
root_dir = Dir.pwd
listen File.join(root_dir, 'sockets', 'app.sock')
pid File.join(root_dir, 'pids', 'app.pid')
stderr_path File.join(root_dir, 'logs', 'app.log')
require 'rubygems'
require 'sqlite3'
require 'sinatra'
require './main.rb'
run Sinatra::Application
require 'slim'
before do
@db = SQLite3::Database.new('/mnt/s3fs/sample.db')
end
after do
@db.close
end
get '/users' do
@users = @db.execute('SELECT * FROM users')
slim <<-SLIM
h1 Users
div
a href="/users/new" Create
- if @users.empty?
p No data.
- else
table
tr
th name
th age
- @users.each do |user|
tr
td= user[0]
td= user[1]
SLIM
end
get '/users/new' do
slim <<-SLIM
div
a href="/users" List
form method="POST" action="/users"
div
label for="name" Name
input type="text" id="name" name="name"
div
label for="age" Age
input type="number" id="number" name="age" minimum="0"
div
button type="submit" Submit
SLIM
end
post '/users' do
@db.execute(
'INSERT INTO users(name, age) VALUES(?, ?)',
[params['name'], params['age']]
)
redirect to('/users')
end
こんな感じで、コードを準備したら、
unicorn -c unicorn.rb
とやればアプリケーションサーバーが起動します。
WEBサーバーを用意する
nginxでアプリケーションサーバーにプロキシしてあげれば完成です。
sudo apt-get install nginx
user www-data;
- worker_processes 4;
+ worker_processes auto;
pid /run/nginx.pid;
.
.
.
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
- include /etc/nginx/sites-enabled/*;
+ include /etc/nginx/sites-enabled/*.conf;
.
.
.
upstream unicorn {
server unix:/var/www/app/sockets/app.sock fail_timeout=0;
}
server {
listen 80;
server_name loalhost;
root /var/www/app/;
location / {
try_files @uri @uri/ @app;
}
location @app {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_pass http://unicorn;
}
error_page 404 /404.html;
error_page 422 /422.html;
error_page 400 401 403 500 502 503 504 /500.html;
}
Nginxの設定を作成したら再起動します。
sudo nginx -t && sudo service nginx reload
ここまでできたら、EC2に付与されたパブリックDNSなり、パブリックIPなりでシステムにアクセス出来るようになります。
まとめ
- S3にデータを置くことで、バックアップなどの運用を気にせずにDBを持つことが出来るようになります。
- RDSを利用しないので、発生する料金はS3の使用量と、データ転送量のみで割安です。
- S3とEC2との間の通信には結構な時間がかかるので、処理時間は遅いです。
- 身内で公開するレベルの小さなシステムであれば、非常に手軽に作成できて、運用費もそこまでかからないので、このような構成を選択するのは全然ありだなぁという感想でした。