ねむみの極み

CloudFormationに入門してみた

こんにちは。
この記事はTechCommit Advent Calendar 2023 4日目の記事です。
4日目が空いていたので、3日目に続いて担当してみました。

はじめに

私はAWSを勉強しているのですが、CloudFormationはあまり触ったことがなく、
なんとなく敬遠していました。
でも避けては通れないので、やっとこさ入門しました。

いきなり長いテンプレートで複雑な構成のリソースを作るのは大変なので、ネットで見つけた記事を参考にS3バケットをいろいろ作ってみることにしました。

記事ではテンプレートにJSONを使っていましたが、YAMLの方がすっきりして見えるのでYAMLで書き直しました。
脳死コピペ防止にもよいです。

※CloudFormationでは、テンプレートをもとにリソースを作成することを「スタックの作成」というらしいです。

では始めましょう。

No.1 一番シンプル

1
2
3
4
5
6
AWSTemplateFormatVersion: 2010-09-09
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: cfn-1 #ここだけ好きな名前にする

たったこれだけで、S3バケットが一つ作れました。
意外と簡単ジャマイカ。


No.2 バケット名をAWSコンソールから指定できるようにする

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
AWSTemplateFormatVersion: 2010-09-09
Parameters: #これ
  S3BucketName:
    Type: String
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName:
        Fn::Sub: ${S3BucketName} #これ

Parametersを使うと、スタックの作成時にコンソールから値を入力し、
テンプレート内で使用することができます。
渡した値は、Fn::Sub:という組み込み関数を使うことで、取り出せます。

↓No.1ではバケット名をテンプレート内で指定しましたが、No.2ではこの画面から好きな名前を決めることができるようになりました。


No.3 別の組み込み関数を使ってみる 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  S3BucketName:
    Type: String
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName:
        Ref: S3BucketName #これ

Refという組み込み関数を使ってみました。よく使うみたいです。
Fn::Subとの違いは↓です。

組み込み関数 Fn::Sub は、入力文字列の変数を、指定した値に置き換えます。
(公式ドキュメント)


組み込み関数 Ref は、指定したパラメータまたはリソースの値を返します。
(公式ドキュメント)


No.4 コンソールに情報を出力してみる

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  S3BucketName:
    Type: String
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName:
        Fn::Sub: ${S3BucketName}
Outputs: #これ
  BucketName1:
    Value:
      Fn::Sub: ${S3BucketName} #いろんな
  BucketName2:
    Value:
      Ref: S3BucketName #書き方が
  BucketName3:
    Value:
      Ref: S3Bucket #あるね

Outputsを使うと、テンプレート内で指定した内容をコンソール画面に出力することができます。
いろいろな書き方をしてみましたが、以下のようにちゃんと出力されました。

No.5 バケットを2つ作ってみる

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  S3BucketName1: #☆
    Type: String
  S3BucketName2: #★
    Type: String
Resources:
  S3Bucket1: #☆
    Type: AWS::S3::Bucket
    Properties:
      BucketName:
        Fn::Sub: ${S3BucketName1}
  S3Bucket2: #★
    Type: AWS::S3::Bucket
    Properties:
      BucketName:
        Fn::Sub: ${S3BucketName2}
星が付いているところは好きな名前で良いことが分かりました。


No.6 静的Webサイトホスティングができるバケットを作ってみる

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  S3BucketName:
    Type: String
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      AccessControl: PublicRead
      BucketName:
        Fn::Sub: ${S3BucketName}
      WebsiteConfiguration: #トップページとエラーページを設定
        IndexDocument: index.html
        ErrorDocument: error.html
  BucketPolicy: #バケットポリシーが新登場
    Type: AWS::S3::BucketPolicy
    Properties:
      PolicyDocument:
        ID: WebhostingPolicy
        Version: 2012-10-17
        Statement:
          Sid: PublicReadBucketObjects
          Action: s3:GetObject
          Effect: Allow
          Resource:
            Fn::Sub: arn:aws:s3:::${S3BucketName}/*
          Principal: "*"
      Bucket:
        Ref: S3Bucket
Outputs:
  WebsiteURL:
    Value:
      Fn::GetAtt:
        S3Bucket.WebsiteURL #URLを出力させる
    Description: URL for website hosted on S3

これ、スタック作成時にテンプレートエラーは起きなかったので書き方は問題ないと思うのですが、私の環境では権限エラーか何かでうまくいきませんでした。
掘るとハマりそうなので一旦諦めました。
うまくいったら教えてください・・・

ちなみにFn::GetAttとは

Fn::GetAtt 組み込み関数は、テンプレートのリソースから属性の値を返します。
(公式ドキュメント)

だそうです

おわりに

というわけで、S3バケットの作成を通してCloudFormationを触ってみました。
次回はうらさくさんの【Python】forループとlambda式関数を組み合わせるときのTipsです!