예제 #1
0
    def add_alarm(self, description, metric, namespace, threshold, instance):
        """
        Adds an alarm to this sns topic. For this to be useful, subscriptions must be added to this topic
        using the add_subscription function above.
        :param description: A description for the Alarm being created
        :param metric: The metric to track and alarm on.
        :param namespace: the namespace that the provided metric belongs to.
        :param threshold: The threshold to alarm on
        :param instance: an instance to refer to in particular
        """

        alarm = cloudwatch.Alarm(
            '{0}Alarm{1}'.format(self.trop_topic.title, str(len(self.alarms))),
            AlarmDescription=description,
            AlarmActions=[Ref(self.trop_topic.title)],
            OKActions=[Ref(self.trop_topic.title)],
            MetricName=metric,
            Namespace=namespace,
            Threshold=threshold,
            ComparisonOperator="GreaterThanOrEqualToThreshold",
            EvaluationPeriods='1',
            Period='300',
            Statistic='Sum',
            DependsOn=self.trop_topic.title,
            Dimensions=[
                cloudwatch.MetricDimension(Name='InstanceId',
                                           Value=Ref(instance))
            ])

        self.alarms.append(alarm)
        self.template.add_resource(alarm)
예제 #2
0
def add_autorecovery_to_instance(template_obj, instance):
    """Creates a cloudwatch alarm to recover a failed instance."""
    # This url was really helpful in configuring this:
    #   http://docs.aws.amazon.com/ \
    #       AWSEC2/latest/UserGuide/UsingAlarmActions.html
    template_obj.add_resource(
        cloudwatch.Alarm(
            'InstanceAutoRecovery%s' % (instance.name, ),
            ActionsEnabled='true',
            AlarmActions=[
                Join('',
                     ['arn:aws:automate:',
                      Ref('AWS::Region'), ':ec2:recover'])
            ],
            AlarmDescription='Recover failed instance',
            ComparisonOperator='GreaterThanThreshold',
            Dimensions=[
                cloudwatch.MetricDimension(Name='InstanceId',
                                           Value=Ref(instance))
            ],
            EvaluationPeriods=2,
            MetricName='StatusCheckFailed_System',
            Namespace='AWS/EC2',
            Period=60,
            Statistic='Average',
            Threshold='0',
        ))
예제 #3
0
    def add_resource(self):
        """Add resources to template."""
        template = self.template
        variables = self.get_variables()

        template.add_resource(
            cloudwatch.Alarm(
                'CloudWatchAlarm',
                AlarmActions=[
                    Join(':', [
                        'arn:aws:automate',
                        Ref('AWS::Region'), 'ec2:recover'
                    ])
                ],
                AlarmDescription='Trigger a recovery when the instance'
                ' status check fails for 15 consecutive'
                ' minutes.',
                AlarmName=variables['AlarmName'].ref,
                ComparisonOperator='GreaterThanThreshold',
                Dimensions=[
                    cloudwatch.MetricDimension(
                        Name='InstanceId', Value=variables['InstanceId'].ref)
                ],
                EvaluationPeriods=15,
                MetricName='EC2_SystemStatusCheck_Failed',
                Namespace='AWS/EC2',
                Period=60,
                Statistic='Minimum',
                Threshold='0',
            ))
예제 #4
0
    def _build_alarm(self, template, topics):

        t = template

        elb_name = self.elb_stack.stack_name

        elb_output = self.elb_stack.output_elb()

        if elb_output in t.parameters:
            elb_ref = Ref(t.parameters[elb_output])
        else:
            elb_ref = Ref(t.add_parameter(Parameter(elb_output,
                                                    Type='String')))

        t.add_resource(
            alarm.Alarm('{}HealthHosts'.format(elb_name),
                        AlarmDescription='{} Health Hosts'.format(elb_name),
                        MetricName='HealthyHostCount',
                        Namespace='AWS/ELB',
                        Statistic='Average',
                        Period=str(60),
                        Dimensions=[
                            alarm.MetricDimension(Name='LoadBalancerName',
                                                  Value=elb_ref)
                        ],
                        EvaluationPeriods=str(3),
                        Threshold=str(2),
                        ComparisonOperator='LessThanThreshold',
                        AlarmActions=topics,
                        InsufficientDataActions=[],
                        OKActions=topics,
                        TreatMissingData='missing'))
예제 #5
0
    def _build_alarm(self, template, topics):

        instance_output = self.ec2_stack.output_instance()

        if instance_output in template.parameters:
            instance_param = template.parameters[instance_output]
        else:
            instance_param = template.add_parameter(
                Parameter(instance_output, Type='String'))

        template.add_resource(
            alarm.Alarm(
                '{}InstanceFailAlarm'.format(self.ec2_stack.get_stack_name()),
                AlarmDescription='Alarm for instance failure',
                Namespace='AWS/EC2',
                MetricName="StatusCheckFailed_System",
                Dimensions=[
                    alarm.MetricDimension(Name="InstanceId",
                                          Value=Ref(instance_param))
                ],
                Statistic="Average",
                Period=str(self.alarm_params['period']),
                Threshold=str(self.alarm_params['threshold']),
                EvaluationPeriods=str(self.alarm_params['evaluations']),
                ComparisonOperator="GreaterThanThreshold",
                AlarmActions=topics,
                InsufficientDataActions=topics,
                OKActions=topics))
예제 #6
0
    def _build_alarm(self, t, topics):

        defaults = self.get_defaults()
        default_attrs = self.get_default_attrs()

        instance_output = self.ec2_stack.output_instance()

        if instance_output in t.parameters:
            instance_param = t.parameters[instance_output]
        else:
            instance_param = t.add_parameter(
                Parameter(instance_output, Type='String'))

        a = t.add_resource(
            alarm.Alarm(
                '{}EC2HighCpuAlarm'.format(self.name),
                AlarmDescription='Alarm for high CPU (>{})'.format(
                    defaults['threshold']),
                Period=str(defaults['period']),
                Threshold=str(defaults['threshold']),
                EvaluationPeriods=str(defaults['evaluations']),
                AlarmActions=topics,
                InsufficientDataActions=topics,
                OKActions=topics,
                Dimensions=[
                    alarm.MetricDimension(Name='InstanceId',
                                          Value=Ref(instance_param))
                ],
            ))

        for k, v in default_attrs.items():
            setattr(a, k, v)
예제 #7
0
    def create_elasticache_cloudwatch_alarms(self, elasticache_cache_cluster):
        for index in [1, 2]:
            self.add_resource(
                cloudwatch.Alarm(
                    'alarmCacheCluster{0:0>3}CPUUtilization'.format(index),
                    AlarmDescription='Cache cluster CPU utilization',
                    AlarmActions=[Ref(self.notification_topic_arn)],
                    Statistic='Average',
                    Period=300,
                    Threshold='75',
                    EvaluationPeriods=1,
                    ComparisonOperator='GreaterThanThreshold',
                    MetricName='CPUUtilization',
                    Namespace='AWS/ElastiCache',
                    Dimensions=[
                        cloudwatch.MetricDimension(
                            'metricCacheClusterName',
                            Name='CacheClusterId',
                            Value=Join('-', [
                                Ref(elasticache_cache_cluster),
                                '{0:0>3}'.format(index)
                            ]))
                    ],
                ))

            self.add_resource(
                cloudwatch.Alarm(
                    'alarmCacheCluster{0:0>3}FreeableMemory'.format(index),
                    AlarmDescription='Cache cluster freeable memory',
                    AlarmActions=[Ref(self.notification_topic_arn)],
                    Statistic='Average',
                    Period=60,
                    Threshold=str(int(5e+06)),  # 5MB in bytes
                    EvaluationPeriods=1,
                    ComparisonOperator='LessThanThreshold',
                    MetricName='FreeableMemory',
                    Namespace='AWS/ElastiCache',
                    Dimensions=[
                        cloudwatch.MetricDimension(
                            'metricCacheClusterName',
                            Name='CacheClusterId',
                            Value=Join('-', [
                                Ref(elasticache_cache_cluster),
                                '{0:0>3}'.format(index)
                            ]))
                    ],
                ))
예제 #8
0
    def __init__(self, key):
        for n, v in getattr(cfg, key).items():
            if not ('Enabled' in v and v['Enabled'] is True):
                continue
            resname = f'{key}{n}'
            # parameters
            p_EvaluationPeriods = Parameter(f'{resname}EvaluationPeriods')
            p_EvaluationPeriods.Description = (
                'Number of periods for alarm evaluation - 0 to disable - '
                'empty for default based on env/role')
            p_EvaluationPeriods.AllowedValues = [
                '', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
            ]

            p_Period = Parameter(f'{resname}Period')
            p_Period.Description = (
                'Period lenght in seconds (multiple of 60) - '
                'empty for default based on env/role')
            p_Period.AllowedValues = ['', '60', '120', '180', '240', '300']

            p_Threshold = Parameter(f'{resname}Threshold')
            p_Threshold.Description = ('Threshold for alarm triggering - '
                                       'empty for default based on env/role')
            p_Threshold.AllowedValues = [
                '', '10', '15', '20', '25', '30', '35', '40', '45', '50', '55',
                '60', '65', '70', '75', '80', '85', '90', '95', '100'
            ]

            add_obj([
                p_EvaluationPeriods,
                # p_Period,
                p_Threshold,
            ])

            # conditions
            c_EvaluationPeriods = get_condition(resname, 'not_equals', '0',
                                                f'{resname}EvaluationPeriods')

            add_obj(c_EvaluationPeriods)

            # resources
            r_Alarm = clw.Alarm(resname)
            auto_get_props(r_Alarm, v, recurse=True)
            if hasattr(r_Alarm, 'Metrics'):
                r_Alarm.Period = Ref('AWS::NoValue')
            if not hasattr(r_Alarm, 'Condition'):
                r_Alarm.Condition = resname

            add_obj(r_Alarm)

            # outputs
            o_Alarm = Output(resname)
            o_Alarm.Value = get_subvalue(
                'Period=${1M},EvaluationPeriods=${2M},Threshold=${3M}', [
                    f'{resname}Period', f'{resname}EvaluationPeriods',
                    f'{resname}Threshold'
                ])

            add_obj(o_Alarm)
