はじめに
AWSのCloudFormationに対して、なんとなくとっつきにくいイメージを持っていたので、手始めによくある設定のS3バケットをテンプレート化してみました。
CloudFormationテンプレート作成環境を整える
VScodeでCloudFormationテンプレートを書くにあたって、以下の記事を参考に環境を整えました。
拡張は"CloudFormation support for Visual Studio Code"と"cfn-lint"のみ導入しました。"pydot"と"indent-rainbow"は現状必要なさそうだったので導入していません。
S3バケットのパラメータ設計
作成するバケットのパラメータを一度GUIベースで考えてみます。
AWSインフラ環境を新規構築する際によくある設定として以下のパラメータで作成します。
-
作成バケット
-
アクセスログ用バケット
-
コンテンツ用バケット
-
共通設定
-
パブリックアクセス:ブロック。
-
デフォルト暗号化:有効。S3管理キー(SSE-S3)。
- バケットアクセスログ:有効。アクセスログ用バケットにバケット名ごとにディレクトリ作成して格納。(アクセスログ用バケット自体のアクセスログの記録は無効)
-
タグ:「Key:Env, Value:CFn-test」を付与。
-
アクセスログ用バケット設定
-
ライフサイクルルール:有効。スコープは全体。"オブジェクトの現行バージョンを有効期限切れ"設定で有効期限は3日。
テンプレート用パラメータの確認
AWS公式ドキュメント(AWS CloudFormation User Guide)からS3バケットに関するPropertiesを確認します。
Propertiesとしては以下の設定項目があるようです。
Properties:
AccelerateConfiguration:
AccelerateConfiguration
AccessControl: String
AnalyticsConfigurations:
- AnalyticsConfiguration
BucketEncryption:
BucketEncryption
BucketName: String
CorsConfiguration:
CorsConfiguration
IntelligentTieringConfigurations:
- IntelligentTieringConfiguration
InventoryConfigurations:
- InventoryConfiguration
LifecycleConfiguration:
LifecycleConfiguration
LoggingConfiguration:
LoggingConfiguration
MetricsConfigurations:
- MetricsConfiguration
NotificationConfiguration:
NotificationConfiguration
ObjectLockConfiguration:
ObjectLockConfiguration
ObjectLockEnabled: Boolean
OwnershipControls:
OwnershipControls
PublicAccessBlockConfiguration:
PublicAccessBlockConfiguration
ReplicationConfiguration:
ReplicationConfiguration
Tags:
- Tag
VersioningConfiguration:
VersioningConfiguration
WebsiteConfiguration:
WebsiteConfiguration
テンプレートに必要な項目の確認
公式ドキュメント記載の各パラメータを確認しながら、今回の設定に必要なパラメータを抜き出します。GUIの設定項目名とほとんど同じなので意外と簡単です。
Properties:
#バケットACL設定
AccessControl: String
#デフォルト暗号化設定
BucketEncryption:
BucketEncryption
#バケット名設定
BucketName: String
#ライフサイクルルール設定
LifecycleConfiguration:
LifecycleConfiguration
#アクセスログ設定
LoggingConfiguration:
LoggingConfiguration
#パブリックアクセスブロック設定
PublicAccessBlockConfiguration:
PublicAccessBlockConfiguration
#タグ設定
Tags:
- Tag
完成したCloudFormationテンプレート
公式ドキュメントをベースに各パラメータの記載方法を確認しながらテンプレートを作成し、最終的に出来上がったものが以下のテンプレートです。
AWSTemplateFormatVersion: "2010-09-09"
Description: Create S3 Bucket
Parameters:
BucketNameAccessLog:
Type: String
Description: Name for AccessLog
BucketNameBucket01:
Type: String
Description: Name for Bucket_1
Resources:
AccessLogBucket:
Type: AWS::S3::Bucket
Properties:
AccessControl: LogDeliveryWrite
BucketName: !Ref BucketNameAccessLog
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
LifecycleConfiguration:
Rules:
- Id: "LifeCycle-01"
Status: Enabled
ExpirationInDays: 3
Tags:
- Key: Env
Value: CFn-test
Bucket01:
Type: AWS::S3::Bucket
Properties:
AccessControl: Private
BucketName: !Ref BucketNameBucket01
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
LoggingConfiguration:
DestinationBucketName: !Ref BucketNameAccessLog
LogFilePrefix: !Join ["", [!Ref BucketNameBucket01, "/"]]
Tags:
- Key: Env
Value: CFn-test
CloudFormationStackを作成して流した実行結果の確認
考慮した点や途中発生したエラーについて
テンプレートの使いまわしができるように書く
テンプレート中のBucketName:
やLogFilePrefix:
部分は最初ベタ書きでバケット名やプレフィックスを書いていたものの、使いまわしができるようにPropertiesセクションで変数として定義し、組み込み関数の"!Ref"を使ってResourcesセクションから呼び出せるように変更しました。
LogFilePrefix:
の部分は"!Join"を使って指定したバケット名ごとにディレクトリが作成されるように変更しました。
Propertiesセクションに記載した項目はデプロイ時にパラメータとして指定し、入力した値に従ってデプロイされます。
アクセスログ用バケットのACL設定
アクセスログ用バケットのACL設定について最初はAccessControl: Private
と記載していましたが、実際に流してみると「You must give the log-delivery group WRITE and READ_ACP permissions to the target bucket.」とエラーが出て作成されませんでした。
エラーの内容としてはバケットのACLでログ配信グループの書き込み許可がないために発生したエラーであり、AccessControl: LogDeliveryWrite
と記載するのが正解のようです。
ドキュメント:AccessControl:で指定するパラメータと内容
「GUIから設定する時にアクセスログ用バケット側のACL設定いじった記憶がないなぁ」と思いましたが、GUIからアクセスログの設定をする際にはこのアクセスログ用バケットのACL設定を自動で書き換えてくれていたので意識することがなかっただけでした。GUIでポチポチと設定する時は自動でやってくれる部分もCloudFormationだと明示的に設定しなければいけない部分が出てくるということが分かりました。
おわりに
Azureでは「今GUIで作ったリソースをテンプレート化するとどうなるのだろう?」というのがWebコンソールからすぐに確認できるのですが、
AWSでは今あるリソースのテンプレートを確認する機能がWebコンソールとしてはないため、なんとなくCloudFormationに対してとっつきにくいイメージを持っていました(初見だとCFnのWebデザイナーもよくわからない...)。
しかし、CFnテンプレートに記載する内容はGUIの設定項目と似ているため、書き方を把握してしまえば意外と簡単に作成できることを実感しました。
今回はParametersとResourcesセクションを使ってみましたが、今後MappingsやConditionsセクションも活用してみたいです。