如何解决Cloudformation Elasticbeanstalk 为共享负载均衡器指定目标组
我有两个 Cloudformation 模板
我面临的问题是 Environment
模板创建了一个 AWS::ElasticBeanstalk::Environment
,它随后创建了一个新的 CFN 堆栈,其中包含诸如 ASG 和目标组(或众所周知的进程)之类的内容弹性豆茎)。这些资源不是用于创建环境的 AWS 拥有的 CFN 模板的输出。
设置时
- Namespace: aws:elasticbeanstalk:environment
OptionName: LoadBalancerIsShared
Value: true
在我的弹性 beanstalk 环境的选项设置中,没有创建负载平衡器,这很好。然后我尝试将侦听器规则附加到我的负载平衡器侦听器。
ListenerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Priority: 1
ListenerArn:
Fn::ImportValue: !Sub '${NetworkStackName}-HTTPS-Listener'
Actions:
- Type: forward
TargetGroupArn: WHAT_GOES_HERE
Conditions:
- Field: host-header
HostHeaderConfig:
Values:
- mywebsite.com
DependsOn:
- Environment
这里的问题是,据我所知,我无法访问由弹性 beanstalk 环境资源创建的目标组的 ARN。如果我创建了一个目标组,那么它就不会链接到弹性 beantalk 并且不存在任何实例。
我找到了 this page 声明
Elastic Beanstalk 为您的环境创建的资源具有名称。您可以使用这些名称通过函数获取有关资源的信息,或修改资源的属性以自定义其行为。
但是因为它们位于不同的堆栈中(我事先不知道其名称),而不是模板的输出,所以我不知道如何获取它们。
--
编辑:
marcin 在他们的回答中向我指出了自定义资源的方向。我已经稍微扩展了它并让它工作。实现在几个方面略有不同
- 它在 Node 中而不是 Python 中
- 示例中的 api 调用
describe_environment_resources
返回了一个资源列表,但似乎不是全部。在我的实现中,我获取 Auto Scaling 组,并使用物理资源 ID 使用 Cloudformation API 在它所属的堆栈中查找其他资源。
const AWS = require('aws-sdk');
const cfnResponse = require('cfn-response');
const eb = new AWS.ElasticBeanstalk();
const cfn = new AWS.CloudFormation();
exports.handler = (event,context) => {
if (event['RequestType'] !== 'Create') {
console.log(event[RequestType],'is not Create');
return cfnResponse.send(event,context,cfnResponse.SUCCESS,{
Message: `${event['RequestType']} completed.`,});
}
eb.describeEnvironmentResources(
{ EnvironmentName: event['ResourceProperties']['EBEnvName'] },function (err,{ EnvironmentResources }) {
if (err) {
console.log('Exception',e);
return cfnResponse.send(event,cfnResponse.Failed,{});
}
const PhysicalResourceId = EnvironmentResources['AutoScalingGroups'].find(
(group) => group.Name
)['Name'];
const { StackResources } = cfn.describeStackResources(
{ PhysicalResourceId },{ StackResources }) {
if (err) {
console.log('Exception',e);
return cfnResponse.send(event,{});
}
const TargetGroup = StackResources.find(
(resource) =>
resource.LogicalResourceId === 'AWSEBV2LoadBalancerTargetGroup'
);
cfnResponse.send(event,{
TargetGroupArn: TargetGroup.PhysicalResourceId,});
}
);
}
);
};
Cloudformation 模板
LambdaBasicExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AWSCloudFormationReadOnlyAccess
- arn:aws:iam::aws:policy/AWSElasticBeanstalkReadOnly
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
GetEBLBTargetGroupLambda:
Type: AWS::Lambda::Function
Properties:
Handler: index.handler
Description: 'Get ARN of EB Load balancer'
Timeout: 30
Role: !GetAtt 'LambdaBasicExecutionRole.Arn'
Runtime: nodejs12.x
Code:
ZipFile: |
... code ...
ListenerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Priority: 1
ListenerArn:
Fn::ImportValue: !Sub '${NetworkStackName}-HTTPS-Listener'
Actions:
- Type: forward
TargetGroupArn:
Fn::GetAtt: ['GetEBLBTargetGroupResource','TargetGroupArn']
Conditions:
- Field: host-header
HostHeaderConfig:
Values:
- mydomain.com
我在做这件事时学到的东西,希望能帮助到其他人
- 使用默认的 cfn-response 库在 Node 中使用
async
处理程序很困难,该库不是异步的,导致 Cloudformation 创建(和删除)过程在回滚之前挂起数小时。 - 如果您使用
cfn-response
,则 cloudformation 会自动包含ZipFile
库。如果您非常愿意手动包含代码(您也可以将其包装在一个 Promise 中并使用异步 lambda 处理程序),那么该代码在 AWS Docs 上可用。 npm 上也有包可以达到同样的效果。 - Node 14.x 无法运行,Cloudformation 出现错误。不幸的是,我没有记下它是什么。
- 提供的示例中使用的策略
AWSElasticBeanstalkFullAccess
不再存在,并已替换为AdministratorAccess-AWSElasticBeanstalk
。 - 我上面的示例需要较少的宽松政策,但我尚未在测试中解决这个问题。如果它只能读取特定的弹性豆茎环境等就更好了。
解决方法
据我所知,我无权访问由弹性豆茎环境资源创建的目标组的 ARN
确实如此。克服这个问题的方法是通过 custom resource。事实上,我为我的 previous answers 之一开发了完全可用的非常相似的资源,因此您可以查看它并采用您的模板。该资源返回 EB 负载均衡器的 ARN,但您可以修改它以获取 EB 目标组的 ARN。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。