예제 #9
0
    def create_cloud_watch_resources(self, app_server_lb):
        self.add_resource(cw.Alarm(
            'alarmAppServerBackend4XX',
            AlarmDescription='Application server backend 4XXs',
            AlarmActions=[Ref(self.notification_topic_arn)],
            Statistic='Sum',
            Period=300,
            Threshold='20',
            EvaluationPeriods=1,
            ComparisonOperator='GreaterThanThreshold',
            MetricName='HTTPCode_Backend_4XX',
            Namespace='AWS/ELB',
            Dimensions=[
                cw.MetricDimension(
                    'metricLoadBalancerName',
                    Name='LoadBalancerName',
                    Value=Ref(app_server_lb)
                )
            ],
        ))

        self.add_resource(cw.Alarm(
            'alarmAppServerBackend5XX',
            AlarmDescription='Application server backend 5XXs',
            AlarmActions=[Ref(self.notification_topic_arn)],
            Statistic='Sum',
            Period=60,
            Threshold='0',
            EvaluationPeriods=1,
            ComparisonOperator='GreaterThanThreshold',
            MetricName='HTTPCode_Backend_5XX',
            Namespace='AWS/ELB',
            Dimensions=[
                cw.MetricDimension(
                    'metricLoadBalancerName',
                    Name='LoadBalancerName',
                    Value=Ref(app_server_lb)
                )
            ],
        ))
예제 #10
0
 def add_alarm(self, name, dimensions, alarm, description, namespace,
               threshold, comparison_operator, statistic, metric_name):
     return self.add_resource(
         cloudwatch.Alarm(name,
                          MetricName=metric_name,
                          ComparisonOperator=comparison_operator,
                          Period=300,
                          EvaluationPeriods=1,
                          Statistic=statistic,
                          Namespace=namespace,
                          AlarmDescription=description,
                          Dimensions=dimensions,
                          Threshold=threshold,
                          AlarmActions=[alarm]))
예제 #11
0
 def add_cpu_usage_alarm_ondemand_high(self):
     self.CPUUsageAlarmHighOndemand = self.template.add_resource(
         cloudwatch.Alarm(
             "CPUUsageAlarmHighOndemand",
             AlarmDescription="Alarm if CPUUtilization go above 60%",
             Namespace="AWS/EC2",
             MetricName="CPUUtilization",
             Dimensions=[
                 cloudwatch.MetricDimension(
                     Name="AutoScalingGroupName",
                     Value=Ref(self.AutoscalingGroupOnDemand)),
             ],
             Statistic="Average",
             Period="300",
             EvaluationPeriods="2",
             Threshold="60",
             ComparisonOperator="GreaterThanOrEqualToThreshold",
             AlarmActions=[Ref(self.scalingPolicyOndemandUp)]))
예제 #12
0
 def add_cpu_usage_alarm_ondemand_low(self):
     self.CPUUsageAlarmLowOndemand = self.template.add_resource(
         cloudwatch.Alarm(
             "CPUUsageAlarmLowOndemand",
             AlarmDescription="Alarm if CPUUtilization go below 5%",
             Namespace="AWS/EC2",
             MetricName="CPUUtilization",
             Dimensions=[
                 cloudwatch.MetricDimension(
                     Name="AutoScalingGroupName",
                     Value=Ref(self.AutoscalingGroupOnDemand)),
             ],
             Statistic="Average",
             Period="300",
             EvaluationPeriods="1",
             Threshold="5",
             ComparisonOperator="LessThanThreshold",
             AlarmActions=[Ref(self.scalingPolicyOndemandDown)]))
예제 #13
0
 def add_cpu_credit_balance_ondemand_low(self):
     self.CPUCreditAlarmLowOndemand = self.template.add_resource(
         cloudwatch.Alarm(
             "CPUCreditAlarmLowOndemand",
             AlarmDescription="Alarm if CPU Credits go below 10",
             Namespace="AWS/EC2",
             MetricName="CPUCreditBalance",
             Dimensions=[
                 cloudwatch.MetricDimension(
                     Name="AutoScalingGroupName",
                     Value=Ref(self.AutoscalingGroupOnDemand)),
             ],
             Statistic="Average",
             Period="60",
             EvaluationPeriods="10",
             Threshold="10",
             ComparisonOperator="LessThanThreshold",
             AlarmActions=[Ref(self.scalingPolicyOndemandUp)]))
예제 #14
0
 def create_cloud_watch_resources(self, worker_auto_scaling_group):
     self.add_resource(
         cw.Alarm('alarmWorkerCPU',
                  AlarmDescription='Worker scaling group high CPU',
                  AlarmActions=[Ref(self.notification_topic_arn)],
                  Statistic='Average',
                  Period=300,
                  Threshold='50',
                  EvaluationPeriods=1,
                  ComparisonOperator='GreaterThanThreshold',
                  MetricName='CPUUtilization',
                  Namespace='AWS/EC2',
                  Dimensions=[
                      cw.MetricDimension(
                          'metricAutoScalingGroupName',
                          Name='AutoScalingGroupName',
                          Value=Ref(worker_auto_scaling_group))
                  ]))
def _inject_alarms(template, packages):
    for package in packages:
        cannot_package_alarm = cloudwatch.Alarm(
            'CannotPackage%s' % package,
            AlarmDescription=(
                'Alarm that triggers if Chalice fails to package %s.' % package
            ),
            ComparisonOperator='LessThanThreshold',
            EvaluationPeriods=1,
            Period=3600,
            MetricName='package',
            Namespace='ChalicePackageCanary',
            Threshold='1',
            Statistic='Minimum',
            Dimensions=[cloudwatch.MetricDimension(
                Name='Name',
                Value=package
            )]
        )
        template.add_resource(cannot_package_alarm)
예제 #16
0
    def add_resources(self):
        """Add resources to template."""
        template = self.template
        variables = self.get_variables()

        template.add_resource(
            cloudwatch.Alarm(
                'Alarm',
                AlarmDescription=If(
                    'AlarmDescriptionSpecified',
                    variables['AlarmDescription'].ref,
                    Ref('AWS::NoValue')
                ),
                AlarmName=If(
                    'AlarmNameSpecified',
                    variables['AlarmName'].ref,
                    Ref('AWS::NoValue')
                ),
                Namespace=variables['Namespace'].ref,
                Statistic=variables['Statistic'].ref,
                Period=variables['StatisticPeriod'].ref,
                EvaluationPeriods=variables['EvaluationPeriods'].ref,
                Threshold=variables['AlarmThreshold'].ref,
                AlarmActions=variables['AlertTopicArn'].ref,
                OKActions=variables['AlertTopicArn'].ref,
                ComparisonOperator=variables['ComparisonOperator'].ref,
                Dimensions=If(
                    'MetricDimensionSpecified',
                    [cloudwatch.MetricDimension(
                        Name=variables['DimensionName'].ref,
                        Value=variables['DimensionValue'].ref)],
                    Ref('AWS::NoValue')),
                MetricName=variables['MetricName'].ref,
                TreatMissingData=If(
                    'TreatMissingDataSpecified',
                    variables['TreatMissingData'].ref,
                    Ref('AWS::NoValue')
                )
            )
        )
t.add_description(
    "A set of serverless Lambda functions that shut down services that exceed"
    " billing limits. **WARNING** This template creates Lambda functions and "
    "Amazon CloudWatch alarms. You will be billed for the AWS resources used "
    "if you create a stack from this template.")

if ALL_SERVICES_BILLING_ALARM_LIMIT:

    exceed_billing_limit_alarm = t.add_resource(
        cloudwatch.Alarm(
            'AllServicesBillingAlarm',
            AlarmDescription='Alarm if all services exceed billing limit',
            Namespace='AWS/Billing',
            MetricName='EstimatedCharges',
            Dimensions=[
                cloudwatch.MetricDimension(Name='Currency', Value='USD'),
            ],
            Statistic='Maximum',
            Period='300',
            EvaluationPeriods='1',
            Threshold=str(ALL_SERVICES_BILLING_ALARM_LIMIT),
            ComparisonOperator='GreaterThanThreshold',
            #AlarmActions=Ref('BillingAlarmNotification'),
            #InsufficientDataActions=Ref('BillingAlarmNotification'),
        ))

print(t.to_yaml())

