--- AWSTemplateFormatVersion: 2010-09-09 Description: Amazon Elastic File System - Add data to grow existing file system Metadata: Authors: Description: Darryl Osborne (darrylo@amazon.com) License: Description: 'Copyright 2018 Amazon.com, Inc. and its affiliates. All Rights Reserved. SPDX-License-Identifier: MIT-0' AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Amazon EFS Parameters Parameters: - ElasticFileSystem - Growth - Success - SecurityGroup - NumberOfSubnets - Subnet - InstanceType - KeyName ParameterLabels: ElasticFileSystem: default: File System Id Growth: default: Add data (GiB) InstanceType: default: Instance Type KeyName: default: Existing Key Pair NumberOfSubnets: default: Number of subnets SecurityGroup: default: Security Group Subnet: default: Subnets Success: default: "Success on:" Parameters: ElasticFileSystem: AllowedPattern: ^(fs-)([a-z0-9]{8})$ Description: The Amazon EFS file system id. Type: String Growth: ConstraintDescription: Must be an integer. Description: Amount of dummy data (GiB) to add to the file system (min 0, max 6144). Amazon EFS storage charges apply. MaxValue: 6144 MinValue: 0 Type: Number InstanceType: AllowedValues: - t2.nano - t2.micro - t2.small - t2.medium - t2.large - t2.xlarge - t2.2xlarge - m3.medium - m3.large - m3.xlarge - m3.2xlarge - m4.large - m4.xlarge - m4.2xlarge - m4.4xlarge - m4.10xlarge - m4.16xlarge - m5.large - m5.xlarge - m5.2xlarge - m5.4xlarge - m5.12xlarge - m5.24xlarge - c3.large - c3.xlarge - c3.2xlarge - c3.4xlarge - c3.8xlarge - c4.large - c4.xlarge - c4.2xlarge - c4.4xlarge - c4.8xlarge - c5.large - c5.xlarge - c5.2xlarge - c5.4xlarge - c5.9xlarge - c5.18xlarge - r3.large - r3.xlarge - r3.2xlarge - r3.4xlarge - r3.8xlarge - r4.large - r4.xlarge - r4.2xlarge - r4.4xlarge - r4.8xlarge - r4.16xlarge - x1.16xlarge - x1.32xlarge - x1e.xlarge - x1e.2xlarge - x1e.4xlarge - x1e.8xlarge - x1e.16xlarge - x1e.32xlarge - d2.xlarge - d2.2xlarge - d2.4xlarge - d2.8xlarge - h1.2xlarge - h1.4xlarge - h1.8xlarge - h1.16xlarge - i2.xlarge - i2.2xlarge - i2.4xlarge - i2.8xlarge - i3.large - i3.xlarge - i3.2xlarge - i3.4xlarge - i3.8xlarge - i3.16xlarge - f1.2xlarge - f1.16xlarge - g2.2xlarge - g2.8xlarge - g3.4xlarge - g3.8xlarge - g3.16xlarge - p2.xlarge - p2.8xlarge - p2.16xlarge - p3.2xlarge - p3.8xlarge - p3.16xlarge ConstraintDescription: Must be a valid Amazon EC2 instance type. Default: c5.large Description: The Amazon EC2 instance type that adds data to the file system. Type: String KeyName: Description: Name of an existing EC2 key pair Type: AWS::EC2::KeyPair::KeyName NumberOfSubnets: AllowedValues: - 1 - 2 - 3 - 4 - 5 - 6 Default: 3 Description: Number of subnets. This must match your selections in the list of Subnets below. Type: String SecurityGroup: Description: Select the EC2 security group that allows SSH access to the instance and NFS access to the EFS file system. Type: AWS::EC2::SecurityGroup::Id Subnet: Description: Select existing public subnets. Type: List Success: AllowedValues: - "Data-add start" - "Data-add complete" Default: "Data-add complete" Description: Select which event signals success. Type: String Conditions: NumberofSubnets1: !Equals [ 1, !Ref NumberOfSubnets ] NumberofSubnets2: !Equals [ 2, !Ref NumberOfSubnets ] NumberofSubnets3: !Equals [ 3, !Ref NumberOfSubnets ] NumberofSubnets4: !Equals [ 4, !Ref NumberOfSubnets ] NumberofSubnets5: !Equals [ 5, !Ref NumberOfSubnets ] SuccessStart: !Equals [ 'Data-add start', !Ref Success ] Mappings: RegionMap: us-east-1: AMI: ami-97785bed us-east-2: AMI: ami-f63b1193 us-west-2: AMI: ami-f2d3638a us-west-1: AMI: ami-824c4ee2 ca-central-1: AMI: ami-a954d1cd eu-west-1: AMI: ami-d834aba1 eu-west-2: AMI: ami-403e2524 eu-west-3: AMI: ami-8ee056f3 eu-central-1: AMI: ami-5652ce39 ap-southeast-1: AMI: ami-68097514 ap-northeast-2: AMI: ami-863090e8 ap-northeast-1: AMI: ami-ceafcba8 ap-southeast-2: AMI: ami-942dd1f6 ap-south-1: AMI: ami-531a4c3c sa-east-1: AMI: ami-84175ae8 Resources: InstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Path: / Roles: - !Ref InstanceRole InstanceRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - ec2.amazonaws.com Action: - sts:AssumeRole Path: / Policies: - PolicyName: !Join [ '', [ 'policy-', !Ref 'AWS::StackName' ] ] PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - autoscaling:DescribeAutoScalingGroups - autoscaling:DescribeAutoScalingInstances - autoscaling:DescribePolicies - autoscaling:UpdateAutoScalingGroup Resource: '*' AutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: Cooldown: 60 HealthCheckGracePeriod: 120 HealthCheckType: EC2 LaunchConfigurationName: !Ref LaunchConfiguration MaxSize: 1 MinSize: 0 DesiredCapacity: 1 Tags: - Key: Name Value: !Join [ '', [ 'EFS ', !Ref ElasticFileSystem, ' data load... will auto terminate.' ] ] PropagateAtLaunch: true VPCZoneIdentifier: !If [ NumberofSubnets1, [ !Select [ 0, !Ref Subnet ] ], !If [ NumberofSubnets2, [ !Select [ 0, !Ref Subnet ], !Select [ 1, !Ref Subnet ] ], !If [ NumberofSubnets3, [ !Select [ 0, !Ref Subnet ], !Select [ 1, !Ref Subnet ], !Select [ 2, !Ref Subnet ] ], !If [ NumberofSubnets4, [ !Select [ 0, !Ref Subnet ], !Select [ 1, !Ref Subnet ], !Select [ 2, !Ref Subnet ], !Select [ 3, !Ref Subnet ] ], !If [ NumberofSubnets5, [ !Select [ 0, !Ref Subnet ], !Select [ 1, !Ref Subnet ], !Select [ 2, !Ref Subnet ], !Select [ 3, !Ref Subnet ], !Select [ 4, !Ref Subnet ] ], [ !Select [ 0, !Ref Subnet ], !Select [ 1, !Ref Subnet ], !Select [ 2, !Ref Subnet ], !Select [ 3, !Ref Subnet ], !Select [ 4, !Ref Subnet ], !Select [ 5, !Ref Subnet ] ] ] ] ] ] ] CreationPolicy: ResourceSignal: Count: !If [ SuccessStart, 0 , 1 ] Timeout: PT12H UpdatePolicy: AutoScalingReplacingUpdate: WillReplace: true AutoScalingPolicy: Type: AWS::AutoScaling::ScalingPolicy Properties: AdjustmentType: ChangeInCapacity AutoScalingGroupName: !Ref AutoScalingGroup Cooldown: 60 PolicyType: SimpleScaling ScalingAdjustment: 1 LaunchConfiguration: Type: AWS::AutoScaling::LaunchConfiguration Metadata: AWS::CloudFormation::Init: configSets: efs_add_storage: - efs-add-storage efs-add-storage: files: /tmp/efs-add-storage.sh: content: !Sub | #!/bin/bash -x FILE_SYSTEM_ID=$1 DATA_DIRECTORY=$2 GROWTH=$3 if [ $# -lt 3 ]; then echo "Invalid # of arguments. Require: file system id, data directory, file system growth (GiB) " exit 0 fi # get region from instance meta-data availabilityzone=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone) region=${!availabilityzone:0:-1} # get instance id instance_id=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) # get autoscaling group name asg_name=$(aws autoscaling describe-auto-scaling-instances --instance-ids $instance_id --region $region --output text --query 'AutoScalingInstances[0].AutoScalingGroupName') # set the number of threads to the number of vcpus threads=$(( $(nproc --all) * 8 )) # wait for file system DNS name to be propagated results=1 while [[ $results != 0 ]]; do nslookup $FILE_SYSTEM_ID.efs.$region.amazonaws.com results=$? if [[ results = 1 ]]; then sleep 30 fi done # mount file system sudo mkdir -p /$FILE_SYSTEM_ID sudo chown ec2-user:ec2-user /$FILE_SYSTEM_ID sudo mountpoint -q /$FILE_SYSTEM_ID || sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 $FILE_SYSTEM_ID.efs.$region.amazonaws.com:/ /$FILE_SYSTEM_ID # create directory if not exists sudo mkdir -p /$FILE_SYSTEM_ID/$DATA_DIRECTORY sudo chown ec2-user:ec2-user /$FILE_SYSTEM_ID/$DATA_DIRECTORY # dd 1GiB files to file system to match DATA_SIZE files=$GROWTH if [ $(( $files / $threads )) == 0 ]; then runs=0 parallel_threads=$(( $files % $threads )) else runs=$(( $files / $threads )) parallel_threads=$threads fi while [ $runs -ge 0 ]; do if [ $runs == 0 ]; then parallel_threads=$(( $files % $threads )) seq 0 $(( $parallel_threads - 1 )) | parallel --will-cite -j $parallel_threads --compress dd if=/dev/zero of=/$FILE_SYSTEM_ID/$DATA_DIRECTORY/1G-dd-$(date +%Y%m%d%H%M%S.%3N)-{} bs=1M count=1024 oflag=sync runs=$(($runs-1)) else seq 0 $(( $parallel_threads - 1 )) | parallel --will-cite -j $parallel_threads --compress dd if=/dev/zero of=/$FILE_SYSTEM_ID/$DATA_DIRECTORY/1G-dd-$(date +%Y%m%d%H%M%S.%3N)-{} bs=1M count=1024 oflag=sync runs=$(($runs-1)) fi done # set ASG to zero which terminates instance aws autoscaling update-auto-scaling-group --auto-scaling-group-name $asg_name --desired-capacity 0 --region $region mode: 000777 owner: root group: root Properties: BlockDeviceMappings: - DeviceName: /dev/xvda Ebs: DeleteOnTermination: true VolumeSize: 10 VolumeType: gp2 IamInstanceProfile: !Ref InstanceProfile ImageId: !FindInMap [ RegionMap, !Ref 'AWS::Region', AMI ] InstanceMonitoring: true InstanceType: !Ref InstanceType KeyName: !Ref KeyName SecurityGroups: - !Ref SecurityGroup UserData: "Fn::Base64": !Sub | #cloud-config repo_update: true repo_upgrade: all packages: - parallel runcmd: - yum --enablerepo=epel install nload -y - ntpstat - /opt/aws/bin/cfn-init --configsets efs_add_storage --verbose --stack ${AWS::StackName} --resource LaunchConfiguration --region ${AWS::Region} - /tmp/efs-add-storage.sh ${ElasticFileSystem} throughput_data ${Growth} - /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource AutoScalingGroup --region ${AWS::Region}