#author("2019-02-22T01:09:29+00:00","","")
[[AWSメモ]] >
* AWS CloudFormationメモ [#q8714c67]
#setlinebreak(on);

#contents
-- 関連
--- [[AWS API Gateway&LambdaをFlaskに移行しやすいように作る]]
--- [[AWS IotにPublishされたデータをDynamoDBに登録する]]
--- [[PythonでAWS DynamoDBのCRUDを書いてみる]]
--- [[AWS Lambdaで環境変数を使用する]]
-- 参考
--- https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/Welcome.html

** 概要 [#dd0e7442]
#html(<div style="padding-left: 10px;">)
AWS CloudFormation を利用するとインフラ全体をテキストファイルでモデル(ソース)化できる。
AWS上に作成する必要があるリソースを全てCloudFormationテンプレートとして定義しておく事で、環境の複製やデプロイの自動化などが安全容易に行える為、非常に有用。
#html(</div>)

** テンプレート形式 [#a83d7460]
#html(<div style="padding-left: 10px;">)

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/template-formats.html

CloudFormation テンプレートは JSON または YAML で以下の形式で記述する。
#mycode2(){{
AWSTemplateFormatVersion: "2010-09-09"
Description: Sample template
Resources:
  SampleResource1:              # リソースの論理名
    Type: AWS::Xxxx::Xxxx    # リソースタイプ
    Properties:                       # リソースのプロパティ
        .
        .
  SampleResource2:              # リソースの論理名
    Type: AWS::Xxxx::Xxxx    # リソースタイプ
    Properties:                       # リソースのプロパティ
        .
        .
}}

各項目の内容は以下の通り。
| 項目名 | 説明 | 参考URL |h
| AWSTemplateFormatVersion | 形式バージョン | https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/format-version-structure.html |
| Description | 説明 | https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/template-description-structure.html |

#html(</div>)

** 組み込み関数の利用 [#d4cfd34e]
#html(<div style="padding-left: 10px;">)

スタックの管理に役立ついくつかの組み込み関数が用意されている。
ここでは使用頻度の高い GetAtt と Ref について記載する。
※GetAtt、Ref ともに ARN や ID を参照する際に多用する。

参考
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html

*** GetAtt [#q6e79d07]
#html(<div style="padding-left: 10px;">)

GetAtt はテンプレートのリソースから属性の値を返す事ができる。
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html

YAMLの場合
#mycode2(){{
Fn::GetAtt: [ logicalNameOfResource, attributeName ]    # 完全名関数
!GetAtt logicalNameOfResource.attributeName               # 短縮形
}}

#html(</div>)

*** Ref [#l9fec0fa]
#html(<div style="padding-left: 10px;">)

Ref は指定したパラメータまたはリソースの値を返す事ができる。
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html

YAMLの場合
#mycode2(){{
Ref: logicalName    # 完全名関数
!Ref logicalName    # 短縮形
}}

