はじめに
こんにちは、あんころです!
この前、投稿したハッカソンの振り返り記事の中で、こんなことを書いていました。
特にIaCの部分は、ハッカソン中は「とりあえず環境が作れればOK」という目標で進めてしまいました。今回はうまくいきましたが、同じことを次回も再現できるかと問われると、正直自信がありません。その再現性のなさに課題を感じているので、ハッカソン後に改めて時間を取り、きちんと理解を深めようと思います。別途まとめ記事を投稿予定です。
有言実行ということで、今回はCDKを用いてAWSインフラ環境をどのように構築するかを整理します。
この記事はフロント・バックエンドの開発経験はあるけれどインフラはほぼ触ったことないよ〜という方を対象にしています。自分自身がまさにそうだったので、つまずいたポイントを含めて丁寧にまとめていきます。
記事は3回に分けて投稿します。
- 第1回:CDKとは何か・CDKセットアップ手順、Hello World環境構築まで
- 第2回:VPCを理解してLambdaをPrivate Subnetに移す
- 第3回:AuroraをVPC内に立ててLambdaから接続する
今回は第1回目です。
この記事のゴール
- IaCとは何かがわかる
- IaCの代表ツールであるCDKについてわかる
- CDKとCloudFormationの関係がわかる
- CDKを使って簡単なインフラ環境(Hello World)を動かす流れがイメージできる
IaCとは何か
Iacは、Infrastruction as Codeの略で、コードを使ってインフラ環境を管理・構築していく手法のことです。
手動で作る場合の問題点
AWSコンソールを手動でポチポチ操作してインフラを作る場合、以下のような問題があります。
- ヒューマンエラーが起きやすい:設定の入力ミスや項目の設定忘れが発生しやすい
- 再現性のなさ:同じ環境をもう一度を作ろうとしても、何をどう設定したかの記録が残らない
- 知識がないと操作すらできない:どの画面で何を設定すればいいかわからず、手が止まりがち
コードで管理するとどう嬉しいのか
手動 → コードによって以下のようなメリットが生まれます。
- 変更履歴が残る:Gitで管理できるので、いつ・何を・なぜ変えたのかが追える
- 属人化をなくす:手動だとインフラの設定は担当者しか把握できませんが、コードで書くことでインフラの状態が誰でも読める形で残る。フロントやバックエンドの人も状況を把握できるようになります。
- レビューができる:インフラの変更をコードとしてチームで確認できる
IaCツールの種類
AWSのインフラをコードで管理できるツールはいくつかあります。主要なものを簡単に紹介します。
| ツール | 言語 | 特徴 |
|---|---|---|
| Terraform | HCL (独自言語) | AWS以外のクラウド(Google CloudやAzure)にも対応するマルチクラウド対応ツール |
| AWS SAM | YAML | Lambda・API Gatewayに特化したサーバーレス向けツール |
| AWS CDK | TypeScript / Python等 | AWSが提供するツール。慣れた言語でインフラを書くことができる。 |
今回CDKを選んだ理由
- TypeScriptで書ける:普段から慣れている言語なのでコードを追いやすい
- AWS公式ツールなので互換性が高い:AWSの他サービスとの連携がスムーズにできる
- 全体をカバーできる:SAMはLambda・API Gatewayなどのサーバーレス構成に特化しており設定がシンプルな分、VPCやAuroraのような構成には対応しきれない側面があります。一方で、CDKはAWSのほぼ全サービスをカバーしているため、今回のような全体構成の管理には適していると判断しました。
CDKとCloudFormationの関係性
CloudFormationとは
CloudFormationはAWSが提供するインフラ自動構築サービスです。YAMLファイルにインフラの構成を書いた「テンプレート」と呼ばれるものをAWSに送ると、その内容通りにAWSリソースを自動で作ってくれます。
この「テンプレート」から実際に作られたAWSリソースのまとまりを「スタック」と呼びます。
テンプレート (設計図)
↓ AWSに送信
スタック (実際に作られたAWSリソースのまとまり)
├── VPC
├── Lambda
└── API Gateway
ただし、このテンプレートを手書きすると非常に冗長になります。VPCを1つ作るだけでも100行以上のYAMLが必要になり非常に大変です。
そこでCDKの登場です。CDKを使うと、TypeScriptなど慣れた言語でインフラを定義でき、cdk deploy を実行すると自動でCloudFormationのテンプレートに変換し、AWSのCloudFormationサービスに転送してくれます。
転送の流れ
コードを作成してからどのようにAWS側に送られるかの流れは以下のようになります。
1. CDKのコード (TypeScript)を作る
2. cdk deployを実行する
3. CDKがコードをCloudFormationテンプレートに変換する
4. ローカル上のCDKがAWSのCloudFormationサービスに転送する
5. CloudFormationがテンプレートを実行し、
スタック(実際のAWSリソース)を生成する。
IaCにも注意点がある
ただし、IaCを使えば解決というわけではありません。CDKのセットアップとインフラの管理コードを書いた後、cdk deploy のコマンド一つで環境が作れてしまう分、中身がブラックボックス化するリスクがあります。つまり「よくわからないけど環境は作れた」という状態です。
自分自身、ハッカソン中はまさにこの状況に陥りました。だからこそ、何が起きているかをきちんと理解する時間を設けなければならないと強く思いました。
このハッカソンの経験から感じたのは、インフラの基礎理解があってこそ、IaCは強力な武器になるということです。
- 基礎理解がある → IaC:何が起きているかわかった上で爆速で環境を構築できる
- 基礎理解がない → IaC:何となく動いているだけで、問題が起きた時に対処できない
基礎がない状態でIaCに頼るのは、諸刃の剣だなと思います。少しずつわからないことをわかるようにし、自分の武器にしていきましょう!
それでは実際に手を動かしてみましょう。シンプルなHello World環境を作ることから始めます。
Hello Worldを動かす
見ただけではわからない部分があると思うので、実際にインフラ環境を構築してみましょう!
今回では、以下のシンプルな構成を目指します。
ブラウザ
↓ HTTPリクエスト
API Gateway (エンドポイント(URL)を公開する)
↓ Lambda呼び出し
Lambda (Hello Worldを返す)
cdk deploy をしてURLをブラウザで叩いたら Hello Worldが返ってくる環境を作っていきます。以下の手順を示してきます。
1. ツールのインストール
以下の3つをインストールします。
# Node.js (CDKの実行に必要)
brew install node
# AWS CLI (AWSの操作をターミナル上から行うツール)
brew install awscli
# AWS CDK
npm install -g aws-cdk
# インストール確認
node --version # v20.x.x
aws --version # aws-cli/2.x.x
cdk --version # 2.x.x
2. AWS CLIの認証設定
ローカル環境からcdk deployを実行する際、AWSに「誰がデプロイするか」を証明する必要があります。そのためにアクセスキーを発行し、AWS CLIに設定をします。
AWSコンソールでの操作
- IAM → ユーザー → ユーザーを作成
- 許可ポリシー:
AdministratorAccess - 作成後:セキュリティ認証情報 → アクセスキーを作成
- Access Key IDとSecret Access Keyをメモする
AWS CLIに認証情報を設定
# AWS Access Key ID: (メモした値)
# AWS Secret Access Key: (メモした値)
# Default region name: ap-northeast-1
# Default output format: json
# 確認 (アカウント情報が返れば成功)
aws sts get-caller-identity
3. CDKプロジェクトの作成
mkdir infra && cd infra
cdk init app --language typescript
実行後には以下のファイルが生成されます。
infra/
├── bin/
│ └── infra.ts # エントリーポイント(スタックをここで列挙する)
├── lib/
│ └── infra-stack.ts # インフラの定義を書くファイル
├── cdk.json # CDKの設定ファイル
└── package.json
4. Lambdaのコードを書く
lambda/ ディレクトリを作成し、ハンドラーを書きます。
mkdir lambda
lambda/hello.tsを作成:
export const handler = async () => {
return {
statusCode: 200,
body: JSON.stringify({ message: "Hello World" }),
};
};
5. LambdaとAPI GatewayをCDKで定義する
TypeScriptのビルドに必要なesbuildをインストールします。
npm install --save-dev esbuild
次に、lib/infra-stack.ts を以下の内容に書き換えます。
import * as cdk from 'aws-cdk-lib/core';
import { Construct } from 'constructs';
import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs";
import * as apigw from "aws-cdk-lib/aws-apigateway";
import * as path from "path";
export class InfraStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Lambda関数の定義
const helloFn = new NodejsFunction(this, "HelloFunction", {
entry: path.join(__dirname, "../lambda/hello.ts"),
handler: "handler",
});
// API Gatewayの定義
new apigw.LambdaRestApi(this, "HelloApi", {
handler: helloFn,
});
}
}
- NodejsFunction:TypeScriptをDockerなしでローカルビルドしてLambdaにデプロイしてくれるCDK組み込みのクラス
- LambdaRestApi:API GatewayとLambdaを一言で紐づけてくれるクラスのこと
6. Bootstrapの実行 (初回のみ)
BootstrapはCDKが内部で使うS3バケットやIAMロールをAWS側に用意させるコマンドのことです。アカウント✖️リージョンごとに1回だけ実行すればOKです。
# アカウントIDの確認
aws sts get-caller-identity
cdk bootstrap aws://アカウントID/ap-northeast-1
7. cdk deployの実行
6までできたらcdk deployを実行しましょう
cdk deploy
途中で以下のような確認が出たらy を入力します。
Do you wish to deploy these changes (y/n)? y
8. 動作確認
デプロイ完了後、ターミナルに以下のようなURLが表示されます。
Outputs:
InfraStack.HelloApiEndpoint = https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/
ブラウアまたはcurlで叩いてみます。
curl https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/
# → {"message":"Hello World"}
Hello Worldが返ってきたら成功です!
9. 後片付け
検証が終わったらリソースを削除して動作を止めます。
cdk destroy
まとめ
- IaCとは何か:インフラの構成をコードで管理する手法のこと。コンソールの手動操作と比べて、変更履歴が残る・属人かを防ぐ・チームでレビューできるというメリットがある。
- CDKとTerraformの違い:TerraformはAWS以外のクラウドにも対応できるマルチクラウド対応ツールで、独自言語(HCL)で書く。CDKはAWS専用だが、TypeScriptなど慣れた言語で書けてAWSサービスとの親和性が高い。
-
CDKとCloudFormationの関係:
cdk deploy時にCloudFormationテンプレートへ自動変換され、AWSに送られる。実際のリソース生成はCloudFormationが担っている。
次回は、現在パブリックに置いているLambdaをVPC内のPrivate Subnetに移す手順を扱います。「VPCって何だっけ?」というところから、必要な概念について丁寧にまとめていこうと思います。
ありがとうございました!