Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

CloudFormation/SAMのススメ

 CloudFormation/SAMのススメ

CloudFormation と SAM を使って AWS の構築を自動化する方法とは?よくあるパターンは、テンプレート化して再利用性を高めましょう。

Eiji KOMINAMI / 小南英司

October 19, 2020
Tweet

More Decks by Eiji KOMINAMI / 小南英司

Other Decks in Technology

Transcript

  1. ⼩南 英司 Eiji KOMINAMI JAWS KOBE & OSAKA CloudFormation &

    SAMのススメ - よくあるパターンは全部テンプレ化しちゃいましょう -
  2. 2 ⾃⼰紹介 ⼩南 英司(こみなみ えいじ) サーバサイドの構築 から アプリの実装 まで プリキュア応援アプリの開発/実装

    ⾼校野球速報アプリの開発/実装 M-1グランプリ視聴者投票システムの構築 ...など @eijikominami
  3. 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上に⾃動で構築
  4. 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プログラム等を作成
  5. 7 CloudFormation導⼊で何を変えたかったか マネージメントコンソールからの⾯倒な⼿動操作 設定の抜け漏れや作業ミスの発⽣ • 作業順序(サービスAを設定した後じゃないとサービスBが設定できない) • 正しく設定されているかを後から検証することが困難 ⾼い作業コストと時間の浪費 •

    同じパターンのアーキテクチャを何度も⼿作業で構築(テスト環境/本番環境, 案件A/案件B...) 複雑なリソース管理/運⽤ ウィザード等で作成した過去のリソースの乱⽴ ロールバックやスクラップ&ビルドが困難 ⼿間が掛かる上に更新が滞る管理⽤のドキュメント システム構成の属⼈化 作業者によって微妙に異なる設定
  6. 8 CloudFormation/SAMのメリット① 再利⽤可能なテンプレート 複数環境への展開が容易 • 変数のパラメータ化 • 異なるリージョン, 異なるステージ, 複数のシステム/プロジェクトで利⽤できる

    バージョン管理可能 安全で⾃動化されたデプロイ 依存関係や実⾏順序を⾃動的に判断しデプロイ デプロイ失敗時にロールバックが可能 スクラップ&ビルドが容易 • CloudFormationスタックを削除すれば、関連するリソース全てが消える(⼀部例外あり) 合理的かつ継続したデプロイプロセスを構築可能に
  7. 9 CloudFormation/SAMのメリット② リソースのグループ化 テンプレートの分割とネストされたスタック • 複数のCloudFormationスタックを組み合わせてデプロイが可能 関連するリソースを同時に作成 • リソースに権限を付与 :

    Service-Linked ロール, IAM ロール, S3バケットポリシー • ログの出⼒ : S3バケット, CloudWatch Logs • リソースの監視 : CloudWatch アラーム, EventBridge, SNS サーバレスアプリケーションを迅速に構築(SAM) テンプレートとLambdaプログラムを⼀括管理 サーバレスサービスに特化した機能 • 簡略化したテンプレート構⽂の提供 • ローカル開発環境にLambdaの実⾏環境を構築可能
  8. 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 が実⾏されない ...など
  9. 11 CloudFormation/SAMの注意点② CloudFormationの制限 1つのテンプレートに含むことのできるリソース数は200まで • 上限を超える場合は、テンプレートの分割を検討 1つのテンプレートに含むことのできるパラメータ数は60まで • 変数を⽤いて複雑な処理を⾏う場合は、Mappingsセクションの活⽤も検討 1つのテンプレートの本⽂サイズは51,200バイトまで

    • 上限を超える場合は、テンプレートをS3にアップロードした上でデプロイ 1つのアカウントで作成できるスタック数は200まで • 上限を超える場合は、上限緩和申請も検討 作成するAWSサービスの制限 • オブジェクトを全て削除しないとS3バケットを削除できない – DeletionPolicy: Retain を指定してスタック削除時にバケットを保持 • 同時に作成できるDynamoDBテーブル数の上限 • Detective は GuardDuty 有効化から 48時間経過後に有効化可能 ...など
  10. 12 CloudFormation/SAMの注意点③ その他の注意点 四則演算やforループなどは使⽤できない スタック内のリソースの⼿動による設定変更(ドリフト) • ドリフト検出機能を⽤いて設定変更を検知可能 • 正しいテンプレートを⽤いて再デプロイしてもドリフトは解消されない •

    ⼿動であるべき姿に戻す or スタックから当該リソースの切り離しと再度インポート Parametersセクション • Default は初回作成時のみ有効 • Description を⽇本語にすると⽂字化け ➡ CDK(AWS Cloud Development Kit)の利⽤を検討
  11. 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 Config Amazon GuardDuty Amazon Inspector Alarm Amazon SNS AWS 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
  12. 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 S3 Amazon 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
  13. 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アラーム ⾯倒なアラーム設定を簡単セットアップ
  14. 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 事前に作成したルール
  15. 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 の実⾏
  16. 22 モジュラーアプローチ 複数のテンプレートに分割し再利⽤性を⾼める AWS Cloud Tokyo (ap-northeast-1) security stack S3

    Bucket AWS Security Hub AWS CloudTrail AWS Config Amazon GuardDuty Amazon Inspector Alarm Amazon SNS AWS 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 の利⽤ 親テンプレート ネストされたテンプレート ネストされたテンプレート 親テンプレート 挿⼊されたテンプレート ネストされたテンプレートは 変更セットを確認できない
  17. 複数のテンプレートに分割し再利⽤性を⾼める detective.yaml securityhub.yaml inspector.yaml iam.yaml guardduty.yaml config.yaml cloudtrail.yaml 23 モジュラーアプローチ

    AWS Cloud Tokyo (ap-northeast-1) Amazon SNS AWS Personal Health IAM Role ServiceLinkedRole Amazon EventBridge ネストされたスタックの利⽤ AWS::Include の利⽤ 親テンプレート ネストされたテンプレート ネストされたテンプレート 親テンプレート 挿⼊されたテンプレート ネストされたテンプレートは 変更セットを確認できない
  18. 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/JT8z1 GitHub eijikominami/aws-cloudformation-templates
  19. 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/JT8g4 GitHub eijikominami/aws-cloudformation-templates