この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
静的コンテンツで構成され、ファイルサイズが大きく、かつアクセス数が多いWebサイトの場合、S3にWebコンテンツを配置し、その前にCloudFrontを置くのが一般的な構成です。クラウドデザインパターンで言うところのCache Distributionパターンですね。
しかしこの構成、Webサイト数が多くなると設定の手間が膨大になります。流れとしては
- S3にバケットを作成する。
- バケットポリシーを設定する。
- バケットにStatic Website Hostingの設定をする。
- CloudFrontでDistributionを作成する。
- DNSのWebサイトのレコードを変更し、CloudFrontへ向ける。
をサイト数分繰り返します。面倒臭い。何とか一撃で出来ないものか。ということでAWS SDK for Rubyでやりました。
ソース
※IAM Role for EC2でPowerUsers権限を与えたEC2から実行することを想定しているので、ACCESS_KEY等の設定はしていません。
#!/usr/bin/ruby
require 'rubygems'
require 'aws-sdk'
# Create Bucket
s3 = AWS::S3.new
chkbckt1 = s3.buckets[ARGV[0]]
if chkbckt1.exists? == true then
puts "Failed: S3 bucket is already exists."
exit(1)
end
bucket = s3.buckets.create(ARGV[0])
# Configure Bucket Policy
policy = AWS::S3::Policy.new
policy.allow(
:actions => [:get_object],
:resources => "arn:aws:s3:::#{ARGV[0]}/*",
:principals => :any)
bucket.policy = policy
# Configure Static Website Hosting
bucket.configure_website do |cfg|
cfg.index_document_suffix = 'index.html'
cfg.error_document_key = 'error.html'
end
chkbckt2 = s3.buckets[ARGV[0]]
if chkbckt2.exists? == false then
puts "Failed: S3 bucket not created."
exit(1)
end
# Create CloudFront distributions
cf = AWS::CloudFront.new
cf_config = {
:distribution_config => {
:caller_reference => Time.now.nsec.to_s,
:aliases => {
:quantity => 1,
:items => [
"#{ARGV[0]}"
]
},
:origins => {
:quantity => 1,
:items => [
:id => "S3-#{ARGV[0]}.s3.amazonaws.com",
:domain_name => "#{ARGV[0]}.s3.amazonaws.com",
:custom_origin_config => {
:http_port => 80,
:https_port => 443,
:origin_protocol_policy => "http-only"
}
]
},
:default_cache_behavior => {
:target_origin_id => "S3-#{ARGV[0]}.s3.amazonaws.com",
:forwarded_values => {
:query_string => false,
:cookies => {
:forward => "none"
}
},
:trusted_signers => {
:enabled => false,
:quantity => 0
},
:viewer_protocol_policy => "allow-all",
:min_ttl => 0
},
:cache_behaviors => {
:quantity => 0
},
:price_class => "PriceClass_All",
:default_root_object => "index.html",
:logging => {
:enabled => false,
:bucket => "",
:prefix => "",
:include_cookies => false
},
:comment => "",
:enabled => true
}
}
begin
cf.client.create_distribution(cf_config)
puts "Create Distribution Success!"
rescue
puts "Failed: Distribution not created."
bucket.delete
end
実行
こんな感じでスクリプトファイルの後にドメイン名を引数として付けて実行します。
./cdonepunch.rb www.smokeymonkey.me
S3
バケットポリシーはこうなります。
{
"Version": "2008-10-17",
"Id": "1234567890",
"Statement": [
{
"Sid": "1234567890",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::www.smokeymonkey.me/*"
}
]
}
そしてStatic Website Hostingはこんな感じ。
CloudFront
各設定はこんな感じになります。
General
Origins
Behaviors
まとめ
ここではログ保存とかキャッシュ期間とかは考慮していないのでその辺は要件に併せて調整が必要です。が、もちろんそれもこのスクリプトを改造するだけで出来ます。
AWS SDK for Rubyはだいたいなんでも出来て優秀だなぁと思います。この辺の業務改善スクリプトは今後も作っていきたいし、作ったものはDevelopers.IOでアウトプットしていきます!