1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【AWS CDK (Python)】 CDKスタックへパラメータを渡す方法

Posted at

はじめに

本記事は、私自身の備忘録を兼ねてAWS CDKをこれから始める方の一助になればと思い、AWS CDKの使い方等をまとめたものです。
今回は、AWS CDKを実行する際にCDKスタックにパラメータを渡してスタックやリソースの設定を制御する方法を確認しています。
なお、本記事は私自身の経験を基に記載していますが、間違いがあったらすみません。

CDKスタックにパラメータを渡したい状況

AWS CDKでリソースをデプロイする際にスタックにパラメータを渡したくなることがあります。
例えば、
・デプロイする環境を分けたい場合(例:dev、prodなど)
・デプロイするリージョンをパラメータで指定したい場合
などです。
もちろんコードにべた書きでも良いのですが、実行するたびにコードを書き換えるのも手間なので実行時にパラメータで渡せるようにする方法を確認します。

環境

本記事は以下の環境を使用して記載しています。

  • AWS Cloud9
  • AWS CDK:2.80.0
  • Python: 3.10.11
  • Node.js: 16.20.0

また、以下の記事に基づいてAWS CDKの環境を作成しています。

CDKスタックへパラメータを渡す方法

では、本題のCDKスタックへパラメータを渡す方法を確認します。今回は、環境を分けるパラメータとしてENVを渡したいと思います。
スタックへパラメータを渡す方法は、2通りありますので、それぞれ確認していきます。

cdkコマンドで渡す方法

cdkコマンドでENVを指定するのですが、まずはcdkコマンドで渡すパラメータをCDKのプログラムで受け取るところを確認します。
パラメータは、cdk.App().node.try_get_context("パラメータ名")で受け取れます。
app.pyを以下のように変更してENVパラメータを取得するようにしました。
取得したENVパラメータをスタックをロードする際にスタック名に追加し、加えてスタックにパラメータとして渡すようにしています。

app.py
#!/usr/bin/env python3
import os
import aws_cdk as cdk
from cdk_app.cdk_app_stack import CdkAppStack

app = cdk.App()

# ↓↓ コマンドからパラメータを取得 ↓↓
param_env = app.node.try_get_context("ENV")
# ↑↑ コマンドからパラメータを取得 ↑↑

# ↓↓ スタック名に追加&パラメータで渡す ↓↓
CdkAppStack(app, "CdkAppStack-" + param_env,
        param=param_env
    )
# ↑↑ スタック名に追加&パラメータで渡す ↑↑

app.synth()

なお、スタックのプログラムは以下のようにS3バケットを作成するようになっていて、リソースの論理ID、S3バケットの名前にパラメータとして渡されたENVパラメータを付けるようにしています。

cdk_app/cdk_app_stack.py
from aws_cdk import (
    Stack,
    aws_s3 as s3,
    RemovalPolicy
)
from constructs import Construct

class CdkAppStack(Stack):

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

        s3bucket = s3.Bucket(
            self,
            "MyS3Bucket-" + param_env,
            bucket_name = "cdk-test-bucket-" + param_env,
            removal_policy=RemovalPolicy.DESTROY
        )

この状態でデプロイします。コマンドでパラメータを渡す際は-c パラメータ名=パラメータ値を付けて実行します。ここでは、パラメータ値としてdevを指定しました。
app.pyでENVパラメータをスタックをロードする際にスタック名に追加したので、スタック名にdevが付いていることが確認できます。

(.venv) user_name:~/environment/cdk-app (master) $ cdk deploy -c ENV=dev

✨  Synthesis time: 18.12s

(中略)
CdkAppStack-dev: deploying... [1/1]
CdkAppStack-dev: creating CloudFormation changeset...

 ✅  CdkAppStack-dev

✨  Deployment time: 36.81s

Stack ARN:
(中略)

✨  Total time: 54.93s

マネージメントコンソールでS3バケットを確認してみます。バケット名にもdevが付いてますね。
image.png

今度は、パラメータ値としてprodを指定して実行してみます。パラメータ値をスタック名に付けるようにしているので、先ほどとは別スタックとして起動することが確認できます。

(.venv) user_name:~/environment/cdk-app (master) $ cdk deploy -c ENV=prod

✨  Synthesis time: 17.4s

(中略)
CdkAppStack-prod: deploying... [1/1]
CdkAppStack-prod: creating CloudFormation changeset...

 ✅  CdkAppStack-prod

✨  Deployment time: 36.65s

Stack ARN:
(中略)

✨  Total time: 54.05s

再度、S3バケットを確認してみると、prodが付いたバケットが追加されてました!
image.png

これで、cdkコマンドでパラメータを渡す方法が確認できました。次の確認をする前にS3バケットを削除しておきます。

(.venv) user_name:~/environment/cdk-app (master) $ cdk destroy -c ENV=dev
(.venv) user_name:~/environment/cdk-app (master) $ cdk destroy -c ENV=prod