#with open('aws_kill_switch_cloudfront.yaml', 'w') as f:
#    f.write(t.to_yaml())
예제 #18
0
    def __init__(self, parameters, vpc, loadbalancer):
        """
        :type parameters Parameters
        :type vpc VPC
        :type loadbalancer LoadBalancer
        """
        super(EC2, self).__init__()

        # Ec2 instance
        self.instance_role = iam.Role(
            "InstanceRole",
            AssumeRolePolicyDocument=aws.Policy(Statement=[
                aws.Statement(Effect=aws.Allow,
                              Action=[sts.AssumeRole],
                              Principal=aws.Principal("Service",
                                                      ["ec2.amazonaws.com"]))
            ]),
            Path="/",
        )

        self.instance_role_policy = iam.PolicyType(
            "InstanceRolePolicy",
            PolicyName=Join("-", [Ref("AWS::StackName"), "instance-policy"]),
            PolicyDocument=aws.Policy(Statement=[
                aws.Statement(Effect=aws.Allow,
                              Action=[
                                  aws.Action("logs", "CreateLogGroup"),
                                  aws.Action("logs", "CreateLogStream"),
                                  aws.Action("logs", "PutLogEvents"),
                                  aws.Action("logs", "DescribeLogStreams"),
                              ],
                              Resource=["arn:aws:logs:*:*:*"])
            ]),
            Roles=[Ref(self.instance_role)])

        self.instance_profile = iam.InstanceProfile(
            "InstanceProfile", Path="/", Roles=[Ref(self.instance_role)])

        self.launch_configuration = autoscaling.LaunchConfiguration(
            "LaunchConfiguration",
            ImageId=FindInMap("AMIMap", Ref(AWS_REGION), "AMI"),
            InstanceType=Ref(parameters.ec2_instance_type),
            KeyName=Ref(parameters.key_pair),
            InstanceMonitoring=True,
            SecurityGroups=[
                GetAtt(loadbalancer.instance_security_group, "GroupId"),
            ],
            IamInstanceProfile=Ref(self.instance_profile),
        )

        self.auto_scaling_group = autoscaling.AutoScalingGroup(
            "AutoScalingGroup",
            LaunchConfigurationName=Ref(self.launch_configuration),
            MinSize=1,
            DesiredCapacity=1,
            MaxSize=10,
            HealthCheckType='ELB',
            HealthCheckGracePeriod=300,
            VPCZoneIdentifier=[
                Ref(vpc.public_subnet_1),
                Ref(vpc.public_subnet_2)
            ],
            LoadBalancerNames=[Ref(loadbalancer.load_balancer)],
            Tags=[autoscaling.Tag("Name", Ref("AWS::StackName"), True)],
            UpdatePolicy=policies.UpdatePolicy(
                AutoScalingRollingUpdate=policies.AutoScalingRollingUpdate(
                    PauseTime="PT30S",
                    MinInstancesInService=1,
                    MaxBatchSize=10,
                    WaitOnResourceSignals=False)),
            TerminationPolicies=[
                'OldestLaunchConfiguration', 'ClosestToNextInstanceHour',
                'Default'
            ],
            MetricsCollection=[
                autoscaling.MetricsCollection(Granularity="1Minute")
            ])

        self.scale_up_policy = autoscaling.ScalingPolicy(
            "ScaleUPPolicy",
            AdjustmentType='ChangeInCapacity',
            AutoScalingGroupName=Ref(self.auto_scaling_group),
            PolicyType='StepScaling',
            MetricAggregationType='Average',
            StepAdjustments=[
                autoscaling.StepAdjustments(MetricIntervalLowerBound=0,
                                            ScalingAdjustment=1)
            ],
        )

        self.scale_down_policy = autoscaling.ScalingPolicy(
            "ScaleDOWNPolicy",
            AdjustmentType='ChangeInCapacity',
            AutoScalingGroupName=Ref(self.auto_scaling_group),
            PolicyType='StepScaling',
            MetricAggregationType='Average',
            StepAdjustments=[
                autoscaling.StepAdjustments(MetricIntervalUpperBound=0,
                                            ScalingAdjustment=-1)
            ],
        )

        self.ec2_high_cpu_usage_alarm = cloudwatch.Alarm(
            "EC2HighCPUUsageAlarm",
            ActionsEnabled=True,
            AlarmActions=[Ref(self.scale_up_policy)],
            ComparisonOperator='GreaterThanThreshold',
            Dimensions=[
                cloudwatch.MetricDimension(Name='AutoScalingGroupName',
                                           Value=Ref(self.auto_scaling_group))
            ],
            EvaluationPeriods=3,
            MetricName='CPUUtilization',
            Namespace='AWS/EC2',
            Period=300,
            Statistic='Average',
            Threshold='70',
        )

        self.ec2_low_cpu_usage_alarm = cloudwatch.Alarm(
            "EC2LowCPUUsageAlarm",
            ActionsEnabled=True,
            AlarmActions=[Ref(self.scale_down_policy)],
            ComparisonOperator='LessThanThreshold',
            Dimensions=[
                cloudwatch.MetricDimension(Name='AutoScalingGroupName',
                                           Value=Ref(self.auto_scaling_group))
            ],
            EvaluationPeriods=3,
            MetricName='CPUUtilization',
            Namespace='AWS/EC2',
            Period=300,
            Statistic='Average',
            Threshold='20',
        )
    route53.HealthCheck('MainDomainCheck',
                        HealthCheckConfig=route53.HealthCheckConfiguration(
                            EnableSNI=True,
                            FullyQualifiedDomainName=Ref(main_domain),
                            Port='443',
                            Type='HTTPS')))

main_domain_alarm = template.add_resource(
    cloudwatch.Alarm(
        'MainDomainAlarm',
        AlarmActions=[Ref(notifications)],
        AlarmDescription=Join(
            '', ['Health check for ', Ref(main_domain)]),
        ComparisonOperator='LessThanThreshold',
        Dimensions=[
            cloudwatch.MetricDimension(Name='HealthCheckId',
                                       Value=Ref(main_domain_check))
        ],
        EvaluationPeriods=1,
        MetricName='HealthCheckStatus',
        Namespace='AWS/Route53',
        OKActions=[Ref(notifications)],
        Period=60,  # seconds
        Statistic='Minimum',
        Threshold='1.0',
    ))
# endregion

if __name__ == '__main__':
    print(template.to_json())
예제 #20
0
    def create_rds_cloudwatch_alarms(self, rds_database):
        self.add_resource(
            cloudwatch.Alarm(
                'alarmDatabaseServerCPUUtilization',
                AlarmDescription='Database server CPU utilization',
                AlarmActions=[Ref(self.notification_topic_arn)],
                Statistic='Average',
                Period=300,
                Threshold='75',
                EvaluationPeriods=1,
                ComparisonOperator='GreaterThanThreshold',
                MetricName='CPUUtilization',
                Namespace='AWS/RDS',
                Dimensions=[
                    cloudwatch.MetricDimension('metricDatabaseServerName',
                                               Name='DBInstanceIdentifier',
                                               Value=Ref(rds_database))
                ],
            ))

        self.add_resource(
            cloudwatch.Alarm(
                'alarmDatabaseServerDiskQueueDepth',
                AlarmDescription='Database server disk queue depth',
                AlarmActions=[Ref(self.notification_topic_arn)],
                Statistic='Average',
                Period=60,
                Threshold='10',
                EvaluationPeriods=1,
                ComparisonOperator='GreaterThanThreshold',
                MetricName='DiskQueueDepth',
                Namespace='AWS/RDS',
                Dimensions=[
                    cloudwatch.MetricDimension('metricDatabaseServerName',
                                               Name='DBInstanceIdentifier',
                                               Value=Ref(rds_database))
                ],
            ))

        self.add_resource(
            cloudwatch.Alarm(
                'alarmDatabaseServerFreeStorageSpace',
                AlarmDescription='Database server free storage space',
                AlarmActions=[Ref(self.notification_topic_arn)],
                Statistic='Average',
                Period=60,
                Threshold=str(int(5.0e+09)),  # 5GB in bytes
                EvaluationPeriods=1,
                ComparisonOperator='LessThanThreshold',
                MetricName='FreeStorageSpace',
                Namespace='AWS/RDS',
                Dimensions=[
                    cloudwatch.MetricDimension('metricDatabaseServerName',
                                               Name='DBInstanceIdentifier',
                                               Value=Ref(rds_database))
                ],
            ))

        self.add_resource(
            cloudwatch.Alarm(
                'alarmDatabaseServerFreeableMemory',
                AlarmDescription='Database server freeable memory',
                AlarmActions=[Ref(self.notification_topic_arn)],
                Statistic='Average',
                Period=60,
                Threshold=str(int(1.28e+08)),  # 128MB in bytes
                EvaluationPeriods=1,
                ComparisonOperator='LessThanThreshold',
                MetricName='FreeableMemory',
                Namespace='AWS/RDS',
                Dimensions=[
                    cloudwatch.MetricDimension('metricDatabaseServerName',
                                               Name='DBInstanceIdentifier',
                                               Value=Ref(rds_database))
                ],
            ))
