

這是 AWS CDK v2 開發人員指南。較舊的 CDK v1 已於 2022 年 6 月 1 日進入維護，並於 2023 年 6 月 1 日結束支援。

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 設定環境以搭配 AWS CDK 使用
<a name="configure-env"></a>

您可以透過多種方式設定 AWS 環境，以搭配 AWS 雲端開發套件 (AWS CDK) 使用 。管理 AWS 環境的最佳方法會根據您的特定需求而有所不同。

您應用程式中的每個 CDK 堆疊最終都必須與環境建立關聯，以判斷堆疊部署的位置。

如需 AWS 環境的簡介，請參閱 [AWS CDK 的環境](environments.md)。

## 您可以從其中指定環境
<a name="configure-env-where"></a>

您可以在登入資料和組態檔案中指定環境，或使用 AWS 建構程式庫中建構`Stack`的 ` [env](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#env) ` 屬性。

### 登入資料和組態檔案
<a name="configure-env-where-files"></a>

您可以使用 AWS 命令列界面 (AWS CLI) 來建立 `credentials`和 `config` 檔案，以存放、組織和管理 AWS 環境資訊。若要進一步了解這些檔案，請參閱《 * AWS 命令列界面使用者指南*》中的[組態和登入資料檔案設定](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html)。

存放在這些檔案中的值會依*設定檔*進行組織。您命名設定檔的方式和這些檔案中的鍵值對，會根據您設定程式設計存取的方法而有所不同。若要進一步了解不同方法，請參閱[設定 AWS CDK CLI 的安全登入資料](configure-access.md)。

一般而言， AWS CDK 會從 `credentials` 檔案解析 AWS 帳戶資訊，並從 `config` 檔案解析 AWS 區域資訊。

設定 `credentials`和 `config` 檔案後，您可以指定要搭配 AWS CDK CLI 和透過環境變數使用的環境。

### 堆疊建構的 env 屬性
<a name="configure-env-where-env"></a>

您可以使用 `Stack` 建構的 ` [env](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#env) ` 屬性來指定每個堆疊的環境。此屬性定義要使用的帳戶和區域。您可以將硬式編碼值傳遞至此屬性，或傳遞 CDK 提供的環境變數。

若要傳遞環境變數，請使用 `AWS_DEFAULT_ACCOUNT`和 `AWS_DEFAULT_REGION` 環境變數。這些環境變數可以從 `credentials`和 `config` 檔案傳遞值。您也可以在 CDK 程式碼中使用邏輯來判斷這些環境變數的值。

## AWS CDK 的環境優先順序
<a name="configure-env-precedence"></a>

如果您使用多種方法來指定環境， AWS CDK 會遵循下列優先順序：

1. 使用 `Stack` 建構的 `env` 屬性指定的硬式編碼值。

1.  `AWS_DEFAULT_ACCOUNT` 和 `AWS_DEFAULT_REGION`環境變數，以 `Stack` 建構的 `env` 屬性指定。

1. 與來自 `credentials`和 `config` 檔案的設定檔相關聯的環境資訊，並使用 `--profile`選項傳遞至 CDK CLI。

1. 來自 `credentials`和 `config` 檔案的`default`設定檔。

## 何時指定環境
<a name="configure-env-when"></a>

當您使用 CDK 進行開發時，請先定義 CDK 堆疊，其中包含代表 AWS 資源的建構。接下來，您將每個 CDK 堆疊合成為 an AWS CloudFormation 範本。然後，您將 CloudFormation 範本部署到您的環境。您指定環境的方式會決定何時套用環境資訊，並可能影響 CDK 行為和結果。

### 在範本合成時指定環境
<a name="configure-env-when-synth"></a>

當您使用 `Stack` 建構的 `env` 屬性指定環境資訊時，您的環境資訊會套用至範本合成。執行`cdk synth`或`cdk deploy`產生環境特定的 CloudFormation 範本。

