Menu
AWS CloudFormation
User Guide (API Version 2010-05-15)

Amazon Elastic File System Sample Template

Amazon Elastic File System (Amazon EFS) is a file storage service for Amazon Elastic Compute Cloud (Amazon EC2) instances. With Amazon EFS, your applications have storage when they need it because storage capacity grows and shrinks automatically as you add and remove files.

The following sample template deploys EC2 instances (in an Auto Scaling group) that are associated with an Amazon EFS file system. To associate the instances with the file system, the instances run the cfn-init helper script, which downloads and installs the nfs-utils yum package, creates a new directory, and then uses the file system's DNS name to mount the file system at that directory. The file system's DNS name resolves to a mount target’s IP address in the Amazon EC2 instance's Availability Zone. For more information about the DNS name structure, see Mounting File Systems in the Amazon Elastic File System User Guide.

To measure Network File System activity, the template includes custom Amazon CloudWatch metrics. The template also creates a VPC, subnet, and security groups. To allow the instances to communicate with the file system, the VPC must have DNS enabled, and the mount target and the EC2 instances must be in the same Availability Zone (AZ), which is specified by the subnet.

The security group of the mount target enables a network connection to TCP port 2049, which is required for an NFSv4 client to mount a file system. For more information on security groups for EC2 instances and mount targets, see Security in the Amazon Elastic File System User Guide.

Note

If you make an update to the mount target that causes it to be replaced, instances or applications that use the associated file system might be disrupted. This can cause uncommitted writes to be lost. To avoid disruption, stop your instances when you update the mount target by setting the desired capacity to zero. This allows the instances to unmount the file system before the mount target is deleted. After the mount update has completed, start your instances in a subsequent update by setting the desired capacity.

JSON

