AWS CDK 超入門!―Hello, world 後編―
この記事は某有志アドベントカレンダー 2023の 3 日目の記事です。
目次
プロジェクト名を決めよう
CDK ではプロジェクト名は結構重要です。以下の 3 つの要件を充たすように決めるのがオススメです。
- AWS アカウントとリージョンの中ではユニークになるようにする
- 英小文字のケバブケース(例 my-project)
- 長すぎない(❌ my-organization-my-section-my-project)
本稿では my-cdk-project という名前で CDK プロジェクトを作成していきます。これにより、 MyCdkProjectStack という名前のスタック(=リソースの集まり)がデプロイされることになります。簡潔さを保つため、 1 プロジェクト 1 スタックにするのがオススメです。
CDK プロジェクトの作成
まずは、my-cdk-project の親ディレクトリに移動して以下のコマンドを実行します。[1]
mkdir my-cdk-project && cd $_
npx -y cdk@latest init --language typescript --generate-only
npm install -D @types/source-map-support
npm install
--generate-only
をつけないと、勝手に Git の操作等を実行されてしまうので、つけるのがオススメです。
以下のコマンドを実行して、適切に表示されたらプロジェクトの作成は完了です。
npx cdk list
# => MyCdkProjectStack と表示される
プロジェクトの使い方
最初に把握する必要があるのは、主に以下の 2 つのファイルです。bin の方はスタックをどこにデプロイするか、lib はスタックの詳細を記述します。リソースを追加したくなったら、lib 以下をどんどん編集していくという感じです。
.
├── bin
│ └── my-cdk-project.ts
└── lib
└── my-cdk-project-stack.ts
どのリージョンにデプロイするか
CDK・CloudFormation のデプロイはスタックという単位で行なわれます。このスタックをどの AWS アカウントのどのリージョンにデプロイするか指定する必要があります。大きく分けて 2 つの指定の方法があります。いずれにしても、明示的に指定することが推奨されます。
- 環境変数で指定する
- スタックごとに直接指定する
さきほど作成した CDK プロジェクトのソースにそれぞれの場合の指定の方法がコメントアウントされています。
new MyCdkProjectStack(app, 'MyCdkProjectStack', {
/* 現在のCLI設定で暗示されているAWSアカウントとリージョンにこのスタックを特化するには、次の行のコメントを解除してください。 */
// env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },
/* スタックをデプロイするアカウントとリージョンが正確にわかっている場合は、次の行のコメントを解除してください。 */
// env: { account: '123456789012', region: 'ap-northeast-1' },
});
多くの場合は、アクセスキーの AWS アカウントとデプロイ先の AWS アカウントが一致していると思いますので、環境変数で指定するのがおすすめです。前編で行ったようにアクセスキーか名前つきプロファイルを指定して cdk コマンドを実行している場合、CDK_DEFAULT_ACCOUNT
も CDK_DEFAULT_REGION
も自動で設定されますので、以下のコードで OK です。
new MyCdkProjectStack(app, 'MyCdkProjectStack', {
env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },
});
作るリソースを理解しよう
続いて lib を編集したいところですが、CDK はリソースの管理をコードで行う機能であるため、イチから何かを作る場合は、まず Web コンソール上で試しにリソース作成して理解を試みるのがオススメです。
IAM Role は権限のセットです。ユーザーなど、何かしらの操作を行う主体(=プリンシパル)も自分自身の権限をもつことができますが、 IAM Role になりきる(assume)ことで IAM Role の権限を使うことができます。ここでは Web コンソール上で、自分のアカウントの Lambda を自由に操作できる IAM Role を作成します。作成ボタンから画面の案内にそって作成していきます。
最後の画像を見ていただくと分かるように、 IAM Role には信頼ポリシーと許可ポリシーのリストが含まれることが分かります。さらに、画面からはインラインポリシーをアタッチすることができます。
この場合もポリシーを作成して、 IAM Role に追加しただけだと分かります。それではこれと同様のものを CDK で作成していきましょう。
実装
以下の通り実装します。
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as iam from 'aws-cdk-lib/aws-iam';
export class MyCdkProjectStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
new iam.Role(this, 'MyCdkProjectStack-test-lambda-full-access', {
assumedBy: new iam.AccountPrincipal(this.account),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('AWSLambda_FullAccess')
],
roleName: 'test-lambda-full-access',
inlinePolicies: {
'test-lambda-invoke': new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: [
'lambda:InvokeFunction'
],
resources: [
`arn:aws:lambda:*:${this.account}:function:*`
]
})
]
})
},
})
}
}
今回は IAM Role を作成したいので、new iam.Role
で IAM Role をデプロイしています。引数は (this, <id>, <option>)
という定型を覚えれば理解しやすいです。
まず id はリソースの ID で、基本的にはスタック内でユニークであれば問題ありませんが、運用上はスタック名を添えておくと考えることが少なくてハッピーだったりします。
続いて option の中身を順番に見ていきます。Web コンソールで作成した内容に対応させていけば理解しやすいと思います。
- assumedBy → 信頼されたエンティティ(≈このロールを使える人)
- managedPolicies → 許可ポリシーで選択したもの
- roleName → ロール名
- inlinePolicies → アタッチしたインラインポリシー
Web コンソールを見ながら各リソースごとに何ができるか理解すれば、あとは CDK に書き起こすだけです。
デプロイ
いよいよデプロイします。
AWS_PROFILE=my-profile npx cdk deploy
今回は IAM に関するリソースをデプロイすることになるため、デプロイしてよいか内容確認がなされます。問題なければ y でデプロイを続行してください。
Web Console で確認
作られたスタックは Web コンソール上の CloudFormation のサービスから確認できます。作成開始から完了までのイベントを見ることができます。エラーが起きたときなどもここから詳細を確認できます。
さらにリソースのタブではどのようなリソースがスタックに含まれるのか確認できます。
想定通りのものが作成されていることが分かります。
デストロイ
お片付けのために、削除を実行します。
AWS_PROFILE=my-profile npx cdk destroy
# => Are you sure you want to delete: MyCdkProjectStack (y/n)? y
最後に Web Console で無事に削除されたことを確認してください。
まとめ
Hello, world! の H の字もでてきませんでしたが、Hello, world! できました🎉
-
初期化コマンド cdk init は引数にテンプレートを取ることもできます。 cdk init --list でテンプレートの一覧を取得可能です。が、 lib を作るのはかなりコアな開発と言えるので、実質的に app の選択肢しかないです。さらにテンプレートは app がデフォルトなので、ひとまずテンプレートのことは忘れて OK です。 ↩︎
Discussion