如何使用 CloudFormation 将域名作为 Elastic Beanstalk 环境的别名?
How to alias a domain name to an Elastic Beanstalk Environment using CloudFormation?
将子域名别名为 Elastic Beanstalk 环境 ELB 的正确 Route 53 CloudFormation 配置是什么?
我已将 HostedZoneId
从 Amazon Route 53 Hosted Zone ID table 复制到映射:
"Beanstalk2Route53HostedZoneId" : {
"us-east-1" : { "HostedZoneId": "Z117KPS5GTRQ2G" },
"us-west-1" : { "HostedZoneId": "Z1LQECGX5PH1X" },
"us-west-2" : { "HostedZoneId": "Z38NKT9BP95V3O" },
"eu-west-1" : { "HostedZoneId": "Z2NYPWQ7DFZAZH" },
"eu-central-1" : { "HostedZoneId": "Z1FRNW7UH4DEZJ" },
"ap-northeast-1" : { "HostedZoneId": "Z1R25G3KIG2GBW" },
"ap-northeast-2" : { "HostedZoneId": "Z3JE5OI70TWKCP" },
"ap-southeast-1" : { "HostedZoneId": "Z16FZ9L249IFLT" },
"ap-southeast-2" : { "HostedZoneId": "Z2PCDNR3VC2G1N" },
"sa-east-1" : { "HostedZoneId": "Z10X7K2B4QSOFV" }
}
我的资源有两个 Beanstalk 环境:
"MyBeanstalkConfig": {
"Type": "AWS::ElasticBeanstalk::ConfigurationTemplate",
"Properties": {
"OptionSettings": {
{ "Namespace": "aws:elb:listener:80", "OptionName": "ListenerEnabled", "Value" : "false" },
{ "Namespace": "aws:elb:listener:443", "OptionName": "ListenerEnabled", "Value" : "true" },
{ "Namespace": "aws:elb:listener:443", "OptionName": "InstancePort", "Value" : "8081" },
{ "Namespace": "aws:elb:listener:443", "OptionName": "ListenerProtocol", "Value" : "HTTPS" },
{ "Namespace": "aws:elb:listener:443", "OptionName": "SSLCertificateId", "Value" : "arn:aws:iam::[accountNbr]:server-certificate/example-cert-name" },
[...]
}
}
},
"MyStageBeanstalkEnv": {
"Type": "AWS::ElasticBeanstalk::Environment",
"Properties": {
"Description": "Stage Environment",
"TemplateName": { "Ref": "MyBeanstalkConfig" },
[...]
}
},
"MyProdBeanstalkEnv": {
"Type": "AWS::ElasticBeanstalk::Environment",
"Properties": {
"Description": "Production Environment",
"TemplateName": { "Ref": "MyBeanstalkConfig" },
[...]
}
},
输出:
"StageEndpoint" : {
"Description" : "endpoint of the stage environment",
"Value" : { "Fn::GetAtt" : [ "MyStageBeanstalkEnv", "EndpointURL" ] }
},
"ProdEndpoint" : {
"Description" : "endpoint of the production environment",
"Value" : { "Fn::GetAtt" : [ "MyProdBeanstalkEnv", "EndpointURL" ] }
}
舞台和产品 Beanstalk 环境都在工作,即它们响应对 MyStageBeanstalkEnv.eu-west-1.elasticbeanstalk.com
的调用以及 { "Fn::GetAtt" : [ "MyStageBeanstalkEnv", "EndpointURL" ] }
返回的端点(看起来像 awseb-[abc-123-xyz].eu-west-1.elb.amazonaws.com
)。
毫不奇怪,该证书无效,因为它期望域名为 stage.example.com
或 prod.example.com
.
现在我尝试添加 Route 53 配置:
"ExampleDomainHostedZone": {
"Type" : "AWS::Route53::HostedZone",
"Properties" : {
"Name" : "example.com"
}
},
"ExampleDomainRecordSetGroup" : {
"Type" : "AWS::Route53::RecordSetGroup",
"Properties" : {
"HostedZoneId" : { "Ref": "ExampleDomainHostedZone" },
"RecordSets" : [{
"AliasTarget" : {
"DNSName" : { "Fn::GetAtt" : ["MyStageBeanstalkEnv", "EndpointURL"] },
"EvaluateTargetHealth" : false,
"HostedZoneId" : { "Fn::FindInMap" : [ "Beanstalk2Route53HostedZoneId", {"Ref" : "AWS::Region"}, "HostedZoneId" ]}
},
"Name" : "stage.example.com",
"Type": "A"
},
{
"AliasTarget" : {
"DNSName" : { "Fn::GetAtt" : ["MyProdBeanstalkEnv", "EndpointURL"] },
"EvaluateTargetHealth" : false,
"HostedZoneId" : { "Fn::FindInMap" : [ "Beanstalk2Route53HostedZoneId", {"Ref" : "AWS::Region"}, "HostedZoneId" ]}
},
"Name" : "prod.example.com",
"Type": "A"
}]
}
},
当我尝试更新 CloudFormation 堆栈时,我在 AWS 控制台中收到以下错误:
16:12:00 UTC+0200 CREATE_FAILED AWS::Route53::RecordSetGroup ExampleDomainRecordSetGroup Tried to create an alias that targets awseb-[abc-123-xyz].eu-west-1.elb.amazonaws.com., type A in zone Z2NYPWQ7DFZAZH, but the alias target name does not lie within the target zone
在此上下文中,awseb-[abc-123-xyz].eu-west-1.elb.amazonaws.com
与 Beanstalk ELB 提供的 URL 相同。
评论:
- 我已经按照描述 To add an alias resource record set in Amazon Route 53 成功地在 AWS 控制台中将 Route 53 别名资源记录设置到相同的 Beanstalk 环境,因此“只是”将这些配置步骤转移到 CloudFormation 的问题模板。
- 堆栈部署在
eu-west-1
。
- 我还尝试创建两个单独的
AWS::Route53::RecordSet
资源,而不是使用 AWS::Route53::RecordSetGroup
资源,但堆栈更新失败并出现相同的错误。
一些谷歌搜索提示(配置别名时不能使用1, 2) the Amazon Route 53 Hosted Zone ID。据说eu-west-1
具有elasticbeanstalk.eu-west-1.amazonaws.com
端点的托管区域ID Z2NYPWQ7DFZAZH
。但是,当使用 AWS CLI 仔细检查 Beanstalk 实际生成的 ELB 配置时,我发现:
$ aws elb describe-load-balancers --region eu-west-1
{
"LoadBalancerDescriptions": [
{
[...]
"CanonicalHostedZoneNameID": "Z3NF1Z3NOM5OY2",
"CanonicalHostedZoneName": "awseb-[abc-123-xyz].eu-west-1.elb.amazonaws.com",
}
]
}
换句话说,托管区域名称 id 不同。此外,CanonicalHostedZoneName
等于 AliasTarget
中的 DNSName
,即 awseb-[abc-123-xyz].eu-west-1.elb.amazonaws.com
,这与 [=25= 中使用的 elasticbeanstalk.eu-west-1.amazonaws.com
不同].因此,我更改了映射以包含 CLI 输出提供的 CanonicalHostedZoneNameID
:
"Beanstalk2Route53HostedZoneId" : {
"eu-west-1" : { "HostedZoneId": "Z3NF1Z3NOM5OY2" }
}
现在可以成功更新堆栈了。遗憾的是,仅适用于 eu-west-1
,但如果/当我将堆栈部署到其他区域时,可以更新程序。
堆栈更新后,DNS 名称(stable.example.com
和 unstable.example.com
)仍然没有响应。 Updating Your Registrar's Name Servers 解决了这个问题。
我对 CloudFront 的 Route53 别名有同样的问题。
我构建了 HostedZOneId 映射,但它对我不起作用,
通过搜索 AWS 文档,我发现了这个:
The hosted zone ID.
For load balancers, use the canonical hosted zone ID of the load balancer.
For Amazon S3, use the hosted zone ID for your bucket's website endpoint.
For CloudFront, use Z2FDTNDATAQYW2.
For a list of hosted zone IDs of other services, see the relevant service in the AWS Regions and Endpoints.
所以我只是对其进行了硬编码:
"AliasTarget": {
"HostedZoneId": "Z2FDTNDATAQYW2",
"DNSName": {
"Fn::GetAtt": ["MyCloudFrontDistribution", "DomainName"]
}
}
有两种方法可以通过 Alias 从 Route53 连接到 ElasticBeanstalk:
- 使用 ElasticBeanstalk 端点,例如
foobar.u8k2abcm4.eu-central-1.elasticbeanstalk.com/
- 使用来自 ElasticBeanstalk 环境的 LoadBalancer 端点,例如
awseb-[abc-123-xyz].eu-west-1.elb.amazonaws.com
从 "Fn::GetAtt" : ["BeanstalkEnvironment", "EndpointURL"]
返回的值是 LoadBalancer 端点 (docs), therefor the LoadBalancer Mapping Table must be used, see here(而不是 ElasticBeanstalk 的端点)。
不确定if/how它在 ElasticBeanstalk Env 负载不均衡的情况下是否有效。
将子域名别名为 Elastic Beanstalk 环境 ELB 的正确 Route 53 CloudFormation 配置是什么?
我已将 HostedZoneId
从 Amazon Route 53 Hosted Zone ID table 复制到映射:
"Beanstalk2Route53HostedZoneId" : {
"us-east-1" : { "HostedZoneId": "Z117KPS5GTRQ2G" },
"us-west-1" : { "HostedZoneId": "Z1LQECGX5PH1X" },
"us-west-2" : { "HostedZoneId": "Z38NKT9BP95V3O" },
"eu-west-1" : { "HostedZoneId": "Z2NYPWQ7DFZAZH" },
"eu-central-1" : { "HostedZoneId": "Z1FRNW7UH4DEZJ" },
"ap-northeast-1" : { "HostedZoneId": "Z1R25G3KIG2GBW" },
"ap-northeast-2" : { "HostedZoneId": "Z3JE5OI70TWKCP" },
"ap-southeast-1" : { "HostedZoneId": "Z16FZ9L249IFLT" },
"ap-southeast-2" : { "HostedZoneId": "Z2PCDNR3VC2G1N" },
"sa-east-1" : { "HostedZoneId": "Z10X7K2B4QSOFV" }
}
我的资源有两个 Beanstalk 环境:
"MyBeanstalkConfig": {
"Type": "AWS::ElasticBeanstalk::ConfigurationTemplate",
"Properties": {
"OptionSettings": {
{ "Namespace": "aws:elb:listener:80", "OptionName": "ListenerEnabled", "Value" : "false" },
{ "Namespace": "aws:elb:listener:443", "OptionName": "ListenerEnabled", "Value" : "true" },
{ "Namespace": "aws:elb:listener:443", "OptionName": "InstancePort", "Value" : "8081" },
{ "Namespace": "aws:elb:listener:443", "OptionName": "ListenerProtocol", "Value" : "HTTPS" },
{ "Namespace": "aws:elb:listener:443", "OptionName": "SSLCertificateId", "Value" : "arn:aws:iam::[accountNbr]:server-certificate/example-cert-name" },
[...]
}
}
},
"MyStageBeanstalkEnv": {
"Type": "AWS::ElasticBeanstalk::Environment",
"Properties": {
"Description": "Stage Environment",
"TemplateName": { "Ref": "MyBeanstalkConfig" },
[...]
}
},
"MyProdBeanstalkEnv": {
"Type": "AWS::ElasticBeanstalk::Environment",
"Properties": {
"Description": "Production Environment",
"TemplateName": { "Ref": "MyBeanstalkConfig" },
[...]
}
},
输出:
"StageEndpoint" : {
"Description" : "endpoint of the stage environment",
"Value" : { "Fn::GetAtt" : [ "MyStageBeanstalkEnv", "EndpointURL" ] }
},
"ProdEndpoint" : {
"Description" : "endpoint of the production environment",
"Value" : { "Fn::GetAtt" : [ "MyProdBeanstalkEnv", "EndpointURL" ] }
}
舞台和产品 Beanstalk 环境都在工作,即它们响应对 MyStageBeanstalkEnv.eu-west-1.elasticbeanstalk.com
的调用以及 { "Fn::GetAtt" : [ "MyStageBeanstalkEnv", "EndpointURL" ] }
返回的端点(看起来像 awseb-[abc-123-xyz].eu-west-1.elb.amazonaws.com
)。
毫不奇怪,该证书无效,因为它期望域名为 stage.example.com
或 prod.example.com
.
现在我尝试添加 Route 53 配置:
"ExampleDomainHostedZone": {
"Type" : "AWS::Route53::HostedZone",
"Properties" : {
"Name" : "example.com"
}
},
"ExampleDomainRecordSetGroup" : {
"Type" : "AWS::Route53::RecordSetGroup",
"Properties" : {
"HostedZoneId" : { "Ref": "ExampleDomainHostedZone" },
"RecordSets" : [{
"AliasTarget" : {
"DNSName" : { "Fn::GetAtt" : ["MyStageBeanstalkEnv", "EndpointURL"] },
"EvaluateTargetHealth" : false,
"HostedZoneId" : { "Fn::FindInMap" : [ "Beanstalk2Route53HostedZoneId", {"Ref" : "AWS::Region"}, "HostedZoneId" ]}
},
"Name" : "stage.example.com",
"Type": "A"
},
{
"AliasTarget" : {
"DNSName" : { "Fn::GetAtt" : ["MyProdBeanstalkEnv", "EndpointURL"] },
"EvaluateTargetHealth" : false,
"HostedZoneId" : { "Fn::FindInMap" : [ "Beanstalk2Route53HostedZoneId", {"Ref" : "AWS::Region"}, "HostedZoneId" ]}
},
"Name" : "prod.example.com",
"Type": "A"
}]
}
},
当我尝试更新 CloudFormation 堆栈时,我在 AWS 控制台中收到以下错误:
16:12:00 UTC+0200 CREATE_FAILED AWS::Route53::RecordSetGroup ExampleDomainRecordSetGroup Tried to create an alias that targets awseb-[abc-123-xyz].eu-west-1.elb.amazonaws.com., type A in zone Z2NYPWQ7DFZAZH, but the alias target name does not lie within the target zone
在此上下文中,awseb-[abc-123-xyz].eu-west-1.elb.amazonaws.com
与 Beanstalk ELB 提供的 URL 相同。
评论:
- 我已经按照描述 To add an alias resource record set in Amazon Route 53 成功地在 AWS 控制台中将 Route 53 别名资源记录设置到相同的 Beanstalk 环境,因此“只是”将这些配置步骤转移到 CloudFormation 的问题模板。
- 堆栈部署在
eu-west-1
。 - 我还尝试创建两个单独的
AWS::Route53::RecordSet
资源,而不是使用AWS::Route53::RecordSetGroup
资源,但堆栈更新失败并出现相同的错误。
一些谷歌搜索提示(配置别名时不能使用1, 2) the Amazon Route 53 Hosted Zone ID。据说eu-west-1
具有elasticbeanstalk.eu-west-1.amazonaws.com
端点的托管区域ID Z2NYPWQ7DFZAZH
。但是,当使用 AWS CLI 仔细检查 Beanstalk 实际生成的 ELB 配置时,我发现:
$ aws elb describe-load-balancers --region eu-west-1
{
"LoadBalancerDescriptions": [
{
[...]
"CanonicalHostedZoneNameID": "Z3NF1Z3NOM5OY2",
"CanonicalHostedZoneName": "awseb-[abc-123-xyz].eu-west-1.elb.amazonaws.com",
}
]
}
换句话说,托管区域名称 id 不同。此外,CanonicalHostedZoneName
等于 AliasTarget
中的 DNSName
,即 awseb-[abc-123-xyz].eu-west-1.elb.amazonaws.com
,这与 [=25= 中使用的 elasticbeanstalk.eu-west-1.amazonaws.com
不同].因此,我更改了映射以包含 CLI 输出提供的 CanonicalHostedZoneNameID
:
"Beanstalk2Route53HostedZoneId" : {
"eu-west-1" : { "HostedZoneId": "Z3NF1Z3NOM5OY2" }
}
现在可以成功更新堆栈了。遗憾的是,仅适用于 eu-west-1
,但如果/当我将堆栈部署到其他区域时,可以更新程序。
堆栈更新后,DNS 名称(stable.example.com
和 unstable.example.com
)仍然没有响应。 Updating Your Registrar's Name Servers 解决了这个问题。
我对 CloudFront 的 Route53 别名有同样的问题。 我构建了 HostedZOneId 映射,但它对我不起作用, 通过搜索 AWS 文档,我发现了这个:
The hosted zone ID.
For load balancers, use the canonical hosted zone ID of the load balancer.
For Amazon S3, use the hosted zone ID for your bucket's website endpoint.
For CloudFront, use Z2FDTNDATAQYW2.
For a list of hosted zone IDs of other services, see the relevant service in the AWS Regions and Endpoints.
所以我只是对其进行了硬编码:
"AliasTarget": {
"HostedZoneId": "Z2FDTNDATAQYW2",
"DNSName": {
"Fn::GetAtt": ["MyCloudFrontDistribution", "DomainName"]
}
}
有两种方法可以通过 Alias 从 Route53 连接到 ElasticBeanstalk:
- 使用 ElasticBeanstalk 端点,例如
foobar.u8k2abcm4.eu-central-1.elasticbeanstalk.com/
- 使用来自 ElasticBeanstalk 环境的 LoadBalancer 端点,例如
awseb-[abc-123-xyz].eu-west-1.elb.amazonaws.com
从 "Fn::GetAtt" : ["BeanstalkEnvironment", "EndpointURL"]
返回的值是 LoadBalancer 端点 (docs), therefor the LoadBalancer Mapping Table must be used, see here(而不是 ElasticBeanstalk 的端点)。
不确定if/how它在 ElasticBeanstalk Env 负载不均衡的情况下是否有效。