如何从 CloudFormation 中的 Elastic Beanstalk 环境中提取负载均衡器名称
Posted
技术标签:
【中文标题】如何从 CloudFormation 中的 Elastic Beanstalk 环境中提取负载均衡器名称【英文标题】:How To Extract Load Balancer Name from Elastic Beanstalk Environment in CloudFormation 【发布时间】: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 字符串中提取名称字符串。
【问题讨论】:
【参考方案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。
很遗憾,如果你有一个应用程序负载均衡器,你就不能使用这个技巧。
【讨论】:
以上是关于如何从 CloudFormation 中的 Elastic Beanstalk 环境中提取负载均衡器名称的主要内容,如果未能解决你的问题,请参考以下文章
从 CloudFormation 模板中的 DropDownList 中选择多个值
AWS CloudFormation:如何从另一个AWS账户为Lambda代码指定存储桶?
从 lambda 函数中检索 cloudformation 堆栈名称