Open10
【AWS】CloudFormationメモ
はじめに
実際にCloudFormationに触れながら、調べた事項をメモしていく。
CloudFormation参考
CloudFormationに関する用語
用語 | 概要 |
---|---|
テンプレート | リソースや属性、依存関係についてあるべき状態を定義するもの (JSON or YAMLファイルで定義していくことになる) |
スタック | テンプレートからプロビジョニングされるリソースの集合を指す |
スタックセット | 複数のAWSアカウントおよびリージョンにわたってスタックをデプロイ、管理するための機能 |
変更セット | テンプレートの変更前後の差分と変更に伴う影響を事前に確認するもの |
組み込み関数 | テンプレート内にて、実行するまでわからない値をプロパティに代入する際などに利用する |
CloudFormationに関する開発ツール
ツール | 概要 |
---|---|
cfn-lint | ・AWSの、CloudFormation専用のLinter ・Linterにより、テンプレートを書きながらミスに気付くことができるようになる ・Pip、Homebrew、Docker、各IDE、などのPluginとして導入が可能 |
CloudFormation Rain | ・AWS CloudFormationのテンプレートとスタックを操作するためのCLIツール ・テンプレートファイルの作成補助や比較、スタックのイベントログ出力などを行えるようになる |
Amazon CodeWhisperer | ・AWSの、AIコーディング支援サービス ・コードサジェスト(コードの提案)やコードの補完が可能になる |
AWS Application Composer[1] | ・アーキテクチャ構築を支援してくれるツール ・GUI上でAWSのアーキテクチャ構築が可能になる |
参考サイト
-
こちらの「AWS Application Composer」は、「AWS CloudFormation Designer」の改良版とのこと。
※「AWS Application Composer」の画面を開いたところ、以下のメッセージが画面上部に表示された
また、AWS公式ドキュメント には「AWS Application Composer」を推奨する旨の記載があった
↩︎
CloudFormationのデプロイパターン
マネジメントコンソールや、CLIから手動でテンプレートをデプロイ
- CI/CDの整備をするほどの頻度や規模でない場合や、ヒューマンエラーによるリスクが少ない等、自動化の恩恵を受けづらい時に利用
CI/CDパイプラインからデプロイ
- デプロイ前のテストも含めた、自動化を実現したい時に利用
Gitからの同期
- Gitベースでコード管理しており、開発用途でCDを簡易に自動化したい時に利用
参考サイト
テンプレートセクション
以下セクションがあり、「Resources」のみ必須セクションとなる
---
# テンプレートのバージョンを指定
AWSTemplateFormatVersion: "version date"
# テンプレートの説明を指定
Description:
String
# テンプレートに関する追加情報を指定
Metadata:
template metadata
# スタック作成・更新時にテンプレートに渡す値を指定
Parameters:
set of parameters
# スタック作成・更新時に利用するルールを指定
Rules:
set of rules
# キーと関連する値のマッピングを指定
Mappings:
set of mappings
# 制御条件を指定
Conditions:
set of conditions
# テンプレートを処理する際に適用するマクロを1つ以上指定
Transform:
set of transforms
# スタックリソースと、そのプロパティを指定
Resources:
set of resources
# スタックのプロパティを確認すると返される値を指定
Outputs:
set of outputs
参考サイト
「cfn-lint」インストール手順メモ
手順
- VSCodeで拡張機能をインストール
拡張機能から、「cfn-lint(CloudFormation Linter)」をインストールする
- 「cfn-lint」のドキュメントに従い、Python用パッケージをインストールする
※私の環境では、インストールコマンド実行時にエラーが出た
ターミナル
pip3 install cfn-lint
エラー内容全文
% pip3 install cfn-lint
error: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try brew install
xyz, where xyz is the package you are trying to
install.
If you wish to install a Python library that isn't in Homebrew,
use a virtual environment:
python3 -m venv path/to/venv
source path/to/venv/bin/activate
python3 -m pip install xyz
If you wish to install a Python application that isn't in Homebrew,
it may be easiest to use 'pipx install xyz', which will manage a
virtual environment for you. You can install pipx with
brew install pipx
You may restore the old behavior of pip by passing
the '--break-system-packages' flag to pip, or by adding
'break-system-packages = true' to your pip.conf file. The latter
will permanently disable this error.
If you disable this error, we STRONGLY recommend that you additionally
pass the '--user' flag to pip, or set 'user = true' in your pip.conf
file. Failure to do this can result in a broken Homebrew installation.
Read more about this behavior here: <https://peps.python.org/pep-0668/>
note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.
3. エラーメッセージ内容に従い、仮想環境を作成して、そこに「cfn-lint」をインストールする
ターミナル
# 今回は「~/」直下に仮想環境を作成した
python3 -m venv ~/cfn-lint-python-venv
source ~/cfn-lint-python-venv/bin/activate
python3 -m pip install cfn-lint
# 書式: python3 -m venv <保存パス/保存名>
# 書式: source <保存パス/保存名>/bin/activate
# 書式: python3 -m pip install cfn-lint
4. 「cfn-lint」のインストール確認&パスを取得
VSCodeの設定時に利用するので、パスをテキストエディタなどに書き留めておく
ターミナル
% which cfn-lint
<保存パス/保存名>/bin/cfn-lint
5. VSCode設定画面で「cfn-lint」のパスを設定する
Macの場合、[command + ,(カンマ)] で設定画面を開き、”Cfn Lint:Path”に項番4のパスを設定する
※パスは、仮想環境を保存した場所によって変わります
- VSCodeを再起動する
- 「cfn-lint」の動作確認をし、適切に動作したらインストール完了
※適当なテンプレートファイルを作成後、誤った定義をした際に「cfn-lint」が動作したら完了
参考サイト
「cfn-lint」の、"Unresolved tag: !Ref YAML" 対応
概要
- CloudFormationテンプレート内に、"! Ref"を定義したところ表題のメッセージが表示された
そのため対応を行う(メッセージに関する解説は、下に記載のサイトにて説明されていた)
対応
- VSCodeの設定画面から「yaml.customTags」を検索し、表示された ”settings.json” より以下の設定を追記&保存した
settings.json
"yaml.customTags": [
"!Base64",
"!Cidr sequence",
"!And sequence",
"!Equals sequence",
"!If sequence",
"!Not sequence",
"!Or sequence",
"!Condition",
"!FindInMap sequence",
"!GetAtt",
"!GetAtt sequence",
"!GetAZs",
"!ImportValue",
"!Join sequence",
"!Select sequence",
"!Split sequence",
"!Sub",
"!Sub sequence",
"!Transform mapping",
"!Ref"
]
参考サイト
「スタック」、「スタックセット」の違いメモ
違いのまとめ
特徴 | スタック(Stack) | スタックセット(StackSets) |
---|---|---|
適用範囲 | 単一のリージョン | 複数のリージョンおよびアカウント |
管理の複雑さ | 比較的シンプル | 複数アカウント、リージョンに対応、より複雑 |
使用シナリオ | 単一のアプリケーションやサービスのリソース管理 | 複数のビジネスユニットやグローバル展開が必要な場合 |
操作 | 個別のスタックの操作 | スタックセットを使って複数リージョン/アカウントのスタックを管理 |
メリット・デメリット
スタック
メリット | デメリット |
---|---|
・単一リージョンでの設定・管理がシンプル ・小規模なデプロイメントに最適 |
・複数リージョンやアカウント間での一貫性を保つのが困難 |
スタックセット
メリット | デメリット |
---|---|
・複数のリージョンやアカウントで同じ構成を一括展開可能 ・AWS Organizationsとの統合で一元管理が可能 |
・設定や管理が複雑になる ・誤って複数リージョンに展開するとリソースの使用量が急増する可能性がある |
VPCエンドポイントの、プレフィックスリストIDが取得できない件
やりたかったこと
- CloudFormationテンプレートでセキュリティグループを作成する際に、VPCエンドポイント(S3など)のプレフィックスリストIDを参照したかった
※参照イメージとしては以下(エラーとなる記載方法)
CloudFormationテンプレート
Resources:
〜省略〜
PublicSubnetEgressVPCEndpointS3:
Type: AWS::EC2::SecurityGroupEgress
Properties:
GroupId: !Ref PublicSubnetSG
IpProtocol: -1
DestinationPrefixListId: !GetAtt S3VPCEndpoint.PrefixList.PrefixListId # <=左記の様な形で、VPCエンドポイントのプレフィックスリストIDを参照したかった
〜省略〜
代替策
- 実際は方法あるかもしれないが、結局は手動で値を設定することとした。
(プレフィックスリストIDをマネジメントコンソールから直接コピーし、テンプレートのパラメータ値として渡す方法とした)
参考URL
EC2インスタンス作成用テンプレート内の、ユーザーデータが実行されなくてハマった件
経緯
以下手順で進めたところ、ユーザーデータが実行されなかった(※誤った認識による対応)
- CloudFormationテンプレートを使ってEC2インスタンスを作成
- テンプレート内にユーザーデータを追記して、CloudFormationからスタックの更新を実施
- EC2インスタンスを再起動し、ユーザーデータを反映(各パッケージのインストール)を試みた
=>想定では各パッケージがインストールされると思っていたが、インストールされなかった
結論
EC2インスタンスを再起動しても、ユーザーデータ内の処理は実行されない。
ユーザーデータ内の処理は、EC2インスタンスの初回起動時のみ実行される。
(完全に誤った認識をしており、無駄な確認をしておりました)
テンプレートメモ
CloudFormationテンプレート
VPC内にEC2インスタンスを1つ作成(Ubuntu)
AWSTemplateFormatVersion: "2010-09-09"
Description: EC2 Setup template
Parameters:
SystemName:
Type: String
Description: "Set system name prefix. "
Default: "test"
EnvName:
Type: String
Description: "Set environment prefix(dev, stg, prd, etc..)"
Default: "dev"
VPCID:
Type: String
Description: "VPC ID"
Default: "vpc-xxxxxxxxxx"
SubnetID:
Type: String
Description: "Subnet ID"
Default: "subnet-xxxxxxxxxx"
SGID:
Type: String
Description: "SecurityGroup ID"
Default: "sg-xxxxxxxxxx"
Resources:
# -------------------------------------------------- #
# EC2インスタンス
# -------------------------------------------------- #
Ec2Instance:
Type: AWS::EC2::Instance
Properties:
AvailabilityZone: !Select [0, !GetAZs ""]
ImageId: ami-0cab37bd176bb80d3
InstanceType: t2.micro
VpcId: !Ref VPCID
NetworkInterfaces:
- AssociatePublicIpAddress: false
DeviceIndex: 0
SubnetId: !Ref SubnetID
GroupSet:
- !Ref SGID
BlockDeviceMappings:
- DeviceName: "/dev/sda1"
Ebs:
VolumeType: "gp3"
VolumeSize: 10
UserData:
Fn::Base64: |
#!/bin/bash
apt-get update
apt-get -y upgrade
apt-get install -y git
apt-get install -y unzip
apt-get install nodejs npm -y
apt-get install python3 python3-pip -y
snap install aws-cli --classic
Tags:
- Key: Name
Value: !Sub "${SystemName}-${EnvName}-private-a-subnet1-ec2"
参考