예제 #21
0
    def set_up_stack(self):
        """Sets up the stack"""
        if not self.INPUTS or not self.STACK_NAME_PREFIX or not self.HEALTH_ENDPOINT:
            raise MKInputError(
                'Must define INPUTS, STACK_NAME_PREFIX, and HEALTH_ENDPOINT')

        super(AppServerStack, self).set_up_stack()

        tags = self.get_input('Tags').copy()
        self.add_description('{} App Server Stack for Cac'.format(
            self.STACK_NAME_PREFIX))

        assert isinstance(tags, dict), 'tags must be a dictionary'

        self.availability_zones = get_availability_zones()

        tags.update({'StackType': 'AppServer'})
        self.default_tags = tags

        self.app_server_instance_type_parameter = self.add_parameter(
            Parameter(
                'AppServerInstanceType',
                Type='String',
                Default='t2.medium',
                Description='NAT EC2 instance type',
                AllowedValues=EC2_INSTANCE_TYPES,
                ConstraintDescription='must be a valid EC2 instance type.'),
            source='AppServerInstanceType')

        self.param_app_server_iam_profile = self.add_parameter(
            Parameter('AppServerIAMProfile',
                      Type='String',
                      Description='IAM Profile for instances'),
            source='AppServerIAMProfile')

        self.app_server_ami = self.add_parameter(Parameter(
            'AppServerAMI',
            Type='String',
            Description='{} Server EC2 AMI'.format(self.STACK_NAME_PREFIX)),
                                                 source='AppServerAMI')

        self.keyname_parameter = self.add_parameter(Parameter(
            'KeyName',
            Type='String',
            Default='cac',
            Description='Name of an existing EC2 key pair'),
                                                    source='KeyName')

        self.param_color = self.add_parameter(Parameter(
            'StackColor',
            Type='String',
            Description='Stack color',
            AllowedValues=['Blue', 'Green', 'Orange']),
                                              source='StackColor')

        self.param_stacktype = self.add_parameter(Parameter(
            'StackType',
            Type='String',
            Description='Stack type',
            AllowedValues=['Development', 'Staging', 'Production']),
                                                  source='StackType')

        self.param_public_hosted_zone_name = self.add_parameter(
            Parameter('PublicHostedZoneName',
                      Type='String',
                      Description='Public hosted zone name'),
            source='PublicHostedZoneName')

        self.param_vpc = self.add_parameter(Parameter(
            'VpcId', Type='String', Description='Name of an existing VPC'),
                                            source='VpcId')

        self.param_notification_arn = self.add_parameter(
            Parameter(
                'GlobalNotificationsARN',
                Type='String',
                Description='Physical resource ID on an AWS::SNS::Topic for '
                'notifications'),
            source='GlobalNotificationsARN')

        self.param_ssl_certificate_arn = self.add_parameter(
            Parameter('SSLCertificateARN',
                      Type='String',
                      Description=
                      'Physical resource ID on an AWS::IAM::ServerCertificate '
                      'for the application server load balancer'),
            source='SSLCertificateARN')

        self.param_public_subnets = self.add_parameter(
            Parameter('PublicSubnets',
                      Type='CommaDelimitedList',
                      Description='A list of public subnets'),
            source='AppServerPublicSubnets')

        self.param_private_subnets = self.add_parameter(
            Parameter('PrivateSubnets',
                      Type='CommaDelimitedList',
                      Description='A list of private subnets'),
            source='AppServerPrivateSubnets')

        self.param_bastion_security_group = self.add_parameter(
            Parameter('BastionSecurityGroup',
                      Type='String',
                      Description='The ID of the bastion security group'),
            source='BastionSecurityGroup')

        self.param_database_security_group = self.add_parameter(
            Parameter('DatabaseSecurityGroup',
                      Type='String',
                      Description='The ID of the database security group'),
            source='DatabaseSecurityGroup')

        self.param_nat_security_group = self.add_parameter(
            Parameter('NATSecurityGroup',
                      Type='String',
                      Description='The ID of the NAT security group'),
            source='NATSecurityGroup')

        self.param_min_size = self.add_parameter(Parameter(
            'ASGMinSize',
            Type='Number',
            Default='1',
            Description='Min size of ASG'),
                                                 source='ASGMinSize')

        self.param_max_size = self.add_parameter(Parameter(
            'ASGMaxSize',
            Type='Number',
            Default='1',
            Description='Max size of ASG'),
                                                 source='ASGMaxSize')

        self.param_desired_capacity = self.add_parameter(
            Parameter('ASGDesiredCapacity',
                      Type='Number',
                      Default='1',
                      Description='Desired capacity of ASG'),
            source='ASGDesiredCapacity')

        #
        # Security Group
        #
        app_server_load_balancer_security_group = self.add_resource(
            ec2.SecurityGroup(
                'sgAppServerLoadBalancer',
                GroupDescription=
                'Enables access to app servers via a load balancer',
                VpcId=Ref(self.param_vpc),
                SecurityGroupIngress=[
                    ec2.SecurityGroupRule(IpProtocol='tcp',
                                          CidrIp=ALLOW_ALL_CIDR,
                                          FromPort=p,
                                          ToPort=p) for p in [80, 443]
                ],
                Tags=Tags(Name='sgAppServerLoadBalancer',
                          Color=Ref(self.param_color))))

        app_server_security_group = self.add_resource(
            ec2.SecurityGroup(
                'sgAppServer',
                GroupDescription='Enables access to App Servers',
                VpcId=Ref(self.param_vpc),
                SecurityGroupIngress=[
                    ec2.SecurityGroupRule(IpProtocol='tcp',
                                          CidrIp=VPC_CIDR,
                                          FromPort=p,
                                          ToPort=p) for p in [22, 80, 443]
                ] + [
                    ec2.SecurityGroupRule(IpProtocol='tcp',
                                          SourceSecurityGroupId=Ref(sg),
                                          FromPort=80,
                                          ToPort=80)
                    for sg in [app_server_load_balancer_security_group]
                ] + [
                    ec2.SecurityGroupRule(IpProtocol='tcp',
                                          SourceSecurityGroupId=Ref(sg),
                                          FromPort=443,
                                          ToPort=443)
                    for sg in [app_server_load_balancer_security_group]
                ],
                SecurityGroupEgress=[
                    ec2.SecurityGroupRule(IpProtocol='tcp',
                                          CidrIp=ALLOW_ALL_CIDR,
                                          FromPort=p,
                                          ToPort=p)
                    for p in [80, 443, PAPERTRAIL_PORT]
                ],
                Tags=Tags(Name='sgAppServer', Color=Ref(self.param_color))))

        # ELB to App Server
        self.add_resource(
            ec2.SecurityGroupEgress(
                'sgEgressELBtoAppHTTP',
                GroupId=Ref(app_server_load_balancer_security_group),
                DestinationSecurityGroupId=Ref(app_server_security_group),
                IpProtocol='tcp',
                FromPort=80,
                ToPort=80))

        self.add_resource(
            ec2.SecurityGroupEgress(
                'sgEgressELBtoAppHTTPS',
                GroupId=Ref(app_server_load_balancer_security_group),
                DestinationSecurityGroupId=Ref(app_server_security_group),
                IpProtocol='tcp',
                FromPort=443,
                ToPort=443))

        # Bastion to App Server, app server to db, app server to inet
        rules = [(self.param_bastion_security_group, app_server_security_group,
                  [80, 443, 22]),
                 (app_server_security_group,
                  self.param_database_security_group, [POSTGRES]),
                 (app_server_security_group, self.param_nat_security_group,
                  [80, 443, 22, 587, PAPERTRAIL_PORT])]
        for num, (srcsg, destsg, ports) in enumerate(rules):
            for port in ports:
                self.add_resource(
                    ec2.SecurityGroupEgress(
                        'sgEgress{}p{}'.format(num, port),
                        GroupId=Ref(srcsg),
                        DestinationSecurityGroupId=Ref(destsg),
                        IpProtocol='tcp',
                        FromPort=port,
                        ToPort=port))
                self.add_resource(
                    ec2.SecurityGroupIngress('sgIngress{}p{}'.format(
                        num, port),
                                             GroupId=Ref(destsg),
                                             SourceSecurityGroupId=Ref(srcsg),
                                             IpProtocol='tcp',
                                             FromPort=port,
                                             ToPort=port))

        #
        # ELB
        #
        app_server_load_balancer = self.add_resource(
            elb.LoadBalancer(
                'elbAppServer',
                ConnectionDrainingPolicy=elb.ConnectionDrainingPolicy(
                    Enabled=True, Timeout=300),
                CrossZone=True,
                SecurityGroups=[Ref(app_server_load_balancer_security_group)],
                Listeners=[
                    elb.Listener(LoadBalancerPort='80',
                                 Protocol='HTTP',
                                 InstancePort='80',
                                 InstanceProtocol='HTTP'),
                    elb.Listener(LoadBalancerPort='443',
                                 Protocol='HTTPS',
                                 InstancePort='443',
                                 InstanceProtocol='HTTP',
                                 SSLCertificateId=Ref(
                                     self.param_ssl_certificate_arn))
                ],
                HealthCheck=elb.HealthCheck(
                    Target=self.HEALTH_ENDPOINT,
                    HealthyThreshold='3',
                    UnhealthyThreshold='2',
                    Interval='30',
                    Timeout='5',
                ),
                Subnets=Ref(self.param_public_subnets),
                Tags=Tags(Name='elbAppServer', Color=Ref(self.param_color))))

        self.add_resource(
            cw.Alarm('alarmAppServerBackend4xx',
                     AlarmActions=[Ref(self.param_notification_arn)],
                     Statistic='Sum',
                     Period=300,
                     Threshold='5',
                     EvaluationPeriods=1,
                     ComparisonOperator='GreaterThanThreshold',
                     MetricName='HTTPCode_Backend_4XX',
                     Namespace='AWS/ELB',
                     Dimensions=[
                         cw.MetricDimension(
                             'metricLoadBalancerName',
                             Name='LoadBalancerName',
                             Value=Ref(app_server_load_balancer))
                     ]))

        self.add_resource(
            cw.Alarm('alarmAppServerBackend5xx',
                     AlarmActions=[Ref(self.param_notification_arn)],
                     Statistic='Sum',
                     Period=60,
                     Threshold='0',
                     EvaluationPeriods=1,
                     ComparisonOperator='GreaterThanThreshold',
                     MetricName='HTTPCode_Backend_5XX',
                     Namespace='AWS/ELB',
                     Dimensions=[
                         cw.MetricDimension(
                             'metricLoadBalancerName',
                             Name='LoadBalancerName',
                             Value=Ref(app_server_load_balancer))
                     ]))

        #
        # ASG
        #
        app_server_launch_config = self.add_resource(
            asg.LaunchConfiguration(
                'lcAppServer',
                ImageId=Ref(self.app_server_ami),
                IamInstanceProfile=Ref(self.param_app_server_iam_profile),
                InstanceType=Ref(self.app_server_instance_type_parameter),
                KeyName=Ref(self.keyname_parameter),
                SecurityGroups=[Ref(app_server_security_group)]))

        autoscaling_group = self.add_resource(
            asg.AutoScalingGroup(
                'asgAppServer',
                AvailabilityZones=self.get_input(
                    'AppServerAvailabilityZones').split(','),
                Cooldown=300,
                DesiredCapacity=Ref(self.param_desired_capacity),
                HealthCheckGracePeriod=600,
                HealthCheckType='ELB',
                LaunchConfigurationName=Ref(app_server_launch_config),
                LoadBalancerNames=[Ref(app_server_load_balancer)],
                MaxSize=Ref(self.param_max_size),
                MinSize=Ref(self.param_min_size),
                NotificationConfiguration=asg.NotificationConfiguration(
                    TopicARN=Ref(self.param_notification_arn),
                    NotificationTypes=[
                        asg.EC2_INSTANCE_LAUNCH, asg.EC2_INSTANCE_LAUNCH_ERROR,
                        asg.EC2_INSTANCE_TERMINATE,
                        asg.EC2_INSTANCE_TERMINATE_ERROR
                    ]),
                VPCZoneIdentifier=Ref(self.param_private_subnets),
                Tags=[
                    asg.Tag('Name', '{}Server'.format(self.STACK_NAME_PREFIX),
                            True),
                    asg.Tag('Color', Ref(self.param_color), True)
                ]))

        # autoscaling policies
        autoscaling_policy_add = self.add_resource(
            asg.ScalingPolicy('scalingPolicyAddAppServer',
                              AdjustmentType='ChangeInCapacity',
                              AutoScalingGroupName=Ref(autoscaling_group),
                              Cooldown=600,
                              ScalingAdjustment='1'))

        autoscaling_policy_remove = self.add_resource(
            asg.ScalingPolicy('scalingPolicyRemoveAppServer',
                              AdjustmentType='ChangeInCapacity',
                              AutoScalingGroupName=Ref(autoscaling_group),
                              Cooldown=600,
                              ScalingAdjustment='-1'))

        if self.STACK_NAME_PREFIX == 'Otp':
            # trigger scale down if CPU avg usage < 10% for 3 consecutive 5 min periods
            self.add_resource(
                cw.Alarm('alarmAppServerLowCPU',
                         AlarmActions=[Ref(autoscaling_policy_remove)],
                         Statistic='Average',
                         Period=300,
                         Threshold='10',
                         EvaluationPeriods=3,
                         ComparisonOperator='LessThanThreshold',
                         MetricName='CPUUtilization',
                         Namespace='AWS/EC2',
                         Dimensions=[
                             cw.MetricDimension('metricAutoScalingGroupName',
                                                Name='AutoScalingGroupName',
                                                Value=Ref(autoscaling_group))
                         ]))

            # trigger scale up if CPU avg usage >= 30% for a 5 min period
            self.add_resource(
                cw.Alarm('alarmAppServerHighCPU',
                         AlarmActions=[
                             Ref(self.param_notification_arn),
                             Ref(autoscaling_policy_add)
                         ],
                         Statistic='Average',
                         Period=300,
                         Threshold='30',
                         EvaluationPeriods=1,
                         ComparisonOperator='GreaterThanOrEqualToThreshold',
                         MetricName='CPUUtilization',
                         Namespace='AWS/EC2',
                         Dimensions=[
                             cw.MetricDimension('metricAutoScalingGroupName',
                                                Name='AutoScalingGroupName',
                                                Value=Ref(autoscaling_group))
                         ]))
        else:
            # scale web servers based on network usage
            self.add_resource(
                cw.Alarm('alarmAppServerLowNetworkUsage',
                         AlarmActions=[Ref(autoscaling_policy_remove)],
                         Statistic='Average',
                         Period=300,
                         Threshold='500000',
                         EvaluationPeriods=3,
                         ComparisonOperator='LessThanThreshold',
                         MetricName='NetworkOut',
                         Namespace='AWS/EC2',
                         Dimensions=[
                             cw.MetricDimension('metricAutoScalingGroupName',
                                                Name='AutoScalingGroupName',
                                                Value=Ref(autoscaling_group))
                         ]))

            self.add_resource(
                cw.Alarm('alarmAppServerHighNetworkUsage',
                         AlarmActions=[
                             Ref(self.param_notification_arn),
                             Ref(autoscaling_policy_add)
                         ],
                         Statistic='Average',
                         Period=300,
                         Threshold='10000000',
                         EvaluationPeriods=1,
                         ComparisonOperator='GreaterThanOrEqualToThreshold',
                         MetricName='NetworkOut',
                         Namespace='AWS/EC2',
                         Dimensions=[
                             cw.MetricDimension('metricAutoScalingGroupName',
                                                Name='AutoScalingGroupName',
                                                Value=Ref(autoscaling_group))
                         ]))

        #
        # DNS name
        #
        self.create_resource(
            route53.RecordSetType(
                'dnsName',
                Name=Join('.', [
                    Ref(self.param_color),
                    Ref(self.param_stacktype), self.STACK_NAME_PREFIX,
                    Ref(self.param_public_hosted_zone_name)
                ]),
                Type='A',
                AliasTarget=route53.AliasTarget(
                    GetAtt(app_server_load_balancer,
                           'CanonicalHostedZoneNameID'),
                    GetAtt(app_server_load_balancer, 'DNSName')),
                HostedZoneName=Ref(self.param_public_hosted_zone_name)))

        self.add_output([
            Output('{}ServerLoadBalancerEndpoint'.format(
                self.STACK_NAME_PREFIX),
                   Description='Application server endpoint',
                   Value=GetAtt(app_server_load_balancer, 'DNSName')),
            Output('{}ServerLoadBalancerHostedZoneNameID'.format(
                self.STACK_NAME_PREFIX),
                   Description='ID of canonical hosted zone name for ELB',
                   Value=GetAtt(app_server_load_balancer,
                                'CanonicalHostedZoneNameID'))
        ])