如果您在 `env` 屬性中使用環境變數，則必須使用 `--profile`選項搭配 CDK CLI 命令，以傳入包含來自登入資料和組態檔案之環境資訊的設定檔。然後，此資訊將在範本合成時套用，以產生環境特定的範本。

CloudFormation 範本中的環境資訊優先於其他方法。例如，如果您使用 提供不同的環境`cdk deploy --profile <profile>`，則會忽略設定檔。

當您以這種方式提供環境資訊時，您可以在 CDK 應用程式中使用環境相依程式碼和邏輯。這也表示，根據其合成所在的機器、使用者或工作階段，合成的範本可能不同。這種方法在開發期間通常是可接受的或理想的，但不建議用於生產用途。

### 在堆疊部署時指定環境
<a name="configure-env-when-deploy"></a>

如果您未使用 `Stack` 建構的 `env` 屬性指定環境，CDK CLI 會在合成時產生與環境無關的 CloudFormation 範本。然後，您可以使用 指定要部署到 的環境`cdk deploy --profile <profile>`。

如果您在部署與環境無關的範本時未指定設定檔，CDK CLI 將嘗試使用部署時您 `credentials`和 `config` 檔案的`default`設定檔中的環境值。

如果部署時無法使用環境資訊， AWS CloudFormation 會嘗試透過 `stack.account`、 `stack.region`和 等環境相關屬性，在部署時解析環境資訊`stack.availabilityZones`。

對於與環境無關的堆疊，堆疊中的建構無法使用環境資訊，而且您無法使用需要環境資訊的邏輯。例如，您無法像 一樣編寫程式碼，`if (stack.region ==== 'us-east-1')`也無法使用需要環境資訊的建構方法，例如 ` [Vpc.fromLookup](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options) `。若要使用這些功能，您必須使用 `env` 屬性指定環境。

對於與環境無關的堆疊，使用可用區域的任何建構都會看到兩個可用區域，允許將堆疊部署到任何區域。

## 如何使用 AWS CDK 指定環境
<a name="configure-env-how"></a>

### 為每個堆疊指定硬式編碼的環境
<a name="configure-env-how-hard-coded"></a>

使用 `Stack` 建構的 `env` 屬性來指定堆疊 AWS 的環境值。以下是範例：

**Example**  

```
const envEU  = { account: '2383838383', region: 'eu-west-1' };
const envUSA = { account: '8373873873', region: 'us-west-2' };

new MyFirstStack(app, 'first-stack-us', { env: envUSA });
new MyFirstStack(app, 'first-stack-eu', { env: envEU });
```

```
const envEU  = { account: '2383838383', region: 'eu-west-1' };
const envUSA = { account: '8373873873', region: 'us-west-2' };

new MyFirstStack(app, 'first-stack-us', { env: envUSA });
new MyFirstStack(app, 'first-stack-eu', { env: envEU });
```

```
env_EU = cdk.Environment(account="8373873873", region="eu-west-1")
env_USA = cdk.Environment(account="2383838383", region="us-west-2")

MyFirstStack(app, "first-stack-us", env=env_USA)
MyFirstStack(app, "first-stack-eu", env=env_EU)
```

```
public class MyApp {

    // Helper method to build an environment
    static Environment makeEnv(String account, String region) {
        return Environment.builder()
                .account(account)
                .region(region)
                .build();
    }

    public static void main(final String argv[]) {
        App app = new App();

        Environment envEU = makeEnv("8373873873", "eu-west-1");
        Environment envUSA = makeEnv("2383838383", "us-west-2");

        new MyFirstStack(app, "first-stack-us", StackProps.builder()
                .env(envUSA).build());
        new MyFirstStack(app, "first-stack-eu", StackProps.builder()
                .env(envEU).build());

        app.synth();
    }
}
```

