Cloudformation Elasticbeanstalk 为共享负载均衡器指定目标组
Cloudformation Elasticbeanstalk specify target group for shared load balancer
我有两个 Cloudformation 模板
- 创建 VPC、ALB 和任何其他共享资源等的
- 创建弹性 beantalk 环境和相关侦听器规则以使用导入的共享负载均衡器将流量定向到此环境的一个(调用此模板
Environment
)
我面临的问题是 Environment
模板创建了一个 AWS::ElasticBeanstalk::Environment
,它随后创建了一个新的 CFN 堆栈,其中包含 ASG 和目标组(或流程原样)等内容弹性豆茎已知)。这些资源不是用于创建环境的 AWS 拥有的 CFN 模板的输出。
设置时
- Namespace: aws:elasticbeanstalk:environment
OptionName: LoadBalancerIsShared
Value: true
在我的弹性 beantalk 环境的选项设置中,没有创建负载平衡器,这很好。然后我尝试将侦听器规则附加到我的负载均衡器侦听器。
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
这里的问题是,据我所知,我无法访问由弹性 beantalk 环境资源创建的目标组的 ARN。如果我创建一个目标组,那么它不会链接到 elastic beanstalk 并且不存在任何实例。
我找到了this page,其中指出
The resources that Elastic Beanstalk creates for your environment have names. You can use these names to get information about the resources with a function, or modify properties on the resources to customize their behavior.
但是因为它们在不同的堆栈中(我事先不知道名称),而不是模板的输出,所以我不知道如何获取它们。
--
编辑:
Marcin 在他们的回答中向我指出了自定义资源的方向。我稍微扩展了它并让它工作。实现在几个方面略有不同
- 它在 Node 中而不是 Python
- 示例中的 api 调用
describe_environment_resources
提供了 returns 资源列表,但似乎不是所有资源。在我的实现中,我获取了自动缩放组,并使用物理资源 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, context, cfnResponse.FAILED, {});
}
const PhysicalResourceId = EnvironmentResources['AutoScalingGroups'].find(
(group) => group.Name
)['Name'];
const { StackResources } = cfn.describeStackResources(
{ PhysicalResourceId },
function (err, { StackResources }) {
if (err) {
console.log('Exception', e);
return cfnResponse.send(event, context, cfnResponse.FAILED, {});
}
const TargetGroup = StackResources.find(
(resource) =>
resource.LogicalResourceId === 'AWSEBV2LoadBalancerTargetGroup'
);
cfnResponse.send(event, context, cfnResponse.SUCCESS, {
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
我在做这件事的过程中学到的东西,希望对其他人有所帮助
- 在 Node 中使用
async
处理程序很难使用默认的 cfn-response 库,它不是异步的,并且会导致 Cloudformation 创建(和删除)过程在回滚之前挂起许多小时。
- 如果您使用
ZipFile
,cloudformation 会自动包含 cfn-response
库。如果您愿意手动包含该代码,则可以在 AWS Docs 上找到该代码(您也可以将其包装在一个 promise 中,然后使用异步 lambda 处理程序)。 npm上也有实现同样效果的包。
- 节点 14.x 无法 运行,Cloudformation 抛出错误。不幸的是,我没有记下它是什么。
- 提供的示例中使用的策略
AWSElasticBeanstalkFullAccess
不再存在,已替换为 AdministratorAccess-AWSElasticBeanstalk
。
- 我上面的示例需要附加不太宽松的政策,但我还没有在我的测试中解决这个问题。如果只能读取具体的elastic beanstalk环境等就更好了
I don't have access as far as I can tell to the ARN of the target group created by the elastic beanstalk environment resource
没错。克服这个问题的方法是通过 custom resource. In fact I developed fully working, very similar resource for one of my ,因此您可以查看它并采用您的模板。 EB 负载均衡器的资源 returns ARN,但您可以修改它以获取 EB 目标组的 ARN。
我有两个 Cloudformation 模板
- 创建 VPC、ALB 和任何其他共享资源等的
- 创建弹性 beantalk 环境和相关侦听器规则以使用导入的共享负载均衡器将流量定向到此环境的一个(调用此模板
Environment
)
我面临的问题是 Environment
模板创建了一个 AWS::ElasticBeanstalk::Environment
,它随后创建了一个新的 CFN 堆栈,其中包含 ASG 和目标组(或流程原样)等内容弹性豆茎已知)。这些资源不是用于创建环境的 AWS 拥有的 CFN 模板的输出。
设置时
- Namespace: aws:elasticbeanstalk:environment
OptionName: LoadBalancerIsShared
Value: true
在我的弹性 beantalk 环境的选项设置中,没有创建负载平衡器,这很好。然后我尝试将侦听器规则附加到我的负载均衡器侦听器。
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
这里的问题是,据我所知,我无法访问由弹性 beantalk 环境资源创建的目标组的 ARN。如果我创建一个目标组,那么它不会链接到 elastic beanstalk 并且不存在任何实例。
我找到了this page,其中指出
The resources that Elastic Beanstalk creates for your environment have names. You can use these names to get information about the resources with a function, or modify properties on the resources to customize their behavior.
但是因为它们在不同的堆栈中(我事先不知道名称),而不是模板的输出,所以我不知道如何获取它们。
--
编辑:
Marcin 在他们的回答中向我指出了自定义资源的方向。我稍微扩展了它并让它工作。实现在几个方面略有不同
- 它在 Node 中而不是 Python
- 示例中的 api 调用
describe_environment_resources
提供了 returns 资源列表,但似乎不是所有资源。在我的实现中,我获取了自动缩放组,并使用物理资源 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, context, cfnResponse.FAILED, {});
}
const PhysicalResourceId = EnvironmentResources['AutoScalingGroups'].find(
(group) => group.Name
)['Name'];
const { StackResources } = cfn.describeStackResources(
{ PhysicalResourceId },
function (err, { StackResources }) {
if (err) {
console.log('Exception', e);
return cfnResponse.send(event, context, cfnResponse.FAILED, {});
}
const TargetGroup = StackResources.find(
(resource) =>
resource.LogicalResourceId === 'AWSEBV2LoadBalancerTargetGroup'
);
cfnResponse.send(event, context, cfnResponse.SUCCESS, {
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
我在做这件事的过程中学到的东西,希望对其他人有所帮助
- 在 Node 中使用
async
处理程序很难使用默认的 cfn-response 库,它不是异步的,并且会导致 Cloudformation 创建(和删除)过程在回滚之前挂起许多小时。 - 如果您使用
ZipFile
,cloudformation 会自动包含cfn-response
库。如果您愿意手动包含该代码,则可以在 AWS Docs 上找到该代码(您也可以将其包装在一个 promise 中,然后使用异步 lambda 处理程序)。 npm上也有实现同样效果的包。 - 节点 14.x 无法 运行,Cloudformation 抛出错误。不幸的是,我没有记下它是什么。
- 提供的示例中使用的策略
AWSElasticBeanstalkFullAccess
不再存在,已替换为AdministratorAccess-AWSElasticBeanstalk
。 - 我上面的示例需要附加不太宽松的政策,但我还没有在我的测试中解决这个问题。如果只能读取具体的elastic beanstalk环境等就更好了
I don't have access as far as I can tell to the ARN of the target group created by the elastic beanstalk environment resource
没错。克服这个问题的方法是通过 custom resource. In fact I developed fully working, very similar resource for one of my