예제 #1
0
 def _load_balancer(self):
     return LoadBalancer(
         "LoadBalancer",
         ConnectionDrainingPolicy=elb.ConnectionDrainingPolicy(
             Enabled=True,
             Timeout=120,
         ),
         AccessLoggingPolicy=elb.AccessLoggingPolicy(
             EmitInterval=5,
             Enabled=True,
             S3BucketName=self.config['elb_logging_bucket'],
             S3BucketPrefix="ELB",
         ),
         Subnets=self.config['public_subnet'],
         HealthCheck=elb.HealthCheck(
             Target="HTTP:80/",
             HealthyThreshold="5",
             UnhealthyThreshold="2",
             Interval="20",
             Timeout="15",
         ),
         Listeners=[
             elb.Listener(
                 LoadBalancerPort=self.config['elb_port'],
                 InstancePort=self.config['instance_port'],
                 Protocol="HTTP",
                 InstanceProtocol="HTTP",
             ),
         ],
         CrossZone=True,
         SecurityGroups=self.config['elb_sg'],
         LoadBalancerName="duy%sELB" % self.config['env'],
         Scheme="internet-facing",
     )
예제 #2
0
    def __init__(self, title, **kwargs):
        super().__init__(title, **kwargs)

        self.AccessLoggingPolicy = If(
            'LoadBalancerLog',
            elb.AccessLoggingPolicy(
                EmitInterval=get_endvalue('LoadBalancerLog'),
                Enabled=True,
                S3BucketName=Sub(cfg.BucketLogs),
                S3BucketPrefix=''), Ref('AWS::NoValue'))
        self.ConnectionDrainingPolicy = elb.ConnectionDrainingPolicy(
            Enabled=True, Timeout=5)
        self.ConnectionSettings = elb.ConnectionSettings(
            IdleTimeout=get_endvalue('LoadBalancerIdleTimeout'))
        self.CrossZone = True
        self.HealthCheck = elb.HealthCheck(
            HealthyThreshold=get_endvalue('HealthyThresholdCount'),
            Interval=get_endvalue('HealthCheckIntervalSeconds'),
            Target=get_endvalue('HealthCheckTarget'),
            Timeout=get_endvalue('HealthCheckTimeoutSeconds'),
            UnhealthyThreshold=get_endvalue('UnhealthyThresholdCount'))
        self.LBCookieStickinessPolicy = If('LoadBalancerCookieSticky', [
            elb.LBCookieStickinessPolicy(PolicyName='LBCookieStickinessPolicy',
                                         CookieExpirationPeriod=get_endvalue(
                                             'LoadBalancerCookieSticky'))
        ], Ref('AWS::NoValue'))
        self.SecurityGroups = [GetAtt('SecurityGroupLoadBalancer', 'GroupId')]
