前回EFSの立ち上げだけやりましたので、今回はEC2をマウントさせます。
CloudFormation Template
めっちゃ長いです。あとしれっとus-east-1決め打ちです。
AMIは使い慣れてるAMIMOTO AMIを使いました。
ec2-single-with-efs.json
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "AMIMOTO EFS Maunted Stack Example\n",
"Resources": {
"IAMRoleForEC2Instance": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": [
"sts:AssumeRole"
]
}
},
"Path": "/"
}
},
"IAMForEC2": {
"Type": "AWS::IAM::InstanceProfile",
"Properties": {
"Path": "/",
"Roles": [
{
"Ref": "IAMRoleForEC2Instance"
}
]
}
},
"EC2WaitHandle": {
"Type": "AWS::CloudFormation::WaitConditionHandle"
},
"EC2WaitCondition": {
"Type": "AWS::CloudFormation::WaitCondition",
"DependsOn": "EC2",
"Properties": {
"Handle": {
"Ref": "EC2WaitHandle"
},
"Timeout": "1800"
}
},
"SecurityGroupPublic": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "SG for ELB",
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": "80",
"ToPort": "80",
"CidrIp": "0.0.0.0/0"
}
],
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackName"
}
}
],
"VpcId": {
"Ref": "VpcId"
}
}
},
"SecurityGroupInstance": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "SG for EC2 Instance",
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": "22",
"ToPort": "22",
"CidrIp": {
"Ref": "SSHLocation4EC2"
}
}
],
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackName"
}
}
],
"VpcId": {
"Ref": "VpcId"
}
}
},
"SecurityGroupInternal": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Allow connect between EC2 Instance and ELB",
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackName"
}
}
],
"VpcId": {
"Ref": "VpcId"
}
}
},
"SecurityGroupInternalSelfIngress80": {
"Type": "AWS::EC2::SecurityGroupIngress",
"DependsOn": "SecurityGroupInternal",
"Properties": {
"GroupId": {
"Ref": "SecurityGroupInternal"
},
"SourceSecurityGroupId": {
"Ref": "SecurityGroupInternal"
},
"IpProtocol": "tcp",
"ToPort": "80",
"FromPort": "80"
}
},
"SecurityGroupInternalSelfIngress443": {
"Type": "AWS::EC2::SecurityGroupIngress",
"DependsOn": "SecurityGroupInternal",
"Properties": {
"GroupId": {
"Ref": "SecurityGroupInternal"
},
"SourceSecurityGroupId": {
"Ref": "SecurityGroupInternal"
},
"IpProtocol": "tcp",
"ToPort": "443",
"FromPort": "443"
}
},
"EC2": {
"Type": "AWS::EC2::Instance",
"Properties": {
"AvailabilityZone": {
"Ref": "AvailabilityZone"
},
"BlockDeviceMappings": [
{
"DeviceName": "/dev/sdb",
"VirtualName": "ephemeral0"
},
{
"DeviceName": "/dev/sdc",
"VirtualName": "ephemeral1"
}
],
"DisableApiTermination": "false",
"EbsOptimized": "false",
"InstanceInitiatedShutdownBehavior": "stop",
"ImageId": "ami-0c417066",
"InstanceType": {
"Ref": "InstanceType"
},
"KeyName": {
"Ref": "KeyName"
},
"Monitoring": "false",
"Tenancy": "default",
"SecurityGroupIds": [
{
"Ref": "SecurityGroupInstance"
},
{
"Ref": "SecurityGroupInternal"
}
],
"IamInstanceProfile": {
"Ref": "IAMForEC2"
},
"SubnetId": {
"Ref": "SubnetId"
},
"Tags": [
{
"Key": "Name",
"Value": {
"Ref": "AWS::StackName"
}
}
],
"UserData": {
"Fn::Base64": {
"Fn::Join": [
"",
[
"#!/bin/bash\n",
"/opt/aws/bin/cfn-init -s ",
{
"Ref": "AWS::StackName"
},
" -r EC2 ",
" --region ",
{
"Ref": "AWS::Region"
},
"\n",
"yum install -y nfs-utils\n",
"mount -t nfs4 -o nfsvers=4.1 $(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone).",
{
"Ref": "EFSFileSystem"
},
".efs.us-east-1.amazonaws.com:/ /var/www/vhosts\n",
"/opt/aws/bin/cfn-signal -e $? -r \"WordPress setup complete\" '",
{
"Ref": "EC2WaitHandle"
},
"'\n",
"\n"
]
]
}
}
}
},
"EIP": {
"Type": "AWS::EC2::EIP",
"Properties": {
"InstanceId": {
"Ref": "EC2"
},
"Domain": "vpc"
}
},
"ELB": {
"Type": "AWS::ElasticLoadBalancing::LoadBalancer",
"Properties": {
"Subnets": [
{
"Ref": "SubnetId"
}
],
"HealthCheck": {
"HealthyThreshold": "2",
"Interval": "30",
"Target": "TCP:80",
"Timeout": "10",
"UnhealthyThreshold": "2"
},
"Listeners": [
{
"InstancePort": "80",
"LoadBalancerPort": "80",
"Protocol": "HTTP",
"InstanceProtocol": "HTTP"
}
],
"Instances": [
{
"Ref": "EC2"
}
],
"SecurityGroups": [
{
"Ref": "SecurityGroupInternal"
},
{
"Ref": "SecurityGroupPublic"
}
]
}
},
"EFSFileSystem": {
"Type": "AWS::EFS::FileSystem",
"Properties": {
"FileSystemTags": [
{
"Key": "Name",
"Value": "EFSTest"
}
]
}
},
"EFSMoutTarget": {
"Type": "AWS::EFS::MountTarget",
"Properties": {
"FileSystemId": {
"Ref": "EFSFileSystem"
},
"SecurityGroups": [
{
"Ref": "SecurityGroupFileSystem"
}
],
"SubnetId": {
"Ref": "SubnetId"
}
}
},
"SecurityGroupFileSystem": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "SG for EFS",
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": "2049",
"ToPort": "2049",
"CidrIp": "0.0.0.0/0"
}
],
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackName"
}
}
],
"VpcId": {
"Ref": "VpcId"
}
}
}
},
"Parameters": {
"KeyName": {
"Description": "Name of an existing EC2 key pair to enable SSH access to the instances",
"Type": "AWS::EC2::KeyPair::KeyName",
"ConstraintDescription": "Must be the name of an existing EC2 KeyPair."
},
"InstanceType": {
"Description": "EC2 instance type",
"Type": "String",
"AllowedValues": [
"t2.micro",
"t2.small",
"t2.medium",
"m3.medium",
"m3.large",
"m3.xlarge",
"m3.2xlarge",
"m4.large",
"m4.xlarge",
"m4.2xlarge",
"m4.4xlarge",
"m4.10xlarge",
"c3.large",
"c3.xlarge",
"c3.2xlarge",
"c3.4xlarge",
"c3.8xlarge",
"c4.large",
"c4.xlarge",
"c4.2xlarge",
"c4.4xlarge",
"c4.8xlarge",
"g2.2xlarge",
"hi1.4xlarge",
"hs1.8xlarge",
"i2.xlarge",
"i2.2xlarge",
"i2.4xlarge",
"i2.8xlarge",
"r3.large",
"r3.xlarge",
"r3.2xlarge",
"r3.4xlarge",
"r3.8xlarge"
],
"ConstraintDescription": "Must be a valid EC2 instance type."
},
"AvailabilityZone": {
"Description": "Pick an AvailabilityZone for the Primary Subnet. The public subnet will be created in this zone.",
"Type": "AWS::EC2::AvailabilityZone::Name"
},
"SSHLocation4EC2": {
"Description": "The IP address range that can be used to SSH to the EC2 instances",
"Type": "String",
"MinLength": "9",
"MaxLength": "18",
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"ConstraintDescription": "Must be a valid IP CIDR range of the form x.x.x.x/x."
},
"SubnetId": {
"Description": "Your VPC Subnet ID",
"Type": "String"
},
"VpcId": {
"Description": "Your VPC ID",
"Type": "String"
}
},
"Outputs": {
}
}
kumogataから起動する
$ kumogata create ec2-single-with-efs.json STACK_NAME \
-s AWS_SECRET_KEY \
-k AWS_ACCESS_KEY \
-r us-east-1 \
-p "KeyName=KEY_NAME,SSHLocation4EC2=0.0.0.0/0,AvailabilityZone=us-east-1a,InstanceType=t2.small,VpcId=vpc-XXXXX,SubnetId=subnet-XXXXX" \
--capabilities=CAPABILITY_IAM
ざっくり中身
EFSの起動
EFS自体は以下のようにするだけでOKです。
{
"EFSFileSystem": {
"Type": "AWS::EFS::FileSystem",
"Properties": {
"FileSystemTags": [
{
"Key": "Name",
"Value": "EFSTest"
}
]
}
}
}
EFSをマウントする
EFSのマウント先は以下のように設定します。
EFSのリソースIDとVPCのサブネットID、あとセキュリティグループを指定します。
efs_mount.json
{
"EFSMoutTarget": {
"Type": "AWS::EFS::MountTarget",
"Properties": {
"FileSystemId": {
"Ref": "EFSFileSystem"
},
"SecurityGroups": [
{
"Ref": "SecurityGroupFileSystem"
}
],
"SubnetId": {
"Ref": "SubnetId"
}
}
}
}
セキュリティグループはこんな感じ、2049のポートを解放させます。
CiderIpを0.0.0.0/0にしていますが、可能ならばIP列挙にしたほうがいいかも。
sg_for_efs.json
{
"SecurityGroupFileSystem": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "SG for EFS",
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": "2049",
"ToPort": "2049",
"CidrIp": "0.0.0.0/0"
}
],
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackName"
}
}
],
"VpcId": {
"Fn::FindInMap": [
"MPVpcId",
{
"Ref": "AWS::Region"
},
"ID"
]
}
}
}
}
最後にEC2のUserDataにてEFSのマウントを設定しています。
とりあえずWebドキュメントルートだけマウントさせようということで、パスは「/var/www/vhosts」を指定しました。
"yum install -y nfs-utils\n",
"mount -t nfs4 -o nfsvers=4.1 $(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone).",
{
"Ref": "EFSFileSystem"
},
".efs.us-east-1.amazonaws.com:/ /var/www/vhosts\n",
うまくいけば、SSH接続後こんな感じになります。
[ec2-user@ip-172-30-0-149 vhosts]$ df -h
ファイルシス サイズ 使用 残り 使用% マウント位置
/dev/xvda1 9.8G 4.2G 5.6G 43% /
devtmpfs 993M 60K 993M 1% /dev
tmpfs 1002M 0 1002M 0% /dev/shm
us-east-1a.fs-7111eb38.efs.us-east-1.amazonaws.com:/ 8.0E 0 8.0E 0% /var/www/vhosts
今後
ここまできたらDBもRDSにしてAutoScaleさせるしかないよねーと思うわけです。
goofys版の記事(http://qiita.com/wokamoto/items/c470a51f711f2373f6f3 )がすでにあるので、パフォーマンス比較まで持って行きたいところ・・・