メインコンテンツまでスキップ

AWS Cloud Formation

Overview

AWS Cloudformationについてまとめているセクション。

ユビキタス

プロビジョニング(provisioning) 必要なものを準備すること
そこから転じてIT分野では、システムやサービスの需要に応じて、サーバーやネットワークなどのITインフラ設備を調達・設定することを「プロビジョニング」と呼んでいます。

AWS CloudFormationの概念

リファレンス

AWS CloudFormationを使用する際には、テンプレートとスタックの作業を行う。
テンプレートは、AWSリソースとそのプロパティを記述するために作成する。
スタックを作成するたびに、CloudFormationはテンプレートに記述されているリソースをプロビジョニングする。

CloudFormation のプロビジョニング時間に影響を与えるもの

CloudFormation において、スタック作成のボタンを押してからステータスがCREATE_COMPLETEになるまでの時間に影響を与える要素を知る必要がある。

プロビジョニングの時間に影響を与えるものは以下。

  • テンプレート情報の解析
  • リソースの作成(Creation)
  • リソースの安定化(Stabilization)
  • リソースの依存関係(明示的、暗黙的を含む)

リソースの安定化(Stabilization)

CloudFormation に”CONFIGURATION_COMPLETE”のイベントを追加、スタック作成が最大 40% 高速に

通常、AWS CLI やマネジメントコンソールでリソースを作成する場合、作成した直後からいきなり対象リソースにアクセスできるわけではない。

EC2 であれば作成直後であればライフサイクル上ではpendingであり、直後にいきなりアクセスはできず基本的にrunningになってからアクセスできる。
また EC2 に限らず ECS なども同様でステータスActiveにならないと正常にアクセスできない。

しかし CloudFormation の場合、各リソースに対してDescribeInstancesなどの Describe 系 API を呼び出し続け、ステータスが Active になるまで作成完了のステータスとならない。

そのため CloudFormation では作成完了のCREATE_COMPLETEになったタイミングですぐにそのリソースにアクセスできるようになる

この Describe 系 API を呼び出し続ける期間がリソースの安定化(Stabilization)

ヒント

この安定化の検証が所定のタイムアウト期間内に完了しない場合は、CREATE_FAILEDとマークされロールバックされる。
このタイムアウト期間は AWS サービスごとに一意に定義されている。

フォーマット

CloudFormationテンプレートはJSONまたはYAML形式のテキストファイル。

change setが失敗するとき

AWS CloudFormationスタックの更新で、DynamoDBテーブル名や他の一意であるべきリソース名を変更する際には注意が必要です。一度作成したリソースは、名前が固定される場合が多く、その名前を変更することはできません。
論理IDを変更した場合、CloudFormationは新しいリソースを作成しようとしますが、既存のリソース(このケースで言うと、DynamoDBテーブル)があると、その名前のリソースがすでに存在するためにエラーが発生します。

一般的な解決策は以下のとおりです:

  1. リソース削除: 既存のリソース(このケースではDynamoDBテーブル)を手動で削除してから再デプロイします。ただし、これはテーブルのデータもすべて削除するので注意が必要です。

  2. 名前変更: CloudFormationテンプレートでリソースの名前を変更し、新しい名前でリソースを作成します。ただし、このアプローチでは、新旧のリソースが並存する形になります。

  3. スタックの削除と再作成: もっとも単純だが危険な方法です。すべてのリソースを含むスタックを削除して、新しい論理IDでスタックを再作成します。これもすべてのデータが失われる可能性があります。

このエラーは、開発環境で頻繁に発生することがあり、リソースの命名規則や管理方法をしっかりと計画することが重要です。注意して操作してください。

AWS CloudFormationテンプレートの各セクションについて

AWSTemplateFormatVersion

このセクションでは、テンプレートのバージョンを定義します。これはオプションです。

AWSTemplateFormatVersion: '2010-09-09'

Description

このセクションはテンプレートの説明を提供します。これはオプションです。

Description: An example template

Metadata

このセクションはテンプレートの追加情報、たとえば関連するドキュメントや設定情報などを格納します。