예제 #3
0
def generate_cloudformation_template():
    enable_elb = sys.argv[1]
    input_scaling_policies = ast.literal_eval(sys.argv[2])
    input_alarms = ast.literal_eval(sys.argv[3])

    enable_elb = enable_elb == 'True'
    elb_listeners = ast.literal_eval(sys.argv[4])

    template = Template()

    template.add_description("""\
    Configures Auto Scaling Group for the app""")

    project_name = template.add_parameter(
        Parameter(
            "Name",
            Type="String",
            Description="Instances will be tagged with this name",
        ))

    scalecapacity = template.add_parameter(
        Parameter(
            "ScaleCapacity",
            Default="1",
            Type="String",
            Description="Number of api servers to run",
        ))

    minsize = template.add_parameter(
        Parameter(
            "MinScale",
            Type="String",
            Description="Minimum number of servers to keep in the ASG",
        ))

    maxsize = template.add_parameter(
        Parameter(
            "MaxScale",
            Type="String",
            Description="Maximum number of servers to keep in the ASG",
        ))

    signalcount = template.add_parameter(
        Parameter(
            "SignalCount",
            Default="1",
            Type="String",
            Description=
            "No. of signals CF must receive before it sets the status as CREATE_COMPLETE",
        ))

    signaltimeout = template.add_parameter(
        Parameter(
            "SignalTimeout",
            Default="PT5M",
            Type="String",
            Description=
            "Time that CF waits for the number of signals that was specified in Count ",
        ))

    minsuccessfulinstancespercent = template.add_parameter(
        Parameter(
            "MinSuccessfulInstancesPercent",
            Default="100",
            Type="String",
            Description=
            "% instances in a rolling update that must signal success for CF to succeed",
        ))

    environment = template.add_parameter(
        Parameter(
            "Environment",
            Type="String",
            Description="The environment being deployed into",
        ))

    subnet = template.add_parameter(
        Parameter(
            "Subnets",
            Type="CommaDelimitedList",
        ))

    launchconfigurationname = template.add_parameter(
        Parameter(
            "LaunchConfigurationName",
            Type="String",
        ))

    health_check_grace_period = template.add_parameter(
        Parameter(
            "HealthCheckGracePeriod",
            Type="String",
            Default="300",
        ))

    if enable_elb:
        elb_subnets = template.add_parameter(
            Parameter(
                "LoadBalancerSubnets",
                Type="CommaDelimitedList",
            ))

        elb_bucket_name = template.add_parameter(
            Parameter("LoadBalancerBucketName",
                      Type="String",
                      Description="S3 Bucket for the ELB access logs"))

        template.add_condition("ElbLoggingCondition",
                               Not(Equals(Ref(elb_bucket_name), "")))

        elb_schema = template.add_parameter(
            Parameter(
                "LoadBalancerSchema",
                Type="String",
            ))

        health_check_interval = template.add_parameter(
            Parameter(
                "LoadBalancerHealthCheckInterval",
                Type="String",
            ))

        health_check_timeout = template.add_parameter(
            Parameter(
                "LoadBalancerHealthCheckTimeout",
                Type="String",
            ))

        healthy_threshold = template.add_parameter(
            Parameter(
                "LoadBalancerHealthyThreshold",
                Type="String",
            ))

        unhealthy_threshold = template.add_parameter(
            Parameter(
                "LoadBalancerUnHealthyThreshold",
                Type="String",
            ))

        enable_connection_draining = template.add_parameter(
            Parameter(
                "LoadBalancerEnableConnectionDraining",
                Type="String",
                Default="True",
            ))

        connection_draining_timeout = template.add_parameter(
            Parameter(
                "LoadBalancerConnectionDrainingTimeout",
                Type="String",
                Default="30",
            ))

        loadbalancersecuritygroup = template.add_parameter(
            Parameter(
                "LoadBalancerSecurityGroup",
                Type="CommaDelimitedList",
                Description="Security group for api app load balancer.",
            ))

        hostedzone = template.add_parameter(
            Parameter(
                "HostedZoneName",
                Description=
                "The DNS name of an existing Amazon Route 53 hosted zone",
                Type="String",
            ))

        dns_record = template.add_parameter(
            Parameter(
                "DNSRecord",
                Type="String",
            ))

        dns_ttl = template.add_parameter(
            Parameter(
                "DNSTTL",
                Default="300",
                Type="String",
            ))

        new_weight = template.add_parameter(
            Parameter(
                "NewDnsWeight",
                Type="String",
                Default="100",
            ))

        health_check_protocol = template.add_parameter(
            Parameter(
                "LoadBalancerHealthCheckProtocol",
                Type="String",
            ))

        template.add_condition("ElbTCPProtocolCondition",
                               Equals(Ref(health_check_protocol), "TCP"))

        health_check_port = template.add_parameter(
            Parameter(
                "LoadBalancerHealthCheckPort",
                Type="String",
            ))

        health_check_path = template.add_parameter(
            Parameter(
                "LoadBalancerHealthCheckPath",
                Type="String",
            ))

        load_balancer_listeners = []
        for listener in elb_listeners:
            load_balancer_listeners.append(
                elb.Listener(
                    LoadBalancerPort=listener['load_balancer_port'],
                    InstancePort=listener['instance_port'],
                    Protocol=listener['protocol'],
                    InstanceProtocol=Ref(health_check_protocol),
                ))

        loadbalancer = template.add_resource(
            elb.LoadBalancer(
                "LoadBalancer",
                AccessLoggingPolicy=If(
                    "ElbLoggingCondition",
                    elb.AccessLoggingPolicy(EmitInterval=60,
                                            Enabled=True,
                                            S3BucketName=Ref(elb_bucket_name),
                                            S3BucketPrefix="ELBLogs"),
                    Ref("AWS::NoValue")),
                ConnectionDrainingPolicy=elb.ConnectionDrainingPolicy(
                    Enabled=Ref(enable_connection_draining),
                    Timeout=Ref(connection_draining_timeout),
                ),
                Subnets=Ref(elb_subnets),
                HealthCheck=elb.HealthCheck(
                    Target=Join("", [
                        Ref(health_check_protocol), ":",
                        Ref(health_check_port),
                        If("ElbTCPProtocolCondition", Ref("AWS::NoValue"),
                           Ref(health_check_path))
                    ]),
                    HealthyThreshold=Ref(healthy_threshold),
                    UnhealthyThreshold=Ref(unhealthy_threshold),
                    Interval=Ref(health_check_interval),
                    Timeout=Ref(health_check_timeout),
                ),
                Listeners=load_balancer_listeners,
                CrossZone=True,
                SecurityGroups=Ref(loadbalancersecuritygroup),
                Scheme=Ref(elb_schema)))

        route53record = template.add_resource(
            RecordSetType(
                "DNS",
                HostedZoneName=Join("", [Ref(hostedzone), "."]),
                Name=Join("", [Ref(dns_record), ".",
                               Ref(hostedzone), "."]),
                ResourceRecords=[GetAtt(loadbalancer, "DNSName")],
                SetIdentifier=Ref(project_name),
                TTL=Ref(dns_ttl),
                Type="CNAME",
                Weight=Ref(new_weight),
            ))

    autoscalinggroup = template.add_resource(
        AutoScalingGroup(
            "AutoscalingGroup",
            Tags=[
                Tag("Name", Ref(project_name), True),
                Tag("Environment", Ref(environment), True)
            ],
            LaunchConfigurationName=Ref(launchconfigurationname),
            MinSize=Ref(minsize),
            MaxSize=Ref(maxsize),
            DesiredCapacity=Ref(scalecapacity),
            VPCZoneIdentifier=Ref(subnet),
            HealthCheckGracePeriod=Ref(health_check_grace_period),
            CreationPolicy=CreationPolicy(
                ResourceSignal=ResourceSignal(Count=Ref(signalcount),
                                              Timeout=Ref(signaltimeout)),
                AutoScalingCreationPolicy=AutoScalingCreationPolicy(
                    MinSuccessfulInstancesPercent=Ref(
                        minsuccessfulinstancespercent))),
            UpdatePolicy=UpdatePolicy(
                AutoScalingRollingUpdate=AutoScalingRollingUpdate(
                    MaxBatchSize='1',
                    MinInstancesInService='1',
                    MinSuccessfulInstancesPercent=Ref(
                        minsuccessfulinstancespercent),
                    PauseTime=Ref(signaltimeout),
                    WaitOnResourceSignals=True))))

    autoscalinggroup.HealthCheckType = 'EC2'
    if enable_elb:
        autoscalinggroup.LoadBalancerNames = [Ref(loadbalancer)]
        autoscalinggroup.HealthCheckType = 'ELB'

    created_scaling_policies = dict()
    for scaling_policy in input_scaling_policies:
        policy_properties = {
            'AdjustmentType': scaling_policy['adjustment_type'],
            'AutoScalingGroupName': Ref(autoscalinggroup),
            'Cooldown': scaling_policy['cooldown'],
            'PolicyType': scaling_policy['policy_type'],
            'ScalingAdjustment': scaling_policy['scaling_adjustment'],
        }
        if scaling_policy['policy_type'] != "SimpleScaling" \
                and 'estimated_instance_warmup' in scaling_policy:
            policy_properties['EstimatedInstanceWarmup'] = \
                scaling_policy['estimated_instance_warmup']

        if scaling_policy['policy_type'] != "SimpleScaling" \
                and 'metric_aggregation_type' in scaling_policy:
            policy_properties['MetricAggregationType'] = scaling_policy[
                'metric_aggregation_type']

        if scaling_policy['adjustment_type'] == "PercentChangeInCapacity" \
                and 'min_adjustment_magnitude' in scaling_policy:
            policy_properties['MinAdjustmentMagnitude'] = scaling_policy[
                'min_adjustment_magnitude']

        if 'step_adjustments' in scaling_policy:
            policy_properties['StepAdjustments'] = scaling_policy[
                'step_adjustments']

        created_scaling_policies[
            scaling_policy['name']] = template.add_resource(
                ScalingPolicy(scaling_policy['name'], **policy_properties))

    for alarm in input_alarms:
        template.add_resource(
            Alarm(
                alarm['name'],
                ActionsEnabled=True,
                AlarmActions=[
                    Ref(created_scaling_policies[alarm['scaling_policy_name']])
                ],
                AlarmDescription=alarm['description'],
                ComparisonOperator=alarm['comparison'],
                Dimensions=[
                    MetricDimension(Name="AutoScalingGroupName",
                                    Value=Ref(autoscalinggroup)),
                ],
                EvaluationPeriods=alarm['evaluation_periods'],
                InsufficientDataActions=[],
                MetricName=alarm['metric'],
                Namespace=alarm['namespace'],
                OKActions=[],
                Period=alarm['period'],
                Statistic=alarm['statistics'],
                Threshold=str(alarm['threshold']),
                Unit=alarm['unit'],
            ))

    template.add_output(
        Output("StackName", Value=Ref(project_name), Description="Stack Name"))
    if enable_elb:
        template.add_output(
            Output("DomainName",
                   Value=Ref(route53record),
                   Description="DNS to access the service"))
        template.add_output(
            Output("LoadBalancer",
                   Value=GetAtt(loadbalancer, "DNSName"),
                   Description="ELB dns"))
    template.add_output(
        Output("AutoScalingGroup",
               Value=Ref(autoscalinggroup),
               Description="Auto Scaling Group"))
    template.add_output(
        Output("LaunchConfiguration",
               Value=Ref(launchconfigurationname),
               Description="LaunchConfiguration for this deploy"))

    return template