コンテキスト変数で渡す方法

次にコンテキスト変数を利用してパラメータを取得します。コンテキスト変数は、CDKの設定ファイルであるcdk.jsonに設定します。cdk.json内の"context""ENV": "dev"を追加します。

cdk.json
{
  "app": "python3 app.py",
  "watch": {
    "include": [
      "**"
    ],
    "exclude": [
      "README.md",
      "cdk*.json",
      "requirements*.txt",
      "source.bat",
      "**/__init__.py",
      "python/__pycache__",
      "tests"
    ]
  },
  "context": {
    "@aws-cdk/aws-lambda:recognizeLayerVersion": true,
    "@aws-cdk/core:checkSecretUsage": true,
    "@aws-cdk/core:target-partitions": [
      "aws",
      "aws-cn"
    ],
    "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
    "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
    "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
    "@aws-cdk/aws-iam:minimizePolicies": true,
    "@aws-cdk/core:validateSnapshotRemovalPolicy": true,
    "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
    "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
    "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
    "@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
    "@aws-cdk/core:enablePartitionLiterals": true,
    "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
    "@aws-cdk/aws-iam:standardizedServicePrincipals": true,
    "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
    "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
    "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
    "@aws-cdk/aws-route53-patters:useCertificate": true,
    "@aws-cdk/customresources:installLatestAwsSdkDefault": false,
    "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
    "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
    "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
    "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
    "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
    "@aws-cdk/aws-redshift:columnId": true,
    "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
    "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
    "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
    "# comment": "# ↓↓ パラメータ追加 ↓↓",
    "ENV": "dev",
    "# comment": "# ↑↑ パラメータ追加 ↑↑"
  }
}

コンテキスト変数で渡す場合もcdk.App().node.try_get_context("パラメータ名")で受け取れるので、app.pyやcdk_app/cdk_app_stack.pyは先ほどのままです。

app.py(再掲)
#!/usr/bin/env python3
import os
import aws_cdk as cdk
from cdk_app.cdk_app_stack import CdkAppStack

app = cdk.App()

# ↓↓ コマンドからパラメータを取得 ↓↓
param_env = app.node.try_get_context("ENV")
# ↑↑ コマンドからパラメータを取得 ↑↑

# ↓↓ スタック名に追加&パラメータで渡す ↓↓
CdkAppStack(app, "CdkAppStack-" + param_env,
        param=param_env
    )
# ↑↑ スタック名に追加&パラメータで渡す ↑↑

app.synth()
cdk_app/cdk_app_stack.py(再掲)
from aws_cdk import (
    Stack,
    aws_s3 as s3,
    RemovalPolicy
)
from constructs import Construct

class CdkAppStack(Stack):

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

        s3bucket = s3.Bucket(
            self,
            "MyS3Bucket-" + param_env,
            bucket_name = "cdk-test-bucket-" + param_env,
            removal_policy=RemovalPolicy.DESTROY
        )

この状態でデプロイします。

(.venv) user_name:~/environment/cdk-app (master) $ cdk deploy

マネージメントコンソールでS3バケットを確認してみます。バケット名にdevが付きました。
image.png

これで、コンテキスト変数でパラメータを渡す方法が確認できました。S3バケットを削除しておきます。

(.venv) user_name:~/environment/cdk-app (master) $ cdk destroy

最後に、cdkコマンドとコンテキスト変数両方で同じパラメータ名に別のパラメータ値を渡すとどうなるか試してみます。
コンテキスト変数でENVパラメータにdevを指定した状態で、cdkコマンドでENVパラメータにprodを指定して実行します。

cdk.json(再掲)
{
  "app": "python3 app.py",
  "watch": {
(中略)
  },
  "context": {
    "@aws-cdk/aws-lambda:recognizeLayerVersion": true,
(中略)
    "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
    "# comment": "# ↓↓ パラメータ追加 ↓↓",
    "ENV": "dev",
    "# comment": "# ↑↑ パラメータ追加 ↑↑"
  }
}
(.venv) user_name:~/environment/cdk-app (master) $ cdk deploy -c ENV=prod

✨  Synthesis time: 15.92s

(中略)
CdkAppStack-prod: deploying... [1/1]
CdkAppStack-prod: creating CloudFormation changeset...

 ✅  CdkAppStack-prod

✨  Deployment time: 36.76s

Stack ARN:
(中略)

✨  Total time: 52.68s

デプロイするとCdkAppStack-prodスタックが作成され、S3バケットにもprodが付いてますね。cdkコマンドでの指定が優先されるようです。
image.png

まとめ

AWS CDKでスタックにパラメータを渡す方法を確認しました。用途によってcdkコマンドから渡す方法とコンテキスト変数で渡す方法と使い分ける必要がありそうですね。
最後まで読んでいただいてありがとうございます。
少しでも参考になれば幸いです。

参考文献

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?