예제 #22
0
    def add_resources(self):

        metadata = {
            "AWS::CloudFormation::Init": {
                "configSets": {
                    "wordpress_install": [
                        "install_wordpress"]
                },
                "install_wordpress": {
                    "packages": {
                        "apt": {
                            "apache2": [],
                            "php": [],
                            "php-mysql": [],
                            "php7.0": [],
                            "php7.0-mysql": [],
                            "libapache2-mod-php7.0": [],
                            "php7.0-cli": [],
                            "php7.0-cgi": [],
                            "php7.0-gd": [],
                            "mysql-client": [],
                            "sendmail": []
                        }
                    },
                    "sources": {
                        "/var/www/html": "http://wordpress.org/latest.tar.gz"
                    },
                    "files": {
                        "/tmp/create-wp-config": {
                            "content": {
                                "Fn::Join": ["", [
                                    "#!/bin/bash\n",
                                    "cp /var/www/html/wordpress/wp-config-sample.php /var/www/html/wordpress/wp-config.php\n",
                                    "sed -i \"s/'database_name_here'/'", Ref(
                                        self.DBName), "'/g\" wp-config.php\n",
                                    "sed -i \"s/'username_here'/'", Ref(
                                        self.DBUser), "'/g\" wp-config.php\n",
                                    "sed -i \"s/'password_here'/'", Ref(
                                        self.DBPass), "'/g\" wp-config.php\n",
                                    "sed -i \"s/'localhost'/'", Ref(
                                        self.RDSEndpoint), "'/g\" wp-config.php\n"
                                ]]
                            },
                            "mode": "000500",
                            "owner": "root",
                            "group": "root"
                        }
                    },
                    "commands": {
                        "01_configure_wordpress": {
                            "command": "/tmp/create-wp-config",
                            "cwd": "/var/www/html/wordpress"
                        }
                    }
                }
            }
        }

        self.WaitHandle = self.template.add_resource(cloudformation.WaitConditionHandle(
            "WaitHandle",
        ))

        self.WaitCondition = self.template.add_resource(cloudformation.WaitCondition(
            "WaitCondition",
            Handle=Ref(self.WaitHandle),
            Timeout="600",
            DependsOn="WebServerAutoScalingGroup",
        ))

        self.WebServerLaunchConfiguration = self.template.add_resource(autoscaling.LaunchConfiguration(
            "WebServerLaunchConfiguration",
            Metadata=metadata,
            UserData=Base64(Join("", [
                "#!/bin/bash -x\n",
                "apt-get update\n",
                "apt-get install python-pip nfs-common -y \n",
                "mkdir -p /var/www/html/\n",
                "EC2_AZ=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone)\n",
                "echo \"$EC2_AZ.", Ref(self.FileSystemID), ".efs.", Ref(
                    "AWS::Region"), ".amazonaws.com:/ /var/www/html/ nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 0 0\" >> /etc/fstab\n"
                "mount -a\n",
                "pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz\n",

                # "exec > /tmp/userdata.log 2>&1\n",
                "/usr/local/bin/cfn-init -v  --stack ", Ref("AWS::StackName"),
                "         --resource WebServerLaunchConfiguration ",
                "         --configsets wordpress_install ",
                "         --region ", Ref("AWS::Region"),
                "\n",
                "/bin/mv /var/www/html/wordpress/* /var/www/html/\n",
                "/bin/rm -f /var/www/html/index.html\n",
                "/bin/rm -rf /var/www/html/wordpress/\n",
                "chown www-data:www-data /var/www/html/* -R\n",
                "/usr/sbin/service apache2 restart\n",
                "/usr/bin/curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar\n",
                "/bin/chmod +x wp-cli.phar\n",
                "/bin/mv wp-cli.phar /usr/local/bin/wp\n",
                "cd /var/www/html/\n",
                "if ! $(sudo -u www-data /usr/local/bin/wp core is-installed); then\n",
                "sudo -u www-data /usr/local/bin/wp core install ",
                "--url='", Ref(self.Hostname), ".", Ref(self.Domain), "' ",
                "--title='Cloudreach Meetup - ", Ref(
                    self.Environment), "' ",
                "--admin_user='******' ",
                "--admin_password='******' ",
                "--admin_email='*****@*****.**'\n",
                "wget  https://s3-eu-west-1.amazonaws.com/sceptre-meetup-munich/header.jpg -O /var/www/html/wp-content/themes/twentyseventeen/assets/images/header.jpg\n",
                "chown www-data:www-data /var/www/html/wp-content/themes/twentyseventeen/assets/images/header.jpg\n",

                "fi\n",

                "/usr/local/bin/cfn-signal -e $? --stack ", Ref(
                    "AWS::StackName"), "   -r \"Webserver setup complete\" '", Ref(self.WaitHandle), "'\n"

            ]
            )),
            ImageId=FindInMap("AWSRegion2AMI", Ref("AWS::Region"), "AMI"),
            KeyName=Ref(self.KeyName),
            SecurityGroups=[Ref(self.WebSecurityGroup)],
            InstanceType=Ref(self.InstanceType),
            AssociatePublicIpAddress=True,
        ))

        self.WebServerAutoScalingGroup = self.template.add_resource(autoscaling.AutoScalingGroup(
            "WebServerAutoScalingGroup",
            MinSize=Ref(self.WebServerCapacity),
            DesiredCapacity=Ref(self.WebServerCapacity),
            MaxSize=Ref(self.WebServerCapacity),
            VPCZoneIdentifier=[Ref(self.Subnet1), Ref(self.Subnet2)],
            AvailabilityZones=[Ref(self.AvailabilityZone1),
                               Ref(self.AvailabilityZone2)],
            Tags=autoscaling.Tags(
                Name=Join("-", [Ref(self.Project), "web", "asg"]),
                Environment=Ref(self.Environment),
                Project=Ref(self.Project),
            ),
            LoadBalancerNames=[Ref(self.ElasticLoadBalancer)],
            LaunchConfigurationName=Ref(self.WebServerLaunchConfiguration),
        ))

        self.WebServerScaleUpPolicy = self.template.add_resource(autoscaling.ScalingPolicy(
            "WebServerScaleUpPolicy",
            ScalingAdjustment="1",
            Cooldown="60",
            AutoScalingGroupName=Ref(self.WebServerAutoScalingGroup),
            AdjustmentType="ChangeInCapacity",
        ))

        self.WebServerScaleDownPolicy = self.template.add_resource(autoscaling.ScalingPolicy(
            "WebServerScaleDownPolicy",
            ScalingAdjustment="-1",
            Cooldown="60",
            AutoScalingGroupName=Ref(self.WebServerAutoScalingGroup),
            AdjustmentType="ChangeInCapacity",
        ))

        self.CPUAlarmLow = self.template.add_resource(cloudwatch.Alarm(
            "CPUAlarmLow",
            EvaluationPeriods="2",
            Dimensions=[
                cloudwatch.MetricDimension(
                    Name="AutoScalingGroupName",
                    Value=Ref(self.WebServerAutoScalingGroup)
                ),
            ],
            AlarmActions=[Ref(self.WebServerScaleDownPolicy)],
            AlarmDescription="Scale-down if CPU < 70% for 1 minute",
            Namespace="AWS/EC2",
            Period="60",
            ComparisonOperator="LessThanThreshold",
            Statistic="Average",
            Threshold="70",
            MetricName="CPUUtilization",
        ))

        self.CPUAlarmHigh = self.template.add_resource(cloudwatch.Alarm(
            "CPUAlarmHigh",
            EvaluationPeriods="2",
            Dimensions=[
                cloudwatch.MetricDimension(
                    Name="AutoScalingGroupName",
                    Value=Ref("WebServerAutoScalingGroup")
                ),
            ],
            AlarmActions=[Ref(self.WebServerScaleUpPolicy)],
            AlarmDescription="Scale-up if CPU > 50% for 1 minute",
            Namespace="AWS/EC2",
            Period="60",
            ComparisonOperator="GreaterThanThreshold",
            Statistic="Average",
            Threshold="50",
            MetricName="CPUUtilization",
        ))