예제 #4
0
    def __init__(self, title, template, network_config, elb_config):
        """
        Public Class to create an Elastic Loadbalancer in the unit stack environment
        AWS Cloud Formation: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-elb.html
        Troposphere: https://github.com/cloudtools/troposphere/blob/master/troposphere/elasticloadbalancing.py
        :param title: Name of the Cloud formation stack object
        :param template: The troposphere template to add the Elastic Loadbalancer to.
        :param network_config: object containing network related variables
        :param elb_config: object containing elb related variables, including list of listeners (elb_listener_config)
        """
        self.title = title + 'Elb'
        self.elb_r53 = None
        self.elb_config = elb_config
        self.network_config = network_config
        super(Elb, self).__init__(vpc=network_config.vpc, title=title, template=template)
        elb_listeners = elb_config.elb_listeners_config
        subnets = network_config.public_subnets if elb_config.public_unit is True else network_config.private_subnets

        # Create ELB
        self.trop_elb = self.template.add_resource(
            elb.LoadBalancer(self.title,
                             CrossZone=True,
                             HealthCheck=elb.HealthCheck(
                                 Target=elb_config.elb_health_check,
                                 HealthyThreshold=elb_config.healthy_threshold,
                                 UnhealthyThreshold=elb_config.unhealthy_threshold,
                                 Interval=elb_config.interval,
                                 Timeout=elb_config.timeout),
                             Listeners=[elb.Listener(LoadBalancerPort=elb_listener.loadbalancer_port,
                                                     Protocol=elb_listener.loadbalancer_protocol,
                                                     InstancePort=elb_listener.instance_port,
                                                     InstanceProtocol=elb_listener.instance_protocol) for elb_listener
                                        in elb_listeners],
                             Scheme='internet-facing' if elb_config.public_unit is True else 'internal',
                             SecurityGroups=[self.security_group],
                             Subnets=subnets,
                             Tags=Tags(Name=self.title)))
        if network_config.get_depends_on():
            self.trop_elb.DependsOn = network_config.get_depends_on()

        # App sticky session cookies
        sticky_app_cookie_policies = []
        # sticky_app_cookie defaults to None, gather listeners that have cookies
        listeners_with_cookies = [listener for listener in elb_listeners if listener.sticky_app_cookie]

        for listener_num, listener in enumerate(listeners_with_cookies):
            policy_name = self.title + 'AppCookiePolicy' + listener.sticky_app_cookie \
                          + str(listener.instance_port) + str(listener.loadbalancer_port) \
                          + str(listener.instance_protocol)

            sticky_app_cookie_policies.append(elb.AppCookieStickinessPolicy(
                CookieName=listener.sticky_app_cookie,
                PolicyName=policy_name
            ))

            # Even though ELB.Listeners.PolicyNames is a List in the cloudformation documentation,
            # it only accepts a single list element, not multiple...
            self.trop_elb.Listeners[listener_num].PolicyNames = [policy_name]

        if sticky_app_cookie_policies:
            self.trop_elb.AppCookieStickinessPolicy = sticky_app_cookie_policies

        # Create SSL for Listeners
        for listener in self.trop_elb.Listeners:
            if elb_config.ssl_certificate_id:
                listener.SSLCertificateId = elb_config.ssl_certificate_id

        # Create ELB Log Bucket
        if elb_config.elb_log_bucket:
            self.trop_elb.AccessLoggingPolicy = elb.AccessLoggingPolicy(
                EmitInterval='60',
                Enabled=True,
                S3BucketName=elb_config.elb_log_bucket,
                S3BucketPrefix=Join('', [Ref('AWS::StackName'),
                                         '-',
                                         self.title])
            )

        if not elb_config.public_unit:
            self.create_r53_record(network_config.private_hosted_zone_domain)
        elif network_config.public_hosted_zone_name:
            self.create_r53_record(network_config.public_hosted_zone_name)

        else:
            self.template.add_output(Output(
                self.trop_elb.title,
                Description='URL of the {0} ELB'.format(self.title),
                Value=Join('', ['http://', GetAtt(self.trop_elb, 'DNSName')])
            ))

        self.network_config.endpoints[title] = GetAtt(self.trop_elb, 'DNSName')
