Pulumi中如何控制资源创建顺序

How to control resource creation order in Pulumi

我正在尝试创建一些资源并且需要执行某种创建顺序。例如创建一个 aws.s3.Bucket 用于存储日志,然后才能将其用作 aws.cloudfront.Distribution.

的输入

使用Pulumi时如何控制资源创建顺序?

一般情况下,Pulumi 会自动处理资源创建的顺序。在 TypeScript 中,这甚至由语言的类型系统通过 pulumi.Input<T>pulumi.Output<T> 类型强制执行。但了解这些类型的细节实际上并不是必需的。

Pulumi 引擎会将所有 "parameters" 或 "inputs" 解析为资源。因此,如果您将一个资源用作配置另一个资源的参数,则将首先创建依赖资源。即它按照您希望的方式工作。

但是,在某些情况下,您需要明确地将一种资源标记为依赖于另一种资源。当 Pulumi 程序之外存在某种耦合时,就会发生这种情况。

要指定显式依赖项,您可以向资源提供 pulumi.ResourceOptions 的实例,并设置其 dependsOn 属性。 Pulumi 引擎将在处理资源之前解析 dependsOn 数组中的所有资源。

这里有一个简单的例子,展示了 Pulumi 确定顺序的这两种方式。 AWS S3 存储桶是一种包含文件(称为对象)的资源。必须先创建存储桶,然后才能在其中创建任何对象。

// Create a bucket named "example-bucket", available at s3://example-bucket.
let bucket = new aws.s3.Bucket("bucket",
    {
        bucket: "example-bucket",
    });

let file1 = new aws.s3.BucketObject("file1", {
    // The bucket field of BucketObjectArgs is an instance of
    // aws.s3.Bucket. Pulumi will know to create the "bucket"
    // resource before this BucketObject resource.
    bucket: bucket,
});

let file2 = new aws.s3.BucketObject("file2",
    {
        // The bucket field of BucketObjectArgs is a string. So
        // Pulumi does not know to block creating the file2 resource
        // until the S3 bucket exists.
        bucket: "example-bucket",
    } as aws.s3.BucketArgs,
    {
        // By putting "bucket" in the "dependsOn" array here,
        // the Pulumi engine will create the bucket resource before
        // this file2 resource.
        dependsOn: [ bucket ],
    } as pulumi.ResourceOptions);

简单回答

official docs 关于此选项的信息非常丰富:

The dependsOn option provides a list of explicit resource dependency resources.

Pulumi automatically tracks dependencies between resources when you supply an input argument that came from another resource’s output properties.
In some cases, however, you may need to explicitly specify additional dependencies that Pulumi doesn’t know about, but must respect.
This might happen if a dependency is external to the infrastructure itself — such as an application dependency — or is implied due to an ordering or eventual consistency requirement.
These dependencies ensure that resource creation, update, and deletion is done in the correct order.

下面的示例演示了使 res2 依赖于 res1,即使 没有 属性 级依赖:

#Python
res1 = MyResource("res1");
res2 = MyResource("res2", opts=ResourceOptions(depends_on=[res1]));

#Golang
res1, _ := NewMyResource(ctx, "res1", &MyResourceArgs{/*...*/})
res2, _ := NewMyResource(ctx, "res2", &MyResourceArgs{/*...*/}, pulumi.DependsOn([]Resource{res1}))

#JS
let res1 = new MyResource("res1", {/*...*/});
let res2 = new MyResource("res2", {/*...*/}, { dependsOn: [res1] });


如果您想了解幕后发生的事情

了解 creation and deletion order

Pulumi executes resource operations in parallel whenever possible, but understands that some resources may have dependencies on other resources.
If an output of one resource is provided as an input to another, the engine records the dependency between these two resources as part of the state and uses these when scheduling operations.
This list can also be augmented by using the dependsOn resource option.

By default, if a resource must be replaced, Pulumi will attempt to create a new copy the the resource before destroying the old one.
This is helpful because it allows updates to infrastructure to happen without downtime.
This behavior can be controlled by the deleteBeforeReplace option.
If you have disabled auto-naming by providing a specific name for a resource, it will be treated as if it was marked as deleteBeforeReplace automatically (otherwise the create operation for the new version would fail since the name is in use).