예제 #23
0
def main():
    t = Template()
    t.add_version('2010-09-09')
    t.set_description("AWS CloudFormation ECS example")

    # Add the Parameters

    AMI = t.add_parameter(Parameter(
        "AMI",
        Type="String",
    ))

    ClusterSize = t.add_parameter(Parameter(
        "ClusterSize",
        Type="String",
    ))

    ClusterType = t.add_parameter(Parameter(
        "ClusterType",
        Type="String",
    ))

    InstanceType = t.add_parameter(Parameter(
        "InstanceType",
        Type="String",
    ))

    IamInstanceProfile = t.add_parameter(
        Parameter(
            "IamInstanceProfile",
            Type="String",
        ))

    KeyName = t.add_parameter(
        Parameter(
            "KeyName",
            Type="AWS::EC2::KeyPair::KeyName",
        ))

    MaxClusterSize = t.add_parameter(
        Parameter(
            "MaxClusterSize",
            Type="String",
        ))

    RollingUpdate = t.add_parameter(Parameter(
        "RollingUpdate",
        Type="String",
    ))

    Stage = t.add_parameter(Parameter(
        "Stage",
        Type="String",
    ))

    Subnets = t.add_parameter(
        Parameter(
            "Subnets",
            Type="List<AWS::EC2::Subnet::Id>",
        ))

    VpcCidr = t.add_parameter(Parameter(
        "VpcCidr",
        Type="String",
    ))

    VpcId = t.add_parameter(Parameter(
        "VpcId",
        Type="AWS::EC2::VPC::Id",
    ))

    ContainerInstances = t.add_resource(
        LaunchConfiguration(
            'ContainerInstances',
            UserData=Base64(
                Join('', [
                    '#!/bin/bash -xe\n', 'echo ECS_CLUSTER=',
                    Ref('AWS::StackName'), '>> /etc/ecs/ecs.config\n',
                    'systemctl enable [email protected]\n',
                    'systemctl start [email protected]\n',
                    '/usr/bin/cfn-signal -e $? ', '         --stack ',
                    Ref('AWS::StackName'),
                    '         --resource ECSAutoScalingGroup ',
                    '         --region ',
                    Ref('AWS::Region'), '\n'
                ])),
            ImageId=Ref(AMI),
            KeyName=Ref(KeyName),
            SecurityGroups=[Ref('EcsSecurityGroup')],
            IamInstanceProfile=Ref(IamInstanceProfile),
            InstanceType=Ref(InstanceType)))

    ECSCluster = t.add_resource(
        Cluster('EcsCluster', ClusterName=Ref('AWS::StackName')))

    ECSAutoScalingGroup = t.add_resource(
        AutoScalingGroup(
            'ECSAutoScalingGroup',
            DesiredCapacity=Ref(ClusterSize),
            MinSize=Ref(ClusterSize),
            MaxSize=Ref(MaxClusterSize),
            VPCZoneIdentifier=Ref(Subnets),
            LaunchConfigurationName=Ref('ContainerInstances'),
            HealthCheckType="EC2",
            UpdatePolicy=UpdatePolicy(
                AutoScalingReplacingUpdate=AutoScalingReplacingUpdate(
                    WillReplace=True, ),
                AutoScalingRollingUpdate=AutoScalingRollingUpdate(
                    PauseTime='PT5M',
                    MinInstancesInService=Ref(ClusterSize),
                    MaxBatchSize='1',
                    WaitOnResourceSignals=True)),
            Tags=[
                Tag("Project", "demo", True),
                Tag("Stage", Ref(Stage), True),
                Tag("Name", "home-ecs", True),
            ]))

    t.add_resource(
        ScalingPolicy("EcsAsgScaleDown",
                      AdjustmentType="PercentChangeInCapacity",
                      AutoScalingGroupName=Ref("ECSAutoScalingGroup"),
                      MetricAggregationType="Average",
                      MinAdjustmentMagnitude="1",
                      PolicyType="StepScaling",
                      StepAdjustments=[
                          StepAdjustments(MetricIntervalLowerBound="-10",
                                          MetricIntervalUpperBound="0",
                                          ScalingAdjustment="-10"),
                          StepAdjustments(MetricIntervalUpperBound="-10",
                                          ScalingAdjustment="-20")
                      ]))

    t.add_resource(
        ScalingPolicy('EcsScaleUp',
                      AdjustmentType="PercentChangeInCapacity",
                      AutoScalingGroupName=Ref("ECSAutoScalingGroup"),
                      EstimatedInstanceWarmup="300",
                      MetricAggregationType="Average",
                      MinAdjustmentMagnitude="1",
                      PolicyType="StepScaling",
                      StepAdjustments=[
                          StepAdjustments(MetricIntervalLowerBound="0",
                                          MetricIntervalUpperBound="10",
                                          ScalingAdjustment="10"),
                          StepAdjustments(MetricIntervalLowerBound="10",
                                          ScalingAdjustment="20")
                      ]))

    t.add_resource(
        cloudwatch.Alarm("EcsScaleDownAlarm",
                         ActionsEnabled="True",
                         MetricName="CPUUtilization",
                         AlarmActions=[Ref("EcsAsgScaleDown")],
                         AlarmDescription="Scale down ECS Instances",
                         Namespace="AWS/EC2",
                         Statistic="Average",
                         Period="60",
                         EvaluationPeriods="6",
                         Threshold="25",
                         ComparisonOperator="LessThanThreshold",
                         Dimensions=[
                             cloudwatch.MetricDimension(
                                 Name="AutoScalingGroupName",
                                 Value=Ref("ECSAutoScalingGroup"))
                         ]))

    t.add_resource(
        cloudwatch.Alarm("EcsAsgScaleUpAlarm",
                         ActionsEnabled="True",
                         MetricName="CPUUtilization",
                         AlarmActions=[Ref("EcsScaleUp")],
                         AlarmDescription="Scale up ECS Instances",
                         Namespace="AWS/EC2",
                         Statistic="Average",
                         Period="60",
                         EvaluationPeriods="3",
                         Threshold="65",
                         ComparisonOperator="GreaterThanThreshold",
                         Dimensions=[
                             cloudwatch.MetricDimension(
                                 Name="AutoScalingGroupName",
                                 Value=Ref("ECSAutoScalingGroup"))
                         ]))

    EC2SecurityGroup = t.add_resource(
        ec2.SecurityGroup('EcsSecurityGroup',
                          GroupDescription='ECS InstanceSecurityGroup',
                          SecurityGroupIngress=[
                              ec2.SecurityGroupRule(IpProtocol='tcp',
                                                    FromPort='22',
                                                    ToPort='22',
                                                    CidrIp='0.0.0.0/0'),
                              ec2.SecurityGroupRule(IpProtocol='tcp',
                                                    FromPort='31000',
                                                    ToPort='61000',
                                                    CidrIp='0.0.0.0/0')
                          ],
                          VpcId=Ref(VpcId)))

    with open("ecs-ec2-cluster-cf.yaml", "w") as yamlout:
        yamlout.write(t.to_yaml())
예제 #24
0
    Tags=[asg.Tag('Name', 'Tiler', True)]
))

#
# CloudWatch Resources
#
t.add_resource(cw.Alarm(
    'alarmTilerBackend4XX',
    AlarmDescription='Tiler API server backend 4XXs',
    AlarmActions=[Ref(notification_arn_param)],
    Statistic='Sum',
    Period=300,
    Threshold='20',
    EvaluationPeriods=1,
    ComparisonOperator='GreaterThanThreshold',
    MetricName='HTTPCode_Backend_4XX',
    Namespace='AWS/ELB',
    Dimensions=[
        cw.MetricDimension(
            'metricLoadBalancerName',
            Name='LoadBalancerName',
            Value=Ref(tiler_load_balancer)
        )
    ],
))