예제 #5
0
    def generate_load_balancer(self, lb_name, typ, port, cert_arn, log_bucket):

        lb_name = self.cfn_name(lb_name)

        if typ not in ['internal', 'internet-facing']:
            raise NameError("Load balancer type must be of type internal, internet-facing")

        # Use the system security groups (automatic) if internal, else use the limited external security group
        sg = self.security_groups if typ == 'internal' else [Ref(self.elb_external_security_group)]

        return elasticloadbalancing.LoadBalancer(
            lb_name,
            AccessLoggingPolicy=elasticloadbalancing.AccessLoggingPolicy(
                EmitInterval=60,
                Enabled=True,
                S3BucketName=log_bucket,
                S3BucketPrefix="ELB/{}/{}".format(self.env, lb_name)
            ),
            ConnectionDrainingPolicy=elasticloadbalancing.ConnectionDrainingPolicy(
                Enabled=True,
                Timeout=60
            ),
            ConnectionSettings=elasticloadbalancing.ConnectionSettings(
                IdleTimeout=3600
            ),
            CrossZone=False,
            HealthCheck=elasticloadbalancing.HealthCheck(
                HealthyThreshold=5,
                Interval=30,
                Target='HTTP:{}/ping'.format(port),
                Timeout=5,
                UnhealthyThreshold=2
            ),
            LoadBalancerName=lb_name,
            Listeners=[
                elasticloadbalancing.Listener(
                    InstancePort=port,
                    InstanceProtocol='HTTP',
                    LoadBalancerPort=80,
                    Protocol='HTTP'
                ),
                elasticloadbalancing.Listener(
                    InstancePort=port,
                    InstanceProtocol='HTTP',
                    LoadBalancerPort=443,
                    Protocol='HTTPS',
                    SSLCertificateId=cert_arn
                ),
                elasticloadbalancing.Listener(
                    InstancePort=port,
                    InstanceProtocol='TCP',
                    LoadBalancerPort=8443,
                    Protocol='SSL',
                    SSLCertificateId=cert_arn
                )
            ],
            Policies=[
                elasticloadbalancing.Policy(
                    PolicyName='ELBSecurityPolicyNoTLS10',
                    PolicyType='SSLNegotiationPolicyType',
                    Attributes=[{
                        'Name': 'Reference-Security-Policy',
                        # Disable TLS 1.0 and migrate to TLS 1.2 default for external ELB
                        'Value': 'ELBSecurityPolicy-TLS-1-2-2017-01'
                    }]
                )
            ],
            Scheme=typ,
            SecurityGroups=sg,
            Subnets=[s['SubnetId'] for s in self.get_subnets('private' if typ == 'internal' else 'public')],
            Tags=self.get_tags(
                service_override="InternalELB" if typ == 'internal' else "ExternalELB",
                role_override=lb_name
            ) + [ec2.Tag('Name', lb_name)]
        )