Metadata: 
Instances:
Description: Information about the instances

Parameters

このセクションでテンプレートに入力パラメーターを定義します。これによってテンプレートは再利用可能になります。

Parameters:
InstanceType:
Description: EC2 instance type
Type: String
Default: t2.micro

Mappings

このセクションでは、マッピングテーブルを作成できます。
これはある値に基づいて他の値を参照する際に使用されます。

Mappings: 
RegionMap:
us-east-1:
HVM64: ami-0123456789abcdef0

Conditions

このセクションでは、リソースの作成条件を定義する。
たとえば、特定の環境に依存するリソースを制御する際に使用されます。

Conditions:
CreateProdResources: !Equals [ !Ref EnvType, prod ]

Transform

このセクションでは、マクロを指定してテンプレートをプリプロセッシングできます。

Transform:
- AWS::Serverless-2016-10-31

プリプロセッシングとは
ソフトウェアのビルドプロセスやデータ変換の一部として行われる、事前の処理ステップを指す。

Resources (必須)

このセクションは必須であり、AWSリソースを定義する
テンプレート内で作成・更新・または削除するAWSリソースを定義する場所。
各リソースは一意の論理IDと一連のプロパティを持ち、これによってCloudFormationがリソースをどのように作成または設定するかが決まります。

Resources:
MyBucket:
Type: AWS::S3::Bucket

Outputs

このセクションでは、スタック作成後に出力する値を定義します。

Outputs:
BucketName:
Value: !Ref MyBucket
Description: Name of the S3 bucket

これらのセクションを組み合わせて、AWSのリソースと設定を効率的に管理するテンプレートを作成できます。

スタック

単一のユニットとして管理できるAWSリソースのコレクション。
つまり、スタックを作成、更新、削除することで、リソースのコレクションを作成、更新、削除できます。 スタック内のすべてのリソースは、スタックのAWS CloudFormationテンプレートで定義されます。

yml内のセクション

Outputsセクション

  • 別スタックで値を参照(ImportValue)する
  • CloudFormationコンソールに値を出力する

aws ymlでの特別な記法

CloudFormationの書き方 覚え書き
loudFormationをYAMLで書くときは短縮記法

これを参考にする

!Sub

!Subは文字列結合っぽい

!Ref

以下の用途で使用する

  • Parametersセクションで指定したパラメーターの参照
  • Resourcesセクションで指定したリソースの参照

!ImportValue

別のスタックでエクスポートされた値を参照する時に使用する。

AWSTemplateFormatVersion: '2010-09-09'

Description: Parameter Store

# GUI、外部からパラメーターを指定する場合の書き方
# ドロップダウンによる選択肢、デフォルト値も指定可能
# この中を参照するには!Refや${}
Parameters:
Project:
Description: "Project"
Type: String
AllowedPattern: '^[0-9a-z]*$'
Environment:
Description: "Environment"
Type: String
Default: "sbx"
AllowedValues:
- "prd"
- "stg"
- "dev"
- "sbx"
AllowedPattern: '^[0-9a-z]{3}$'
ParamKey:
Description: ""
Type: String
AllowedPattern: '^[0-9a-zA-Z._/-]+$'
ParamValue:
Description: ""
Type: String
ParamType:
Description: ""
Type: String
AllowedValues:
- "String"
- "SecureString"
ParamDescription:
Description: ""
Type: String

Resources:
SSMParameter:
Type: "AWS::SSM::Parameter"
Properties:
Description: !Ref ParamDescription
Name: !Sub "/${Project}/${Environment}/${ParamKey}"
Value: !Ref ParamValue
Type: !Ref ParamType

擬似パラメーター

擬似パラメーターは AWS CloudFormation で事前定義されたパラメーター
以下のようなパラメーターをRefを使って参照できる

AWS::AccountId スタックが作成されるアカウントのAWSアカウントID AWS::Region スタックが作成されるAWSリージョン AWS::StackName スタックの名前

Parameter Store/Secrets Managerを使った参照をする