t.add_resource(cw.Alarm(
    'alarmTilerBackend5XX',
    AlarmDescription='Tiler API server backend 5XXs',
    AlarmActions=[Ref(notification_arn_param)],
    Statistic='Sum',
예제 #25
0
    def add_resources(self):
        """Add resources to template."""
        template = self.template
        variables = self.get_variables()

        additional_tags = {}
        for key in variables['OtherTags'].iterkeys():
            if isinstance(variables['OtherTags'][key], dict):
                tag_name = variables['OtherTags'][key]['Name']
            else:
                tag_name = key
            additional_tags[tag_name] = variables[key].ref

        rdsclientsecuritygroup = template.add_resource(
            ec2.SecurityGroup(
                'RdsClientSecurityGroup',
                VpcId=variables['VpcId'].ref,
                SecurityGroupEgress=[
                    ec2.SecurityGroupRule(
                        IpProtocol='-1',
                        FromPort='0',
                        ToPort='65535',
                        CidrIp='0.0.0.0/0')
                ],
                GroupDescription=Join('-', [variables['ApplicationName'].ref,
                                            'RdsClientSecurityGroup',
                                            variables['EnvironmentName'].ref]),
                Tags=Tags(
                    Name=Join('-', ['rds-clients',
                                    variables['ApplicationName'].ref,
                                    variables['EnvironmentName'].ref]),
                    Environment=variables['EnvironmentName'].ref,
                    Application=variables['ApplicationName'].ref,
                    **additional_tags
                )
            )
        )
        template.add_output(
            Output(
                'RdsClientSecurityGroup',
                Description='The ID of the RDS client security group '
                            'associated with the environment',
                Value=Ref(rdsclientsecuritygroup)
            )
        )

        rdsserversecuritygroup = template.add_resource(
            ec2.SecurityGroup(
                'RdsServerSecurityGroup',
                SecurityGroupIngress=[
                    ec2.SecurityGroupRule(
                        IpProtocol='tcp',
                        FromPort=FindInMap('RdsMap',
                                           variables['RdsEngineType'].ref,
                                           'RdsPort'),
                        ToPort=FindInMap('RdsMap',
                                         variables['RdsEngineType'].ref,
                                         'RdsPort'),
                        SourceSecurityGroupId=Ref(rdsclientsecuritygroup))
                ],
                VpcId=variables['VpcId'].ref,
                SecurityGroupEgress=[
                    ec2.SecurityGroupRule(
                        IpProtocol='-1',
                        FromPort='0',
                        ToPort='65535',
                        CidrIp='0.0.0.0/0')
                ],
                GroupDescription=Join('-', [variables['ApplicationName'].ref,
                                            'RdsServerSecurityGroup',
                                            variables['EnvironmentName'].ref]),
                Tags=Tags(
                    Name=Join('-', ['rds-server',
                                    variables['ApplicationName'].ref,
                                    variables['EnvironmentName'].ref]),
                    Environment=variables['EnvironmentName'].ref,
                    Application=variables['ApplicationName'].ref,
                    **additional_tags
                )
            )
        )
        template.add_output(
            Output(
                rdsserversecuritygroup.title,
                Description='The ID of the RDS server security group '
                            'associated with the rds',
                Value=Ref(rdsserversecuritygroup)
            )
        )

        template.add_resource(
            ec2.SecurityGroupIngress(
                'VpnSgIngress',
                Condition='VpnAccessEnabled',
                GroupId=Ref(rdsserversecuritygroup),
                IpProtocol='tcp',
                FromPort=FindInMap('RdsMap',
                                   variables['RdsEngineType'].ref,
                                   'RdsPort'),
                ToPort=FindInMap('RdsMap',
                                 variables['RdsEngineType'].ref,
                                 'RdsPort'),
                SourceSecurityGroupId=variables['VPNSecurityGroup'].ref
            )
        )

        rdsdatabaseinstance = template.add_resource(
            rds.DBInstance(
                'RdsDatabaseInstance',
                DBParameterGroupName=If(
                    'CustomParameterGroup',
                    variables['ParameterGroupName'].ref,
                    FindInMap('RdsMap',
                              variables['RdsEngineType'].ref,
                              'RdsParameterGroupName')),
                AllowMajorVersionUpgrade=variables['AllowMajorVersionUpgrade'].ref,  # noqa
                MasterUsername=FindInMap('RdsMap',
                                         variables['RdsEngineType'].ref,
                                         'RdsMasterUsername'),
                LicenseModel=FindInMap('RdsMap',
                                       variables['RdsEngineType'].ref,
                                       'RdsLicenseModel'),
                VPCSecurityGroups=variables['RdsServerSecurityGroup'].ref,
                Engine=FindInMap('RdsMap',
                                 variables['RdsEngineType'].ref,
                                 'RdsEngine'),
                MultiAZ=variables['MultiAZ'].ref,
                Tags=Tags(
                    Name=variables['RdsInstanceIdentifier'].ref,
                    Environment=variables['EnvironmentName'].ref,
                    Application=variables['ApplicationName'].ref,
                    **additional_tags
                ),
                AutoMinorVersionUpgrade=variables['AutoMinorVersionUpgrade'].ref,  # noqa
                PreferredBackupWindow='03:00-04:00',
                AllocatedStorage=variables['RdsAllocatedStorage'].ref,
                DBSubnetGroupName=variables['DBSubnetGroupName'].ref,
                PreferredMaintenanceWindow='sat:06:00-sat:07:00',
                EngineVersion=FindInMap('RdsMap',
                                        variables['RdsEngineType'].ref,
                                        'RdsEngineVersion'),
                BackupRetentionPeriod=variables['BackupRetentionDays'].ref,
                StorageType='gp2',
                MasterUserPassword=variables['DBPassword'].ref,
                KmsKeyId=If('KmsKeyEnabled',
                            variables['KmsKey'].ref,
                            Ref('AWS::NoValue')),
                StorageEncrypted=variables['Encrypted'].ref,
                DBInstanceClass=variables['RdsInstanceClass'].ref,
                Port=FindInMap('RdsMap',
                               variables['RdsEngineType'].ref,
                               'RdsPort'),
                DBInstanceIdentifier=If(
                    'IdentifierSpecified',
                    variables['RdsInstanceIdentifier'].ref,
                    Join(
                        '-',
                        [variables['ApplicationName'].ref,
                         variables['EnvironmentName'].ref])),
                DBSnapshotIdentifier=If('SnapshotSpecified',
                                        variables['RdsSnapshotIdentifier'].ref,
                                        Ref('AWS::NoValue'))
            )
        )

        rdsdatabasereadreplica = template.add_resource(
            rds.DBInstance(
                'RdsDatabaseReadReplica',
                DBParameterGroupName=If(
                    'CustomParameterGroup',
                    variables['ParameterGroupName'].ref,
                    FindInMap('RdsMap',
                              variables['RdsEngineType'].ref,
                              'RdsParameterGroupName')),
                VPCSecurityGroups=variables['RdsServerSecurityGroup'].ref,
                SourceDBInstanceIdentifier=Ref(rdsdatabaseinstance),
                DBInstanceClass=variables['RdsInstanceClass'].ref,
                StorageType='gp2',
                DBInstanceIdentifier=If(
                    'IdentifierSpecified',
                    Join(
                        '-',
                        [variables['RdsInstanceIdentifier'].ref,
                         'readreplica']),
                    Ref('AWS::NoValue')),
                SourceRegion=If(
                    'SourceRegionSpecified',
                    variables['SourceRegion'].ref,
                    Ref('AWS::NoValue')),
                Engine=FindInMap('RdsMap',
                                 variables['RdsEngineType'].ref,
                                 'RdsEngine'),
                EngineVersion=FindInMap('RdsMap',
                                        variables['RdsEngineType'].ref,
                                        'RdsEngineVersion'),
                Condition='IsReadReplica',
            )
        )

        template.add_resource(
            cloudwatch.Alarm(
                'HighCPUAlarm',
                Condition='SnsTopicSpecified',
                ActionsEnabled='true',
                AlarmActions=variables['SNSTopic'].ref,
                AlarmDescription='CPU Utilization Alarm for RDS',
                AlarmName=Join('-', [variables['EnvironmentName'].ref,
                                     'CPUUtilization',
                                     'RDS',
                                     'alarm']),
                ComparisonOperator=variables['CpuComparisonOperator'].ref,
                OKActions=variables['SNSTopic'].ref,
                EvaluationPeriods=variables['CpuEvaluationPeriods'].ref,
                MetricName='CPUUtilization',
                Namespace='AWS/RDS',
                Period=variables['CpuPeriod'].ref,
                Statistic=variables['CpuStatistic'].ref,
                Threshold=variables['CpuThreshold'].ref
            )
        )

        template.add_resource(
            cloudwatch.Alarm(
                'FreeStorageSpace',
                Condition='SnsTopicSpecified',
                ActionsEnabled='true',
                AlarmActions=variables['SNSTopic'].ref,
                AlarmDescription='Disk Space Alarm for RDS',
                AlarmName=Join('-', [variables['EnvironmentName'].ref,
                                     'FreeDiskSpace',
                                     'RDS',
                                     'alarm']),
                ComparisonOperator=variables['DiskComparisonOperator'].ref,
                OKActions=variables['SNSTopic'].ref,
                EvaluationPeriods=variables['DiskEvaluationPeriods'].ref,
                MetricName='FreeStorageSpace',
                Namespace='AWS/RDS',
                Period=variables['DiskPeriod'].ref,
                Statistic=variables['DiskStatistic'].ref,
                Threshold=variables['DiskThreshold'].ref
            )
        )

        template.add_resource(
            cloudwatch.Alarm(
                'FreeableMemory',
                Condition='SnsTopicSpecified',
                ActionsEnabled='true',
                AlarmActions=variables['SNSTopic'].ref,
                AlarmDescription='Free memory Alarm for RDS',
                AlarmName=Join('-', [variables['EnvironmentName'].ref,
                                     'FreeableMemory',
                                     'RDS',
                                     'alarm']),
                ComparisonOperator=variables['MemoryComparisonOperator'].ref,
                OKActions=variables['SNSTopic'].ref,
                EvaluationPeriods=variables['MemoryEvaluationPeriods'].ref,
                MetricName='FreeableMemory',
                Namespace='AWS/RDS',
                Period=variables['MemoryPeriod'].ref,
                Statistic=variables['MemoryStatistic'].ref,
                Threshold=variables['MemoryThreshold'].ref
            )
        )
        template.add_output(
            Output(
                'RdsDatabaseInstance',
                Description='The name of the RDS instance for the environment',
                Value=GetAtt(rdsdatabaseinstance, 'Endpoint.Address')
            )
        )
        template.add_output(
            Output(
                'RdsDatabaseReadReplica',
                Description='The name of the RDS read replica for the '
                            'environment',
                Value=GetAtt(rdsdatabasereadreplica, 'Endpoint.Address'),
                Condition='IsReadReplica'
            )
        )
예제 #26
0
    def add_ec2(self, ami_name, instance_type, asg_size, cidr, hosted_zone):
        """
        Helper method creates ingress given a source cidr range and a set of
        ports
        @param ami_name [string] Name of the AMI for launching the app
        @param instance_type [string] Instance for the application
        @param asg_size [int] Sets the size of the asg
        @param cidr [string] Range of addresses for this vpc
        @param hosted_zone [string] Name of the hosted zone the elb will be
        mapped to
        """
        print "Creating EC2"

        self.internal_security_group = self.add_sg_with_cidr_port_list(
            "ASGSG",
            "Security Group for EC2",
            'vpcId',
            cidr,
            [{"443": "443"}, {"80": "80"}]
        )

        self.public_lb_security_group = self.add_sg_with_cidr_port_list(
            "ELBSG",
            "Security Group for accessing EC2 publicly",
            'vpcId',
            '0.0.0.0/0',
            [{"443": "443"}]
        )

        name = self.env_name.replace('-', '')

        public_subnet_count = len(self._subnets.get('public').get('public'))
        public_subnets = [{'Ref': x} for x in ["publicAZ%d" % n for n in range(0, public_subnet_count)]]
        public_alb = self.add_resource(alb.LoadBalancer(
            "PublicALB",
            Scheme='internet-facing',
            Subnets=public_subnets,
            SecurityGroups=[Ref(sg) for sg in [self.public_lb_security_group]]
        ))

        target_group = self.add_resource(alb.TargetGroup(
            "AppTargetGroup80",
            Port=80,
            Protocol="HTTP",
            VpcId=self.vpc_id
        ))
        certificate = 'arn:aws:acm:us-east-1:422548007577:certificate/d9b8fbd2-13bb-4d6e-aba4-53061b1580f9'
        alb_ssl_listener = self.add_resource(alb.Listener(
            "ALBListner",
            Port=443,
            Certificates=[alb.Certificate(CertificateArn=certificate)],
            Protocol="HTTPS",
            DefaultActions=[alb.Action(
                Type="forward",
                TargetGroupArn=Ref(target_group))],
            LoadBalancerArn=Ref(public_alb)
        ))

        self.add_elb_dns_alias(public_alb, '', hosted_zone)
        policies = ['cloudwatchlogs']
        policies_for_profile = [self.get_policy(policy, 'EC2') for policy in policies]

        asg = self.add_asg(
            "EC2",
            min_size=asg_size,
            max_size=6,
            ami_name=ami_name,
            # load_balancer=public_elb,
            instance_profile=self.add_instance_profile(name, policies_for_profile, name),
            instance_type=instance_type,
            security_groups=['commonSecurityGroup', Ref(self.internal_security_group)],
            subnet_layer='private',
            update_policy=UpdatePolicy(
                AutoScalingRollingUpdate=AutoScalingRollingUpdate(
                    PauseTime='PT5M',
                    MinInstancesInService=1,
                    # The maximum number of instances that are terminated at a given time, left at 1 to ease into updates.
                    # Can be increased at a later time
                    MaxBatchSize='1'
                )
            ),
            user_data=Base64(Join('', [
                '#!/bin/bash\n',
                'echo Good to go'
            ])))

        asg.resource['Properties']['TargetGroupARNs'] = [Ref(target_group)]

        # Cluster Memory Scaling policies
        asg_scale_up_policy = self.add_resource(
            autoscaling.ScalingPolicy(
                name + 'ScaleUpPolicy',
                AdjustmentType='ChangeInCapacity',
                AutoScalingGroupName=Ref(asg),
                Cooldown=300,
                ScalingAdjustment=1
            )
        )

        # ELB latency above a threshold
        self.add_resource(
            cloudwatch.Alarm(
                name + 'LatencyHigh',
                MetricName='Latency',
                ComparisonOperator='GreaterThanThreshold',
                Period=300,
                EvaluationPeriods=1,
                Statistic='Average',
                Namespace='AWS/ELB',
                AlarmDescription=name + 'LatencyHigh',
                Dimensions=[cloudwatch.MetricDimension(Name='LoadBalancerName', Value=Ref(public_alb))],
                Threshold='6',
                AlarmActions=[
                  Ref(asg_scale_up_policy),
                  'arn:aws:sns:us-east-1:422548007577:notify-pat'
                ]
            )
        )
예제 #27
0
    def create_cloudfront_distributions(self):
        blue_tile_distribution = self.add_resource(
            cf.Distribution(
                'tileDistributionBlue',
                DistributionConfig=cf.DistributionConfig(
                    Origins=[
                        cf.Origin(Id='tileOriginId',
                                  DomainName=Join('.', [
                                      'blue-tiles',
                                      Ref(self.public_hosted_zone_name)
                                  ]),
                                  CustomOriginConfig=cf.CustomOrigin(
                                      OriginProtocolPolicy='http-only'))
                    ],
                    DefaultCacheBehavior=cf.DefaultCacheBehavior(
                        ForwardedValues=cf.ForwardedValues(QueryString=True),
                        TargetOriginId='tileOriginId',
                        ViewerProtocolPolicy='allow-all'),
                    Enabled=True)))

        self.add_resource(
            cw.Alarm('alarmTileDistributionBlueOrigin4XX',
                     AlarmDescription='Tile distribution origin 4XXs',
                     AlarmActions=[Ref(self.notification_topic_arn)],
                     Statistic='Average',
                     Period=300,
                     Threshold='20',
                     EvaluationPeriods=1,
                     ComparisonOperator='GreaterThanThreshold',
                     MetricName='4xxErrorRate',
                     Namespace='AWS/CloudFront',
                     Dimensions=[
                         cw.MetricDimension('metricDistributionId',
                                            Name='DistributionId',
                                            Value=Ref(blue_tile_distribution)),
                         cw.MetricDimension('metricRegion',
                                            Name='Region',
                                            Value='Global')
                     ]))

        self.add_resource(
            cw.Alarm('alarmTileDistributionBlueOrigin5XX',
                     AlarmDescription='Tile distribution origin 5XXs',
                     AlarmActions=[Ref(self.notification_topic_arn)],
                     Statistic='Average',
                     Period=60,
                     Threshold='0',
                     EvaluationPeriods=1,
                     ComparisonOperator='GreaterThanThreshold',
                     MetricName='5xxErrorRate',
                     Namespace='AWS/CloudFront',
                     Dimensions=[
                         cw.MetricDimension('metricDistributionId',
                                            Name='DistributionId',
                                            Value=Ref(blue_tile_distribution)),
                         cw.MetricDimension('metricRegion',
                                            Name='Region',
                                            Value='Global')
                     ]))

        green_tile_distribution = self.add_resource(
            cf.Distribution(
                'tileDistributionGreen',
                DistributionConfig=cf.DistributionConfig(
                    Origins=[
                        cf.Origin(Id='tileOriginId',
                                  DomainName=Join('.', [
                                      'green-tiles',
                                      Ref(self.public_hosted_zone_name)
                                  ]),
                                  CustomOriginConfig=cf.CustomOrigin(
                                      OriginProtocolPolicy='http-only'))
                    ],
                    DefaultCacheBehavior=cf.DefaultCacheBehavior(
                        ForwardedValues=cf.ForwardedValues(QueryString=True),
                        TargetOriginId='tileOriginId',
                        ViewerProtocolPolicy='allow-all'),
                    Enabled=True)))

        self.add_resource(
            cw.Alarm('alarmTileDistributionGreenOrigin4XX',
                     AlarmDescription='Tile distribution origin 4XXs',
                     AlarmActions=[Ref(self.notification_topic_arn)],
                     Statistic='Average',
                     Period=300,
                     Threshold='20',
                     EvaluationPeriods=1,
                     ComparisonOperator='GreaterThanThreshold',
                     MetricName='4xxErrorRate',
                     Namespace='AWS/CloudFront',
                     Dimensions=[
                         cw.MetricDimension(
                             'metricDistributionId',
                             Name='DistributionId',
                             Value=Ref(green_tile_distribution)),
                         cw.MetricDimension('metricRegion',
                                            Name='Region',
                                            Value='Global')
                     ]))

        self.add_resource(
            cw.Alarm('alarmTileDistributionGreenOrigin5XX',
                     AlarmDescription='Tile distribution origin 5XXs',
                     AlarmActions=[Ref(self.notification_topic_arn)],
                     Statistic='Average',
                     Period=60,
                     Threshold='0',
                     EvaluationPeriods=1,
                     ComparisonOperator='GreaterThanThreshold',
                     MetricName='5xxErrorRate',
                     Namespace='AWS/CloudFront',
                     Dimensions=[
                         cw.MetricDimension(
                             'metricDistributionId',
                             Name='DistributionId',
                             Value=Ref(green_tile_distribution)),
                         cw.MetricDimension('metricRegion',
                                            Name='Region',
                                            Value='Global')
                     ]))

        return blue_tile_distribution, green_tile_distribution
        "WebServerScaleDownPolicy",
        ScalingAdjustment="-1",
        Cooldown="60",
        AutoScalingGroupName=Ref(WebServerAutoScalingGroup),
        AdjustmentType="ChangeInCapacity",
    ))

