You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过CloudFormation在现有Elastic Beanstalk环境创建并部署新版本

解决方案:用CloudFormation管理现有Elastic Beanstalk应用版本部署

核心问题分析

  1. 应用版本更新无变更集:AWS::ElasticBeanstalk::ApplicationVersion 资源仅当 SourceBundle 的 S3Key 变化时,才会被CloudFormation识别为需要更新的资源。如果每次部署用同一个S3文件名,CloudFormation会认为没有变更,不会生成新版本。
  2. 现有环境无法纳入栈:直接在模板中定义AWS::ElasticBeanstalk::Environment会触发新环境创建,导致冲突。需要用导入资源或自定义资源的方式关联现有环境。

方法一:将现有环境导入CloudFormation栈(推荐)

这种方式能让CloudFormation完全管理环境的版本更新,步骤如下:

1. 准备匹配现有环境的模板

确保模板中myEnvironment的所有属性和现有环境完全一致(比如SolutionStackName、环境变量、实例配置等),示例模板:

Resources:
  myAppVersion: 
    Type: AWS::ElasticBeanstalk::ApplicationVersion
    Properties: 
      ApplicationName: app-ebs    
      SourceBundle: 
        S3Bucket: my-bucket-name
        S3Key: sample-v1.war  # 每次部署修改这里的文件名(比如加版本号/哈希)
      VersionLabel: !Sub "app-version-${AWS::StackName}-${AWS::Timestamp}"  # 自动生成唯一版本标签

  myEnvironment:
    Type: AWS::ElasticBeanstalk::Environment
    Properties:
      ApplicationName: app-ebs
      EnvironmentName: App-ebs-env
      VersionLabel: !Ref myAppVersion
      SolutionStackName: 64bit Amazon Linux 2 v4.3.12 running Tomcat 8.5 Corretto 8
      # 补充现有环境的其他属性,比如环境变量、InstanceType等,必须和现有环境一致

2. 导入现有环境到栈

  • 打开CloudFormation控制台,选择目标栈,点击导入资源
  • 选择AWS::ElasticBeanstalk::Environment类型,输入现有环境名称App-ebs-env
  • 按照向导完成导入,确保模板属性和现有环境匹配,无冲突

3. 后续部署流程

每次部署新包时:

  1. 将新的WAR包上传到S3,使用新的文件名(比如sample-v2.war)
  2. 更新模板中的S3Key为新文件名
  3. 执行CloudFormation更新栈操作,此时会自动创建新的应用版本,并将现有环境更新到该版本

方法二:用Lambda自定义资源更新现有环境(无需导入)

如果不想将环境纳入CloudFormation管理,可以用Lambda函数调用Elastic Beanstalk API来更新环境版本:

1. 完整模板示例

Resources:
  myAppVersion: 
    Type: AWS::ElasticBeanstalk::ApplicationVersion
    Properties: 
      ApplicationName: app-ebs    
      SourceBundle: 
        S3Bucket: my-bucket-name
        S3Key: sample-v1.war  # 每次部署修改文件名
      VersionLabel: !Sub "app-version-${AWS::StackName}-${AWS::Timestamp}"

  UpdateEnvLambdaRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: UpdateEBSEnvironment
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - elasticbeanstalk:UpdateEnvironment
                Resource: !Sub "arn:aws:elasticbeanstalk:${AWS::Region}:${AWS::AccountId}:environment/app-ebs/App-ebs-env"
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*"

  UpdateEnvLambda:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: python3.11
      Role: !GetAtt UpdateEnvLambdaRole.Arn
      Handler: index.lambda_handler
      Code:
        ZipFile: |
          import boto3
          import cfnresponse

          def lambda_handler(event, context):
              eb_client = boto3.client('elasticbeanstalk')
              try:
                  if event['RequestType'] in ['Create', 'Update']:
                      version_label = event['ResourceProperties']['VersionLabel']
                      eb_client.update_environment(
                          ApplicationName='app-ebs',
                          EnvironmentName='App-ebs-env',
                          VersionLabel=version_label
                      )
                  cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
              except Exception as e:
                  print(f"Error: {str(e)}")
                  cfnresponse.send(event, context, cfnresponse.FAILED, {'Error': str(e)})

  UpdateEnvironmentResource:
    Type: Custom::UpdateEBSEnvironment
    Properties:
      ServiceToken: !GetAtt UpdateEnvLambda.Arn
      VersionLabel: !Ref myAppVersion

2. 部署流程

  1. 每次上传新WAR包到S3,修改模板中的S3Key
  2. 更新CloudFormation栈,此时会创建新的应用版本,触发Lambda函数调用API更新现有环境到新版本

关键注意事项

  • 唯一版本标识:每次部署必须修改S3Key,或者显式指定唯一的VersionLabel,否则CloudFormation不会创建新的应用版本
  • 权限配置:方法二中的Lambda角色必须拥有elasticbeanstalk:UpdateEnvironment权限,且资源范围限定到目标环境
  • 环境属性匹配:方法一中导入环境时,模板属性必须和现有环境完全一致,否则导入会失败

内容的提问来源于stack exchange,提问作者Chuck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 02:47:05