⼩南 英司
Eiji KOMINAMI
JAWS KOBE & OSAKA
CloudFormation & SAMのススメ
- よくあるパターンは全部テンプレ化しちゃいましょう -
2
⾃⼰紹介
⼩南 英司(こみなみ えいじ)
サーバサイドの構築 から アプリの実装 まで
プリキュア応援アプリの開発/実装
⾼校野球速報アプリの開発/実装
M-1グランプリ視聴者投票システムの構築
...など
@eijikominami
3
Agenda - CloudFormation & SAM の魅⼒を伝えたい
利⽤するメリットと注意点
既存のテンプレートの活⽤
スタック構築Tips
利⽤するメリットと注意点
4
5
CloudFormationとは...
AWSリソース群をテンプレート化し、
迅速かつ適切な順序でプロビジョニング/管理できるサービス
Resources:
MyKinesis:
Type: 'AWS::Kinesis::Stream'
Properties:
ShardCount: 1
MyLambda:
Type: 'AWS::Lambda::Function'
Properties:
Code:
ZipFile: |
import boto3
def lambda_handler(event, context):
records = decode_records(event)
……………………………………………
Handler: index.lambda_handler
Role: arn:aws:iam:0123456789:role/IAMRoleForLambda
Runtime: python3.8
MyLambdaEventSourceMapping:
Type: 'AWS::Lambda::EventSourceMapping'
Properties:
EventSourceArn: !GetAtt MyKinesis.Arn
FunctionName: !GetAtt MyLambda.Arn
MyDynamoDBTable:
Type: 'AWS::DynamoDB::Table'
Properties:
AttributeDefinitions:
- AttributeName: user_id
AttributeType: S
KeySchema:
- AttributeName: user_id
KeyType: HASH
②ʼAWS CLI からデプロイ
①テンプレートファイルを作成
②マネージメントコンソールからデプロイ
AWS Cloud
Region
Amazon Kinesis
Lambda
Amazon DynamoDB
③AWS上に⾃動で構築
6
Serverless Application Modelとは...
CloudFormationを拡張した
サーバレスアプリケーション構築⽤フレームワーク
Resources:
MyKinesis:
Type: 'AWS::Kinesis::Stream'
Properties:
ShardCount: 1
MyLambda:
Type: 'AWS::Serverless::Function'
Properties:
CodeUri: myLambda/
Events:
KinesisEvent:
Properties:
StartingPosition: TRIM_HORIZON
Stream: !GetAtt MyKinesis.Arn
Type: Kinesis
MyDynamoDBTable:
Type: 'AWS::DynamoDB::Table'
Properties:
AttributeDefinitions:
- AttributeName: user_id
AttributeType: S
KeySchema:
- AttributeName: user_id
KeyType: HASH
AWS Cloud
Amazon Kinesis
Lambda
Amazon DynamoDB
③AWS上に⾃動で構築
テンプレートファイル
template.yaml
aws-lambda-powertools
ライブラリ設定ファイル
requirements.txt
import base64
import json
import boto3
import os
import copy
from aws_lambda_powertools import Logger
from aws_lambda_powertools import Tracer
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('test')
user_id_key_name = 'user_id'
group_id_key_name = 'group_id'
attributes_key_name = 'attributes'
@logger.inject_lambda_context(log_event=True)
@tracer.capture_lambda_handler
def lambda_handler(event, context):
records = decode_records(event)
for record in records:
user_id = record['data'][user_id_key_name]
group_id = record['data'][group_id_key_name]
attributes = copy.deepcopy(record['data'])
del attributes[user_id_key_name]
del attributes[group_id_key_name]
update_data(user_id, group_id, attributes)
Lambdaプログラム
lambda_function.py
Amazon S3
②SAM CLIを⽤いて
ビルド/パッケージ化/デプロイ
①テンプレートファイルや
Lambdaプログラム等を作成
7
CloudFormation導⼊で何を変えたかったか
マネージメントコンソールからの⾯倒な⼿動操作
設定の抜け漏れや作業ミスの発⽣
• 作業順序(サービスAを設定した後じゃないとサービスBが設定できない)
• 正しく設定されているかを後から検証することが困難
⾼い作業コストと時間の浪費
• 同じパターンのアーキテクチャを何度も⼿作業で構築(テスト環境/本番環境, 案件A/案件B...)
複雑なリソース管理/運⽤
ウィザード等で作成した過去のリソースの乱⽴
ロールバックやスクラップ&ビルドが困難
⼿間が掛かる上に更新が滞る管理⽤のドキュメント
システム構成の属⼈化
作業者によって微妙に異なる設定
8
CloudFormation/SAMのメリット①
再利⽤可能なテンプレート
複数環境への展開が容易
• 変数のパラメータ化
• 異なるリージョン, 異なるステージ, 複数のシステム/プロジェクトで利⽤できる
バージョン管理可能
安全で⾃動化されたデプロイ
依存関係や実⾏順序を⾃動的に判断しデプロイ
デプロイ失敗時にロールバックが可能
スクラップ&ビルドが容易
• CloudFormationスタックを削除すれば、関連するリソース全てが消える(⼀部例外あり)
合理的かつ継続したデプロイプロセスを構築可能に
9
CloudFormation/SAMのメリット②
リソースのグループ化
テンプレートの分割とネストされたスタック
• 複数のCloudFormationスタックを組み合わせてデプロイが可能
関連するリソースを同時に作成
• リソースに権限を付与 : Service-Linked ロール, IAM ロール, S3バケットポリシー
• ログの出⼒ : S3バケット, CloudWatch Logs
• リソースの監視 : CloudWatch アラーム, EventBridge, SNS
サーバレスアプリケーションを迅速に構築(SAM)
テンプレートとLambdaプログラムを⼀括管理
サーバレスサービスに特化した機能
• 簡略化したテンプレート構⽂の提供
• ローカル開発環境にLambdaの実⾏環境を構築可能
10
CloudFormation/SAMの注意点①
未対応のサービスあり、挙動が怪しい場合も。
今後のロードマップや機能改善等の予定は以下を参照
• CloudFormation Public Coverage Roadmap
https://github.com/aws-cloudformation/aws-cloudformation-coverage-roadmap
• AWS SAM - Issue
https://github.com/aws/aws-sam-cli/issues
未対応サービスの例
• CloudFront の Origin Failover
• DynamoDB の Global Tables
• ローンチされたばかりのサービスや新機能 ...など
Issueの例
• EC2インスタンスに付けたタグが同時に作成したEBSには付与されない
• EventBridgeのイベントパターン内でNumber値を指定すると勝⼿にStringに変換されてしまう
• ネストされたスタック内では sam build が実⾏されない
...など
11
CloudFormation/SAMの注意点②
CloudFormationの制限
1つのテンプレートに含むことのできるリソース数は200まで
• 上限を超える場合は、テンプレートの分割を検討
1つのテンプレートに含むことのできるパラメータ数は60まで
• 変数を⽤いて複雑な処理を⾏う場合は、Mappingsセクションの活⽤も検討
1つのテンプレートの本⽂サイズは51,200バイトまで
• 上限を超える場合は、テンプレートをS3にアップロードした上でデプロイ
1つのアカウントで作成できるスタック数は200まで
• 上限を超える場合は、上限緩和申請も検討
作成するAWSサービスの制限
• オブジェクトを全て削除しないとS3バケットを削除できない
– DeletionPolicy: Retain を指定してスタック削除時にバケットを保持
• 同時に作成できるDynamoDBテーブル数の上限
• Detective は GuardDuty 有効化から 48時間経過後に有効化可能 ...など
12
CloudFormation/SAMの注意点③
その他の注意点
四則演算やforループなどは使⽤できない
スタック内のリソースの⼿動による設定変更(ドリフト)
• ドリフト検出機能を⽤いて設定変更を検知可能
• 正しいテンプレートを⽤いて再デプロイしてもドリフトは解消されない
• ⼿動であるべき姿に戻す or スタックから当該リソースの切り離しと再度インポート
Parametersセクション
• Default は初回作成時のみ有効
• Description を⽇本語にすると⽂字化け
➡ CDK(AWS Cloud Development Kit)の利⽤を検討
既存のテンプレートの活⽤
13
14
⾃分でテンプレートを作成しなくても⼤丈夫
公開されている既存のテンプレートを活⽤しよう
Webページからスタック起動URLをクリック
Serverless Application Repository からアプリケーションを選択
マネージメントコンソール
(CloudFormation)が⾃動で起動
デプロイ
CloudFormation
Stack
Template
マネージメントコンソール
(Lambda)が⾃動で起動
Template
デプロイ
CloudFormation
Stack
15
セキュリティサービスの⼀括有効化
AWSアカウント作成時に有効化すべきサービス群
Amazon Inspector
Amazon GuardDuty
AWS Config
AWS CloudTrail
AWS Security Hub
Amazon Detective
AWS Cloud
Tokyo (ap-northeast-1)
security stack
S3
Bucket
AWS Security Hub
AWS CloudTrail
AWS ConfigAmazon GuardDuty
Amazon Inspector
AlarmAmazon SNSAWS Personal Health
IAM Role
ServiceLinkedRole
Amazon EventBridge
IAM Access Analyzer
Amazon
CloudWatch Events
Amazon CloudWatch
Logs
S3
Bucket
Documents
S3
Bucket
Lambda
Amazon Detective
https://git.io/JTWiB
GitHub
eijikominami/aws-cloudformation-templates
16
静的ウェブサイトのホスティング
CloudFront + S3 + CloudWatch Synthetics
AWS WAF 設定可能
OAIによるアクセス制限
ログの有効化
外形監視
https://git.io/JTWPW
GitHub
eijikominami/aws-cloudformation-templates
AWS Cloud
Tokyo (ap-northeast-1)
static-website-hosting-with-ssl stack
Amazon S3Amazon CloudFront
Amazon S3
access log
AWS WAF
Origin Access
Identity
Amazon CloudWatch
Synthetics
AWS Lambda
Amazon S3
Amazon CloudWatch
Logs
log
data
synthetics monitoring
Amazon CloudWatch
Alarm
17
CloudWatchアラームの設定
頻繁に使⽤するサービスのアラーム設定をテンプレート化
そのままデプロイ
⾃分のテンプレートに埋め込み
マネージメントコンソール
(Lambda)が⾃動で起動
Template
デプロイ
CloudFormation
Stack
https://amzn.to/2Hk4CAf
Serverless Application Repository
https://serverlessrepo.aws.amazon.com/applications
AWS Serverless
Application Repository
Resources:
AlarmEC2:
Type: 'AWS::Serverless::Application'
Properties:
Location:
ApplicationId: arn:aws:serverlessrepo:us-east-
1:172664222583:applications/cloudwatch-alarm-about-ec2
SemanticVersion: 1.1.6
Parameters:
CPUUtilizationThreshold: 80
CustomAlarmName: !Ref AWS::StackName
SNSTopicArn: !Ref SNSForDeploymentArn
EC2:
Type: 'AWS::EC2::Instance'
Properties:
Template
デプロイ
リソースの⼀部として埋め込み
CloudWatchアラーム
⾯倒なアラーム設定を簡単セットアップ
スタック構築Tips
18
19
便利なコマンド/ツール群
cfn-lint
テンプレートのプロパティとその値をチェック(Linter)
複数のIDE向けプラグインあり
cfn-guard
テンプレートのポリシーコンプライアンスをチェック
事前に作成したルールに適合するかチェック
2020/10/1 GA
$ cfn-lint template.yaml
W3005 Obsolete DependsOn on resource (IAMRoleForLambda), dependency already enforced by a "Fn:GetAtt" at Resources/LambdaPutData/Properties/Role/Fn::GetAtt
template.yaml:405:11
https://git.io/JU0pI
https://git.io/JT8cf
$ cfn-guard check -t template.yaml -r default.ruleset
[LambdaGetData] failed because [Runtime] is [python3.7] and Lambda runtime requires Python 3.8
Number of failures: 2
AWS::Lambda::Function Runtime == Python3.8 << Lambda runtime requires Python 3.8
事前に作成したルール
20
CodePipelineを⽤いたビルド&デプロイ
テンプレートの更新をトリガに⾃動でデプロイを実⾏
マネージメントコンソールにログインすることなく⾃動で全てが完了
テンプレート コミット ビルド/テスト デプロイ
パイプライン
git push
Cloudformation テンプレートの場合
1. cfn-lint の実⾏
2. cfn-guard の実⾏
SAM テンプレートの場合
1. cfn-lint の実⾏
2. cfn-guard の実⾏
3. sam-validate の実⾏
4. sam-build の実⾏
5. sam-package の実⾏
CodePipelineを⽤いたビルド&デプロイ
テンプレートのプッシュをトリガにデプロイを⾃動で実⾏
マネージメントコンソールにログインすることなく⾃動で全てが完了
22
モジュラーアプローチ
複数のテンプレートに分割し再利⽤性を⾼める
AWS Cloud
Tokyo (ap-northeast-1)
security stack
S3
Bucket
AWS Security Hub
AWS CloudTrail
AWS ConfigAmazon GuardDuty
Amazon Inspector
AlarmAmazon SNSAWS Personal Health
IAM Role
ServiceLinkedRole
Amazon EventBridge
IAM Access Analyzer
Amazon
CloudWatch Events
Amazon CloudWatch
Logs
S3
Bucket
Documents
S3
Bucket
Lambda
Amazon Detective
ネストされたスタックの利⽤
AWS::Include の利⽤
親テンプレート
ネストされたテンプレート
ネストされたテンプレート
親テンプレート
挿⼊されたテンプレート
ネストされたテンプレートは
変更セットを確認できない
複数のテンプレートに分割し再利⽤性を⾼める
detective.yaml
securityhub.yaml
inspector.yaml
iam.yaml
guardduty.yaml
config.yaml cloudtrail.yaml
23
モジュラーアプローチ
AWS Cloud
Tokyo (ap-northeast-1)
Amazon SNSAWS Personal Health
IAM Role
ServiceLinkedRole
Amazon EventBridge
ネストされたスタックの利⽤
AWS::Include の利⽤
親テンプレート
ネストされたテンプレート
ネストされたテンプレート
親テンプレート
挿⼊されたテンプレート
ネストされたテンプレートは
変更セットを確認できない
24
Enjoy CloudFormation and SAM!
Appendix
25
26
テンプレートリファレンス(CloudFormation)
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/template-reference.html
27
テンプレートリファレンス(SAM)
https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-specification-resources-and-properties.html
28
CloudFormation Sample Templates
https://github.com/awslabs/aws-cloudformation-templates
29
AWS Quick Start
https://github.com/aws-quickstart
30
AWS CloudFormation Templates
https://github.com/eijikominami/aws-cloudformation-templates/
31
buildspec ファイル for SAM テンプレート
version: 0.2
phases:
install:
runtime-versions:
python: 3.8
commands:
- pip install -U pip
- pip install -U cfn-lint
# Use the latest version
- pip install -U awscli
# for Lambda
- pip install -U aws-sam-cli
- pip install -U boto3
# for Lambda Powertools
- pip install -U aws-lambda-powertools
# for cloudformation-guard
- wget https://github.com/aws-cloudformation/cloudformation-guard/releases/download/1.0.0/cfn-guard-linux-1.0.0.tar.gz
- tar -xvf cfn-guard-linux-1.0.0.tar.gz
pre_build:
commands:
- find ./ -type f -name "*.yaml" | xargs --no-run-if-empty cfn-lint
- find ./ -type f -name "*.yaml" | xargs -I {} ./cfn-guard-linux/cfn-guard check -r ./security-standards.ruleset -t {}
build:
commands:
- sam validate --template ${TEMPLATE_FILE_PATH}template.yaml
- sam build --template ${TEMPLATE_FILE_PATH}template.yaml
- sam package --template-file .aws-sam/build/template.yaml --s3-bucket ${PACKAGE_BUCKET} --output-template-file packaged.yaml
artifacts:
files:
- packaged.yaml
https://git.io/JT8z1GitHub
eijikominami/aws-cloudformation-templates
32
cfn-guard ルールファイルの例
AWS Security Hub Security Standards に⼀部準拠
AWS::CloudTrail::Trail IsMultiRegionTrail == true << CloudTrail trails should cover all regions
AWS::CloudTrail::Trail EnableLogFileValidation == true << CloudTrail file validation should be enabled
AWS::CloudTrail::Trail CloudWatchLogsLogGroupArn == /.*/ << CloudTrail trails should be integrated with Amazon CloudWatch Logs
AWS::CloudTrail::Trail KMSKeyId == /.*/ << CloudTrail trails should encrypt the logs delivered by it.
AWS::DMS::ReplicationInstance PubliclyAccessible == false << DMS instance should not be publicly accessible
AWS::EC2::Volume Encrypted == true << EC2 volumes should be encrypted
AWS::EC2::Instance BlockDeviceMappings.*.Ebs.Encrypted == true << EC2 volumes should be encrypted
AWS::EC2::SecurityGroup WHEN SecurityGroupIngress.*.ToPort == 22 CHECK SecurityGroupIngress.*.CidrIp != 0.0.0.0/0
AWS::EC2::SecurityGroup WHEN SecurityGroupIngress.*.ToPort == 3389 CHECK SecurityGroupIngress.*.CidrIp != 0.0.0.0/0
AWS::Elasticsearch::Domain EncryptionAtRestOptions.Enabled == true << Domain encryption should be enabled
AWS::GuardDuty::Detector Enable == true << Detector should be enabled
AWS::IAM::Role Policies.*.PolicyDocument.Statement.*.Action.* != ¥* << IAM Role should not allow full "*" administrative privileges
AWS::KMS::Key EnableKeyRotation == true << Key rotation should be enabled
AWS::RDS::DBInstance PubliclyAccessible == false << Databasae should not be publicly accessible
AWS::RDS::DBInstance StorageEncrypted == true << Storage encryption should be enabled
AWS::S3::Bucket BucketEncryption.ServerSideEncryptionConfiguration == /.*/ << S3 bucket encryption should be enabled
AWS::SageMaker::NotebookInstance DirectInternetAccess == Disabled << Notebooks should not have direct internet access
https://git.io/JT8g4GitHub
eijikominami/aws-cloudformation-templates

CloudFormation/SAMのススメ