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

AWS CDK更新ImageBuilder AMI遇栈依赖错误,求解决方案

问题:CDK跨栈更新AMI时的导出资源占用错误

我通过AWS CDK用ImageBuilder创建AMI,再部署到EC2实例。ImageBuilder相关资源放在ImageBuilderStack栈,EC2资源放在EC2Stack栈,后者依赖前者生成的AMI。但更新AMI时出现错误:

Export ImageBuilderStack:ExportsOutputFnGetAttAmiImagebImageIdEB9587C0 cannot be updated as it is in use by EC2Stack

我知道先销毁EC2Stack再重新部署能解决问题,但想通过单个cdk deploy命令一次性完成更新。目前试过cdk deploy EC2-Stack和cdk deploy --all都无法解决。

相关代码片段

ec2_stack.py

from constructs import Construct
from aws_cdk import (
    Stack,
    aws_ec2 as ec2,
    Duration,
    CfnOutput,
)

class Ec2Stack(Stack):

    def __init__(self, scope: Construct, construct_id: str, stacks, stage, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        image_builder_stack = stacks["ImageBuilderStack"]
        iam_stack = stacks["IamStack"]

        image_b = ec2.MachineImage.generic_linux({"us-west-2": 
        image_builder_stack.ami_image_b.attr_image_id}) # 引用ImageBuilderStack生成的AMI

        CfnOutput(self, "AmiOutputB", value=image_builder_stack.ami_image_b.attr_image_id)

        test_ec2 = ec2.Instance(self, "Ec2Instance",
            instance_name="deployment_test",
            vpc=shared_vpc_stack.vpc,
            vpc_subnets=ec2.SubnetSelection(
                subnet_group_name="TestPrivateSubnet"
            ),
            instance_type=ec2.InstanceType.of(ec2.InstanceClass.C5, ec2.InstanceSize.XLARGE9),
            machine_image=image_b,
            role=iam_stack.instance_role,
            security_group=test_security_group,
        )
        test_ec2.node.add_dependency(image_builder_stack.ami_image_b)

image_builder_stack.py

from constructs import Construct
from aws_cdk import (
    Stack,
    aws_imagebuilder as imagebuilder,
    aws_iam as iam,
)

from component_documents import test_doc_b # AMI构建用的Shell命令


class ImageBuilderStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, stacks, stage, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        iam_stack = stacks["IamStack"]

        instance_profile = iam.CfnInstanceProfile(self, "InstanceProfile",
            roles=[iam_stack.image_build_role.role_name],
            instance_profile_name="EC2InstanceProfileForImageBuilder",
        )

        infrastructure_configuration = imagebuilder.CfnInfrastructureConfiguration(self, "InfrastructureConfiguration",
            instance_profile_name=instance_profile.instance_profile_name,
            name="InfrastructureConfig",
            description="Infrastructure configuration for test AMI image",
            terminate_instance_on_failure=True
        )
        infrastructure_configuration.node.add_dependency(instance_profile)

        yaml_data = test_doc_b.return_test_component_doc()  

        test_component = imagebuilder.CfnComponent(stack, f"testComponent-{image_doc}",
            name="Test-Image-Component",
            platform="Linux",
            version= version, # 示例:"1.0.3"
            description="Downloads, installs and configures splunk on Amazon Linux",
            supported_os_versions=["Amazon Linux 2"],
            data=yaml_data  # 用于生成AMI的Shell脚本
        )

        test_image_recipe = imagebuilder.CfnImageRecipe(stack, f"TestImageRecipe-{image_doc}",
            components=[{"componentArn": test_component.attr_arn}],
            name="Test-Image-Recipe",
            # Amazon Linux2 X86 64bit Kernel 5.10
            parent_image="ami-076bca9dd71a9a514",
            version="1.0.1", # 示例:"1.0.3",更新时需递增版本号
            working_directory="/tmp"
        )

        self.test_ami_image = imagebuilder.CfnImage(self, f"TestAmiImage-{image_doc}",
            infrastructure_configuration_arn=infrastructure_configuration.attr_arn,
            image_recipe_arn=test_image_recipe.attr_arn,
            tags={
                "Name": "test AMI"
            }
        )

component_documents.test_doc_b.py

def return_test_component_doc():
    test_component_doc = f'''
    name: TestDeploymentDocument_B
    description: This is document for downloading, installing and deploying
    schemaVersion: 1.0
    phases:
      - name: build
        steps:
          - name: SetEnvironment
            action: ExecuteBash
            inputs:
              commands:
                - sudo yum update -y 
                - echo “Hello World”
'''

stack_creator.py

from constructs import Construct
from aws_cdk import (
    Stack,
    Environment
)

from test_stacks.ec2 import Ec2Stack
from test_stacks.image_builder import ImageBuilderStack

from test_stacks.iam import IamStack

class ApplicationInfrastructure(Stack):

    def __init__(self, scope: Construct, **kwargs) -> None:
        super().__init__(scope, **kwargs)

        stage = self.node.try_get_context("stage")
        env_USA = Environment(account=self.account, region="us-west-2")

        image_builder_stack = ImageBuilderStack(self, "Image-Builder-Stack", env=env_USA, stage="beta")

        ec2_stack = Ec2Stack(self, "EC2-Stack", env=env_USA, stacks={"ImageBuilderStack": 
        image_builder_stack, "IamStack": IamStack},stage="beta")
        ec2_stack.add_dependency(image_builder_stack)

解决方案

方法1:给EC2实例添加替换策略

当AMI变化时,让CDK自动销毁并重建EC2实例,避免导出资源被占用的问题。修改ec2_stack.py中的EC2实例定义:

test_ec2 = ec2.Instance(self, "Ec2Instance",
    # 原有属性保持不变
    update_replace_policy=core.RemovalPolicy.DESTROY,
    deletion_policy=core.RemovalPolicy.DESTROY,
)
# 或者直接修改底层CfnResource的替换策略
test_ec2.instance.cfn_options.update_replace_policy = core.RemovalPolicy.DESTROY

添加后,执行cdk deploy --all即可自动更新AMI和EC2实例。

方法2:确保ImageBuilder版本号递增

ImageBuilder只有在镜像配方(test_image_recipe)的版本号变化时才会生成新AMI。修改image_builder_stack.py中的版本号,每次更新时手动递增,或者自动生成版本号:

# 示例:用时间戳自动生成唯一版本号
from datetime import datetime
version = datetime.now().strftime("%Y.%m.%d.%H%M")

test_image_recipe = imagebuilder.CfnImageRecipe(stack, f"TestImageRecipe-{image_doc}",
    # 其他属性不变
    version=version,
)

方法3:用脚本自动化销毁重建流程

如果上述方法无效,可编写Shell脚本一次性完成操作:

#!/bin/bash
# 强制销毁EC2Stack
cdk destroy EC2-Stack -f
# 更新ImageBuilderStack生成新AMI
cdk deploy Image-Builder-Stack
# 重新部署EC2Stack使用新AMI
cdk deploy EC2-Stack

执行脚本即可完成一次性更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 16:54:57