-->

How To Extract Load Balancer Name from Elastic Bea

2019-08-18 05:20发布

问题:

I have created a Elastic Beanstalk and CloudWatch Alarm in CloudFormation with the following code snippet:

        "ElasticBeanstalkEnvironment": {
        "Type": "AWS::ElasticBeanstalk::Environment",
        "Properties": {
            "ApplicationName": "my-app",
            "EnvironmentName": "my-eb",
            "SolutionStackName": "64bit Amazon Linux 2018.03 v3.0.1 running Tomcat 8 Java 8",
            "OptionSettings": [
                {
                    "Namespace": "aws:elb:loadbalancer",
                    "OptionName": "CrossZone",
                    "Value": "true"
                },
                {
                    "Namespace": "aws:elb:listener:80",
                    "OptionName": "ListenerProtocol",
                    "Value": "HTTP"
                },
                {
                    "Namespace": "aws:elb:listener:80",
                    "OptionName": "InstancePort",
                    "Value": "80"
                },
                etc...
            ]
        },
        "CloudWatchBacken500XXAlarm": {
            "Type": "AWS::CloudWatch::Alarm",
            "Properties" : {
                "AlarmActions": ["arn:aws:sns:us-east-1:12345678:mysnstopic"],
                "Namespace": "AWS/ELB",
                "Dimensions": [{
                    "Name": "LoadBalancerName",
                    "Value" : {
                        "Fn::GetAtt": [
                            "ElasticBeanstalkEnvironment",
                            "EndpointURL"  
                        ]
                    }
                  }],
                "MetricName": "HTTPCode_Backend_5XX",
                "Statistic": "Sum",
                "Period": "60",
                "EvaluationPeriods": "1",
                "ComparisonOperator": "GreaterThanOrEqualToThreshold",
                "Threshold": "1"
                }
        }

You can see that the CloudWatch Alarm is configured to alert if the Elastic Beanstalk's load balancer receives 5XX Errors. However I am not able to get the load balancer Name attribute which would look something like this:

awseb-e-a-AWSEBLoa-AY8LC6V30OAW

Instead the Fn::GetAtt("EndpointURL") attribute returns the load balancer's DNSName which looks something like this:

awseb-e-a-AWSEBLoa-AY8LC6V30OAW-175133046.us-east-1.elb.amazonaws.com

Which will fail to create the CloudWatch alarm correctly as it expects to get the load balancer Name not DNSName.

What's the best way to get the Load Balancer's Name? I don't want to have to create the Load Balancer as an external resource like "AWS::ElasticLoadBalancing::LoadBalancer" or try to use some substring method to extract the Name string from the DNSName string.

回答1:

If you have access to the environment name, you can perform a DescribeEnvironmentResources API call. The response would include information about the loadbalancer of your environment.



回答2:

OK I found a solution, its quite the hack, I have been able to extract the LoadBalancerName from the endpoint using several Split/Select/Join calls on the DNSName string returned from - Fn::GetAtt("EndpointURL"). Here is the code:

"CloudWatchBackend500XXAlarm": {
"Type": "AWS::CloudWatch::Alarm",
"Properties" : {
    "AlarmDescription": "Elastic Beanstalk Has Received 5XX Backend Connection Errors",
    "AlarmActions": ["arn:aws:sns:us-east-1:1234567890:mysnstopic"],
    "Namespace": "AWS/ELB",
    "Dimensions": [
        {
            "Name": "LoadBalancerName",
            "Value": {
                "Fn::Join": ["", [{
                    "Fn::Select": [
                        "0",
                        {
                            "Fn::Split": ["AWSEBLoa-",
                                {
                                    "Fn::GetAtt": [
                                        "ElasticBeanstalkEnvironment",
                                        "EndpointURL"
                                    ]
                                }
                            ]
                        }
                    ]
                },
                "AWSEBLoa-",
                {
                    "Fn::Select": [
                        "0",
                        {
                            "Fn::Split": ["-",
                                {
                                    "Fn::Select": [
                                        "1",
                                        {
                                            "Fn::Split": ["AWSEBLoa-",
                                                {
                                                    "Fn::GetAtt": [
                                                        "ElasticBeanstalkEnvironment",
                                                        "EndpointURL"
                                                    ]
                                                }
                                            ]
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]]
        }
        }
    ],                  
    "MetricName": "HTTPCode_Backend_5XX",
    "Statistic": "Sum",
    "Period": "60",
    "EvaluationPeriods": "1",
    "ComparisonOperator": "GreaterThanOrEqualToThreshold",
    "Threshold": "1"
}

}

ie the code above is able to extract 'awseb-k-3-AWSEBLoa-11B26NY4PQB9A' from 'awseb-k-3-AWSEBLoa-11B26NY4PQB9A-739614614.us-east-1.elb.amazonaws.com' and the CloudWatch alarm works perfectly. I think I would have to adjust the code to work with internal load balancers, ie formatted with 'internal-' at the start of the DNSName but I am fine for now.

I've submitted a request to AWS asking them to add a CloudFormation method to return the LoadBalancer Name and not just the DNSName.