AWS Systems Manager(SSM) パラメータストアやAWS Secret Managerに保存した値を動的に参照できる。

リソースのパラメーターをSSMパラメータストアに外出しして管理する。スタック作成時にも利用する パスワードなど秘匿情報をSSMパラメータストア Secure Strings または Secret Manager に保存してテンプレートからスタックを作成するときに参照するなどの利用シーンがある。

秘匿情報はSSMパラメータストア Secure Strings または Secret Manager に保存しましょう。
テンプレートにパスワードを書いてしまうと、CloudFormationのコンソールから見ることができる状態になってしまいます。
また、大規模な環境で多くのスタックで共通して使われるパラメーターがある場合は、 SSMパラメータストアに保存して利用してもらうと、管理が楽になることが多い。

cdk bootstrap(CDKToolkit)

cdk bootstrap(CDKToolkit)を使いこなす

CDKアプリケーションをデプロイするにあたって必要なリソースを作る呪文が cdk bootstrap というコマンド。
このコマンドを実行すると CDKToolkit という名前の CloudFormation Stack が作成される

drift status(ドリフトステータス)

CloudFormation の ドリフトステータス (drift status) は、「スタックのリソースが、CloudFormation のテンプレートで定義されている状態からズレて(driftして)しまっているかどうか」を示すステータスのこと。

運用のポイント

  • IaC 運用の一貫性を保つため、定期的にドリフト検出を回すと安心。
  • ただし検出できるのは「CloudFormation がサポートするプロパティ」だけで、一部の変更はドリフトとして検出されない(例: 一部のタグ、暗号鍵のローテーションなど)。
  • ドリフトがあってもスタックの更新は可能だが、意図せぬ上書きが起こる可能性あり。
ヒント

CloudFormation の「ドリフト検出」を CI や監視に組み込む例(AWS CLI や CDK での自動化方法)もある

背景

CloudFormation は通常、スタックを作成・更新したときのテンプレートとパラメータをもとにリソースを管理するが、AWSコンソールやCLIで直接変更した場合や、外部の仕組みによってリソースが変わった場合は、その差分を CloudFormation は自動では検知しない。

この「実際の状態」と「テンプレートでの定義」のズレを検出するのが ドリフト検出 (drift detection) で、 その結果が ドリフトステータス に反映される。

主なステータスと確認方法

コンソールでも「アクション → ドリフトを検出」で実行可能

ステータス意味
IN_SYNC実際のリソース状態がテンプレート通り(ドリフトなし)
DRIFTED実際のリソース状態がテンプレートと異なる(ドリフトあり)
NOT_CHECKEDドリフト検出を実行していない
UNKNOWN検出処理中または結果が取得できない
DELETEDリソースが削除されている(スタック上は存在するはずなのに)
aws cloudformation detect-stack-drift --stack-name MyStack
aws cloudformation describe-stack-drift-detection-status --stack-drift-detection-id xxxxx
aws cloudformation describe-stack-resource-drifts --stack-name MyStack

Cloudformation ECR

CloudFormationを使用してECS Fargateを構築してみた

MacOSトラブルシューティング

お、決定打きました。 exec /usr/local/bin/docker-entrypoint.sh: exec format error は アーキテクチャ不一致(arm64でビルド → Fargateはx86_64で実行)でほぼ確定です。Mac(Apple Silicon)でビルド→ECR→Fargate既定x86 という流れだと典型的にこれが出ます。

やることは2択(どちらか一方でOK)👇

① 画像を x86_64 でビルドして再デプロイ(最短)

ターミナルでこれだけやり直し($ECR_REPO_URI はあなたのURI):

REGION=ap-northeast-1 ECR_REPO_URI=232986766679.dkr.ecr.$REGION.amazonaws.com/xoda-server

x86_64 でビルド&プッシュ(buildx推奨)

docker buildx create --use --name xoda-builder >/dev/null 2>&1 || docker buildx use xoda-builder
docker buildx build \
--platform linux/amd64 \
-f docker/server/Dockerfile \
--target production \
-t $ECR_REPO_URI:latest \
--push .

Resource