尚、返される内容はリソースの種類によって異なるので注意が必要。( ARN、ID、名前 の何れかが返されるものが殆どだが  )
※参考: [[Ref: リソースの戻り値の例>https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html#ref-resource-return-examples]]

#html(</div>)

#html(</div>)

** マクロの利用 [#u18013e5]
#html(<div style="padding-left: 10px;">)

*** AWS::Serverless 変換 [#y2dbc281]
#html(<div style="padding-left: 10px;">)
#TODO
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/transform-aws-serverless.html
#html(</div>)

*** 定型コンテンツの挿入 [#ac8ec692]
#html(<div style="padding-left: 10px;">)
#TODO
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/create-reusable-transform-function-snippets-and-add-to-your-template-with-aws-include-transform.html
#html(</div>)

#html(</div>)

** パラメータを使用する [#y20d2825]
#html(<div style="padding-left: 10px;">)

Parameters セクションを利用すると、スタックを作成または更新する際にテンプレートにカスタム値を入力できる。
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html

*** テンプレートの記述例 [#m2f826f0]
#html(<div style="padding-left: 10px;">)

以下に Lambda関数名の接頭文字をパラメータ化する例を記載する。

#mycode2(){{
AWSTemplateFormatVersion : '2010-09-09'
Transform: "AWS::Serverless-2016-10-31"
Description: "Sample Lambda Environments."
Parameters:
  FuncNamePrefix:
    Type: String
    Default: "My"

Resources:
  SampleLambdaEnv:
    Type: "AWS::Serverless::Function"
    Properties:
      FunctionName: !Sub '${FuncNamePrefix}-SampleLambda'
      .
      .
}}
#html(</div>)

*** パラメータの設定方法 [#o8903d12]
#html(<div style="padding-left: 10px;">)

create-stack でパラメータをセット場合は --parameters オプションを指定する
https://docs.aws.amazon.com/cli/latest/reference/cloudformation/create-stack.html

#myterm2(){{
aws cloudformation create-stack --stack-name SampleStack --template-body file://template.yml --parameters FuncNamePrefix="Test" --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND
}}

deploy でパラメータをセットする場合は --parameter-overrides オプションを使用する
https://docs.aws.amazon.com/cli/latest/reference/cloudformation/deploy/index.html
#myterm2(){{
aws cloudformation deploy --stack-name SampleStack --template-file packaged-template.yml --parameter-overrides FuncNamePrefix="Test" --capabilities CAPABILITY_NAMED_IAM CAPABILITY_AUTO_EXPAND
}}

#html(</div>)

*** 関連 [#ib381835]
#html(<div style="padding-left: 10px;">)
- [[AWS Lambdaで環境変数を使用する]]
#html(</div>)

#html(</div>)

** 条件を指定する [#f111df71]
#html(<div style="padding-left: 10px;">)
#TODO
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html
#html(</div>)

** 他スタックの定義を再利用する [#kd44b137]
#html(<div style="padding-left: 10px;">)

*** 定義のエクスポート [#qc8613f9]
#html(<div style="padding-left: 10px;">)

スタックの出力値をエクスポートして、他のテンプレートで使用する事ができる。
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html

テーブル名 及び テーブルのARN をエクスポートする例)
#mycode2(){{
.
.

Resources:
  SampleTable01:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: SampleTable01

Outputs:
  SampleTable01Name:
    Value: !Ref SampleTable01
    Export:
      Name: MyTable01Name
  SampleTable01Arn:
    Value: !GetAtt SampleTable01.Arn
    Export:
      Name: MyTable01Arn
}}

また、エクスポートされている値の一覧は aws cloudformation list-exports で確認する事ができる。

#myterm2(){{
aws cloudformation list-exports

{
    "Exports": [
        {
            "ExportingStackId": "arn:aws:cloudformation:ap-northeast-1:XXXXXXXXXXXX:stack/SampleCreateTables/dbd...5d08", 
            "Value": "arn:aws:dynamodb:ap-northeast-1:XXXXXXXXXXXX:table/SampleTable01", 
            "Name": "MyTable01Arn"
        }, 
        {
            "ExportingStackId": "arn:aws:cloudformation:ap-northeast-1:XXXXXXXXXXXX:stack/SampleCreateTables/dbd...5d08", 
            "Value": "SampleTable01", 
            "Name": "MyTable01Name"
        }
    ]
}
}}

整形して出力
#myterm2(){{
aws cloudformation list-exports | awk 'BEGIN {value=""}{ if ($1 == "\"Value\":") value=$2; if ($1 == "\"Name\":") print $2"\t"value}' | sed 's/[",]//g'

MyTable01Arn	arn:aws:dynamodb:ap-northeast-1:XXXXXXXXXXXX:table/SampleTable01
MyTable01Name	SampleTable01
}}

#html(</div>)

*** エクスポート済みの値の参照 [#gf2375f6]
#html(<div style="padding-left: 10px;">)

エクスポートした値は Fn::ImportValue を使用して別のテンプレートから参照する事ができる。
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html

#mycode2(){{
  SampleIotDataTablePutItemRole:
    Type: AWS::IAM::Role
    Properties:
        .
        .
      Policies:
        - PolicyName: "SampleIotDataTablePutItemPolicy"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action: "dynamoDB:PutItem"
                Resource: !ImportValue MyTable01Arn
}}
#html(</div>)

参考
- チュートリアル: 別の AWS CloudFormation スタックのリソース出力を参照する&br;https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/walkthrough-crossstackref.html

#html(</div>)

