

这是 AWS CDK v2 开发者指南。旧版 CDK v1 于 2022 年 6 月 1 日进入维护阶段，并于 2023 年 6 月 1 日终止支持。

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 管理 AWS CDK 工具包库云程序集源
<a name="toolkit-library-configure-ca"></a>

使用 AWS CDK 工具包库配置云程序集源并自定义 CDK 应用程序的部署方式。本指南介绍如何配置云程序集源以满足您的部署要求和工作流需求。

在使用 CDK 工具包之前，请指定云程序集源。*云程序集源*提供了从 CDK 应用程序生成云程序集的说明。生成的云程序集包含 CDK 工具包部署到 AWS 的合成基础设施工件。

CDK 工具包库提供了多种配置云程序集源的方法，每种方法都适用于不同的场景和工作流。

## 选择云程序集源
<a name="toolkit-library-configure-ca-options"></a>


| 方法 | 适用于 | 考虑因素 | 
| --- | --- | --- | 
|   `fromCdkApp`   |  以任何支持的语言使用现有 CDK 应用程序。  |  需要安装相应的语言运行时。  | 
|   `fromAssemblyBuilder`   |  以内联方式创建 CDK 构造，完全控制合成过程。  |  提供对 CDK 功能的低级访问，可用于构建其他方法（如 `fromCdkApp`）的自定义版本。  | 
|   `fromAssemblyDirectory`   |  使用预合成的云程序集。  |  由于跳过了合成步骤，执行速度更快。  | 
|  自定义源  |  需要完全自定义实现的极其专业的场景。  |  需要从头开始实现 `ICloudAssemblySource` 接口；缺少上下文查找等内置功能；大多数使用案例很少需要。  | 

## 配置云程序集源
<a name="toolkit-library-configure-ca-how"></a>

### 从现有的 CDK 应用程序
<a name="toolkit-library-configure-ca-how-app"></a>

通过 `fromCdkApp` 方法使用以任何支持的语言编写的 CDK 应用程序。当您有一个现有 CDK 应用程序并希望以编程方式部署它时，这种方法非常理想。

```
import { App } from 'aws-cdk-lib';
import { Toolkit } from '@aws-cdk/toolkit-lib';

// Create a toolkit instance
const toolkit = new Toolkit();

// TypeScript app
const cloudAssemblySource = await toolkit.fromCdkApp("ts-node app.ts");

// Deploy a specific stack from the assembly
await toolkit.deploy(cloudAssemblySource, {
    stacks: ['MyStack']
});

// Other language examples:
// JavaScript app
// const cloudAssemblySource = await toolkit.fromCdkApp("node app.js");

// Python app
// const cloudAssemblySource = await toolkit.fromCdkApp("python app.py");

// Java app
// const cloudAssemblySource = await toolkit.fromCdkApp("mvn -e -q exec:java -Dexec.mainClass=com.mycompany.app.App");
```

### 从内联程序集生成器
<a name="toolkit-library-configure-ca-how-builder"></a>

使用程序集生成器函数直接在代码中创建 CDK 应用程序。这种方法对于想要以内联方式定义基础设施的简单部署或测试场景非常有用。

```
import { App, Stack, RemovalPolicy, StackProps } from 'aws-cdk-lib';
import { Bucket } from 'aws-cdk-lib/aws-s3';
import { Toolkit } from '@aws-cdk/toolkit-lib';
import { Construct } from 'constructs';

// Create a cloud assembly source from an inline CDK app
const cloudAssemblySource = await toolkit.fromAssemblyBuilder(async () => {
    const app = new App();

    // Define a simple stack with an S3 bucket
    class MyStack extends Stack {
        constructor(scope: Construct, id: string, props?: StackProps) {
            super(scope, id, props);

            // Create an S3 bucket
            new Bucket(this, 'MyBucket', {
                versioned: true,
                removalPolicy: RemovalPolicy.DESTROY,
                autoDeleteObjects: true
            });
        }
    }

    // Instantiate the stack
    new MyStack(app, 'MyInlineStack');

    return app.synth();
});

// Deploy using the cloud assembly source
await toolkit.deploy(cloudAssemblySource, {
    stacks: ['MyInlineStack']
});
```

