使用Serverless Framework配置双自定义域名映射API Gateway时CloudFormation部署失败问题咨询
这个问题主要是配置错误加上CloudFormation的资源唯一性约束导致的,和Serverless Framework本身无关,咱们一步步拆解:
1. 配置里的明显错误
你的APIBasePathMapping1和APIBasePathMapping2的DependsOn属性写的是APIDomainMapping,但你的自定义资源里根本没有这个名称的资源!正确的做法应该是让每个路径映射依赖对应的域名资源,确保域名创建完成后再创建映射,否则可能出现域名还没就绪就尝试创建映射的情况。
2. CloudFormation的唯一性约束
AWS API Gateway的BasePathMapping资源有个全局唯一性规则:同一个域名+空base path的组合只能存在一个。当你在同一个CloudFormation栈里同时创建两个空base path的映射时,CloudFormation会尝试同时创建这两个资源,而AWS的API会检测到其中一个(先创建的那个)已经存在,就会抛出冲突错误。而你手动添加的情况是,栈已经部署完成,第一个映射已经存在,此时手动添加第二个是直接调用API,不会触发CloudFormation的原子性检查,所以能成功。
修复步骤
步骤一:修正DependsOn配置
把两个路径映射的依赖分别改成对应的域名资源,同时规范!Ref的写法:
Resources: APIDomain1: Type: AWS::ApiGateway::DomainName Properties: RegionalCertificateArn: !ImportValue TF-Cert DomainName: 'api.domain1.com' EndpointConfiguration: Types: - REGIONAL APIDomain2: Type: AWS::ApiGateway::DomainName Properties: RegionalCertificateArn: !ImportValue TF-Cert DomainName: 'api.domain2.com' EndpointConfiguration: Types: - REGIONAL APIBasePathMapping1: Type: AWS::ApiGateway::BasePathMapping DependsOn: APIDomain1 # 修正为对应域名资源 Properties: DomainName: 'api.domain1.com' RestApiId: !Ref ApiGatewayRestApi Stage: ${self:provider.stage} APIBasePathMapping2: Type: AWS::ApiGateway::BasePathMapping DependsOn: APIDomain2 # 修正为对应域名资源 Properties: DomainName: 'api.domain2.com' RestApiId: !Ref ApiGatewayRestApi Stage: ${self:provider.stage}
步骤二:检查证书有效性
确保你导入的TF-Cert证书是包含两个域名的SAN证书(或者是覆盖两个域名的通配符证书)。如果证书只包含其中一个域名,第二个DomainName资源会创建失败,进而导致整个栈部署出错。
步骤三:清理残留资源(如果之前部署失败过)
如果之前的部署已经创建了其中一个映射资源,现在需要先手动删除它:
- 打开AWS API Gateway控制台
- 进入「自定义域名」页面
- 分别查看
api.domain1.com和api.domain2.com的详情,删除已存在的空base path映射 - 重新运行
serverless deploy
额外说明
CloudFormation的栈部署是原子性的,所有资源会尝试一起创建/更新,所以当两个映射资源的唯一键冲突时,整个栈会回滚。而手动添加映射是绕过了栈的原子性检查,直接操作API,所以不会触发冲突报错。只要修正了配置并清理残留资源,就能正常部署两个域名映射了。
内容的提问来源于stack exchange,提问作者Vlad

