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 create_load_balancer(self, tile_server_lb_security_group): tile_server_lb_name = 'elbTileServer' return self.add_resource(elb.LoadBalancer( tile_server_lb_name, ConnectionDrainingPolicy=elb.ConnectionDrainingPolicy( Enabled=True, Timeout=300, ), CrossZone=True, SecurityGroups=[Ref(tile_server_lb_security_group)], Listeners=[ elb.Listener( LoadBalancerPort='80', InstancePort='80', Protocol='HTTP', ), elb.Listener( LoadBalancerPort='443', InstancePort='80', Protocol='HTTPS', SSLCertificateId=Ref(self.ssl_certificate_arn) ) ], HealthCheck=elb.HealthCheck( Target='HTTP:80/health-check/', HealthyThreshold='3', UnhealthyThreshold='2', Interval='30', Timeout='5', ), Subnets=Ref(self.public_subnets), Tags=self.get_tags(Name=tile_server_lb_name) ))
def create_load_balancer(self, worker_lb_security_group): worker_lb_name = 'elbWorker' return self.add_resource(elb.LoadBalancer( worker_lb_name, ConnectionDrainingPolicy=elb.ConnectionDrainingPolicy( Enabled=True, Timeout=300, ), CrossZone=True, SecurityGroups=[Ref(worker_lb_security_group)], Listeners=[ elb.Listener( LoadBalancerPort='80', InstancePort='80', Protocol='HTTP', ) ], HealthCheck=elb.HealthCheck( Target='HTTP:80/', HealthyThreshold='3', UnhealthyThreshold='2', Interval='60', Timeout='10', ), Subnets=Ref(self.public_subnets), Tags=self.get_tags(Name=worker_lb_name) ))
def create_load_balancer(self, elb_args): ''' Method creates a elastic load balancer and adds it to the resources list @param elb_args [dict] collection of keyword arguments for the elastic load balancer ''' health_check_args = elb_args['health_check'] health_check = elb.HealthCheck( Target=health_check_args['target'], HealthyThreshold=health_check_args['healthy_threshold'], UnhealthyThreshold=health_check_args['unhealthy_threshold'], Interval=health_check_args['interval'], Timeout=health_check_args['timeout'], ) listener_args = elb_args['listener'] listener = elb.Listener( LoadBalancerPort=listener_args['load_balancer_port'], InstancePort=listener_args['instance_port'], Protocol=listener_args['protocol'], InstanceProtocol=listener_args['instance_protocol'], ) self.load_balancer = LoadBalancer( "LoadBalancer", ConnectionDrainingPolicy=elb.ConnectionDrainingPolicy( Enabled=True, Timeout=120, ), Subnets=self.subnets, HealthCheck=health_check, Listeners=[ listener, ], CrossZone=True, SecurityGroups=[Ref(self.load_balancer_security_group)], LoadBalancerName="Cloudformation-Loadbalancer", Scheme="internet-facing", ) self.add_resource(self.load_balancer) if elb_args.has_key('output_dns'): self.add_output( Output("ELBDNS", Description="DNS Name of ELB", Value=Join( "", ["http://", GetAtt(self.load_balancer, "DNSName")])))
def add_elb(self): self.ElasticLoadBalancer = self.template.add_resource( elb.LoadBalancer( "ElbWeb", Subnets=[Ref(self.Subnet1), Ref(self.Subnet2)], Listeners=[{ "InstancePort": "80", "LoadBalancerPort": "80", "Protocol": "HTTP" }], CrossZone="true", LoadBalancerName=Join("-", ["elb", Ref(self.Project)]), SecurityGroups=[Ref(self.ElbSecurityGroup)], ConnectionDrainingPolicy=elb.ConnectionDrainingPolicy( Enabled=True, Timeout=300, ), HealthCheck=elb.HealthCheck( HealthyThreshold="3", Interval="30", Target="HTTP:80/", Timeout="5", UnhealthyThreshold="5", ), Tags=Tags( Name=Join("-", ["ELB", Ref(self.Project)]), Environment=Ref(self.Environment), ), )) self.ELBcname = self.template.add_resource( route53.RecordSetType( "ELBcname", HostedZoneName=Join("", [Ref(self.Domain), "."]), Comment="CNAME to Web ELB", Name=Join( ".", [Ref(self.Hostname), Ref(self.Domain)]), Type="CNAME", TTL="60", ResourceRecords=[GetAtt(self.ElasticLoadBalancer, "DNSName")]))
def elastic_lb(template, name, instances, subnets, instance_port=443, load_balancer_port=443, instance_proto="HTTPS", load_balancer_proto='HTTPS', securitygroups=None, health_check=None, scheme=None): """Create an elastic load balancer """ elasticlb = elb.LoadBalancer( name, template=template, Subnets=[Ref(r) for r in subnets], SecurityGroups=[Ref(r) for r in securitygroups], ConnectionDrainingPolicy=elb.ConnectionDrainingPolicy(Enabled=True, Timeout=300), CrossZone=True, Instances=[Ref(r.title) for r in instances]) listener = elb.Listener() listener.LoadBalancerPort = load_balancer_port listener.InstancePort = instance_port listener.Protocol = load_balancer_proto listener.InstanceProtocol = instance_proto if load_balancer_proto == 'HTTPS': listener.SSLCertificateId = PROD_OPS_CERTIFICATE elasticlb.Listeners = [listener] if health_check: elasticlb.HealthCheck = health_check if scheme: elasticlb.Scheme = scheme return elasticlb
def render_elb(context, template, ec2_instances): elb_is_public = True if context['full_hostname'] else False listeners_policy_names = [] app_cookie_stickiness_policy = [] lb_cookie_stickiness_policy = [] if context['elb']['stickiness']: if context['elb']['stickiness']['type'] == 'cookie': app_cookie_stickiness_policy = [ elb.AppCookieStickinessPolicy( CookieName=context['elb']['stickiness']['cookie-name'], PolicyName='AppCookieStickinessPolicy') ] listeners_policy_names.append('AppCookieStickinessPolicy') elif context['elb']['stickiness']['type'] == 'browser': lb_cookie_stickiness_policy = [ elb.LBCookieStickinessPolicy( PolicyName='BrowserSessionLongCookieStickinessPolicy') ] listeners_policy_names.append( 'BrowserSessionLongCookieStickinessPolicy') else: raise ValueError('Unsupported stickiness: %s' % context['elb']['stickiness']) protocols = _elb_protocols(context) listeners = [] elb_ports = [] for protocol in protocols: if protocol == 'http': listeners.append( elb.Listener( InstanceProtocol='HTTP', InstancePort='80', LoadBalancerPort='80', PolicyNames=listeners_policy_names, Protocol='HTTP', )) elb_ports.append(80) elif protocol == 'https': listeners.append( elb.Listener(InstanceProtocol='HTTP', InstancePort='80', LoadBalancerPort='443', PolicyNames=listeners_policy_names, Protocol='HTTPS', SSLCertificateId=context['elb']['certificate'])) elb_ports.append(443) elif isinstance(protocol, int): port = protocol listeners.append( elb.Listener(InstanceProtocol='TCP', InstancePort=str(port), LoadBalancerPort=str(port), PolicyNames=listeners_policy_names, Protocol='TCP')) elb_ports.append(port) else: raise RuntimeError("Unknown procotol `%s`" % context['elb']['protocol']) for _, listener in context['elb']['additional_listeners'].items(): listeners.append( elb.Listener(InstanceProtocol='HTTP', InstancePort=str(listener['port']), LoadBalancerPort=str(listener['port']), PolicyNames=listeners_policy_names, Protocol=listener['protocol'].upper(), SSLCertificateId=context['elb']['certificate'])) elb_ports.append(listener['port']) template.add_resource( elb.LoadBalancer( ELB_TITLE, AppCookieStickinessPolicy=app_cookie_stickiness_policy, ConnectionDrainingPolicy=elb.ConnectionDrainingPolicy( Enabled=True, Timeout=60, ), ConnectionSettings=elb.ConnectionSettings( IdleTimeout=context['elb']['idle_timeout']), CrossZone=True, Instances=lmap(Ref, ec2_instances.values()), # TODO: from configuration Listeners=listeners, LBCookieStickinessPolicy=lb_cookie_stickiness_policy, HealthCheck=elb.HealthCheck( Target=_elb_healthcheck_target(context), HealthyThreshold=str(context['elb']['healthcheck'].get( 'healthy_threshold', 10)), UnhealthyThreshold=str(context['elb']['healthcheck'].get( 'unhealthy_threshold', 2)), Interval=str(context['elb']['healthcheck'].get('interval', 30)), Timeout=str(context['elb']['healthcheck'].get('timeout', 30)), ), SecurityGroups=[Ref(SECURITY_GROUP_ELB_TITLE)], Scheme='internet-facing' if elb_is_public else 'internal', Subnets=context['elb']['subnets'], Tags=elb_tags(context))) template.add_output( mkoutput("ElasticLoadBalancer", "Generated name of the ELB", Ref(ELB_TITLE))) template.add_resource( security_group(SECURITY_GROUP_ELB_TITLE, context['aws']['vpc-id'], _convert_ports_to_dictionary( elb_ports))) # list of strings or dicts if any([context['full_hostname'], context['int_full_hostname']]): dns = external_dns_elb if elb_is_public else internal_dns_elb template.add_resource(dns(context)) if context['full_hostname']: [template.add_resource(cname) for cname in cnames(context)]
def create_load_balancer(template, name, vpc_id, subnets=None, region='us-east-1', availability_zones=None, elb_port=80, security_groups=None, http_health_check_url=None, instance_port=8080, ssl_cert=None): health_target = "HTTP:{}/{}".format(instance_port, http_health_check_url) if http_health_check_url else "TCP:{}".format( instance_port) health_check = elb.HealthCheck( Target=health_target, HealthyThreshold="2", UnhealthyThreshold="10", Interval="30", Timeout="15" ) if not security_groups: security_groups = [ template.add_resource(ec2.SecurityGroup( "ELBSecurityGroup" + name, GroupDescription="ELB SG", SecurityGroupIngress=[ ec2.SecurityGroupRule( IpProtocol="tcp", FromPort=elb_port, ToPort=elb_port, CidrIp="0.0.0.0/0" ), ], VpcId=vpc_id )) ] security_group_refs = [Ref(sg) for sg in security_groups] if not subnets: subnets = _get_vpc_subnets(vpc_id, region) if not availability_zones: availability_zones = _all_az(region) listeners = [ elb.Listener( LoadBalancerPort=elb_port, InstancePort=instance_port, Protocol="HTTP", InstanceProtocol="HTTP" )] if ssl_cert: listeners.append(elb.Listener( LoadBalancerPort="443", InstancePort=instance_port, Protocol="HTTPS", InstanceProtocol="HTTP", SSLCertificateId=ssl_cert )) elb_name = "LoadBalancer" + name lb = template.add_resource(LoadBalancer( elb_name, ConnectionDrainingPolicy=elb.ConnectionDrainingPolicy( Enabled=True, Timeout=120, ), HealthCheck=health_check, Listeners=listeners, CrossZone=True, SecurityGroups=security_group_refs, LoadBalancerName=name, Scheme="internet-facing", Subnets=subnets )) template.add_output(Output( "HostUrl" + name, Description="Microservice endpoint", Value=Join("", ["http://", GetAtt(lb, "DNSName")]) )) return { 'elb': {'name': elb_name, 'elb': lb}, 'security_groups': security_groups }
def generate_cloudformation_template(): template = Template() template.add_description("""\ Configures Auto Scaling Group for the app""") hostedzone = template.add_parameter( Parameter( "HostedZoneName", Description= "The DNS name of an existing Amazon Route 53 hosted zone", Type="String", )) dnsRecord = template.add_parameter(Parameter( "DNSRecord", Type="String", )) loadbalancersecuritygroup = template.add_parameter( Parameter( "LoadBalancerSecurityGroup", Type="String", Description="Security group for api app load balancer.", )) 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", )) environment = template.add_parameter( Parameter( "Environment", Type="String", Description="The environment being deployed into", )) subnet = template.add_parameter( Parameter( "Subnets", Type="CommaDelimitedList", )) loadbalancername = template.add_parameter( Parameter( "LoadBalancerName", Type="String", )) elbSchema = template.add_parameter( Parameter( "LoadBalancerSchema", Type="String", )) healthCheckTarget = template.add_parameter( Parameter( "LoadBalancerHealthCheckTarget", Type="String", )) healthCheckInterval = template.add_parameter( Parameter( "LoadBalancerHealthCheckInterval", Type="String", )) healthCheckTimeout = template.add_parameter( Parameter( "LoadBalancerHealthCheckTimeout", Type="String", )) healthyThreshold = template.add_parameter( Parameter( "LoadBalancerHealthyThreshold", Type="String", )) unhealthyThreshold = template.add_parameter( Parameter( "LoadBalancerUnHealthyThreshold", Type="String", )) launchconfigurationname = template.add_parameter( Parameter( "LaunchConfigurationName", Type="String", )) loadbalancer = template.add_resource( elb.LoadBalancer( "LoadBalancer", ConnectionDrainingPolicy=elb.ConnectionDrainingPolicy( Enabled=True, Timeout=30, ), Subnets=Ref(subnet), HealthCheck=elb.HealthCheck( Target=Ref(healthCheckTarget), HealthyThreshold=Ref(healthyThreshold), UnhealthyThreshold=Ref(unhealthyThreshold), Interval=Ref(healthCheckInterval), Timeout=Ref(healthCheckTimeout), ), Listeners=[ elb.Listener( LoadBalancerPort="80", InstancePort="80", Protocol="HTTP", InstanceProtocol="HTTP", ), ], CrossZone=True, SecurityGroups=[Ref(loadbalancersecuritygroup)], LoadBalancerName=Ref(loadbalancername), Scheme=Ref(elbSchema), )) autoscalinggroup = template.add_resource( AutoScalingGroup("AutoscalingGroup", Tags=[Tag("Environment", Ref(environment), True)], LaunchConfigurationName=Ref(launchconfigurationname), MinSize=Ref(minsize), MaxSize=Ref(maxsize), DesiredCapacity=Ref(scalecapacity), LoadBalancerNames=[Ref(loadbalancer)], VPCZoneIdentifier=Ref(subnet), HealthCheckType='ELB', HealthCheckGracePeriod=30, UpdatePolicy=UpdatePolicy( AutoScalingRollingUpdate=AutoScalingRollingUpdate( PauseTime='PT1M', MinInstancesInService="1", MaxBatchSize='1')))) route53record = template.add_resource( RecordSetType( "myDNSRecord", HostedZoneName=Join("", [Ref(hostedzone), "."]), Name=Join("", [Ref(dnsRecord), ".", Ref(hostedzone), "."]), Type="CNAME", TTL="300", ResourceRecords=[GetAtt(loadbalancer, "DNSName")], )) 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="Created Auto Scaling Group")) template.add_output( Output("LaunchConfiguration", Value=Ref(launchconfigurationname), Description="LaunchConfiguration for this deploy")) return template
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 add_resources(self): self.LoyaltyNavigatorPublicLBSG = self.template.add_resource(ec2.SecurityGroup( "LoyaltyNavigatorPublicLBSG", GroupDescription="Loadbalancer Security Group For Loyalty Navigator Public LB", VpcId=Ref(self.VpcId), SecurityGroupIngress=[ ec2.SecurityGroupRule( IpProtocol="tcp", FromPort=3389, ToPort=3389, CidrIp=Ref(self.AdminCidrBlock), ), ec2.SecurityGroupRule( IpProtocol="tcp", FromPort=80, ToPort=80, CidrIp=Ref(self.AdminCidrBlock), ), ], Tags=self.base_tags + Tags(Name=self.environment_parameters["ClientEnvironmentKey"] + "-LoyaltyNavigatorPublicLBSG"), )) self.LoyaltyNavigatorSG = self.template.add_resource(ec2.SecurityGroup( "LoyaltyNavigatorSG", GroupDescription="Allow communication between Loyalty Navigator Load Balancer and Loyalty NavigatorEc2s", VpcId=Ref(self.VpcId), SecurityGroupIngress=[ ec2.SecurityGroupRule( IpProtocol="tcp", FromPort=3389, ToPort=3389, SourceSecurityGroupId=Ref(self.LoyaltyNavigatorPublicLBSG), ), ec2.SecurityGroupRule( IpProtocol="tcp", FromPort=80, ToPort=80, SourceSecurityGroupId=Ref(self.LoyaltyNavigatorPublicLBSG), ), ], Tags=self.base_tags + Tags(Name=self.environment_parameters["ClientEnvironmentKey"] + "-LoyaltyNavigatorEc2SG"), )) self.LoyaltyNavigatorPublicLoadBalancer = self.template.add_resource(elasticloadbalancing.LoadBalancer( "LoyaltyNavigatorPublicLoadBalancer", LoadBalancerName=self.environment_parameters["ClientEnvironmentKey"] + "-LoyaltyNavigatorPubLB", Scheme="internet-facing", Listeners=[ elasticloadbalancing.Listener( LoadBalancerPort="3389", InstancePort="3389", Protocol="TCP", InstanceProtocol="TCP", ), elasticloadbalancing.Listener( LoadBalancerPort="80", InstancePort="80", Protocol="HTTP", InstanceProtocol="HTTP", ) ], Instances=[], SecurityGroups=[Ref(self.LoyaltyNavigatorPublicLBSG)], Subnets=[Ref(self.RESTPubSubnet1), Ref(self.RESTPubSubnet2)], ConnectionDrainingPolicy=elasticloadbalancing.ConnectionDrainingPolicy( Enabled=True, Timeout=300, ), CrossZone=True, HealthCheck=elasticloadbalancing.HealthCheck( Target=Join("", ["TCP:", "3389"]), HealthyThreshold="3", UnhealthyThreshold="5", Interval="10", Timeout="5", ), Tags=self.base_tags + Tags(Name=self.environment_parameters["ClientEnvironmentKey"] + "-LoyaltyNavigatorPubLB"), )) self.LoyaltyNavigatorLaunchConfiguration = self.template.add_resource(LaunchConfiguration( "LoyaltyNavigatorLaunchConfiguration", ImageId=Ref(self.LoyaltyNavigatorImageId), InstanceType=Ref(self.LoyaltyNavigatorInstanceType), IamInstanceProfile=Ref(self.LoyaltyNavigatorIAMInstanceProfile), KeyName=Ref(self.LoyaltyNavigatorKeyName), SecurityGroups=[Ref(self.LoyaltyNavigatorSG)], )) self.LoyaltyNavigatorAutoScalingGroup = self.template.add_resource(AutoScalingGroup( "LoyaltyNavigatorAutoscalingGroup", AutoScalingGroupName=self.environment_parameters["ClientEnvironmentKey"] + "-LoyaltyNavigatorAutoScalingGroup", LaunchConfigurationName=Ref(self.LoyaltyNavigatorLaunchConfiguration), LoadBalancerNames=[Ref(self.LoyaltyNavigatorPublicLoadBalancer), Ref(self.LoyaltyNavigatorPublicLoadBalancer)], MaxSize=Ref(self.LoyaltyNavigatorASGGroupMaxSize), MinSize=Ref(self.LoyaltyNavigatorASGGroupMinSize), DesiredCapacity=Ref(self.LoyaltyNavigatorASGGroupDesiredSize), HealthCheckType=Ref(self.LoyaltyNavigatorASGHealthCheckType), HealthCheckGracePeriod=Ref(self.LoyaltyNavigatorASGHealthCheckGracePeriod), Cooldown=Ref(self.LoyaltyNavigatorASGCoolDown), VPCZoneIdentifier=[Ref(self.RESTPrivSubnet1), Ref(self.RESTPrivSubnet2)], Tags=[ AutoScalingTag("Name", self.environment_parameters["ClientEnvironmentKey"] + "-LoyaltyNavigator-Ec2", True), AutoScalingTag("Environment", self.environment_parameters["EnvironmentName"], True), AutoScalingTag("ResourceOwner", self.environment_parameters["ResourceOwner"], True), AutoScalingTag("ClientCode", self.environment_parameters["ClientEnvironmentKey"], True), ], ))
def render_elb(context, template, ec2_instances): ensure(any([context['full_hostname'], context['int_full_hostname']]), "An ELB must have either an external or an internal DNS entry") elb_is_public = True if context['full_hostname'] else False listeners_policy_names = [] if context['elb']['stickiness']: cookie_stickiness = [ elb.LBCookieStickinessPolicy( PolicyName="BrowserSessionLongCookieStickinessPolicy") ] listeners_policy_names.append( 'BrowserSessionLongCookieStickinessPolicy') else: cookie_stickiness = [] if context['elb']['protocol'] == 'http': listeners = [ elb.Listener( InstanceProtocol='HTTP', InstancePort='80', LoadBalancerPort='80', PolicyNames=listeners_policy_names, Protocol='HTTP', ), ] elif context['elb']['protocol'] == 'https': listeners = [ elb.Listener(InstanceProtocol='HTTP', InstancePort='80', LoadBalancerPort='443', PolicyNames=listeners_policy_names, Protocol='HTTPS', SSLCertificateId=context['elb']['certificate']), ] else: raise RuntimeError("Unknown procotol `%s`" % context['elb']['protocol']) template.add_resource( elb.LoadBalancer( ELB_TITLE, ConnectionDrainingPolicy=elb.ConnectionDrainingPolicy( Enabled=True, Timeout=60, ), ConnectionSettings=elb.ConnectionSettings( IdleTimeout=context['elb']['idle_timeout']), CrossZone=True, Instances=map(Ref, ec2_instances), # TODO: from configuration Listeners=listeners, LBCookieStickinessPolicy=cookie_stickiness, # TODO: from configuration # seems to default to opening a TCP connection on port 80 # HealthCheck=elb.HealthCheck( # Target=Join('', ['HTTP:', Ref(webport_param), '/']), # HealthyThreshold='3', # UnhealthyThreshold='5', # Interval='30', # Timeout='5', # ) SecurityGroups=[Ref(SECURITY_GROUP_TITLE)], Scheme='internet-facing' if elb_is_public else 'internal', Subnets=context['elb']['subnets'], Tags=elb_tags(context))) dns = external_dns_elb if elb_is_public else internal_dns_elb template.add_resource(dns(context))
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())
def elb_asg_lc_template(app, env, nameSGRDS, rdsPort, instanceType, ami, subnets, elbPort, elbCidrBlock, ec2Port, desiredCapacity, minSize, maxSize, region, nameBucket, officeIP): template = Template() sgELB = template.add_resource( SecurityGroup( "SecurityGroupELB" + app + env, GroupDescription="Security group for " + app + "-" + env, VpcId=ImportValue("VPC" + env), SecurityGroupIngress=[ SecurityGroupRule( IpProtocol="tcp", FromPort=elbPort, ToPort=elbPort, CidrIp=elbCidrBlock, ) ], SecurityGroupEgress=[ SecurityGroupRule(IpProtocol="-1", ToPort=0, FromPort=65535, CidrIp="0.0.0.0/0") ], Tags=Tags( env=env, Name="sg-ELB" + app + "-" + env, app=app, ), )) sgEC2 = template.add_resource( SecurityGroup( "SecurityGroupEC2" + app + env, GroupDescription="Security group for EC2 " + app + "-" + env, VpcId=ImportValue("VPC" + env), DependsOn="SecurityGroupELB" + app + env, SecurityGroupIngress=[ SecurityGroupRule( IpProtocol="tcp", FromPort=ec2Port, ToPort=ec2Port, SourceSecurityGroupId=Ref(sgELB), ), SecurityGroupRule( IpProtocol="tcp", FromPort=22, ToPort=22, CidrIp=officeIP, ), ], SecurityGroupEgress=[ SecurityGroupRule(IpProtocol="-1", ToPort=0, FromPort=65535, CidrIp="0.0.0.0/0") ], Tags=Tags( env=env, Name="sg-EC2-" + app + "-" + env, app=app, ), )) addIngressRDS = template.add_resource( SecurityGroupIngress( "ingressSGRDS" + app + env, SourceSecurityGroupId=Ref(sgEC2), Description="From EC2 instances", GroupId=ImportValue("SG-" + nameSGRDS + "-" + app + "-" + env), IpProtocol="tcp", FromPort=rdsPort, ToPort=rdsPort, DependsOn="SecurityGroupEC2" + app + env, )) launchConfig = template.add_resource( LaunchConfiguration("LaunchConfiguration" + app + env, InstanceType=instanceType, ImageId=ami, SecurityGroups=[Ref(sgEC2)], IamInstanceProfile=ImportValue("Role-" + app + "-" + env))) bucketPolicy = template.add_resource( BucketPolicy("BucketPolicy" + nameBucket + app + env, Bucket=ImportValue("Bucket" + nameBucket + app + env), PolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Action": ["s3:PutObject"], "Effect": "Allow", "Resource": Join("", [ "arn:aws:s3:::", ImportValue("Bucket" + nameBucket + app + env), "/AWSLogs/", Ref("AWS::AccountId"), "/*" ]), "Principal": { "AWS": ["156460612806"] } }] })) lb = template.add_resource( LoadBalancer("LoadBalancer" + app + env, ConnectionDrainingPolicy=elb.ConnectionDrainingPolicy( Enabled=True, Timeout=120, ), Subnets=subnets, HealthCheck=elb.HealthCheck( "HealthCheck", Target="TCP:" + str(ec2Port), HealthyThreshold="5", UnhealthyThreshold="5", Interval="30", Timeout="15", ), Listeners=[ elb.Listener( LoadBalancerPort=elbPort, InstancePort=ec2Port, Protocol="HTTP", InstanceProtocol="HTTP", ), ], CrossZone=True, SecurityGroups=[Ref(sgELB)], LoadBalancerName="lb-" + app + "-" + env, Scheme="internet-facing", AccessLoggingPolicy=AccessLoggingPolicy( "LoggingELB" + app + env, EmitInterval=5, Enabled=True, S3BucketName=ImportValue("Bucket" + nameBucket + app + env), ))) asg = template.add_resource( AutoScalingGroup( "AutoscalingGroup" + app + env, DesiredCapacity=desiredCapacity, Tags=[Tag("Environment", env, True)], LaunchConfigurationName=Ref(launchConfig), MinSize=minSize, MaxSize=maxSize, LoadBalancerNames=[Ref(lb)], AvailabilityZones=GetAZs(region), VPCZoneIdentifier=subnets, HealthCheckType="ELB", HealthCheckGracePeriod=300, UpdatePolicy=UpdatePolicy( AutoScalingReplacingUpdate=AutoScalingReplacingUpdate( WillReplace=True, ), AutoScalingRollingUpdate=AutoScalingRollingUpdate( PauseTime='PT5M', MinInstancesInService="1", MaxBatchSize='1', WaitOnResourceSignals=True, )))) return (template.to_json())
def elb_adder(self, name, instance_list, dns): ports = self.config['apps'].values()[0].get("ports", None) elb_type = self.config['apps'].values()[0].get("type", 'internet-facing') elb_check_type = self.config['apps'].values()[0].get( "elb_check_type", 'TCP') elb_check_path = self.config['apps'].values()[0].get( "elb_check_path", "") if 'HTTP' in elb_check_type.upper() and not elb_check_path: elb_check_path = "/" if instance_list is None: instance_list = [] elb_tags = self.__tag_elb_role_generator() elb_id = ''.join(ch for ch in name if ch.isalnum()) elb_sec_group = name + "_group" elb_sec_group = elb_sec_group.translate(None, '_') elasticlb = self.template.add_resource( elb.LoadBalancer( elb_id, Subnets=self.config['public_subnets'], Scheme=elb_type, LoadBalancerName=Join( "", [Ref("AWS::StackName"), '-', random.randint(1, 999)]), SecurityGroups=[Ref(elb_sec_group)], LBCookieStickinessPolicy=[ elb.LBCookieStickinessPolicy( PolicyName='LBCookeStickinessPolicy', ) ], ConnectionDrainingPolicy=elb.ConnectionDrainingPolicy( Enabled=True, Timeout=300, ), CrossZone=True, Instances=[Ref(r) for r in instance_list], Tags=elb_tags)) elasticlb.Listeners = [ elb.Listener(LoadBalancerPort="80", InstancePort=Ref("WebServerPort"), Protocol="HTTP", PolicyNames=['LBCookeStickinessPolicy']), elb.Listener( LoadBalancerPort="443", InstancePort=Ref("WebServerPort"), Protocol="HTTPS", SSLCertificateId=Ref("CertName"), PolicyNames=['LBCookeStickinessPolicy'], ) ] elasticlb.HealthCheck = elb.HealthCheck(Target=Join( "", [elb_check_type.upper(), ":", ports, elb_check_path]), HealthyThreshold="3", UnhealthyThreshold="5", Interval="30", Timeout="5") if dns: self.dns_adder(dns, elb_id) return elasticlb
def getConnectionDrainingPolicy(self): if self.connectionDrainingPolicy is True: return elb.ConnectionDrainingPolicy( Enabled=True, Timeout=self.connectionDrainingPolicy) else: return elb.ConnectionDrainingPolicy(Enabled=False)
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)] )
Scheme="internet-facing", Listeners=[ elb.Listener(LoadBalancerPort="3000", InstancePort="3000", Protocol="HTTP", InstanceProtocol="HTTP"), ], HealthCheck=elb.HealthCheck( Target="HTTP:3000/", HealthyThreshold="5", UnhealthyThreshold="2", Interval="20", Timeout="15", ), ConnectionDrainingPolicy=elb.ConnectionDrainingPolicy( Enabled=True, Timeout=10, ), CrossZone=True, Subnets=Ref("PublicSubnet"), SecurityGroups=[Ref("LoadBalancerSecurityGroup")], )) ud = Base64( Join('\n', [ "#!/bin/bash", "yum install --enablerepo=epel -y git", "pip install ansible", AnsiblePullCmd, "echo '*/10 * * * * {}' > /etc/cron.d/ansible-pull".format( AnsiblePullCmd) ])) t.add_resource(
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')) ])