** サンプル [#vad9a975]
#html(<div style="padding-left: 10px;">)

参考: [[AWS リソースおよびプロパティタイプのリファレンス>https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html]]

*** Lambda単体 [#gd05e635]
#html(<div style="padding-left: 10px;">)
#TODO
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-reference-lambda.html
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html
#html(</div>)

*** Lambda単体 (AWS::Serverless 変換を利用する場合) [#x629e4d5]
#html(<div style="padding-left: 10px;">)
#TODO
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/transform-aws-serverless.html
https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md
#html(</div>)

*** API Gateway & Lambda [#bcad9846]
#html(<div style="padding-left: 10px;">)
#TODO
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-reference-apigateway.html
#html(</div>)

*** API Gateway & Lambda (AWS::Serverless 変換を利用する場合) [#laf9d052]
#html(<div style="padding-left: 10px;">)
#TODO
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/transform-aws-serverless.html
https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md
#html(</div>)

*** DynamoDB [#p42a469c]
#html(<div style="padding-left: 10px;">)

例)
#mycode2(){{
AWSTemplateFormatVersion: "2010-09-09"
Description: sample dynamodb template
Resources:
  SampleTable01:
    Type: AWS::DynamoDB::Table
    Properties:

      # テーブル名(必須)
      TableName: SampleTable01

      # 請求モード
      BillingMode: PROVISIONED  # プロビジョニング(デフォルト): PROVISIONED、オンデマンド:PAY_PER_REQUEST

      # テーブルキー 及び インデックスのキー項目(必須)
      AttributeDefinitions:
        - AttributeName: pkeyCol  # 項目名
          AttributeType: S        # 文字列:S、数値:N、バイナリ:B
        - AttributeName: skeyCol
          AttributeType: S
        - AttributeName: gsiCol
          AttributeType: S
        - AttributeName: lsiCol
          AttributeType: S

      # キャパシティユニット( BillingMode が PROVISIONED の場合は必須 )
      ProvisionedThroughput:
        ReadCapacityUnits: 5   # 読み込みキャパシティユニット
        WriteCapacityUnits: 5  # 書き込みキャパシティユニット

      # テーブルのキー項目(必須)
      KeySchema:
        - AttributeName: pkeyCol  # 項目名
          KeyType: HASH        # HASH or RANGE
        - AttributeName: skeyCol
          KeyType: RANGE

      # GSI
      GlobalSecondaryIndexes:
        -   
          # インデックス名
          IndexName: SampleTable01_GSI1

          # キー項目
          KeySchema:
            - AttributeName: gsiCol
              KeyType: HASH

          # 射影
          Projection:
            ProjectionType: KEYS_ONLY  # KEYS_ONLY or INCLUDE or ALL

          # キャパシティユニット
          ProvisionedThroughput:
            ReadCapacityUnits: 5   # 読み込みキャパシティユニット
            WriteCapacityUnits: 5  # 書き込みキャパシティユニット

      # LSI
      LocalSecondaryIndexes:
        -   
          # インデックス名
          IndexName: SampleTable01_LSI1

          # キー項目
          KeySchema:
            - AttributeName: pkeyCol
              KeyType: HASH 
            - AttributeName: lsiCol
              KeyType: RANGE

          # 射影
          Projection:
            ProjectionType: KEYS_ONLY  # KEYS_ONLY or INCLUDE or ALL
}}

参考URL
| AWS::DynamoDB::Table | https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html |
| Amazon DynamoDB Table AttributeDefinition | https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-attributedef.html |
| Amazon DynamoDB Table KeySchema | https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-keyschema.html |
| Amazon DynamoDB Table ProvisionedThroughput | https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html |
| Amazon DynamoDB テーブル GlobalSecondaryIndex | https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html |
| Amazon DynamoDB テーブル LocalSecondaryIndex | https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html |

尚、AutoScaling の設定は AWS::ApplicationAutoScaling::ScalableTarget 及び AWS::ApplicationAutoScaling::ScalingPolicy で設定する必要がある。
※ Auto Scaling アクションを実行するサービスにリンクされたロールとして AWSServiceRoleForApplicationAutoScaling_DynamoDBTable を使用できる。
※ https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/AutoScaling.Console.html#AutoScaling.Console.NewTable
※ https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-examples-application-autoscaling
※ https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/AutoScaling.Console.html

関連
 [[DynamoDBのキャパシティユニットについて]]

#html(</div>)

#html(</div>)

** 実行方法 [#t51adc84]
#html(<div style="padding-left: 10px;">)

*** create-stack で作成する場合 [#ud4cda5a]
#html(<div style="padding-left: 10px;">)

#myterm2(){{
# スタック名
STACK_NAME=SampleStack

# 検証&作成&作成完了まで待つ
aws cloudformation validate-template --template-body file://template.yml \
  && aws cloudformation create-stack --stack-name $STACK_NAME --template-body file://template.yml --capabilities CAPABILITY_IAM \
  && aws cloudformation wait stack-create-complete --stack-name $STACK_NAME
}}

#html(</div>)

*** package & deploy で作成する場合 [#aac44185]
#html(<div style="padding-left: 10px;">)

#myterm2(){{
# スタック名
STACK_NAME=SampleStack

# アカウントIDの取得
ACCOUNT_ID=`aws sts get-caller-identity | grep Account | awk '{print $2}' | sed -e "s/[^0-9]//g"`

# S3バケットの作成(バケット名は世界で唯一である必要がある為、末尾にアカウントID等を付与しておく)
aws s3api create-bucket --create-bucket-configuration '{"LocationConstraint": "ap-northeast-1"}' --bucket my-cloudformation-templates-${ACCOUNT_ID}

# 検証&パッケージング&デプロイ
aws cloudformation validate-template --template-body file://template.yml \
  && aws cloudformation package --template-file template.yml --s3-bucket my-cloudformation-templates-${ACCOUNT_ID} --output-template-file packaged-template.yml \
  && aws cloudformation deploy --template-file packaged-template.yml --stack-name $STACK_NAME --capabilities CAPABILITY_IAM
}}

尚、エラーがあった場合は describe-stack-events  で内容を確認できる。
#myterm2(){{
aws cloudformation describe-stack-events --stack-name $STACK_NAME
}}

#html(</div>)

トップ   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS