在CDK中查找或创建S3存储桶?

4

我发现 cdk 在每次部署时尝试重新创建 S3 存储桶。如果我不指定存储桶名称,它会每次生成一个新的无用名称。如果我指定了名称,它会因为该存储桶已经存在而拒绝部署。我该如何使它“upsert”存储桶?

以下是我使用的代码:

const dataIngestBucket = new Bucket(this, 'data-lake', {
  bucketName: `${this.props.environmentName}-my-company-data-lake`
});

1
这不是预期的行为,如果此存储桶位于您的堆栈根目录中。我建议您在部署之前和之后使用 cdk diff 进行检查,以查看在部署相同代码时发生了什么变化。代码中似乎存在循环依赖关系。 - Pedreiro
这也发生在我身上。尽管cdk diff显示我的S3堆栈没有任何更改,但它仍然被部署了。 - Andrej Mohar
3个回答

4
让我用Python来提供一个答案。它可以轻松追踪并转换为任何其他语言。
请参考aws_cdk.aws_s3.Bucket类。
在那里,您将找到在创建类时需要指定的参数,这些参数允许您达到目标,即auto_delete_objects=Trueremoval_policy=cdk.RemovalPolicy.DESTROY

2
非常有帮助。我认为@TechFree关于最佳实践的回答在大多数情况下可能是正确的方法,但这个也能胜任。 - ryanjdillon
这看起来像是一个糟糕的解决方案!我绝对不会希望将策略设置为在生产环境中销毁 - 这样你会丢失客户的数据,不是吗?但你仍然需要维护你的应用程序并定期更新技术栈。 - Andrej Mohar
@AndrejMohar,你给出了比原本问题更多的背景信息,还附上了你粗鲁的个人意见——你的理由是什么?安全性?数据保留?如果没有这样的要求,那么这个解决方案就是合适的。此外,你提到的“定期维护应用程序和更新堆栈”的动机与堆栈删除无关。一旦堆栈部署完成,应该进行更新,而不是为了应用后续变更而重新创建堆栈。 - Kyrylo Kravets
@KyryloKravets,这正是我的观点,OP试图“更新”一个包含S3存储桶的堆栈,如果设置了存储桶名称,S3存储桶的更新将失败(即使在S3存储桶上“不更改任何内容”也可能发生),或者会创建一个全新的存储桶。据我理解,所提到的解决方案会自动删除所有存储桶内容,然后删除存储桶,并从头开始重新创建 - 这一切都发生在堆栈更新而非堆栈删除时。除非是用于临时数据的存储桶,否则你无法说服我这是一个好的生产解决方案。 - Andrej Mohar
说到最后一部分,即使是包含一次性或垃圾文件的桶,我仍然宁愿保留它们“不启用任何自动删除选项”,并将清理工作掌握在我的控制之下(例如,使用定时任务手动清理它们)。我认为拥有自动删除功能的任何东西都是一个糟糕的主意,迟早会给你带来麻烦。 - Andrej Mohar
显示剩余3条评论

3
CDK会在CDK代码更新时自动更新堆栈资源。例如,当您第一次执行创建存储桶的CDK堆栈时,存储桶将使用提供的配置创建。当您更新CDK代码以更新存储桶的生命周期策略或添加CORS时,作为同一堆栈的一部分,堆栈的更新将自动更新存储桶 - 由于Cloud Formation知道现有堆栈上有更新,因此不会重新创建存储桶。
在您的情况下,似乎在删除堆栈资源仍存在的情况下重新创建了堆栈。这会导致Cloud Formation创建一个新的堆栈和其在销毁堆栈时未被删除的资源。
通常,当堆栈更新失败并处于回滚状态时,问题会发生。在那种情况下,重新部署将尝试重新创建存储桶并失败。在那种情况下,可能的选择是:
1. 删除存储桶 2. 删除堆栈 3. 重新部署以重新创建
许多时候,我们不想删除资源,因为它们包含数据;在这种情况下,您可以在CDK代码中使用另一个库(比如Python的boto3)来检查资源是否存在 - 如果不存在,则通过CDK创建。这将导致CDK代码不会尝试创建存储桶,如果它已经存在(至少我还没有看到如何使用CDK本身来查看S3资源是否已经存在)。
另一个重要的问题是与资源相关联的删除策略。 故障排除_资源未被删除 我的S3存储桶、DynamoDB表或其他资源在我执行cdk destroy命令时未被删除。默认情况下,可以包含用户数据的资源具有RETAIN的removalPolicy(Python:removal_policy)属性,并且在堆栈被销毁时不会删除该资源。相反,该资源将与堆栈分离。然后,您必须在堆栈被销毁后手动删除该资源。在此之前,重新部署堆栈将失败,因为在部署过程中创建的新资源名称与孤立资源的名称冲突。如果将资源的删除策略设置为DESTROY,则在销毁堆栈时将删除该资源。但是,即使将删除策略设置为DESTROY,CloudFormation也无法删除非空存储桶。以下摘自同一链接 - AWS CloudFormation无法删除非空的Amazon S3存储桶。如果将Amazon S3存储桶的删除策略设置为DESTROY,并且其中包含数据,则尝试销毁堆栈将失败,因为无法删除存储桶。您可以通过将存储桶的autoDeleteObjects属性设置为true来让AWS CDK在尝试销毁存储桶之前删除其中的对象。
最佳实践是:
  1. 设计堆栈资源的方式应尽量减少更新,以避免可能导致故障。因此,可以创建一个堆栈,其中包含大多数静态资源(例如 ECR、S3 等),这些资源不会经常更改,并且通常独立于主应用程序部署堆栈,后者更容易出现故障。

  2. 避免手动删除堆栈资源,这会破坏堆栈的一致性。

  3. 如果删除堆栈,请确保同时删除堆栈拥有的资源。


-2

摆脱固定的名称!

使用

 final IBucket myBucket = Bucket.Builder.create(this, "mybucket")
            .bucketName(PhysicalName.GENERATE_IF_NEEDED).build();

(Java,但不重要)

您是否获得了一个“随机命名”的存储桶。 在此处描述:https://docs.aws.amazon.com/cdk/latest/guide/resources.html

在模板中像这样使用它(这里是嵌套堆栈)

@Nullable NestedStackProps templateProps = NestedStackProps.builder()
            .parameters(new HashMap<String, String>(){{
                put("S3Bucket", myBucket.getBucketName());

            }})
            .build();

或者你仍然有一个固定的名称(摆脱它!)然后用以下方式获取它们:

final IBucket myBucket = Bucket.fromBucketName(this, "mybucket", "my-hold-bucket-name");

但你不能做这样的事情:

if (!myBucket) then create

(伪代码)

编译/运行时没有资源检查!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接