çãã(åãã¦?)AWSãã¿ã§ãã
ä»äºã§AWSã®VPCãæ§ç¯ãã¦ããã®ã§ãããç»åãåãæ±ããµã¼ãã欲ããã¨ã®è¦æãããã¾ããã
ç»åã表示ããã ããªãCloudFront+S3ã ãã§å¼·åãªç»å(CDN)ãµã¼ããæ§ç¯ãããã¨ãã§ããã®ã§ãããä»åã¯ç»åãµã¤ãºããªã¢ã«ã¿ã¤ã ã§å¤æãã¦è¡¨ç¤ºãã¦ã»ããã¨ã®ãã¨ã§ããã
幸ãã«ã社å ã§ä»¥åãnginxã®http_image_filter_moduleã使ã£ã¦ç»åå¤æãã¦ããå®ä¾(å®ãµã¼ã)ãããã®ã§ãããåèã«æ§ç¯ãã¦ã¿ã¾ããã
æ§æå³
ç°¡åãªå³ã§ãã
ä»åããããã£ããã¨
- ã¦ã¼ã¶ãç¬èªãã¡ã¤ã³ã¨ãããã³ã°ãããCloudFrontã«ã¢ã¯ã»ã¹ããã¨ãCloudFrontã«ç»åããã£ãã·ã¥ããã¦ããã°ãã®ç»åãè¿ãã¾ã
- ããç»åããã£ãã·ã¥ããã¦ããªããã°ELBã»EC2ã¤ã³ã¹ã¿ã³ã¹çµç±ã§S3ã«ããç»åãåå¾ãã¾ã
- EC2ã¤ã³ã¹ã¿ã³ã¹ã«
http_image_filter_module
ãçµã¿è¾¼ã¾ããnginxãã¤ã³ã¹ãã¼ã«ããã¦ãããç»åãµã¤ãºãQueryString(width
,height
ãªã©)ã§æå®ããã¨ãS3ã«ä¿åãã¦ããç»åããªãµã¤ãºãã¦è¿ãã¾ã
ãªããELBãè¨ç½®ãã¦ãããã¨ã以ä¸ã®2ã¤ã®çç±ãããã¾ãã
- ç»åå¤æãµã¼ã(EC2ã¤ã³ã¹ã¿ã³ã¹)ã®è² è·å¯¾ç
- CloudFrontã«ç»åããã£ãã·ã¥ããã¦ããã°é »ç¹ã«ã¢ã¯ã»ã¹ãããè² è·ãä¸ãããã¨ããªãã¨æãã¾ãããæä½éã®è² è·å¯¾çã¯ãã¦ããããã§ããELBé ä¸ã«ç½®ãã¦ãããã¨ã§AutoScalingã«ã対å¿ã§ãã¾ãã
- ç»åå¤æãµã¼ã(EC2ã¤ã³ã¹ã¿ã³ã¹)ãPrivateSubnetã«ç½®ãããã£ã
- ã»ãã¥ãªãã£ç観ç¹ããEC2ã¤ã³ã¹ã¿ã³ã¹ãPublicSubnet(RouteTablesã§Internet Gatewayã«åºã¦ãããããã«è¨å®ãã¦ããSubnet)ã«ç½®ããã¨ã§å¤é¨ããæ»æãããã®ãèæ ®ãã¾ãã
- å¤é¨ããã¢ã¯ã»ã¹ã§ããå ¥ãå£ãELBã®ã¿ã«ããEC2ã¤ã³ã¹ã¿ã³ã¹ã¯ELBããã®ã¢ã¯ã»ã¹(http,https)ã®ã¿ã許容ãããã¨ã§å®å ¨ã«ãµã¼ããéç¨ãããã¨ãã§ããã¨èãã¦ãã¾ã
ç°å¢
- aws-cli 1.4.0
- ELBãEC2ã¤ã³ã¹ã¿ã³ã¹ã®ä½æãªã©ã«ä½¿ãã¾ãããAWS Command Line Toolsãã使ããããã§ã
- nginx 1.6.1
åææ¡ä»¶
- VPC,Subnet,SecurityGroup,NATã¤ã³ã¹ã¿ã³ã¹ãªã©ã®ä½æã»è¨å®ã¯çç¥ãã¦ãã¾ã
- aws-cliã®åæè¨å®ãçç¥ãã¦ãã¾ã
VPCå ã«ELBãä½æã»è¨å®ãã
aws-cliã使ã£ã¦ã¿ã¾ãã
$ aws elb create-load-balancer --load-balancer-name elb-image-filter \
--listeners Protocol=HTTP,LoadBalancerPort=80,InstanceProtocol=HTTP,InstancePort=80 \
--subnets subnet-xxxxxxxxx \
--security-groups sg-xxxxxxxxx \
--output text --query 'DNSName'
elb-image-filter
ã¨ããååã§ä½æãã¾ãããSubnetã¯PublicSubnetãæå®ãã¾ãã
次ã«ELBã®HealthCheckãè¨å®ãã¾ãã
$ aws elb configure-health-check --load-balancer-name elb-image-filter \
--health-check Target=TCP:80,Interval=30,UnhealthyThreshold=2,HealthyThreshold=2,Timeout=5
Interval
ãHealthyThreshold
ãªã©ã¯ã好ã¿ã§è¨å®ãã¦ãã ããã
VPCå ã«EC2ã¤ã³ã¹ã¿ã³ã¹ãä½æãã
ãã¡ããaws-cliã使ã£ã¦ä½æãã¾ããã
$ aws ec2 run-instances --image-id ami-xxxxxxxx \
--key-name xxxxxxxx \
--security-group-ids sg-xxxxxxxx \
--instance-type t2.micro \
--subnet-id subnet-xxxxxxxx \
--count 1 \
--output text --query 'Instances[].InstanceId'
ä½æããEC2ã¤ã³ã¹ã¿ã³ã¹ã«Nameã¿ã°ãä»ãã¾ãã
$ aws ec2 create-tags --resources i-xxxxxxxx --tags Key=Name,Value=vpc-image-filter
å
ã»ã©ä½æããEC2ã¤ã³ã¹ã¿ã³ã¹(i-xxxxxxxx
)ã«vpc-image-filter
ã¨ããNameã¿ã°ãä»ãã¾ããã
ELBé ä¸ã«EC2ã¤ã³ã¹ã¿ã³ã¹ã追å ãã¾ãã
$ aws elb register-instances-with-load-balancer --load-balancer-name elb-image-filter --instances i-xxxxxxxx
ãã®æç¹ã§ã¯ã¾ã nginxãã¤ã³ã¹ãã¼ã«ãã¦ããªã(80ãã¼ãã¯éãã¦ããªã)ãããELBã®HealthCheckã«å¤±æ(OutOfService)ãã¦ãã¾ãã
EC2ã¤ã³ã¹ã¿ã³ã¹ã«nginxãã¤ã³ã¹ãã¼ã«ã»è¨å®ãã
ã¤ã³ã¹ãã¼ã«æ¹æ³ã¯ãnginx(1.4.7)ãã½ã¼ã¹ããã¤ã³ã¹ãã¼ã«ãããåç §ãã¦ã»ããã®ã§ãããä»åã¤ã³ã¹ãã¼ã«ããã¨ãã®ç¸éç¹ã以ä¸ã«æãã¾ãã
- nginxã®ãã¼ã¸ã§ã³ã«ã¤ãã¦
- ä½ã§ãè¯ãã®ã§ãããç¾æç¹(2014/08/18)ã§Stableã§ãã1.6.1ã§ã¤ã³ã¹ãã¼ã«ãã¾ã
- ããã±ã¼ã¸ã®ã¤ã³ã¹ãã¼ã«ã«ã¤ãã¦
http_image_filter_module
ãã¤ã³ã¹ãã¼ã«ããã«ã¯ãgd
ãå¿ è¦ãªã®ã§äºãã¤ã³ã¹ãã¼ã«ãã¦ããã¾ãã
$ sudo yum install gd gd-devel
- configureã®ãªãã·ã§ã³ã«ã¤ãã¦
http_image_filter_module
ãã¤ã³ã¹ãã¼ã«ããã«ã¯ãconfigureã®ãªãã·ã§ã³ã«--with-http_image_filter_module
ãä»ããå¿ è¦ãããã¾ã
$ ./configure --with-http_image_filter_module
nginxãã¤ã³ã¹ãã¼ã«ãããèµ·åãã¾ãã
$ sudo service nginx start
ELBã®HealthCheckãInService
ã«ãªãã®ãå¾
ã¡ã¾ããå
ã»ã©è¨å®ããHealthCheckã ã¨ç´1åç¨åº¦ã§InService
ã«ãªãã¯ãã§ãã
$ aws elb describe-instance-health --load-balancer-name vpc-image-filter --output text --query 'InstanceStates[]'
N/A i-xxxxxxxx N/A InService
ãããã£ã¨å¾
ã£ã¦ãOutOfService
ã«ãªã£ã¦ããããVPCã®ãããã¯ã¼ã¯è¨å®(NetworkACL,SecurityGroup)ãnginx,ELBã®è¨å®ãè¦ç´ãã¦ãã ããã
InService
ã«ãªã£ããããã©ã¦ã¶ããELBã®DNSName(http://elb-image-filter-xxxxxxxx.ap-northeast-1.elb.amazonaws.com/)ã確èªãã¦ãnginxã®ãã¼ã¸(Welcome to nginx!)ã表示ããããã¨ã確èªãã¦ãã ããã
S3ã«ãã±ããä½æ&ç»åã¢ãããã¼ããã
S3ã®ãã±ããä½æã¨ç»åã¢ãããã¼ãã¯ManagementConsoleããè¡ãã¾ããã
ãã±ããåã¯image-filer
ãç»åãã¡ã¤ã«åã¯test.jpg
ã«ãã¾ããã
ç»åãã¢ãããã¼ããã¦ããã®ã¾ã¾ã§ã¯ãã©ã¦ã¶ãã確èªã§ããªãããããã¼ããã·ã§ã³ãå¤æ´ãã¾ãã
ã¢ããã°ã¬ã¼ãããç»åã«å¯¾ãã¦ãä¸å³ã®ããã«ãã¼ããã·ã§ã³ãè¨å®ãã¾ããGrantee
ã«Everyone
ãé¸æããOpen/Download
ã«ãã§ãã¯ãå
¥ãã¦ãã ããã
https://s3-ap-northeast-1.amazonaws.com/image-filter/test.jpgããhttps://image-filter.s3-ap-northeast-1.amazonaws.com/test.jpg ã«ã¢ã¯ã»ã¹ãã¦ç»åã表示ãããã°OKã§ãã
S3ã«ããç»åã®ãµã¤ãºãå¤æããã¦è¡¨ç¤ºããã
ããã§ãããããnginxã®http_image_filter_module
ã使ã£ãè¨å®ãè¡ãã¾ãã
/etc/nginx/nginx.conf
ã«è¨è¿°ãã¦ãã¾ãããå¥ãã¡ã¤ã«ã«è¨è¿°ãã¦Include
ãã¦ãè¯ãã§ãã
è¨å®å
容ã¯ãç°¡åï¼ãªã¢ã«ã¿ã¤ã ç»åå¤æãNginxã ãã§è¡ãæ¹æ³ | cloudrop ãåèã«ãã¾ããã
user nginx nginx;
worker_processes 2;
error_log /var/log/nginx/error.log debug;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
set_real_ip_from 10.0.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive off;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
gzip on;
merge_slashes on;
gzip_static off;
server_tokens off;
server {
listen 80;
server_name localhost;
root /etc/nginx/html;
access_log /var/log/nginx/image-filter-access.log main;
error_log /var/log/nginx/image-filter-error_log;
resolver 8.8.8.8 valid=30s;
image_filter_buffer 5M;
location ~ /(.*\.jpg|png|gif)$ {
set $s3host s3-ap-northeast-1.amazonaws.com/image-filter;
set $file $1;
set $width 150;
set $height 150;
set $quality 100;
if ($query_string !~ .*=.*) {
rewrite ^ /s3_original last;
}
if ($arg_width ~ (\d*)) {
set $width $1;
}
if ($arg_height ~ (\d*)) {
set $height $1;
}
if ($arg_quality = (100|[1-9][0-9]|[1-9])) {
set $quality $1;
}
if ($arg_type = "resize") {
rewrite ^ /s3_resize last;
}
rewrite ^ /s3_crop last;
}
location /s3_original {
internal;
proxy_pass https://$s3host/$file;
}
location /s3_resize {
internal;
proxy_pass https://$s3host/$file;
image_filter resize $width $height;
image_filter_jpeg_quality $quality;
error_page 415 = @empty;
}
location /s3_crop {
internal;
proxy_pass https://$s3host/$file;
image_filter crop $width $height;
image_filter_jpeg_quality $quality;
error_page 415 = @empty;
}
location @empty {
empty_gif;
}
}
}
è¤éãããªè¨å®ã«è¦ãã¾ãããç»åãµã¤ãºãªã©ã®ãã©ã¡ã¼ã¿ã«ãããã£ã¦ãnginx -> S3ã¸ã®ãªãã¼ã¹ãããã·ãè¨å®ãã¦ããã ãã§ãã
nginxãåèµ·å(ORãªãã¼ã)ãã¾ã
$ sudo service nginx reload
http://elb-image-filter-xxxxxxxx.ap-northeast-1.elb.amazonaws.com/test.jpg?width=300&height=500&type=resize ãªã©height
, weight
ã®ãã©ã¡ã¼ã¿å¤ãè¨å®ãããã©ã¦ã¶ããã¢ã¯ã»ã¹ãã¦ãªãµã¤ãºãããç»åã表示ãããã°OKã§ãã
CloudFrontã®è¨å®ãè¡ã
CloudFrontã®CDNä½æã¯ãManagementConsoleã§ãCreate Distributions
ããCloudFrontãä½æãã¾ãã
ä¸å³ã®ããã«ãOrigin Domain Name
ã«ã¯ãELBã®DNSNameãé¸æãã¦ãã ãããOriginID
ã¯èªåçã«å
¥åãããã®ã§å¤æ´ããªãã¦ãè¯ãã§ãã
Default Cache Behavior Settings
ã§ã¯ãForward Query Strings
ãYesã«è¨å®ããã ãã§ãã¨ã¯ããã©ã«ãè¨å®ã§è¯ãã§ãã
Distribution Settings
ã«ãããAlternate Domain Names(CNAMEs)
ã¯å¾ã§è¨å®ãã¾ãã
è¨å®ããã¨CloudFront Distributions
ã®ä¸è¦§ã«è¿½å ããã¾ãã®ã§Status
ãDeployed
ã«ãªãã¾ã§å¾
ã¡ã¾ãã
Deployed
ã«ãªã£ããããã©ã¦ã¶ã§ãhttp://xxxxxxxxxxxxxx.cloudfront.net/test.jpg?width=300&height=500&type=resize ã«ã¢ã¯ã»ã¹ãã¦ç»åã表示ãããã°OKã§ãã
â» xxxxxxxxxxxxx.cloudfront.net
ã¯ä½æãããCloudFrontã®DomanNameã§ãã
ç»åå¤æãµã¼ãã®nginxã®ã¢ã¯ã»ã¹ãã°ã確èªããã¨ãååã¢ã¯ã»ã¹ã®ã¿ã¢ã¯ã»ã¹ãããåããªã¯ã¨ã¹ããããã¨CloudFrontå´ã§ãã£ãã·ã¥ãããããç»åå¤æãµã¼ãã«ã¢ã¯ã»ã¹ãæ¥ãªããªããã¨ãåããã¾ããç°ãªãç»åãµã¤ãºãæå®ãã度ã«ç»åå¤æãµã¼ãã«ã¢ã¯ã»ã¹ããã¾ãããCloudFrontå´ã«ããªãµã¤ãºãããç»åããã£ãã·ã¥ããã¾ãã
ç¬èªãã¡ã¤ã³ã®è¨å®
ããã¾ã§ã§ç»åå¤æãµã¼ãã®æ§ç¯ã¯çµãã£ã¦ããã®ã§ãããURLãhttp://xxxxxxxxxxxxxx.cloudfront.netã
ã®ããã«ãªã£ã¦ãã¾ãã®ã§ãç¬èªãã¡ã¤ã³ã§ç»åã表示ã§ããããã«ãã¾ãã
ãã¡ã¤ã³ãimg.example.com
ã¨ãã¦è¨å®ãã¾ãã
ç¬èªãã¡ã¤ã³ã®è¨å®ã«ã¯ãCloudFrontã¨Route53ã®è¨å®ãå¿ è¦ã§ããã¾ããå¿ è¦ã«å¿ãã¦nginxã®è¨å®ãå¤æ´ãã¾ãã
CloudFrontã®è¨å®
ä¸å³ã®ããã«Alternate Domain Names(CNAMEs)
ã«ç¬èªãã¡ã¤ã³ãè¨å®ãã¾ãã
è¨å®å®äºå¾ãCloudFront Distributions
ã«ã¦CNAMEa
ã®åã«ãã¡ã¤ã³ã表示ãããã°OKã§ãã
Route53ã®è¨å®
ä¸å³ã®ããã«ALIASã¬ã³ã¼ããè¨å®ãã¾ãã
- Name: ç¬èªãã¡ã¤ã³(ãµããã¡ã¤ã³)
- Type: Aã¬ã³ã¼ã
- Alias: Yes
- Alias Target: CloudFrontã§å²ãå½ã¦ããããã¡ã¤ã³(xxxxxxxxxxxxxx.cloudfront.net)
CNAMEã¬ã³ã¼ãã§ãè¯ãã®ã§ãããALIASã¬ã³ã¼ãã®æ¹ãä½è¨ãªãªã¯ã¨ã¹ããããªãã¦æ¸ãã¿ããã§ãã
åèï¼Amazon Route 53ã®ALIASã¬ã³ã¼ãå©ç¨ã®ã¹ã¹ã¡
è¨å®ãå®äºããããdig
ã³ãã³ãã§DNSã¬ã³ã¼ãã確èªãã¦ã¿ã¾ãã
$ dig img.example.com
; <<>> DiG 9.8.3-P1 <<>> img.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30409
;; flags: qr rd ra; QUERY: 1, ANSWER: 8, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;img.example.com. IN A
;; ANSWER SECTION:
img.example.com. 59 IN A 54.230.xxx.xxx
img.example.com. 59 IN A 54.230.xxx.xxx
img.example.com. 59 IN A 54.230.xxx.xxx
img.example.com. 59 IN A 54.230.xxx.xxx
img.example.com. 59 IN A 54.230.xxx.xxx
img.example.com. 59 IN A 54.230.xxx.xxx
img.example.com. 59 IN A 54.230.xxx.xxx
img.example.com. 59 IN A 54.230.xxx.xxx
;; Query time: 112 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Thu Aug 14 19:15:53 2014
;; MSG SIZE rcvd: 178
è¤æ°IPã¢ãã¬ã¹ãè¿ã£ã¦ããããã«ãªãã¯ãã§ãã
nginxã®è¨å®
ServerName
ãå¤æ´ãã¾ããlocalhsot
(ããã©ã«ããµã¼ã)ã§ãè¯ãã®ã§ãããè¤æ°ã®VirtualHostãè¨å®ãããå ´åã¯ServerName
ãELBã®DNSåã«å¤æ´ãã¾ãã
ã¾ããELBã®DNSåãé·ããã¦nginx: [emerg] could not build the server_names_hash, you should increase server_names_hash_bucket_size: 64
ã¨ããã¨ã©ã¼ãåºããããserver_names_hash_bucket_size 128;
ã¨ãããã©ã¡ã¼ã¿ãè¨å®ãã¦ãã¾ãã
ä¸è¨ãnginxã®è¨å®ãã¡ã¤ã«ã®æçµçã§ãã
user nginx nginx;
worker_processes 2;
error_log /var/log/nginx/error.log debug;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
set_real_ip_from 10.0.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive off;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
gzip on;
merge_slashes on;
gzip_static off;
server_tokens off;
server_names_hash_bucket_size 128;
server {
listen 80;
server_name elb-image-filter-xxxxxxxx.ap-northeast-1.elb.amazonaws.com;
root /etc/nginx/html;
access_log /var/log/nginx/image-filter-access.log main;
error_log /var/log/nginx/image-filter-error_log;
resolver 8.8.8.8 valid=30s;
image_filter_buffer 5M;
location ~ /(.*\.jpg|png|gif)$ {
set $s3host s3-ap-northeast-1.amazonaws.com/image-filter;
set $file $1;
set $width 150;
set $height 150;
set $quality 100;
if ($query_string !~ .*=.*) {
rewrite ^ /s3_original last;
}
if ($arg_width ~ (\d*)) {
set $width $1;
}
if ($arg_height ~ (\d*)) {
set $height $1;
}
if ($arg_quality = (100|[1-9][0-9]|[1-9])) {
set $quality $1;
}
if ($arg_type = "resize") {
rewrite ^ /s3_resize last;
}
rewrite ^ /s3_crop last;
}
location /s3_original {
internal;
proxy_pass https://$s3host/$file;
}
location /s3_resize {
internal;
proxy_pass https://$s3host/$file;
image_filter resize $width $height;
image_filter_jpeg_quality $quality;
error_page 415 = @empty;
}
location /s3_crop {
internal;
proxy_pass https://$s3host/$file;
image_filter crop $width $height;
image_filter_jpeg_quality $quality;
error_page 415 = @empty;
}
location @empty {
empty_gif;
}
}
}
nginxãåèµ·å(ORãªãã¼ã)ãã¾ãã
$ sudo service nginx reload
å ¨ã¦è¨å®å®äºå¾ããã©ã¦ã¶ãã http://img.example.com/test.jpg?width=500&height=650&type=resize ã«ã¢ã¯ã»ã¹ãã¦ç»åã表示ããããã¨ã確èªãã¦ãã ããã
ããç»åã表示ãããªãå ´åã¯
ãã£ãã·ã¥ãåé¤ããã¨è¡¨ç¤ºããããã¨ãããã¾ãã
- PCã®DNSãã£ãã·ã¥
Mac OS Xã®å ´å
$ sudo killall -HUP mDNSResponder
- ãã©ã¦ã¶ã®ãã£ãã·ã¥
- ã¹ã¼ãã¼ãªãã¼ããã
æå¾ã«
CloudFrontã¨çµã¿åãããç»åå¤æãµã¼ããæ§ç¯ãã¦ã¿ã¾ããã