```
Amazon.CDK.Environment makeEnv(string account, string region)
{
    return new Amazon.CDK.Environment
    {
        Account = account,
        Region = region
    };
}

var envEU = makeEnv(account: "8373873873", region: "eu-west-1");
var envUSA = makeEnv(account: "2383838383", region: "us-west-2");

new MyFirstStack(app, "first-stack-us", new StackProps { Env=envUSA });
new MyFirstStack(app, "first-stack-eu", new StackProps { Env=envEU });
```

```
env_EU := awscdk.Environment{
	Account: jsii.String("8373873873"),
	Region:  jsii.String("eu-west-1"),
}

env_USA := awscdk.Environment{
	Account: jsii.String("2383838383"),
	Region:  jsii.String("us-west-2"),
}

MyFirstStack(app, "first-stack-us", &awscdk.StackProps{
	Env: &env_USA,
})

MyFirstStack(app, "first-stack-eu", &awscdk.StackProps{
	Env: &env_EU,
})
```

我們建議在生產環境中使用此方法。透過以這種方式明確指定環境，您可以確保堆疊一律部署到特定環境。

### 使用環境變數指定環境
<a name="configure-env-how-env"></a>

 AWS CDK 提供兩個可在 CDK 程式碼中使用的環境變數： `CDK_DEFAULT_ACCOUNT`和 `CDK_DEFAULT_REGION`。當您在堆疊執行個體的 `env` 屬性內使用這些環境變數時，您可以使用 CDK CLI `--profile`選項，從您的登入資料和組態檔案傳遞環境資訊。

以下是如何指定這些環境變數的範例：

**Example**  
透過 Node `process` 物件存取環境變數。  
您需要 `DefinitelyTyped`模組才能`process`在 TypeScript 中使用 。 會為您`cdk init`安裝此模組。不過，如果您正在使用在新增之前建立的專案，或者您沒有使用 設定專案，您應該手動安裝此模組`cdk init`。  

```
npm install @types/node
```

```
new MyDevStack(app, 'dev', {
  env: {
    account: process.env.CDK_DEFAULT_ACCOUNT,
    region: process.env.CDK_DEFAULT_REGION
}});
```
透過 Node `process` 物件存取環境變數。  

```
new MyDevStack(app, 'dev', {
  env: {
    account: process.env.CDK_DEFAULT_ACCOUNT,
    region: process.env.CDK_DEFAULT_REGION
}});
```
使用`os`模組的`environ`字典來存取環境變數。  

```
import os
MyDevStack(app, "dev", env=cdk.Environment(
    account=os.environ["CDK_DEFAULT_ACCOUNT"],
    region=os.environ["CDK_DEFAULT_REGION"]))
```
使用 `System.getenv()`取得環境變數的值。  

```
public class MyApp {

    // Helper method to build an environment
    static Environment makeEnv(String account, String region) {
        account = (account == null) ? System.getenv("CDK_DEFAULT_ACCOUNT") : account;
        region = (region == null) ? System.getenv("CDK_DEFAULT_REGION") : region;

        return Environment.builder()
                .account(account)
                .region(region)
                .build();
    }

    public static void main(final String argv[]) {
        App app = new App();

        Environment envEU = makeEnv(null, null);
        Environment envUSA = makeEnv(null, null);

        new MyDevStack(app, "first-stack-us", StackProps.builder()
                .env(envUSA).build());
        new MyDevStack(app, "first-stack-eu", StackProps.builder()
                .env(envEU).build());

        app.synth();
    }
}
```
使用 `System.Environment.GetEnvironmentVariable()`取得環境變數的值。  

```
Amazon.CDK.Environment makeEnv(string account=null, string region=null)
{
    return new Amazon.CDK.Environment
    {
        Account = account ?? System.Environment.GetEnvironmentVariable("CDK_DEFAULT_ACCOUNT"),
        Region = region ?? System.Environment.GetEnvironmentVariable("CDK_DEFAULT_REGION")
    };
}

new MyDevStack(app, "dev", new StackProps { Env = makeEnv() });
```