### 从现有的程序集目录
<a name="toolkit-library-configure-ca-how-directory"></a>

如果您已有一个合成的云程序集，则可以直接使用它。这在您已经运行 `cdk synth` 或使用由 CI/CD 管线生成的云程序集时非常有用。

```
import { Toolkit } from '@aws-cdk/toolkit-lib';

// Create a toolkit instance
const toolkit = new Toolkit();

// Use an existing cloud assembly directory
const cloudAssemblySource = await toolkit.fromAssemblyDirectory("cdk.out");

// Deploy using the cloud assembly source
await toolkit.deploy(cloudAssemblySource, {
    stacks: ['MyStack']
});
```

## 使用缓存的云程序集
<a name="toolkit-library-configure-ca-cache"></a>

使用云程序集时，您有两种选择：

1. 直接使用云程序集源（简单但可能速度较慢）：

   ```
   // Each operation triggers a new synthesis
   await toolkit.deploy(cloudAssemblySource, { /* options */ });
   await toolkit.list(cloudAssemblySource, { /* options */ });
   ```

1. 缓存云程序集（多个操作更快）：

   ```
   // Synthesize once and reuse
   const cloudAssembly = await toolkit.synth(cloudAssemblySource);
   try {
     // Multiple operations use the same assembly
     await toolkit.deploy(cloudAssembly, { /* options */ });
     await toolkit.list(cloudAssembly, { /* options */ });
   } finally {
     // Clean up when done
     await cloudAssembly.dispose();
   }
   ```

在以下情况下使用缓存的程序集：
+ 您正在执行多个操作（deploy、list、diff 等）。
+ 您的 CDK 应用程序在操作期间不会频繁更改。
+ 您想要更快的性能。

在以下情况下直接使用云程序集源：
+ 您正在执行单个操作。
+ 您的 CDK 应用程序频繁更改。
+ 你想要更简单的代码，不需要优先考虑工具包的操作速度。

**重要**  
为了获得更好的性能，大多数工具包交互都应该使用缓存的程序集。只有当源代码频繁更改且检查更改的开销很大时，才应该避免使用缓存。

### 如何创建、缓存和重复使用云程序集
<a name="toolkit-library-configure-ca-cache-how"></a>

创建云程序集源后，您可以通过合成该源来生成云程序集。云程序集包含部署所需的 AWS CloudFormation 模板和资源。

我们建议您生成一次云程序集，然后将其重复用于多个工具包操作。这种缓存方法比每次操作都重新生成程序集更高效。只有当源代码频繁更改时才考虑重新生成程序集。

下面介绍了如何创建缓存的云程序集：

```
// Generate a cloud assembly from your source
const cloudAssembly = await toolkit.synth(cloudAssemblySource);
```

