【问题标题】:How To Extract Load Balancer Name from Elastic Beanstalk Environment in CloudFormation如何从 CloudFormation 中的 Elastic Beanstalk 环境中提取负载均衡器名称
【发布时间】:2019-01-24 14:54:23
【问题描述】:

我使用以下代码 sn-p 在 CloudFormation 中创建了 Elastic Beanstalk 和 CloudWatch 警报:

        "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"
                }
        }

您可以看到 CloudWatch 警报配置为在 Elastic Beanstalk 的负载均衡器收到 5XX 错误时发出警报。但是我无法获得看起来像这样的负载均衡器名称属性:

awseb-e-a-AWSEBLoa-AY8LC6V30OAW

取而代之的是 Fn::GetAtt("EndpointURL") 属性返回负载均衡器的 DNSName,它看起来像这样:

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

这将无法正确创建 CloudWatch 警报,因为它期望获取负载均衡器名称而不是 DNSName。

获取负载均衡器名称的最佳方法是什么?我不想将负载均衡器创建为外部资源,例如“AWS::ElasticLoadBalancing::LoadBalancer”,或者尝试使用一些子字符串方法从 DNSName 字符串中提取名称字符串。

【问题讨论】:

    标签: amazon-web-services amazon-elastic-beanstalk amazon-cloudformation elastic-load-balancer


    【解决方案1】:

    如果您有权访问环境名称,则可以执行DescribeEnvironmentResources API 调用。响应将包含有关您环境的负载均衡器的信息。

    【讨论】:

    • 他如何将 api 调用集成到 cloudformation 中?
    【解决方案2】:

    好的,我找到了一个解决方案,它完全是 hack,我已经能够使用从 - Fn::GetAtt("EndpointURL") 返回的 DNSName 字符串上的多个 Split/Select/Join 调用从端点提取 LoadBalancerName。这是代码:

    "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"
    }
    

    }

    即上面的代码能够从“awseb-k-3-AWSEBLoa-11B26NY4PQB9A-739614614.us-east-1.elb.amazonaws.com”和CloudWatch 警报完美运行。我想我必须调整代码以使用内部负载平衡器,即在 DNSName 的开头使用“internal-”格式化,但我现在很好。

    我已经向 AWS 提交了一个请求,要求他们添加一个 CloudFormation 方法来返回 LoadBalancer 名称,而不仅仅是 DNSName。

    【讨论】:

      【解决方案3】:

      使用 ebextensions 会更容易创建警报 - 因为获取 ELB 名称就像 Value: { "Ref" : "AWSEBLoadBalancer" }

      创建一个扩展名为 .config 的文件(比如 BackendErrors.config),并将其放在一个名为“.ebextensions”的文件夹中。完整的ebextension如下:

      Resources:
        CloudWatchBacken500XXAlarm:
          Type: AWS::CloudWatch::Alarm
          Properties:
            AlarmDescription: "Elastic Beanstalk Has Received 5XX Backend Connection Errors"
            AlarmName: { "Fn::Join" : ["", [{ "Ref" : "AWSEBEnvironmentName" }, "-Backend-5XX-Alarm." ]]}
            AlarmActions:
              - "arn:aws:sns:us-east-1:123456789012:mysnstopic"
            Namespace: AWS/ELB
            Dimensions:
              - Name: LoadBalancerName
                Value: { "Ref" : "AWSEBLoadBalancer" }
            MetricName: HTTPCode_Backend_5XX
            Statistic: Sum
            Period: 60
            EvaluationPeriods: 1
            Threshold: 1
            ComparisonOperator: GreaterThanOrEqualToThreshold
      

      .ebextensions 文件夹应该在您的应用程序源包的顶层创建:

      ~/workspace/my-application/
      |-- .ebextensions
      |   |-- BackendErrors.config
      

      【讨论】:

        【解决方案4】:

        几年后来到这里,亚马逊现在似乎添加了该属性:

        https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-loadbalancer.html

        引用:

        LoadBalancerFullName

        负载均衡器的全名。例如,app/my-load-balancer/50dc6c495c0c9188。

        所以你现在可以这样做了:

          Dimensions:
            - Name: LoadBalancer
              Value: !GetAtt YourALBRef.LoadBalancerFullName
        

        【讨论】:

        • 问题是如何提取 Elastic Beanstalk 创建的负载均衡器 ARN。
        【解决方案5】:

        如果上面的代码的作用不明显: 它提取 -xxxxxxxx.region.elb.amazonaws.com 之前的名称部分

        这对于经典负载均衡器来说已经足够了,因为它们只有一个名称,而 Cloudwatch 能够通过它们的名称来监控这些负载均衡器。

        对于应用程序负载均衡器,情况就不同了: ApplicationLoadbalancers 除了他们的名字之外,他们确实有自己的arn,格式为:

        arn:aws:elasticloadbalancing:REGION:ACCOUNT:loadbalancer/XXXXX/my-load-balancer/DDDDDDDD

        XXXXX 是一个区域相关的字符串(我在我们找到 application,在欧洲找到 app)和 DDDDDDDD 是任意数字。

        Cloudwatch 需要这个 loadBalancerFullName 来监控这个 LB。 很遗憾,如果你有一个应用程序负载均衡器,你就不能使用这个技巧。

        【讨论】:

          猜你喜欢
          • 2013-08-10
          • 1970-01-01
          • 2014-02-11
          • 2016-12-13
          • 2020-11-21
          • 2019-04-21
          • 1970-01-01
          • 2019-07-30
          • 2017-02-14
          相关资源
          最近更新 更多