CPUAlarmLow = t.add_resource(
    cloudwatch.Alarm(
        "CPUAlarmLow",
        EvaluationPeriods="2",
        Dimensions=[
            cloudwatch.MetricDimension(Name="AutoScalingGroupName",
                                       Value=Ref("WebServerAutoScalingGroup")),
        ],
        AlarmActions=[Ref("WebServerScaleDownPolicy")],
        AlarmDescription="Scale-down if CPU < 70% for 1 minute",
        Namespace="AWS/EC2",
        Period="60",
        ComparisonOperator="LessThanThreshold",
        Statistic="Average",
        Threshold="70",
        MetricName="CPUUtilization",
    ))

CPUAlarmHigh = t.add_resource(
    cloudwatch.Alarm(
        "CPUAlarmHigh",
        EvaluationPeriods="2",
        Dimensions=[
            cloudwatch.MetricDimension(Name="AutoScalingGroupName",
                                       Value=Ref("WebServerAutoScalingGroup")),
                      ]))

alarm = t.add_resource(
    cloudwatch.Alarm(
        'Alarm',
        Condition='AlarmEnabledCondition',
        ActionsEnabled=Ref(param_notification_enabled),
        MetricName=Ref(param_metric_name),
        Namespace=Ref(param_metric_namespace),
        ComparisonOperator=Ref(param_alarm_comparison_operator),
        Statistic=Ref(param_alarm_statistic),
        Threshold=Ref(param_alarm_threshold),
        EvaluationPeriods=Ref(param_alarm_evaluation_periods),
        Period=Ref(param_alarm_period),
        Unit=Ref(param_alarm_unit),
        AlarmActions=[
            If('AlarmTopicCondition', Ref(param_alarm_topic),
               Ref(AWS_NO_VALUE))
        ],
        OKActions=[
            If('OkTopicCondition', Ref(param_ok_topic), Ref(AWS_NO_VALUE))
        ],
        InsufficientDataActions=[
            If('InsufficientDataTopicCondition',
               Ref(param_insufficient_data_topic), Ref(AWS_NO_VALUE))
        ],
        TreatMissingData=Ref(param_treat_missing_data),
    ))

#
# Output