```
import "os"

MyDevStack(app, "dev", &awscdk.StackProps{
	Env: &awscdk.Environment{
		Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")),
		Region:  jsii.String(os.Getenv("CDK_DEFAULT_REGION")),
    },
})
```

透過使用環境變數指定環境，您可以針對不同的環境，讓相同的 CDK 堆疊合成至 AWS CloudFormation 範本。這表示您可以將相同的 CDK 堆疊部署到不同的 AWS 環境，而不必修改 CDK 程式碼。您只需要指定執行 時要使用的設定檔`cdk synth`。

在將相同的堆疊部署到不同的環境時，這種方法非常適合開發環境。不過，我們不建議在生產環境中使用此方法，因為相同的 CDK 程式碼可以合成不同的範本，取決於其合成所在的機器、使用者或工作階段。

### 使用 CDK CLI 從登入資料和組態檔案指定環境
<a name="configure-env-how-files"></a>

部署環境無關範本時，請使用 `--profile`選項搭配任何 CDK CLI 命令來指定要使用的設定檔。以下是使用 `credentials`和 `config`檔案中定義的`myStack``prod`設定檔來部署名為 之 CDK 堆疊的範例：

```
$ cdk deploy <myStack> --profile <prod>
```

如需 `--profile`選項以及其他 CDK CLI 命令和選項的詳細資訊，請參閱 [AWS CDK CLI 命令參考](ref-cli-cmd.md)。

## 使用 AWS CDK 設定環境時的考量事項
<a name="configure-env-considerations"></a>

您在堆疊中使用建構來定義的服務，必須支援您要部署的區域。如需每個區域支援的 AWS 服務清單，請參閱[AWS 依區域的服務](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/)。

您必須擁有有效的 AWS Identity and Access Management (IAM) 登入資料，才能在指定的環境中使用 AWS CDK 執行堆疊部署。

## 範例
<a name="configure-env-examples"></a>

### 從 CDK 堆疊合成與環境無關的 CloudFormation 範本
<a name="configure-env-examples-agnostic"></a>

在此範例中，我們會從 CDK 堆疊建立與環境無關的 CloudFormation 範本。然後，我們可以將此範本部署到任何環境。

以下是我們的範例 CDK 堆疊。此堆疊會定義儲存貯體區域的 Amazon S3 儲存貯體和 CloudFormation 堆疊輸出。在此範例中， `env` 未定義：

**Example**  

```
export class CdkAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Create the S3 bucket
    const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
    });

    // Create an output for the bucket's Region
    new cdk.CfnOutput(this, 'BucketRegion', {
      value: bucket.env.region,
    });
  }
}
```

```
class CdkAppStack extends cdk.Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    // Create the S3 bucket
    const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
    });

    // Create an output for the bucket's Region
    new cdk.CfnOutput(this, 'BucketRegion', {
      value: bucket.env.region,
    });
  }
}
```

```
class CdkAppStack(cdk.Stack):

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

        # Create the S3 bucket
        bucket = s3.Bucket(self, 'amzn-s3-demo-bucket',
            removal_policy=cdk.RemovalPolicy.DESTROY
        )

        # Create an output for the bucket's Region
        cdk.CfnOutput(self, 'BucketRegion',
            value=bucket.env.region
        )
```

```
public class CdkAppStack extends Stack {

    public CdkAppStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        // Create the S3 bucket
        Bucket bucket = Bucket.Builder.create(this, "amzn-s3-demo-bucket")
            .removalPolicy(RemovalPolicy.DESTROY)
            .build();

        // Create an output for the bucket's Region
        CfnOutput.Builder.create(this, "BucketRegion")
            .value(this.getRegion())
            .build();
    }
}
```