然后，您可以对缓存的云程序集执行各种工具包操作，例如 `list()`、`deploy()` 和 `diff()`。通过缓存云程序集，后续工具包操作的执行速度会更快，因为合成只发生一次。有关更多信息，请参阅 [synth - 生成云程序集](toolkit-library-actions.md#toolkit-library-actions-synth)。

### 处置云程序集资源
<a name="toolkit-library-configure-ca-cache-dispose"></a>

使用完毕后，务必处置云程序集以清理临时资源。我们建议使用 try/finally 块来确保正确清理，尤其是在执行多个操作时：

```
// Generate a cloud assembly
const cloudAssembly = await toolkit.synth(cloudAssemblySource);

try {
    // Use the cloud assembly for multiple operations
    await toolkit.list(cloudAssembly);
    await toolkit.deploy(cloudAssembly);
} finally {
    // Always dispose when done
    await cloudAssembly.dispose();
}
```

以下示例展示了如何创建和处置缓存的云程序集：

```
import { Toolkit } from '@aws-cdk/toolkit-lib';

const toolkit = new Toolkit();

// Create cloud assembly source from a CDK app
const cloudAssemblySource = await toolkit.fromCdkApp("ts-node app.ts");

// Create cloud assembly from source
const cloudAssembly = await toolkit.synth(cloudAssemblySource);

try {
    // List stacks in the assembly
    await toolkit.list(cloudAssembly);

    // Check for changes
    await toolkit.diff(cloudAssembly);

    // Deploy if needed
    await toolkit.deploy(cloudAssembly);
} finally {
    // Always dispose when done
    await cloudAssembly.dispose();
}
```

### 了解云程序集生命周期
<a name="toolkit-library-configure-ca-cache-lifetime"></a>

当您使用 `synth()` 创建缓存的云程序集时，会获得一种特殊类型，它既是可读的 `CloudAssembly`，又是 `CloudAssemblySource`。从此缓存的程序集（例如，从 list 或 deploy 操作）生成的任何云程序集都与父程序集的生命周期关联：
+ 只有父程序集的 dispose() 调用才会真正清理资源。
+ 来自 list/deploy 操作的云程序集由其父程序集管理
+ 未能处置缓存的云程序集被视为一个错误

## 云程序集源的最佳实践
<a name="toolkit-library-configure-ca-best-practices"></a>

使用云程序集源时，请考虑以下最佳实践：
+  **选择合适的源方法**：选择最适合您的工作流和要求的方法。
+  **缓存云程序集**：使用 `synth()` 生成一次云程序集，并将其重用于多个操作，以避免不必要的合成，尤其对于大型应用程序。
+  **错误处理**：实现基本的错误处理以捕获错误并向用户显示。简化错误处理，并专注于提供清晰的错误消息。
+  **版本兼容性**：确保您的 CDK 工具包库版本支持您正在使用的云程序集。如果用于创建云程序集的构造库比您的工具包库支持的版本更新，则会收到错误。
+  **环境变量**：请注意，某些环境变量会影响云程序集的合成和部署。`CDK_DEFAULT_ACCOUNT`、`CDK_DEFAULT_REGION`、`CDK_OUTDIR` 和 `CDK_CONTEXT_JSON` 等变量可以覆盖默认行为。请确保根据您的部署环境正确设置这些变量。

以下示例演示了如何在对多个操作重用云程序集时实施错误处理和适当清理：

```
import { Toolkit } from '@aws-cdk/toolkit-lib';

// Example with error handling and proper cleanup
async function deployInfrastructure(): Promise<void> {
    let cloudAssembly;

    try {
        // Generate a cloud assembly once
        cloudAssembly = await toolkit.synth(cloudAssemblySource);

        // Reuse the same cloud assembly for multiple operations
        await toolkit.list(cloudAssembly);    // Uses existing assembly
        await toolkit.deploy(cloudAssembly);   // Uses existing assembly
        await toolkit.diff(cloudAssembly);     // Uses existing assembly
    } catch (error) {
        console.error("Failed to deploy:", error);
    } finally {
        // Always dispose when done
        if (cloudAssembly) {
            await cloudAssembly.dispose();
        }
    }
}

// Call the async function
deployInfrastructure().catch(error => {
    console.error("Deployment failed:", error);
    process.exit(1);
});
```

## 解决可能出现的问题
<a name="toolkit-library-configure-ca-troubleshooting"></a>

请按照以下步骤解决云程序集源可能出现的问题：
+  **安装缺失的依赖项**：运行 `npm install` 安装 CDK 应用所需的依赖项。
+  **修复路径问题**：检查 CDK 应用程序和程序集目录的路径是否存在且可访问。
+  **解决版本不匹配**：更新 CDK 工具包库版本，使其与 CDK 应用程序版本匹配。
+  **修复合成错误**：检查 CDK 应用程序代码是否存在语法错误或无效配置。

当工具包操作期间出现错误时，请简化错误处理，并专注于向用户提供清晰的错误消息。使用完毕后，务必处置云程序集。以下示例展示了基本错误处理和适当的清理：

```
import { Toolkit } from '@aws-cdk/toolkit-lib';

// Example with simple error handling
try {
    // Create the cloud assembly source
    const cloudAssemblySource = await toolkit.fromCdkApp("ts-node app.ts");

    // Synthesize the cloud assembly
    const cloudAssembly = await toolkit.synth(cloudAssemblySource);

    // Use the cloud assembly
    await toolkit.list(cloudAssembly);
} catch (error) {
    // Display the error message
    console.error("Operation failed:", error.message);
} finally {
    // Clean up resources
    await cloudAssembly.dispose();
}
```