AWS CDKを使ってほぼ一撃で静的サイトを構築する
AWS CDKとは?
AWS において Infrastructure as Code (以下 IaC) を実現するためのツールです。 CDK 登場以前も CloudFormation を利用して JSON や YAML での IaC は実現可能でしたが、
- 複数のスタックに共通する構成を定義しづらい
- ほぼ同一構成なリソースを複数作成するのが面倒
という課題がありました。 CDK は プログラミング言語を使って定義できるので、 IF文によるパラメータ切り替えや、ループ処理による複数リソース定義が可能です!
利用できるプログラミング言語は、
です。
今回は、サンプルコードが充実している 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": "" }