```
namespace MyCdkApp
{
    public class CdkAppStack : Stack
    {
        public CdkAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // Create the S3 bucket
            var bucket = new Bucket(this, "amzn-s3-demo-bucket", new BucketProps
            {
                RemovalPolicy = RemovalPolicy.DESTROY
            });

            // Create an output for the bucket's Region
            new CfnOutput(this, "BucketRegion", new CfnOutputProps
            {
                Value = this.Region
            });
        }
    }
}
```

```
func NewCdkAppStack(scope constructs.Construct, id string, props *CdkAppStackProps) awscdk.Stack {
	stack := awscdk.NewStack(scope, &id, &props.StackProps)

	// Create the S3 bucket
	bucket := awss3.NewBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.BucketProps{
		RemovalPolicy: awscdk.RemovalPolicy_DESTROY,
	})

	// Create an output for the bucket's Region
	awscdk.NewCfnOutput(stack, jsii.String("BucketRegion"), &awscdk.CfnOutputProps{
		Value: stack.Region(),
	})

	return stack
}
```

執行 時`cdk synth`，CDK CLI 會產生具有虛擬參數的 CloudFormation 範本，` AWS::Region`做為儲存貯體區域的輸出值。此參數將在部署時解析：

```
Outputs:
  BucketRegion:
    Value:
      Ref: AWS::Region
```

若要將此堆疊部署到登入資料和組態檔案`dev`設定檔中指定的環境，我們會執行下列動作：

```
$ cdk deploy CdkAppStack --profile dev
```

如果我們未指定設定檔，CDK CLI 會嘗試使用登入資料和組態檔案中`default`設定檔的環境資訊。

### 使用邏輯在範本合成時判斷環境資訊
<a name="configure-env-example-logic"></a>

在此範例中，我們將`stack`執行個體的 `env` 屬性設定為使用有效的表達式。我們指定了兩個額外的環境變數 `CDK_DEPLOY_ACCOUNT`和 `CDK_DEPLOY_REGION`。如果存在，這些環境變數可以在合成時間覆寫預設值：

**Example**  

```
new MyDevStack(app, 'dev', {
  env: {
    account: process.env.CDK_DEPLOY_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT,
    region: process.env.CDK_DEPLOY_REGION || process.env.CDK_DEFAULT_REGION
}});
```

```
new MyDevStack(app, 'dev', {
  env: {
    account: process.env.CDK_DEPLOY_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT,
    region: process.env.CDK_DEPLOY_REGION || process.env.CDK_DEFAULT_REGION
}});
```

```
MyDevStack(app, "dev", env=cdk.Environment(
    account=os.environ.get("CDK_DEPLOY_ACCOUNT", os.environ["CDK_DEFAULT_ACCOUNT"]),
    region=os.environ.get("CDK_DEPLOY_REGION", os.environ["CDK_DEFAULT_REGION"])
    )
)
```

```
public class MyApp {

    // Helper method to build an environment
    static Environment makeEnv(String account, String region) {
        account = (account == null) ? System.getenv("CDK_DEPLOY_ACCOUNT") : account;
        region = (region == null) ? System.getenv("CDK_DEPLOY_REGION") : region;
        account = (account == null) ? System.getenv("CDK_DEFAULT_ACCOUNT") : account;
        region = (region == null) ? System.getenv("CDK_DEFAULT_REGION") : region;

        return Environment.builder()
                .account(account)
                .region(region)
                .build();
    }

    public static void main(final String argv[]) {
        App app = new App();

        Environment envEU = makeEnv(null, null);
        Environment envUSA = makeEnv(null, null);

        new MyDevStack(app, "first-stack-us", StackProps.builder()
                .env(envUSA).build());
        new MyDevStack(app, "first-stack-eu", StackProps.builder()
                .env(envEU).build());

        app.synth();
    }
}
```

