LoginSignup
5
5

More than 5 years have passed since last update.

CloudFormationでElasticFileSystem(EFS)をEC2にマウントさせる

Posted at

前回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 )がすでにあるので、パフォーマンス比較まで持って行きたいところ・・・

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5