EFSをマウントするには
EC2のユーザーデータを使うことで、起動時にコマンドを実行することができます。今回はマウントコマンドを実行します。
主に以下の公式ドキュメントを参考にしましたが、今回書いた記事では起動設定をテンプレートには含めません。
必要なリソース
- VPC
- パブリックサブネット(プライベートサブネットでも同じ)
- インターネットゲートウェイ
- ルートテーブル
- EC2
- EFS
- セキュリティグループ
これらをCloudFormationで作成します。その際、以下の設定もリソースとしてテンプレートに含めることになります。
- ルートテーブルにサブネットを関連付ける
- ルートテーブルをVPCにアタッチする
- マウントターゲットを設定する
※インターネットゲートウェイ、ルートテーブル、セキュリティグループの3点は必須ではありません。これらはマウントできているかどうかをEC2にログインして確かめるためだけに使います。
テンプレート
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"VPC": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.0.0.0/16",
"EnableDnsHostnames": true,
"EnableDnsSupport": true
}
},
"Subnet": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.0.0.0/24",
"AvailabilityZone": "ap-northeast-1c",
"VpcId": {
"Ref": "VPC"
}
}
},
"Instance": {
"Type": "AWS::EC2::Instance",
"DependsOn": "MountTarget",
"Properties": {
"KeyName": "private",
"ImageId": "ami-0bc8ae3ec8e338cbc",
"InstanceType": "t2.micro",
"AvailabilityZone": "ap-northeast-1c",
"NetworkInterfaces": [
{
"AssociatePublicIpAddress": true,
"DeviceIndex": "0",
"GroupSet": [
{
"Ref": "SecurityGroup"
},
{
"Fn::GetAtt": [
"VPC",
"DefaultSecurityGroup"
]
}
],
"SubnetId": {
"Ref": "Subnet"
}
}
],
"UserData": {
"Fn::Base64": {
"Fn::Join": [
"",
[
"#!/bin/bash\n",
"sudo mkdir /mnt/efs\n",
{
"Fn::Sub": "sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 ${FileSystem}.efs.${AWS::Region}.amazonaws.com:/ /mnt/efs"
}
]
]
}
}
}
},
"SecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "CloufdFormation test",
"SecurityGroupEgress": [
{
"IpProtocol": "-1",
"FromPort": "-1",
"ToPort": "-1",
"CidrIp": "0.0.0.0/0"
}
],
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": "22",
"ToPort": "22",
"CidrIp": "0.0.0.0/0"
}
],
"VpcId": {
"Ref": "VPC"
}
}
},
"FileSystem": {
"Type": "AWS::EFS::FileSystem",
"Properties": {
"Encrypted": true,
"KmsKeyId": "arn:aws:kms:ap-northeast-1:012345678912:key/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
},
"MountTarget": {
"Type": "AWS::EFS::MountTarget",
"Properties": {
"FileSystemId": {
"Ref": "FileSystem"
},
"SubnetId": {
"Ref": "Subnet"
},
"SecurityGroups": [
{
"Ref": "SecurityGroup"
},
{
"Fn::GetAtt": [
"VPC",
"DefaultSecurityGroup"
]
}
]
}
},
"Route": {
"Type": "AWS::EC2::Route",
"Properties": {
"RouteTableId": {
"Ref": "RouteTable"
},
"DestinationCidrBlock": "0.0.0.0/0",
"GatewayId": {
"Ref": "InternetGateway"
}
}
},
"RouteTable": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VPC"
}
}
},
"InternetGateway": {
"Type": "AWS::EC2::InternetGateway",
"Properties": {}
},
"VPCGatewayAttachment": {
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties": {
"InternetGatewayId": {
"Ref": "InternetGateway"
},
"VpcId": {
"Ref": "VPC"
}
}
},
"SubnetRouteTableAssociation": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"RouteTableId": {
"Ref": "RouteTable"
},
"SubnetId": {
"Ref": "Subnet"
}
}
}
}
}
解説
Ref
リソースのIDを参照するときなどに使います。例えば、ルートテーブルをどのVPCにアタッチするか決めるときに、VPCのIDを参照します。その際、以下のように書くことで作成するVPCのIDを参照することができます。
"RouteTable": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VPC"
}
}
}
DependsON
EC2マウントターゲットの作成は、EC2の作成よりも遅いです。このコードを記述したリソースは、DependsOn
で指定したリソースの作成後に作成されます。
"DependsOn": "MountTarget"
Fn::base64
ユーザーデータを使うときに必要です。
Fn::Join
文字列の結合に使います。リストのインデックス0には、区切り文字を指定します。インデックス1には、結合したい文字列のリストを指定します。
{
"Fn::Join":
[
"", ["pwd\n", "ls"]
]
}
Fn::Sub
変数に格納した値を展開できます。${AWS::Region}
は定義せずともリージョンの値が展開されます。
{
"Fn::Sub": "sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 ${FileSystem}.efs.${AWS::Region}.amazonaws.com:/ /mnt/efs"
}
注意点
EC2インスタンスのセキュリティグループとサブネットIDは、Properties
の中の NetworkInterfaces
の中で設定します。
参考記事