AWS CDKとは?
AWS において Infrastructure as Code (以下 IaC) を実現するためのツールです。 CDK 登場以前も CloudFormation を利用して JSON や YAML での IaC は実現可能でしたが、
- 複数のスタックに共通する構成を定義しづらい
- ほぼ同一構成なリソースを複数作成するのが面倒
という課題がありました。 CDK は プログラミング言語を使って定義できるので、 IF文によるパラメータ切り替えや、ループ処理による複数リソース定義が可能です!
利用できるプログラミング言語は、
- TypeScript
- Python
- .Net
- Java
です。
今回は、サンプルコードが充実している TypeScript を使用して、CloudFront + S3 の静的サイトを構築してみます。
前提
AWS CLIが利用できる状態。 ※AWS CDKは内部的に AWS-CLI と CloudFormation を利用して、リソースを操作しています。
構築手順
CDKのインストール
$ yarn global add aws-cdk
## バージョン確認
$ cdk --version
1.18.0 (build bc924bc)
CDKを書いていく
CDKプロジェクトを作成していきましょう。
$ cdk init --app cdk-static-site --language=typescript
必要なライブラリをインストールします。
$ yarn add @aws-cdk/aws-iam @aws-cdk/aws-s3 @aws-cdk/aws-cloudfront
CloudFront と S3 を定義します。
import cdk = require("@aws-cdk/core");
import s3 = require("@aws-cdk/aws-s3");
import cloudfront = require("@aws-cdk/aws-cloudfront");
import iam = require("@aws-cdk/aws-iam");
type Stage = "prod" | "stg" | "test";
export class CdkStaticSiteStack extends cdk.Stack {
readonly AppDomain: string = "example.com";
readonly AppName: string = "example";
readonly Stage: Stage = "prod";
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// 独自ドメインを設定する場合に使用する(証明書ARNチェック)
// const acmArn: string = this.node.tryGetContext('acmArn');
// if (!acmArn) {
// throw new Error('CloudFrontに設定する証明書のARNをContextに設定してください。');
// }
// CloudFront オリジン用のS3バケットを作成する
const originBucket = new s3.Bucket(this, this.prefix() + "-bucket", {
// バケット名
bucketName: this.prefix() + "-" + this.account,
// バージョニング(無効)
versioned: false,
// CDKスタック削除時の挙動(スタック削除時にバケットも削除する)
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
// CloudFront で設定する オリジンアクセスアイデンティティ を作成する
const oai = new cloudfront.CfnCloudFrontOriginAccessIdentity(
this,
this.prefix() + "-oai",
{
cloudFrontOriginAccessIdentityConfig: {
comment: "s3 access.",
},
}
);
// S3バケットポリシーで、CloudFrontのオリジンアクセスアイデンティティを許可する
const policy = new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ["s3:GetObject"],
principals: [new iam.CanonicalUserPrincipal(oai.attrS3CanonicalUserId)],
resources: [originBucket.bucketArn + "/*"],
});
originBucket.addToResourcePolicy(policy);
// CloudFrontディストリビューションを作成する
const distribution = new cloudfront.CloudFrontWebDistribution(
this,
this.prefix() + "-cloudfront",
{
defaultRootObject: "/index.html",
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
httpVersion: cloudfront.HttpVersion.HTTP2,
priceClass: cloudfront.PriceClass.PRICE_CLASS_200,
originConfigs: [
{
s3OriginSource: {
s3BucketSource: originBucket,
originAccessIdentityId: oai.ref,
},
behaviors: [
{
isDefaultBehavior: true,
compress: true,
minTtl: cdk.Duration.seconds(0),
maxTtl: cdk.Duration.days(365),
defaultTtl: cdk.Duration.days(1),
},
],
},
],
// 独自ドメインを設定する場合に使用する
// viewerCertificate: {
// aliases: [this.AppDomain],
// props: {
// acmCertificateArn: acmArn,
// minimumProtocolVersion: "TLSv1.2_2018",
// sslSupportMethod: "sni-only",
// }
// },
errorConfigurations: [
{
errorCode: 403,
errorCachingMinTtl: 300,
responseCode: 200,
responsePagePath: "/index.html",
},
],
}
);
cdk.Tag.add(this, "App", this.AppName);
cdk.Tag.add(this, "Stage", this.Stage);
}
private prefix(): string {
return this.AppName.toLowerCase() + "-" + this.Stage.toLowerCase();
}
}
デプロイしてみます。
# TypeScriptをコンパイルする
$ yarn build
# CloudFomationテンプレートを生成する
$ cdk synth
# デプロイする
# しばらく待ちます。CloudFrontディストリビューションの作成に10分程度かかります。
$ cdk deploy
$ cdk deploy
が終わり次第、S3にindex.html
をアップロードし、
CloudFrontエンドポイントにアクセスするとindex.html
の内容が表示されるはずです!
まとめ
このように、100行未満のコードを書くだけで、静的サイトが構築できます。
プログラミング言語を利用するので、柔軟に書けて、パラメータ切り替えや構成の再利用が行いやすいです。
今回は単純な構成例ですが、実務での冗長化構成や監視定義など、大規模になればなるほど、
プログラミング言語で定義できる
というのが活きてくるかと思います。
まだまだ発展途上で、AWSJのSAの方にも「まだ手を出すのは早い」と言われたこともありますが、 どんどんCDKで構築していきたいと思います!
補足: 独自ドメインを設定する場合
上記コードの// 独自ドメインを設定する場合に使用する
とコメントしている処理を利用してください。
CDKを実行する前に、ACMで証明書を発行しておき、その証明書のARNをcdk.context.json
に追記してください。
{
"@aws-cdk/core:enableStackNameDuplicates": "true",
"acmArn": ""
}