```
Amazon.CDK.Environment makeEnv(string account=null, string region=null)
{
    return new Amazon.CDK.Environment
    {
        Account = account ??
            System.Environment.GetEnvironmentVariable("CDK_DEPLOY_ACCOUNT") ??
            System.Environment.GetEnvironmentVariable("CDK_DEFAULT_ACCOUNT"),
        Region = region ??
            System.Environment.GetEnvironmentVariable("CDK_DEPLOY_REGION") ??
            System.Environment.GetEnvironmentVariable("CDK_DEFAULT_REGION")
    };
}

new MyDevStack(app, "dev", new StackProps { Env = makeEnv() });
```

```
var account, region string
var b bool

if account, b = os.LookupEnv("CDK_DEPLOY_ACCOUNT"); !b || len(account) == 0 {
	account = os.Getenv("CDK_DEFAULT_ACCOUNT")
}
if region, b = os.LookupEnv("CDK_DEPLOY_REGION"); !b || len(region) == 0 {
	region = os.Getenv("CDK_DEFAULT_REGION")
}

MyDevStack(app, "dev", &awscdk.StackProps{
	Env: &awscdk.Environment{
		Account: &account,
		Region:  &region,
	},
})
```

透過以此方式宣告堆疊的環境，我們可以撰寫簡短的指令碼或批次檔案，並從命令列引數設定變數，然後呼叫 `cdk deploy`。以下是範例。超過前兩個引數的任何引數都會傳遞至 `cdk deploy`，以指定命令列選項或引數：

**Example**  

```
#!/usr/bin/env bash
if [[ $# -ge 2 ]]; then
    export CDK_DEPLOY_ACCOUNT=$1
    export CDK_DEPLOY_REGION=$2
    shift; shift
    npx cdk deploy "$@"
    exit $?
else
    echo 1>&2 "Provide account and region as first two args."
    echo 1>&2 "Additional args are passed through to cdk deploy."
    exit 1
fi
```
將指令碼儲存為 `cdk-deploy-to.sh`，然後執行 `chmod +x cdk-deploy-to.sh`使其可執行。

```
@findstr /B /V @ %~dpnx0 > %~dpn0.ps1 && powershell -ExecutionPolicy Bypass %~dpn0.ps1 %*
@exit /B %ERRORLEVEL%
if ($args.length -ge 2) {
    $env:CDK_DEPLOY_ACCOUNT, $args = $args
    $env:CDK_DEPLOY_REGION,  $args = $args
    npx cdk deploy $args
    exit $lastExitCode
} else {
    [console]::error.writeline("Provide account and region as first two args.")
    [console]::error.writeline("Additional args are passed through to cdk deploy.")
    exit 1
}
```
Windows 版本的指令碼使用 PowerShell 提供與 macOS/Linux 版本相同的功能。它還包含允許它作為批次檔案執行的指示，以便從命令列輕鬆叫用它。它應該儲存為 `cdk-deploy-to.bat`。檔案`cdk-deploy-to.ps1`會在叫用批次檔案時建立。

然後，我們可以編寫使用指令碼部署到特定環境的其他`cdk-deploy-to`指令碼。以下是範例：

**Example**  

```
#!/usr/bin/env bash
# cdk-deploy-to-test.sh
./cdk-deploy-to.sh 123457689 us-east-1 "$@"
```

```
@echo off
rem cdk-deploy-to-test.bat
cdk-deploy-to 135792469 us-east-1 %*
```

以下是使用`cdk-deploy-to`指令碼部署到多個環境的範例。如果第一次部署失敗，程序會停止：

**Example**  

```
#!/usr/bin/env bash
# cdk-deploy-to-prod.sh
./cdk-deploy-to.sh 135792468 us-west-1 "$@" || exit
./cdk-deploy-to.sh 246813579 eu-west-1 "$@"
```

```
@echo off
rem cdk-deploy-to-prod.bat
cdk-deploy-to 135792469 us-west-1 %* || exit /B
cdk-deploy-to 245813579 eu-west-1 %*
```