--- AWSTemplateFormatVersion: 2010-09-09 Description: Reference Architecture to host Moodle on AWS - Creates EFS alarms Parameters: Growth: ConstraintDescription: Must be an integer. Default: 0 Description: Amount of dummy data (GiB) to add to the file system (max 6144 GiB). Amazon EFS storage charges apply. MaxValue: 6144 MinValue: 0 Type: Number CriticalThreshold: AllowedPattern: ^[0-9]+$ ConstraintDescription: Must be an integer. Default: 60 Description: Send critical alarm this minutes before burst credit balance is zero. Type: String SecurityGroup: Description: Select the Amazon EFS security group. Type: AWS::EC2::SecurityGroup::Id ElasticFileSystem: Description: The Amazon EFS file system id. Type: String EmailAddress: Description: The email address for SNS notifications. Type: String InstanceType: AllowedValues: - m5.large - m5.xlarge - m5.2xlarge - m5.4xlarge - m5.8xlarge - m5.12xlarge - m5.16xlarge - m5.24xlarge - c5.large - c5.xlarge - c5.2xlarge - c5.4xlarge - c5.9xlarge - c5.12xlarge - c5.18xlarge - c5.24xlarge - r5.large - r5.xlarge - r5.2xlarge - r5.4xlarge - r5.8xlarge - r5.12xlarge - r5.16xlarge - r5.24xlarge - m5a.large - m5a.xlarge - m5a.2xlarge - m5a.4xlarge - m5a.8xlarge - m5a.12xlarge - m5a.16xlarge - m5a.24xlarge - c5a.large - c5a.xlarge - c5a.2xlarge - c5a.4xlarge - c5a.9xlarge - c5a.12xlarge - c5a.18xlarge - c5a.24xlarge - r5a.large - r5a.xlarge - r5a.2xlarge - r5a.4xlarge - r5a.8xlarge - r5a.12xlarge - r5a.16xlarge - r5a.24xlarge - m6g.large - m6g.xlarge - m6g.2xlarge - m6g.4xlarge - m6g.8xlarge - m6g.12xlarge - m6g.16xlarge - m6g.24xlarge - c6g.large - c6g.xlarge - c6g.2xlarge - c6g.4xlarge - c6g.9xlarge - c6g.12xlarge - c6g.18xlarge - c6g.24xlarge - r6g.large - r6g.xlarge - r6g.2xlarge - r6g.4xlarge - r6g.8xlarge - r6g.12xlarge - r6g.16xlarge - r6g.24xlarge ConstraintDescription: Must be a valid Amazon EC2 instance type. Default: m6g.large Description: The Amazon EC2 instance type that dynamically adjusts thresholds based on permitted throughput changes. Type: String EC2KeyName: Description: Name of an existing EC2 key pair Type: AWS::EC2::KeyPair::KeyName NumberOfSubnets: AllowedValues: - 1 - 2 - 3 Default: 2 Description: Number of subnets. This must match your selections in the list of Subnets below. Type: String Subnet: Description: Select existing subnets. Type: List WarningThreshold: AllowedPattern: ^[0-9]+$ ConstraintDescription: Must be an integer. Default: 180 Description: Send warning alarm this many minutes before burst credit balance is zero. Type: String LatestAmiId : Type : AWS::SSM::Parameter::Value Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 LatestArmAmiId : Type : AWS::SSM::Parameter::Value Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2 Conditions: NumberOfSubnets1: !Equals [ 1, !Ref NumberOfSubnets ] NumberOfSubnets2: !Equals [ 2, !Ref NumberOfSubnets ] NumberOfSubnets3: !Equals [ 3, !Ref NumberOfSubnets ] Subnet0: !Or - !Condition NumberOfSubnets1 - !Condition NumberOfSubnets2 - !Condition NumberOfSubnets3 Subnet1: !Or - !Condition NumberOfSubnets2 - !Condition NumberOfSubnets3 Subnet2: !Condition NumberOfSubnets3 UsingGraviton2Ami: !Or - !Equals ["t4",!Select [0, !Split [ "g.", !Ref InstanceType]]] - !Equals ["c6",!Select [0, !Split [ "g.", !Ref InstanceType]]] - !Equals ["m6",!Select [0, !Split [ "g.", !Ref InstanceType]]] - !Equals ["r6",!Select [0, !Split [ "g.", !Ref InstanceType]]] 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 ManagedPolicyArns: - 'arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore' Path: / Policies: - PolicyName: MoodleEFSFileHelperPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - autoscaling:DescribeAutoScalingGroups - autoscaling:DescribeAutoScalingInstances - autoscaling:DescribePolicies - autoscaling:UpdateAutoScalingGroup Resource: '*' - Effect: Allow Action: - cloudwatch:GetMetricStatistics - cloudwatch:PutMetricAlarm - autoscaling:DescribeAutoScalingGroups - autoscaling:DescribeAutoScalingInstances - autoscaling:DescribePolicies - autoscaling:UpdateAutoScalingGroup - elasticfilesystem:DescribeFileSystems Resource: '*' - Effect: Allow Action: - sns:Publish Resource: !Ref SNSTopic AutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: Cooldown: 60 HealthCheckGracePeriod: 120 HealthCheckType: EC2 LaunchTemplate: LaunchTemplateId: !Ref LaunchTemplate Version: !GetAtt LaunchTemplate.LatestVersionNumber MaxSize: 1 MinSize: 0 DesiredCapacity: 1 Tags: - Key: Name Value: !Join [ '', [ 'Moodle EFS Helper ', !Ref 'ElasticFileSystem', ' ...will auto terminate' ] ] PropagateAtLaunch: true VPCZoneIdentifier: !If [ NumberOfSubnets1, [ !Select [ 0, !Ref Subnet ] ], !If [ NumberOfSubnets2, [ !Select [ 0, !Ref Subnet ], !Select [ 1, !Ref Subnet ] ], [ !Select [ 0, !Ref Subnet ], !Select [ 1, !Ref Subnet ], !Select [ 2, !Ref Subnet ] ] ] ] CreationPolicy: ResourceSignal: Count: 0 Timeout: PT12H UpdatePolicy: AutoScalingReplacingUpdate: WillReplace: true AutoScalingPolicy: Type: AWS::AutoScaling::ScalingPolicy Properties: AdjustmentType: ChangeInCapacity AutoScalingGroupName: !Ref AutoScalingGroup Cooldown: 60 PolicyType: SimpleScaling ScalingAdjustment: 1 BurstCreditBalanceDecreaseAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopic - !Ref AutoScalingPolicy AlarmDescription: !Join [ '', [ 'Set ', !Ref ElasticFileSystem, ' burst credit balance decrease threshold - ', !Ref 'AWS::StackName' ] ] AlarmName: !Join [ '', [ 'Set ', !Ref ElasticFileSystem, ' burst credit balance decrease threshold - ', !Ref 'AWS::StackName' ] ] ComparisonOperator: LessThanThreshold Dimensions: - Name: FileSystemId Value: !Ref ElasticFileSystem EvaluationPeriods: 10 MetricName: PermittedThroughput Namespace: AWS/EFS Period: 60 Statistic: Sum Threshold: 0 TreatMissingData: missing BurstCreditBalanceIncreaseAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopic - !Ref AutoScalingPolicy AlarmDescription: !Join [ '', [ 'Set ', !Ref ElasticFileSystem, ' burst credit balance increase threshold - ', !Ref 'AWS::StackName' ] ] AlarmName: !Join [ '', [ 'Set ', !Ref ElasticFileSystem, ' burst credit balance increase threshold - ', !Ref 'AWS::StackName' ] ] ComparisonOperator: LessThanThreshold Dimensions: - Name: FileSystemId Value: !Ref ElasticFileSystem EvaluationPeriods: 10 MetricName: PermittedThroughput Namespace: AWS/EFS Period: 60 Statistic: Sum Threshold: 0 TreatMissingData: missing CriticalAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopic AlarmDescription: !Join [ '', [ !Ref ElasticFileSystem, ' burst credit balance - Critical - ', !Ref 'AWS::StackName' ] ] AlarmName: !Join [ '', [ !Ref ElasticFileSystem, ' burst credit balance - Critical - ', !Ref 'AWS::StackName' ] ] ComparisonOperator: LessThanThreshold Dimensions: - Name: FileSystemId Value: !Ref ElasticFileSystem EvaluationPeriods: 10 MetricName: BurstCreditBalance Namespace: AWS/EFS Period: 60 Statistic: Sum Threshold: 0 TreatMissingData: missing LaunchTemplate: Type: AWS::EC2::LaunchTemplate Metadata: AWS::CloudFormation::Init: configSets: efs_add_storage: - efs-add-storage set_cloudwatch_alarms: - set-cloudwatch-alarms efs-add-storage: packages: yum: #Only needed to set permissions on the moodle folder httpd: [] 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 directories for Moodle sudo mkdir -p /$FILE_SYSTEM_ID/data sudo mkdir -p /$FILE_SYSTEM_ID/cache sudo mkdir -p /$FILE_SYSTEM_ID/temp chown apache:apache /$FILE_SYSTEM_ID/data/ chown apache:apache /$FILE_SYSTEM_ID/cache/ chown apache:apache /$FILE_SYSTEM_ID/temp/ # create data 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 set-cloudwatch-alarms: files: /tmp/set-cloudwatch-alarms.sh: content: !Join [ "",[ "#!/bin/bash -x\n", "\n", "FILE_SYSTEM_ID=$1\n", "WARNING_THRESHOLD_MINUTES=$2\n", "CRITICAL_THRESHOLD_MINUTES=$3\n", "SNS_ARN=$4\n", "\n", "error=0\n", "\n", "# get region\n", "availability_zone=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone)\n", "region=${availability_zone:0:-1}\n", "\n", "# get instance id\n", "instance_id=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)\n", "\n", "# get autoscaling group name\n", "asg_name=$(aws autoscaling describe-auto-scaling-instances --instance-ids ${instance_id} --region ${region} --output text --query 'AutoScalingInstances[0].AutoScalingGroupName')\n", "\n", "# get autoscaling policy arn\n", "asg_policy_arn=$(aws autoscaling describe-policies --auto-scaling-group-name ${asg_name} --region ${region} --output text --query 'ScalingPolicies[0].PolicyARN')\n", "\n", "# validate FILE_SYSTEM_ID send notification and exit if doesn't exist\n", "aws efs describe-file-systems --file-system-id ${FILE_SYSTEM_ID} --region ${region} --output text --query 'FileSystems[0].[FileSystemId]'\n", "result=$?\n", "if [ $result -ne 0 ]; then\n", " aws sns publish --topic-arn ${SNS_ARN} --region ${region} --message 'Amazon EFS burst credit balance CloudWatch alarm error. File system '${FILE_SYSTEM_ID}' does not exist.'\n", " exit\n", "fi\n", "\n", "# get current permitted throughput\n", "count=1\n", "while [ -z ${permitted_throughput} ] || [ ${permitted_throughput} == null ] && [ ${count} -lt 60 ]; do\n", " permitted_throughput=$(aws cloudwatch get-metric-statistics --namespace AWS/EFS --metric-name PermittedThroughput --dimensions Name=FileSystemId,Value=${FILE_SYSTEM_ID} --start-time $(date --utc +%FT%TZ -d '-120 seconds') --end-time $(date --utc +%FT%TZ -d '-60 seconds') --period 60 --statistics Sum --region ${region} --output json --query 'Datapoints[0].Sum')\n", " sleep 2\n", " count=$(expr ${count} + 1)\n", "done\n", "\n", "# get current burst credit balance\n", "count=1\n", "while [ -z ${burst_credit_balance} ] || [ ${burst_credit_balance} == null ] && [ ${count} -lt 60 ]; do\n", " burst_credit_balance=$(aws cloudwatch get-metric-statistics --namespace AWS/EFS --metric-name BurstCreditBalance --dimensions Name=FileSystemId,Value=${FILE_SYSTEM_ID} --start-time $(date --utc +%FT%TZ -d '-120 seconds') --end-time $(date --utc +%FT%TZ -d '-60 seconds') --period 60 --statistics Sum --region ${region} --output json --query 'Datapoints[0].Sum')\n", " sleep 2\n", " count=$(expr ${count} + 1)\n", "done\n", "\n", "# calculate new burst credit balance warning threshold\n", "burst_credit_balance_threshold_warning=$(( ${burst_credit_balance:0:-2} - ( ( ( ${burst_credit_balance:0:-2} / ( ${permitted_throughput:0:-2} * 60 ) ) - $WARNING_THRESHOLD_MINUTES ) * ( ${permitted_throughput:0:-2} * 60 ) ) ))\n", "\n", "# calculate new burst credit balance critical threshold\n", "burst_credit_balance_threshold_critical=$(( ${burst_credit_balance:0:-2} - ( ( ( ${burst_credit_balance:0:-2} / ( ${permitted_throughput:0:-2} * 60 ) ) - $CRITICAL_THRESHOLD_MINUTES ) * ( ${permitted_throughput:0:-2} * 60 ) ) ))\n", "\n", "# update warning alarm with new burst credit balance warning threshold\n", "aws cloudwatch put-metric-alarm --alarm-name ''${FILE_SYSTEM_ID}' burst credit balance - Warning - '", !Ref 'AWS::StackName', " --alarm-description ''${FILE_SYSTEM_ID}' burst credit balance - Warning - '", !Ref 'AWS::StackName', " --actions-enabled --alarm-actions ${SNS_ARN} --metric-name BurstCreditBalance --namespace AWS/EFS --statistic Sum --dimensions Name=FileSystemId,Value=${FILE_SYSTEM_ID} --period 60 --evaluation-periods 5 --threshold ${burst_credit_balance_threshold_warning} --comparison-operator LessThanThreshold --treat-missing-data missing --region ${region}\n", "result=$?\n", "if [ $result -ne 0 ]; then\n", " aws sns publish --topic-arn ${SNS_ARN} --region ${region} --message 'Amazon EFS burst credit balance CloudWatch alarm error. Check CloudWatch alarms for file system '${FILE_SYSTEM_ID}'.'\n", " error=$(expr ${error} + 1)\n", "fi\n", "\n", "# update critical alarm with new burst credit balance critical threshold\n", "aws cloudwatch put-metric-alarm --alarm-name ''${FILE_SYSTEM_ID}' burst credit balance - Critical - '", !Ref 'AWS::StackName', " --alarm-description ''${FILE_SYSTEM_ID}' burst credit balance - Critical - '", !Ref 'AWS::StackName', " --actions-enabled --alarm-actions ${SNS_ARN} --metric-name BurstCreditBalance --namespace AWS/EFS --statistic Sum --dimensions Name=FileSystemId,Value=${FILE_SYSTEM_ID} --period 60 --evaluation-periods 5 --threshold ${burst_credit_balance_threshold_critical} --comparison-operator LessThanThreshold --treat-missing-data missing --region ${region}\n", "result=$?\n", "if [ $result -ne 0 ]; then\n", " aws sns publish --topic-arn ${SNS_ARN} --region ${region} --message 'Amazon EFS burst credit balance CloudWatch alarm error. Check CloudWatch alarms for file system '${FILE_SYSTEM_ID}'.'\n", " error=$(expr ${error} + 1)\n", "fi\n", "\n", "# update burst credit balance increase threshold based\n", "aws cloudwatch put-metric-alarm --alarm-name 'Set '${FILE_SYSTEM_ID}' burst credit balance increase threshold - '", !Ref 'AWS::StackName', " --alarm-description 'Set '${FILE_SYSTEM_ID}' burst credit balance increase threshold - '", !Ref 'AWS::StackName', " --actions-enabled --alarm-actions ${SNS_ARN} ${asg_policy_arn} --metric-name PermittedThroughput --namespace AWS/EFS --statistic Sum --dimensions Name=FileSystemId,Value=${FILE_SYSTEM_ID} --period 60 --evaluation-periods 5 --threshold ${permitted_throughput:0:-2} --comparison-operator GreaterThanThreshold --treat-missing-data missing --region ${region}\n", "result=$?\n", "if [ $result -ne 0 ]; then\n", " aws sns publish --topic-arn ${SNS_ARN} --region ${region} --message 'Amazon EFS burst credit balance CloudWatch alarm error. Check CloudWatch alarms for file system '${FILE_SYSTEM_ID}'.'\n", " error=$(expr ${error} + 1)\n", "fi\n", "\n", "# update burst credit balance decrease threshold based\n", "aws cloudwatch put-metric-alarm --alarm-name 'Set '${FILE_SYSTEM_ID}' burst credit balance decrease threshold - '", !Ref 'AWS::StackName', " --alarm-description 'Set '${FILE_SYSTEM_ID}' burst credit balance decrease threshold - '", !Ref 'AWS::StackName', " --actions-enabled --alarm-actions ${SNS_ARN} ${asg_policy_arn} --metric-name PermittedThroughput --namespace AWS/EFS --statistic Sum --dimensions Name=FileSystemId,Value=${FILE_SYSTEM_ID} --period 60 --evaluation-periods 5 --threshold ${permitted_throughput:0:-2} --comparison-operator LessThanThreshold --treat-missing-data missing --region ${region}\n", "result=$?\n", "if [ $result -ne 0 ]; then\n", " aws sns publish --topic-arn ${SNS_ARN} --region ${region} --message 'Amazon EFS burst credit balance CloudWatch alarm error. Check CloudWatch alarms for file system '${FILE_SYSTEM_ID}'.'\n", " error=$(expr ${error} + 1)\n", "fi\n", "\n", "# auto terminate instance - setting auto scaling group desired capacity 0\n", "if [ $error -eq 0 ]; then\n", " aws autoscaling update-auto-scaling-group --auto-scaling-group-name ${asg_name} --desired-capacity 0 --region ${region}\n", " else\n", " aws sns publish --topic-arn ${SNS_ARN} --region ${region} --message 'Amazon EFS burst credit balance CloudWatch alarm error. Check CloudWatch alarms for file system '${FILE_SYSTEM_ID}'.'\n", "fi\n", "\n" ] ] mode: 000777 owner: root group: root Properties: LaunchTemplateData: BlockDeviceMappings: - DeviceName: /dev/xvda Ebs: DeleteOnTermination: true VolumeSize: 10 VolumeType: gp3 IamInstanceProfile: Arn: !GetAtt InstanceProfile.Arn ImageId: !If [UsingGraviton2Ami, !Ref LatestArmAmiId, !Ref LatestAmiId] Monitoring: Enabled: true InstanceType: !Ref InstanceType KeyName: !Ref EC2KeyName SecurityGroupIds: - !Ref SecurityGroup UserData: "Fn::Base64": !Sub | #!/bin/bash -xe sudo systemctl enable amazon-ssm-agent sudo systemctl start amazon-ssm-agent sudo systemctl status amazon-ssm-agent yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm yum-config-manager --enable epel yum install -y parallel /opt/aws/bin/cfn-init --configsets set_cloudwatch_alarms --verbose --stack ${AWS::StackName} --resource LaunchTemplate --region ${AWS::Region} /opt/aws/bin/cfn-init --configsets efs_add_storage --verbose --stack ${AWS::StackName} --resource LaunchTemplate --region ${AWS::Region} /tmp/efs-add-storage.sh ${ElasticFileSystem} throughput_data ${Growth} /tmp/set-cloudwatch-alarms.sh ${ElasticFileSystem} ${WarningThreshold} ${CriticalThreshold} ${SNSTopic} /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource AutoScalingGroup --region ${AWS::Region} EfsSizeMonitorFunction: DependsOn: LambdaRole Type: AWS::Lambda::Function Properties: Code: ZipFile: !Sub | import boto3 import os import sys def handler(event, context): if not os.environ.get('filesystemid'): print "Unable to get the environment variable filesystemid" sys.exit(1) else: filesystemid = os.environ.get('filesystemid') if not os.environ.get('region'): print "Unable to get the environment variable region" sys.exit(1) else: region = os.environ.get('region') def efs_get_size(): client = boto3.client('efs') response = client.describe_file_systems(FileSystemId=filesystemid) k = response['FileSystems'][0]['SizeInBytes']['Value'] return k def cloudwatch_put_metric(): client = boto3.client('cloudwatch') client.put_metric_data( MetricData=[ { 'MetricName': 'SizeInBytes', 'Dimensions': [ { 'Name': 'FileSystemId', 'Value': filesystemid }, ], 'Unit': 'None', 'Value': efs_get_size() }, ], Namespace='Custom/EFS' ) print('CloudWatch metric SizeInBytes sucessfully updated.') cloudwatch_put_metric() Description: Lambda function to update the SizeInBytes EFS CloudWatch metric Environment: Variables: filesystemid: !Ref ElasticFileSystem region: !Ref 'AWS::Region' FunctionName: !Join [ '', [ 'efs-', !Ref ElasticFileSystem, '-size-monitor' ] ] Handler: index.handler Role: !GetAtt LambdaRole.Arn Runtime: python3.9 Timeout: 60 LambdaRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: / ManagedPolicyArns: - arn:aws:iam::aws:policy/CloudWatchFullAccess - arn:aws:iam::aws:policy/AmazonElasticFileSystemReadOnlyAccess # EfsLambdaPermission: # Type: AWS::Lambda::Permission # Properties: # FunctionName: !Ref EfsSizeMonitorFunction # Action: lambda:InvokeFunction # Principal: events.amazonaws.com # SourceArn: !GetAtt EfsSizeMonitorEvent.Arn # EfsSizeMonitorEvent: # Type: AWS::Events::Rule # Properties: # Description: Scheduled event to update SizeInBytes EFS CloudWatch metric # Name: !Join [ '', [ 'efs-', !Ref ElasticFileSystem, '-size-monitor-scheduled-event' ] ] # ScheduleExpression: rate(1 minute) # State: ENABLED # Targets: # - Arn: !GetAtt EfsSizeMonitorFunction.Arn # Id: '1' SNSTopic: Type: AWS::SNS::Topic Properties: DisplayName: !Join [ '', [ !Ref ElasticFileSystem, '-alarm-notification' ] ] Subscription: - Endpoint: !Ref EmailAddress Protocol: "email" TopicName: !Join [ '', [ !Ref ElasticFileSystem, '-alarm-notification' ] ] WarningAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopic AlarmDescription: !Join [ '', [ !Ref ElasticFileSystem, ' burst credit balance - Warning - ', !Ref 'AWS::StackName' ] ] AlarmName: !Join [ '', [ !Ref ElasticFileSystem, ' burst credit balance - Warning - ', !Ref 'AWS::StackName' ] ] ComparisonOperator: LessThanThreshold Dimensions: - Name: FileSystemId Value: !Ref ElasticFileSystem EvaluationPeriods: 10 MetricName: BurstCreditBalance Namespace: AWS/EFS Period: 60 Statistic: Sum Threshold: 0 TreatMissingData: missing