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", )
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')]
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
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')
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)] )
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())