예제 #6
0
def main():
    template = Template()
    template.add_version("2010-09-09")

    template.set_description(
        "AWS CloudFormation Sample Template: ELB with 2 EC2 instances")

    AddAMI(template)

    # Add the Parameters
    keyname_param = template.add_parameter(
        Parameter(
            "KeyName",
            Type="String",
            Default="mark",
            Description="Name of an existing EC2 KeyPair to "
            "enable SSH access to the instance",
        ))

    template.add_parameter(
        Parameter(
            "InstanceType",
            Type="String",
            Description="WebServer EC2 instance type",
            Default="m1.small",
            AllowedValues=[
                "t1.micro", "m1.small", "m1.medium", "m1.large", "m1.xlarge",
                "m2.xlarge", "m2.2xlarge", "m2.4xlarge", "c1.medium",
                "c1.xlarge", "cc1.4xlarge", "cc2.8xlarge", "cg1.4xlarge"
            ],
            ConstraintDescription="must be a valid EC2 instance type.",
        ))

    webport_param = template.add_parameter(
        Parameter(
            "WebServerPort",
            Type="String",
            Default="8888",
            Description="TCP/IP port of the web server",
        ))

    # Define the instance security group
    instance_sg = template.add_resource(
        ec2.SecurityGroup(
            "InstanceSecurityGroup",
            GroupDescription="Enable SSH and HTTP access on the inbound port",
            SecurityGroupIngress=[
                ec2.SecurityGroupRule(
                    IpProtocol="tcp",
                    FromPort="22",
                    ToPort="22",
                    CidrIp="0.0.0.0/0",
                ),
                ec2.SecurityGroupRule(
                    IpProtocol="tcp",
                    FromPort=Ref(webport_param),
                    ToPort=Ref(webport_param),
                    CidrIp="0.0.0.0/0",
                ),
            ]))

    # Add the web server instances
    web_instances = []
    for name in ("Ec2Instance1", "Ec2Instance2"):
        instance = template.add_resource(
            ec2.Instance(
                name,
                SecurityGroups=[Ref(instance_sg)],
                KeyName=Ref(keyname_param),
                InstanceType=Ref("InstanceType"),
                ImageId=FindInMap("RegionMap", Ref("AWS::Region"), "AMI"),
                UserData=Base64(Ref(webport_param)),
            ))
        web_instances.append(instance)

    elasticLB = template.add_resource(
        elb.LoadBalancer(
            'ElasticLoadBalancer',
            AccessLoggingPolicy=elb.AccessLoggingPolicy(
                EmitInterval=5,
                Enabled=True,
                S3BucketName="logging",
                S3BucketPrefix="myELB",
            ),
            AvailabilityZones=GetAZs(""),
            ConnectionDrainingPolicy=elb.ConnectionDrainingPolicy(
                Enabled=True,
                Timeout=300,
            ),
            CrossZone=True,
            Instances=[Ref(r) for r in web_instances],
            Listeners=[
                elb.Listener(
                    LoadBalancerPort="80",
                    InstancePort=Ref(webport_param),
                    Protocol="HTTP",
                ),
            ],
            HealthCheck=elb.HealthCheck(
                Target=Join("", ["HTTP:", Ref(webport_param), "/"]),
                HealthyThreshold="3",
                UnhealthyThreshold="5",
                Interval="30",
                Timeout="5",
            )))

    template.add_output(
        Output("URL",
               Description="URL of the sample website",
               Value=Join("",
                          ["http://", GetAtt(elasticLB, "DNSName")])))

    print(template.to_json())