当我使用带有API网关资源的模板运行CloudFormation deploy
时,第一次运行它时,它会创建并部署到阶段。随后我运行它,它会更新资源但不会部署到各个阶段。
这种行为是否符合预期?如果是的话,我是如何在更新时将其部署到阶段的?
(Terraform提到类似的问题:https://github.com/hashicorp/terraform/issues/6613)
答案 0 :(得分:12)
似乎无论何时您的某个Cloudformation资源发生变化,都无法轻松创建新的部署。
解决这个问题的一种方法是使用Lambda支持的自定义资源(请参阅http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html)。
只有在您的某个资源更新后,Lambda才会创建新的部署。要确定您的某个资源是否已更新, 您可能需要围绕此API调用实现自定义逻辑:http://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_DescribeStackEvents.html
为了触发自定义资源的更新,我建议您提供一个Cloudformation参数,用于强制更新自定义资源(例如当前时间或版本号)。
请注意,您必须在自定义资源中添加DependsOn
子句,其中包含与您的API相关的所有资源。否则,可能会在更新所有API资源之前创建部署。
希望这有帮助。
答案 1 :(得分:5)
亚马逊的CloudFormation的话是:
AWS CloudFormation负责为您配置和配置这些资源 http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html
重新部署API不是一项配置任务......这是一项促销活动,是软件发布过程中的一个阶段。
AWS CodePipeline是一种持续交付服务,可用于建模,可视化和自动执行发布软件所需的步骤。 http://docs.aws.amazon.com/codepipeline/latest/userguide/welcome.html
CodePipeline还支持从管道中的Actions执行Lambda函数。因此,如前所述,创建一个Lambda函数来部署您的API,但是从Codepipeline而不是CloudFormation调用它。
详情请咨询此页: http://docs.aws.amazon.com/codepipeline/latest/userguide/actions-invoke-lambda-function.html
答案 2 :(得分:3)
我使用的是上述方法,但部署API网关对我来说似乎很复杂。如果我们要更改资源名称,那么删除和重新创建资源会花费一些时间,这会增加应用程序的停机时间。
我遵循以下方法使用AWS CLI将API网关部署到阶段,并且不会影响Cloudformation堆栈的部署。
我正在做的是,在API网关的部署完成后,在AWS CLI命令下运行。它将使用最新更新来更新现有阶段。
aws apigateway create-deployment --rest-api-id tztstixfwj --stage-name stg --description 'Deployed from CLI'
答案 3 :(得分:2)
这里的答案是使用舞台的AutoDeploy属性:
Stage:
Type: AWS::ApiGatewayV2::Stage
Properties:
StageName: v1
Description: 'API Version 1'
ApiId: !Ref: myApi
AutoDeploy: true
请注意,使用'AutoDeploy'时必须未指定'DeploymentId'属性。
在此处查看文档:{{3}}
答案 4 :(得分:1)
当您的模板指定部署时,CloudFormation仅在尚不存在时才创建该部署。当您尝试再次运行它时,它会发现该部署仍然存在,因此不会重新创建它,因此没有部署。您需要为该部署使用新的资源ID,以便它将创建一个新的部署。请阅读以下内容以获取更多信息:https://currentlyunnamed-theclassic.blogspot.com/2018/12/mastering-cloudformation-for-api.html
答案 5 :(得分:1)
在TheClassic链接的Blogspot帖子中(到目前为止,最好的答案!),请记住,如果没有使用可以插入有效时间戳记代替$ TIMESTAMP $的东西来生成模板,则必须使用时间戳或其他唯一ID手动更新。这是我的功能示例,它成功删除了现有部署并创建了一个新部署,但是当我要创建另一个变更集时,我将不得不手动更新这些唯一值:
rDeployment05012019355:
Type: AWS::ApiGateway::Deployment
DependsOn: rApiGetMethod
Properties:
RestApiId:
Fn::ImportValue:
!Sub '${pApiCoreStackName}-RestApi'
StageName: !Ref pStageName
rCustomDomainPath:
Type: AWS::ApiGateway::BasePathMapping
DependsOn: [rDeployment05012019355]
Properties:
BasePath: !Ref pPathPart
Stage: !Ref pStageName
DomainName:
Fn::ImportValue:
!Sub '${pApiCoreStackName}-CustomDomainName'
RestApiId:
Fn::ImportValue:
!Sub '${pApiCoreStackName}-RestApi'
答案 6 :(得分:1)
我可能来晚了,但是如果API资源发生更改,您可以重新部署这些选项,这可能对仍在寻找选项的人有所帮助-
尝试将AutoDeploy设置为true。如果使用的是V2版本的部署。请注意,您需要通过V2创建APIGW。 V1和V2彼此不兼容。 https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigatewayv2-stage.html#cfn-apigatewayv2-stage-autodeploy
Lambda支持的自定义资源,Lambda依次调用createDeployment API-https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html
CodePipeline,它具有一个调用Lambda函数的操作,就像自定义资源一样-https://docs.aws.amazon.com/codepipeline/latest/userguide/actions-invoke-lambda-function.html
SAM(无服务器应用程序模型)遵循与CloudFormation相似的语法,该语法将资源创建简化为抽象,并使用那些来构建和部署普通的CloudFormation模板。 https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html
如果您正在使用任何抽象层(如Sceptre)来进行云形成,则可以对资源https://sceptre.cloudreach.com/2.3.0/docs/hooks.html
进行任何更新后,通过钩子调用createDeployment因为我一直使用Scepter进行Cloudformation部署,所以我选择了第三个选项。在权杖中实现钩子也很容易。
答案 7 :(得分:0)
使用SAM
AWS :: Serverless :: Api
这会在完成转换时为您完成部署
答案 8 :(得分:0)
这对我有用:
cfn.yml
APIGatewayStage:
类型:'AWS::ApiGateway::Stage'
特性:
舞台名称:!Ref 环境
DeploymentId: !Ref APIGatewayDeployment$TIMESTAMP$
RestApiId: !Ref APIGatewayRestAPI
变量:
lambdaAlias: !Ref 环境
方法设置:
- 资源路径:'/'
数据跟踪启用:真
HttpMethod: ""
日志级别:信息
指标启用:真
依赖于取决于:
- liveLocationsAPIGatewayMethod
- testJTAPIGatewayMethod
APIGatewayDeployment$TIMESTAMP$: 类型:'AWS::ApiGateway::Deployment' 特性: RestApiId: !Ref APIGatewayRestAPI 依赖于取决于: - liveLocationsAPIGatewayMethod - testJTAPIGatewayMethod
bitbucket-pipelines.yml
脚本: - python3 deploy_api.py
deploy_api.py
导入时间
file_name = 'infra/cfn.yml' ts = str(time.time()).split(".")[0] 打印(ts)
以 open(file_name, 'r') 作为文件: 文件数据 = file.read()
filedata = filedata.replace('$TIMESTAMP$', ts)
以 open(file_name, 'w') 作为文件: file.write(filedata)
================================================ ==========================
阅读本文了解更多信息:https://currentlyunnamed-theclassic.blogspot.com/2018/12/mastering-cloudformation-for-api.html