Cache Distributionパターン(CloudFront+S3)を一撃で設定する
はじめに
静的コンテンツで構成され、ファイルサイズが大きく、かつアクセス数が多い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でアウトプットしていきます!