AWS CDK(Python)部署Route53托管区提示CloudWatch Logs ARN无效
问题现象
在Python版AWS CDK中为Route53 HostedZone配置查询日志功能,日志组定义代码:
queryLogGroup = logs.LogGroup(self, 'logGroup', log_group_name='/aws/route53/'+subdomain, retention=logs.RetentionDays.THREE_DAYS, removal_policy=RemovalPolicy.DESTROY )
HostedZone资源定义代码:
subdomainHostedZone = route53.HostedZone( self, 'subdomainHostedZone', zone_name=subdomain, query_logs_log_group_arn=queryLogGroup.log_group_arn )
部署阶段抛出错误:
11:49:59 PM | CREATE_FAILED | AWS::Route53::HostedZone | subdomainHostedZoneE712CA19 Resource handler returned message: "The ARN for the CloudWatch Logs log group is invalid. (Service: Route53, Status Code: 400, Request ID: {Rec-ID}, Extended Request ID: null)" (RequestToken: {Rec-Token}, HandlerErrorCode: GeneralServiceException)
检查生成的CloudFormation模板,HostedZone资源已经通过Fn::GetAtt正确引用日志组ARN,且自动添加了日志资源策略的部署依赖,手动加日志组依赖、切换L1构造手动取ARN的方式都无法解决问题。
排查修复方案
这个报错90%的情况都是踩了Route53查询日志的服务硬限制,按以下优先级排查即可:
最高发原因:日志组部署区域不符合要求
Route53是全局公网服务,公网托管区的查询日志功能强制要求关联的CloudWatch Logs日志组必须创建在us-east-1(弗吉尼亚北部)区域,和CDK栈本身的部署区域无关。如果你的栈部署在非us-east-1区域,栈内创建的日志组会落在栈所在区域,哪怕ARN格式完全合法,Route53也会返回无效错误。
修复方式:单独在us-east-1区域创建日志组,再跨区域引用ARN即可,示例代码:# 定义us-east-1区域环境 us_east_1_env = cdk.Environment(account=self.account, region="us-east-1") # 单独在us-east-1创建栈存放Route53查询日志组 class R53LogStack(cdk.Stack): def __init__(self, scope, construct_id, **kwargs): super().__init__(scope, construct_id, env=us_east_1_env, **kwargs) self.query_log_group = logs.LogGroup(self, 'QueryLogGroup', log_group_name=f'/aws/route53/{subdomain}', retention=logs.RetentionDays.THREE_DAYS, removal_policy=RemovalPolicy.DESTROY ) # 在原有托管区所在栈中,跨栈引用us-east-1日志组的ARN传入HostedZone配置即可特殊区域注意:中国区AWS的Route53查询日志要求日志组创建在
cn-north-1区域,GovCloud区域要求创建在对应分区的主区域,服务主体也要做对应调整。第二排查点:日志组资源策略权限不匹配
CDK自动生成的CloudWatch Logs资源策略在特殊环境(中国区、GovCloud、账号配置了SCP权限边界)下会出现服务主体错误,导致Route53无法访问日志组,也会返回ARN无效的错误。各区域正确的服务主体如下:- 通用商业区域:
route53.amazonaws.com - 中国区:
route53.amazonaws.com.cn - GovCloud区域:
route53.us-gov.amazonaws.com
如果自动生成的策略主体不对,手动给日志组加资源策略覆盖即可:
queryLogGroup.add_to_resource_policy( iam.PolicyStatement( actions=["logs:CreateLogStream", "logs:PutLogEvents"], principals=[iam.ServicePrincipal("route53.amazonaws.com")], # 按所在区域替换主体 resources=[queryLogGroup.log_group_arn] ) )- 通用商业区域:
第三排查点:日志组命名与账号策略冲突
Route53本身对日志组名称没有强制要求,但部分账号的SCP策略会限制AWS服务写入非/aws/前缀的日志组,保持日志组名称以/aws/route53/开头即可,你当前的命名配置符合该要求。
内容的提问来源于stack exchange,提问作者DeltaScratchpad