Copy
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "This template creates an Amazon EFS file system and mount target and associates it with Amazon EC2 instances in an Auto Scaling group. **WARNING** This template creates Amazon EC2 instances and related resources. You will be billed for the AWS resources used if you create a stack from this template.", "Parameters": { "InstanceType" : { "Description" : "WebServer EC2 instance type", "Type" : "String", "Default" : "m1.small", "AllowedValues" : [ "t1.micro", "t2.micro", "t2.small", "t2.medium", "m1.small", "m1.medium", "m1.large", "m1.xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge", "m3.medium", "m3.large", "m3.xlarge", "m3.2xlarge", "c1.medium", "c1.xlarge", "c3.large", "c3.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c4.large", "c4.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "g2.2xlarge", "r3.large", "r3.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "i2.xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "d2.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "hi1.4xlarge", "hs1.8xlarge", "cr1.8xlarge", "cc2.8xlarge", "cg1.4xlarge"], "ConstraintDescription" : "Must be a valid EC2 instance type." }, "KeyName": { "Type": "AWS::EC2::KeyPair::KeyName", "Description": "Name of an existing EC2 key pair to enable SSH access to the ECS instances" }, "AsgMaxSize": { "Type": "Number", "Description": "Maximum size and initial desired capacity of Auto Scaling Group", "Default": "2" }, "SSHLocation" : { "Description" : "The IP address range that can be used to connect to the EC2 instances by using SSH", "Type": "String", "MinLength": "9", "MaxLength": "18", "Default": "0.0.0.0/0", "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." }, "VolumeName" : { "Description" : "The name to be used for the EFS volume", "Type": "String", "MinLength": "1", "Default": "myEFSvolume" }, "MountPoint" : { "Description" : "The Linux mount point for the EFS volume", "Type": "String", "MinLength": "1", "Default": "myEFSvolume" } }, "Mappings" : { "AWSInstanceType2Arch" : { "t1.micro" : { "Arch" : "PV64" }, "t2.micro" : { "Arch" : "HVM64" }, "t2.small" : { "Arch" : "HVM64" }, "t2.medium" : { "Arch" : "HVM64" }, "m1.small" : { "Arch" : "PV64" }, "m1.medium" : { "Arch" : "PV64" }, "m1.large" : { "Arch" : "PV64" }, "m1.xlarge" : { "Arch" : "PV64" }, "m2.xlarge" : { "Arch" : "PV64" }, "m2.2xlarge" : { "Arch" : "PV64" }, "m2.4xlarge" : { "Arch" : "PV64" }, "m3.medium" : { "Arch" : "HVM64" }, "m3.large" : { "Arch" : "HVM64" }, "m3.xlarge" : { "Arch" : "HVM64" }, "m3.2xlarge" : { "Arch" : "HVM64" }, "c1.medium" : { "Arch" : "PV64" }, "c1.xlarge" : { "Arch" : "PV64" }, "c3.large" : { "Arch" : "HVM64" }, "c3.xlarge" : { "Arch" : "HVM64" }, "c3.2xlarge" : { "Arch" : "HVM64" }, "c3.4xlarge" : { "Arch" : "HVM64" }, "c3.8xlarge" : { "Arch" : "HVM64" }, "c4.large" : { "Arch" : "HVM64" }, "c4.xlarge" : { "Arch" : "HVM64" }, "c4.2xlarge" : { "Arch" : "HVM64" }, "c4.4xlarge" : { "Arch" : "HVM64" }, "c4.8xlarge" : { "Arch" : "HVM64" }, "g2.2xlarge" : { "Arch" : "HVMG2" }, "r3.large" : { "Arch" : "HVM64" }, "r3.xlarge" : { "Arch" : "HVM64" }, "r3.2xlarge" : { "Arch" : "HVM64" }, "r3.4xlarge" : { "Arch" : "HVM64" }, "r3.8xlarge" : { "Arch" : "HVM64" }, "i2.xlarge" : { "Arch" : "HVM64" }, "i2.2xlarge" : { "Arch" : "HVM64" }, "i2.4xlarge" : { "Arch" : "HVM64" }, "i2.8xlarge" : { "Arch" : "HVM64" }, "d2.xlarge" : { "Arch" : "HVM64" }, "d2.2xlarge" : { "Arch" : "HVM64" }, "d2.4xlarge" : { "Arch" : "HVM64" }, "d2.8xlarge" : { "Arch" : "HVM64" }, "hi1.4xlarge" : { "Arch" : "HVM64" }, "hs1.8xlarge" : { "Arch" : "HVM64" }, "cr1.8xlarge" : { "Arch" : "HVM64" }, "cc2.8xlarge" : { "Arch" : "HVM64" } }, "AWSRegionArch2AMI" : { "us-east-1" : {"PV64" : "ami-1ccae774", "HVM64" : "ami-1ecae776", "HVMG2" : "ami-8c6b40e4"}, "us-west-2" : {"PV64" : "ami-ff527ecf", "HVM64" : "ami-e7527ed7", "HVMG2" : "ami-abbe919b"}, "us-west-1" : {"PV64" : "ami-d514f291", "HVM64" : "ami-d114f295", "HVMG2" : "ami-f31ffeb7"}, "eu-west-1" : {"PV64" : "ami-bf0897c8", "HVM64" : "ami-a10897d6", "HVMG2" : "ami-d5bc24a2"}, "eu-central-1" : {"PV64" : "ami-ac221fb1", "HVM64" : "ami-a8221fb5", "HVMG2" : "ami-7cd2ef61"}, "ap-northeast-1" : {"PV64" : "ami-27f90e27", "HVM64" : "ami-cbf90ecb", "HVMG2" : "ami-6318e863"}, "ap-southeast-1" : {"PV64" : "ami-acd9e8fe", "HVM64" : "ami-68d8e93a", "HVMG2" : "ami-3807376a"}, "ap-southeast-2" : {"PV64" : "ami-ff9cecc5", "HVM64" : "ami-fd9cecc7", "HVMG2" : "ami-89790ab3"}, "sa-east-1" : {"PV64" : "ami-bb2890a6", "HVM64" : "ami-b52890a8", "HVMG2" : "NOT_SUPPORTED"}, "cn-north-1" : {"PV64" : "ami-fa39abc3", "HVM64" : "ami-f239abcb", "HVMG2" : "NOT_SUPPORTED"} } }, "Resources": { "CloudWatchPutMetricsRole" : { "Type" : "AWS::IAM::Role", "Properties" : { "AssumeRolePolicyDocument" : { "Statement" : [ { "Effect" : "Allow", "Principal" : { "Service" : [ "ec2.amazonaws.com" ] }, "Action" : [ "sts:AssumeRole" ] } ] }, "Path" : "/" } }, "CloudWatchPutMetricsRolePolicy" : { "Type" : "AWS::IAM::Policy", "Properties" : { "PolicyName" : "CloudWatch_PutMetricData", "PolicyDocument" : { "Version": "2012-10-17", "Statement": [ { "Sid": "CloudWatchPutMetricData", "Effect": "Allow", "Action": ["cloudwatch:PutMetricData"], "Resource": ["*"] } ] }, "Roles" : [ { "Ref" : "CloudWatchPutMetricsRole" } ] } }, "CloudWatchPutMetricsInstanceProfile" : { "Type" : "AWS::IAM::InstanceProfile", "Properties" : { "Path" : "/", "Roles" : [ { "Ref" : "CloudWatchPutMetricsRole" } ] } }, "VPC": { "Type": "AWS::EC2::VPC", "Properties": { "EnableDnsSupport" : "true", "EnableDnsHostnames" : "true", "CidrBlock": "10.0.0.0/16", "Tags": [ {"Key": "Application", "Value": { "Ref": "AWS::StackId"} } ] } }, "InternetGateway" : { "Type" : "AWS::EC2::InternetGateway", "Properties" : { "Tags" : [ { "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } }, { "Key" : "Network", "Value" : "Public" } ] } }, "GatewayToInternet" : { "Type" : "AWS::EC2::VPCGatewayAttachment", "Properties" : { "VpcId" : { "Ref" : "VPC" }, "InternetGatewayId" : { "Ref" : "InternetGateway" } } }, "RouteTable":{ "Type":"AWS::EC2::RouteTable", "Properties":{ "VpcId": {"Ref":"VPC"} } }, "SubnetRouteTableAssoc": { "Type" : "AWS::EC2::SubnetRouteTableAssociation", "Properties" : { "RouteTableId" : {"Ref":"RouteTable"}, "SubnetId" : {"Ref":"Subnet"} } }, "InternetGatewayRoute": { "Type":"AWS::EC2::Route", "Properties":{ "DestinationCidrBlock":"0.0.0.0/0", "RouteTableId":{"Ref":"RouteTable"}, "GatewayId":{"Ref":"InternetGateway"} } }, "Subnet": { "Type": "AWS::EC2::Subnet", "Properties": { "VpcId": { "Ref": "VPC" }, "CidrBlock": "10.0.0.0/24", "Tags": [ { "Key": "Application", "Value": { "Ref": "AWS::StackId" } } ] } }, "InstanceSecurityGroup": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "VpcId": { "Ref": "VPC" }, "GroupDescription": "Enable SSH access via port 22", "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", "CidrIp": { "Ref": "SSHLocation" } }, { "IpProtocol": "tcp", "FromPort": "80", "ToPort": "80", "CidrIp": "0.0.0.0/0" } ] } }, "MountTargetSecurityGroup": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "VpcId": { "Ref": "VPC" }, "GroupDescription": "Security group for mount target", "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": "2049", "ToPort": "2049", "CidrIp": "0.0.0.0/0" } ] } }, "FileSystem": { "Type": "AWS::EFS::FileSystem", "Properties": { "PerformanceMode": "generalPurpose", "FileSystemTags": [ { "Key": "Name", "Value": { "Ref" : "VolumeName" } } ] } }, "MountTarget": { "Type": "AWS::EFS::MountTarget", "Properties": { "FileSystemId": { "Ref": "FileSystem" }, "SubnetId": { "Ref": "Subnet" }, "SecurityGroups": [ { "Ref": "MountTargetSecurityGroup" } ] } }, "LaunchConfiguration": { "Type": "AWS::AutoScaling::LaunchConfiguration", "Metadata" : { "AWS::CloudFormation::Init" : { "configSets" : { "MountConfig" : [ "setup", "mount" ] }, "setup" : { "packages" : { "yum" : { "nfs-utils" : [] } }, "files" : { "/home/ec2-user/post_nfsstat" : { "content" : { "Fn::Join" : [ "", [ "#!/bin/bash\n", "\n", "INPUT=\"$(cat)\"\n", "CW_JSON_OPEN='{ \"Namespace\": \"EFS\", \"MetricData\": [ '\n", "CW_JSON_CLOSE=' ] }'\n", "CW_JSON_METRIC=''\n", "METRIC_COUNTER=0\n", "\n", "for COL in 1 2 3 4 5 6; do\n", "\n", " COUNTER=0\n", " METRIC_FIELD=$COL\n", " DATA_FIELD=$(($COL+($COL-1)))\n", "\n", " while read line; do\n", " if [[ COUNTER -gt 0 ]]; then\n", "\n", " LINE=`echo $line | tr -s ' ' `\n", " AWS_COMMAND=\"aws cloudwatch put-metric-data --region ", { "Ref": "AWS::Region" }, "\"\n", " MOD=$(( $COUNTER % 2))\n", "\n", " if [ $MOD -eq 1 ]; then\n", " METRIC_NAME=`echo $LINE | cut -d ' ' -f $METRIC_FIELD`\n", " else\n", " METRIC_VALUE=`echo $LINE | cut -d ' ' -f $DATA_FIELD`\n", " fi\n", "\n", " if [[ -n \"$METRIC_NAME\" && -n \"$METRIC_VALUE\" ]]; then\n", " INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)\n", " CW_JSON_METRIC=\"$CW_JSON_METRIC { \\\"MetricName\\\": \\\"$METRIC_NAME\\\", \\\"Dimensions\\\": [{\\\"Name\\\": \\\"InstanceId\\\", \\\"Value\\\": \\\"$INSTANCE_ID\\\"} ], \\\"Value\\\": $METRIC_VALUE },\"\n", " unset METRIC_NAME\n", " unset METRIC_VALUE\n", "\n", " METRIC_COUNTER=$((METRIC_COUNTER+1))\n", " if [ $METRIC_COUNTER -eq 20 ]; then\n", " # 20 is max metric collection size, so we have to submit here\n", " aws cloudwatch put-metric-data --region ", { "Ref": "AWS::Region" }, " --cli-input-json \"`echo $CW_JSON_OPEN ${CW_JSON_METRIC%?} $CW_JSON_CLOSE`\"\n", "\n", " # reset\n", " METRIC_COUNTER=0\n", " CW_JSON_METRIC=''\n", " fi\n", " fi \n", "\n", "\n", "\n", " COUNTER=$((COUNTER+1))\n", " fi\n", "\n", " if [[ \"$line\" == \"Client nfs v4:\" ]]; then\n", " # the next line is the good stuff \n", " COUNTER=$((COUNTER+1))\n", " fi\n", " done <<< \"$INPUT\"\n", "done\n", "\n", "# submit whatever is left\n", "aws cloudwatch put-metric-data --region ", { "Ref": "AWS::Region" }, " --cli-input-json \"`echo $CW_JSON_OPEN ${CW_JSON_METRIC%?} $CW_JSON_CLOSE`\"" ] ] }, "mode": "000755", "owner": "ec2-user", "group": "ec2-user" }, "/home/ec2-user/crontab" : { "content" : { "Fn::Join" : [ "", [ "* * * * * /usr/sbin/nfsstat | /home/ec2-user/post_nfsstat\n" ] ] }, "owner": "ec2-user", "group": "ec2-user" } }, "commands" : { "01_createdir" : { "command" : {"Fn::Join" : [ "", [ "mkdir /", { "Ref" : "MountPoint" }]]} } } }, "mount" : { "commands" : { "01_mount" : { "command" : { "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:/ /${MountPoint}"} }, "02_permissions" : { "command" : {"Fn::Join" : [ "", [ "chown ec2-user:ec2-user /", { "Ref" : "MountPoint" }]]} } } } } }, "Properties": { "AssociatePublicIpAddress" : true, "ImageId": { "Fn::FindInMap": [ "AWSRegionArch2AMI", { "Ref": "AWS::Region" }, { "Fn::FindInMap": [ "AWSInstanceType2Arch", { "Ref": "InstanceType" }, "Arch" ] } ] }, "InstanceType": { "Ref": "InstanceType" }, "KeyName": { "Ref": "KeyName" }, "SecurityGroups": [ { "Ref": "InstanceSecurityGroup" } ], "IamInstanceProfile" : { "Ref" : "CloudWatchPutMetricsInstanceProfile" }, "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [ "#!/bin/bash -xe\n", "yum install -y aws-cfn-bootstrap\n", "/opt/aws/bin/cfn-init -v ", " --stack ", { "Ref" : "AWS::StackName" }, " --resource LaunchConfiguration ", " --configsets MountConfig ", " --region ", { "Ref" : "AWS::Region" }, "\n", "crontab /home/ec2-user/crontab\n", "/opt/aws/bin/cfn-signal -e $? ", " --stack ", { "Ref" : "AWS::StackName" }, " --resource AutoScalingGroup ", " --region ", { "Ref" : "AWS::Region" }, "\n" ]]}} } }, "AutoScalingGroup": { "Type": "AWS::AutoScaling::AutoScalingGroup", "DependsOn": ["MountTarget", "GatewayToInternet"], "CreationPolicy" : { "ResourceSignal" : { "Timeout" : "PT15M", "Count" : { "Ref": "AsgMaxSize" } } }, "Properties": { "VPCZoneIdentifier": [ { "Ref": "Subnet" } ], "LaunchConfigurationName": { "Ref": "LaunchConfiguration" }, "MinSize": "1", "MaxSize": { "Ref": "AsgMaxSize" }, "DesiredCapacity": { "Ref": "AsgMaxSize" }, "Tags": [ { "Key": "Name", "Value": "EFS FileSystem Mounted Instance", "PropagateAtLaunch": "true" } ] } } }, "Outputs" : { "MountTargetID" : { "Description" : "Mount target ID", "Value" : { "Ref" : "MountTarget" } }, "FileSystemID" : { "Description" : "File system ID", "Value" : { "Ref" : "FileSystem" } } } }

YAML

Copy
AWSTemplateFormatVersion: '2010-09-09' Description: This template creates an Amazon EFS file system and mount target and associates it with Amazon EC2 instances in an Auto Scaling group. **WARNING** This template creates Amazon EC2 instances and related resources. You will be billed for the AWS resources used if you create a stack from this template. Parameters: InstanceType: Description: WebServer EC2 instance type Type: String Default: m1.small AllowedValues: - t1.micro - t2.micro - t2.small - t2.medium - m1.small - m1.medium - m1.large - m1.xlarge - m2.xlarge - m2.2xlarge - m2.4xlarge - m3.medium - m3.large - m3.xlarge - m3.2xlarge - c1.medium - c1.xlarge - c3.large - c3.xlarge - c3.2xlarge - c3.4xlarge - c3.8xlarge - c4.large - c4.xlarge - c4.2xlarge - c4.4xlarge - c4.8xlarge - g2.2xlarge - r3.large - r3.xlarge - r3.2xlarge - r3.4xlarge - r3.8xlarge - i2.xlarge - i2.2xlarge - i2.4xlarge - i2.8xlarge - d2.xlarge - d2.2xlarge - d2.4xlarge - d2.8xlarge - hi1.4xlarge - hs1.8xlarge - cr1.8xlarge - cc2.8xlarge - cg1.4xlarge ConstraintDescription: Must be a valid EC2 instance type. KeyName: Type: AWS::EC2::KeyPair::KeyName Description: Name of an existing EC2 key pair to enable SSH access to the ECS instances AsgMaxSize: Type: Number Description: Maximum size and initial desired capacity of Auto Scaling Group Default: '2' SSHLocation: Description: The IP address range that can be used to connect to the EC2 instances by using SSH Type: String MinLength: '9' MaxLength: '18' Default: 0.0.0.0/0 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. VolumeName: Description: The name to be used for the EFS volume Type: String MinLength: '1' Default: myEFSvolume MountPoint: Description: The Linux mount point for the EFS volume Type: String MinLength: '1' Default: myEFSvolume Mappings: AWSInstanceType2Arch: t1.micro: Arch: PV64 t2.micro: Arch: HVM64 t2.small: Arch: HVM64 t2.medium: Arch: HVM64 m1.small: Arch: PV64 m1.medium: Arch: PV64 m1.large: Arch: PV64 m1.xlarge: Arch: PV64 m2.xlarge: Arch: PV64 m2.2xlarge: Arch: PV64 m2.4xlarge: Arch: PV64 m3.medium: Arch: HVM64 m3.large: Arch: HVM64 m3.xlarge: Arch: HVM64 m3.2xlarge: Arch: HVM64 c1.medium: Arch: PV64 c1.xlarge: Arch: PV64 c3.large: Arch: HVM64 c3.xlarge: Arch: HVM64 c3.2xlarge: Arch: HVM64 c3.4xlarge: Arch: HVM64 c3.8xlarge: Arch: HVM64 c4.large: Arch: HVM64 c4.xlarge: Arch: HVM64 c4.2xlarge: Arch: HVM64 c4.4xlarge: Arch: HVM64 c4.8xlarge: Arch: HVM64 g2.2xlarge: Arch: HVMG2 r3.large: Arch: HVM64 r3.xlarge: Arch: HVM64 r3.2xlarge: Arch: HVM64 r3.4xlarge: Arch: HVM64 r3.8xlarge: Arch: HVM64 i2.xlarge: Arch: HVM64 i2.2xlarge: Arch: HVM64 i2.4xlarge: Arch: HVM64 i2.8xlarge: Arch: HVM64 d2.xlarge: Arch: HVM64 d2.2xlarge: Arch: HVM64 d2.4xlarge: Arch: HVM64 d2.8xlarge: Arch: HVM64 hi1.4xlarge: Arch: HVM64 hs1.8xlarge: Arch: HVM64 cr1.8xlarge: Arch: HVM64 cc2.8xlarge: Arch: HVM64 AWSRegionArch2AMI: us-east-1: PV64: ami-1ccae774 HVM64: ami-1ecae776 HVMG2: ami-8c6b40e4 us-west-2: PV64: ami-ff527ecf HVM64: ami-e7527ed7 HVMG2: ami-abbe919b us-west-1: PV64: ami-d514f291 HVM64: ami-d114f295 HVMG2: ami-f31ffeb7 eu-west-1: PV64: ami-bf0897c8 HVM64: ami-a10897d6 HVMG2: ami-d5bc24a2 eu-central-1: PV64: ami-ac221fb1 HVM64: ami-a8221fb5 HVMG2: ami-7cd2ef61 ap-northeast-1: PV64: ami-27f90e27 HVM64: ami-cbf90ecb HVMG2: ami-6318e863 ap-southeast-1: PV64: ami-acd9e8fe HVM64: ami-68d8e93a HVMG2: ami-3807376a ap-southeast-2: PV64: ami-ff9cecc5 HVM64: ami-fd9cecc7 HVMG2: ami-89790ab3 sa-east-1: PV64: ami-bb2890a6 HVM64: ami-b52890a8 HVMG2: NOT_SUPPORTED cn-north-1: PV64: ami-fa39abc3 HVM64: ami-f239abcb HVMG2: NOT_SUPPORTED Resources: CloudWatchPutMetricsRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: Service: - ec2.amazonaws.com Action: - sts:AssumeRole Path: "/" CloudWatchPutMetricsRolePolicy: Type: AWS::IAM::Policy Properties: PolicyName: CloudWatch_PutMetricData PolicyDocument: Version: '2012-10-17' Statement: - Sid: CloudWatchPutMetricData Effect: Allow Action: - cloudwatch:PutMetricData Resource: - "*" Roles: - Ref: CloudWatchPutMetricsRole CloudWatchPutMetricsInstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Path: "/" Roles: - Ref: CloudWatchPutMetricsRole VPC: Type: AWS::EC2::VPC Properties: EnableDnsSupport: 'true' EnableDnsHostnames: 'true' CidrBlock: 10.0.0.0/16 Tags: - Key: Application Value: Ref: AWS::StackId InternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Application Value: Ref: AWS::StackName - Key: Network Value: Public GatewayToInternet: Type: AWS::EC2::VPCGatewayAttachment Properties: VpcId: Ref: VPC InternetGatewayId: Ref: InternetGateway RouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: Ref: VPC SubnetRouteTableAssoc: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: Ref: RouteTable SubnetId: Ref: Subnet InternetGatewayRoute: Type: AWS::EC2::Route Properties: DestinationCidrBlock: 0.0.0.0/0 RouteTableId: Ref: RouteTable GatewayId: Ref: InternetGateway Subnet: Type: AWS::EC2::Subnet Properties: VpcId: Ref: VPC CidrBlock: 10.0.0.0/24 Tags: - Key: Application Value: Ref: AWS::StackId InstanceSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: VpcId: Ref: VPC GroupDescription: Enable SSH access via port 22 SecurityGroupIngress: - IpProtocol: tcp FromPort: '22' ToPort: '22' CidrIp: Ref: SSHLocation - IpProtocol: tcp FromPort: '80' ToPort: '80' CidrIp: 0.0.0.0/0 MountTargetSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: VpcId: Ref: VPC GroupDescription: Security group for mount target SecurityGroupIngress: - IpProtocol: tcp FromPort: '2049' ToPort: '2049' CidrIp: 0.0.0.0/0 FileSystem: Type: AWS::EFS::FileSystem Properties: PerformanceMode: generalPurpose FileSystemTags: - Key: Name Value: Ref: VolumeName MountTarget: Type: AWS::EFS::MountTarget Properties: FileSystemId: Ref: FileSystem SubnetId: Ref: Subnet SecurityGroups: - Ref: MountTargetSecurityGroup LaunchConfiguration: Type: AWS::AutoScaling::LaunchConfiguration Metadata: AWS::CloudFormation::Init: configSets: MountConfig: - setup - mount setup: packages: yum: nfs-utils: [] files: "/home/ec2-user/post_nfsstat": content: !Sub | #!/bin/bash INPUT="$(cat)" CW_JSON_OPEN='{ "Namespace": "EFS", "MetricData": [ ' CW_JSON_CLOSE=' ] }' CW_JSON_METRIC='' METRIC_COUNTER=0 for COL in 1 2 3 4 5 6; do COUNTER=0 METRIC_FIELD=$COL DATA_FIELD=$(($COL+($COL-1))) while read line; do if [[ COUNTER -gt 0 ]]; then LINE=`echo $line | tr -s ' ' ` AWS_COMMAND="aws cloudwatch put-metric-data --region ${AWS::Region}" MOD=$(( $COUNTER % 2)) if [ $MOD -eq 1 ]; then METRIC_NAME=`echo $LINE | cut -d ' ' -f $METRIC_FIELD` else METRIC_VALUE=`echo $LINE | cut -d ' ' -f $DATA_FIELD` fi if [[ -n "$METRIC_NAME" && -n "$METRIC_VALUE" ]]; then INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) CW_JSON_METRIC="$CW_JSON_METRIC { \"MetricName\": \"$METRIC_NAME\", \"Dimensions\": [{\"Name\": \"InstanceId\", \"Value\": \"$INSTANCE_ID\"} ], \"Value\": $METRIC_VALUE }," unset METRIC_NAME unset METRIC_VALUE METRIC_COUNTER=$((METRIC_COUNTER+1)) if [ $METRIC_COUNTER -eq 20 ]; then # 20 is max metric collection size, so we have to submit here aws cloudwatch put-metric-data --region ${AWS::Region} --cli-input-json "`echo $CW_JSON_OPEN ${!CW_JSON_METRIC%?} $CW_JSON_CLOSE`" # reset METRIC_COUNTER=0 CW_JSON_METRIC='' fi fi COUNTER=$((COUNTER+1)) fi if [[ "$line" == "Client nfs v4:" ]]; then # the next line is the good stuff COUNTER=$((COUNTER+1)) fi done <<< "$INPUT" done # submit whatever is left aws cloudwatch put-metric-data --region ${AWS::Region} --cli-input-json "`echo $CW_JSON_OPEN ${!CW_JSON_METRIC%?} $CW_JSON_CLOSE`" mode: '000755' owner: ec2-user group: ec2-user "/home/ec2-user/crontab": content: "* * * * * /usr/sbin/nfsstat | /home/ec2-user/post_nfsstat\n" owner: ec2-user group: ec2-user commands: 01_createdir: command: !Sub "mkdir /${MountPoint}" mount: commands: 01_mount: command: !Sub > mount -t nfs4 -o nfsvers=4.1 ${FileSystem}.efs.${AWS::Region}.amazonaws.com:/ /${MountPoint} 02_permissions: command: !Sub "chown ec2-user:ec2-user /${MountPoint}" Properties: AssociatePublicIpAddress: true ImageId: Fn::FindInMap: - AWSRegionArch2AMI - Ref: AWS::Region - Fn::FindInMap: - AWSInstanceType2Arch - Ref: InstanceType - Arch InstanceType: Ref: InstanceType KeyName: Ref: KeyName SecurityGroups: - Ref: InstanceSecurityGroup IamInstanceProfile: Ref: CloudWatchPutMetricsInstanceProfile UserData: Fn::Base64: !Sub | #!/bin/bash -xe yum install -y aws-cfn-bootstrap /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource LaunchConfiguration --configsets MountConfig --region ${AWS::Region} crontab /home/ec2-user/crontab /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource AutoScalingGroup --region ${AWS::Region} AutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup DependsOn: - MountTarget - GatewayToInternet CreationPolicy: ResourceSignal: Timeout: PT15M Count: Ref: AsgMaxSize Properties: VPCZoneIdentifier: - Ref: Subnet LaunchConfigurationName: Ref: LaunchConfiguration MinSize: '1' MaxSize: Ref: AsgMaxSize DesiredCapacity: Ref: AsgMaxSize Tags: - Key: Name Value: EFS FileSystem Mounted Instance PropagateAtLaunch: 'true' Outputs: MountTargetID: Description: Mount target ID Value: Ref: MountTarget FileSystemID: Description: File system ID Value: Ref: FileSystem

On this page: