ルートボリュームと3本のデータボリュームを持つEC2からAMIを作成し、CloudFormationで同じ構成を再作成したい。このとき「容量を入力値で変更したい」「4本のうち1本だけに用途タグを付けたい」という要件は、ボリュームの定義方法を分けることで実現できます。
基本は、通常のディスクをEC2のBlockDeviceMappingsで定義し、個別タグが必要なデータディスクだけをAWS::EC2::Volumeとして作成する方法です。別定義にしたディスクはAMI側の自動作成対象から除外し、VolumeAttachmentで接続します。
最初に、AMIに含まれる4本のディスクを確認する
元のEC2に4本接続されていたことだけで判断せず、作成済みAMIのブロックデバイスマッピングを確認します。各デバイス名とスナップショットIDの対応を記録してください。同じデバイス名を指定して容量を上書きすることが重要です。
aws ec2 describe-images --image-ids ami-REPLACE_ME --region ap-northeast-1 --query "Images[0].{Root:RootDeviceName,Disks:BlockDeviceMappings}" --output json
以下は、AMIに /dev/sda1、/dev/sdb、/dev/sdc、/dev/sdd が含まれる場合の構成例です。実際のデバイス名はAMIに合わせて置き換えます。
| ディスク | 作成方法 | 設定内容 |
|---|---|---|
| ルート /dev/sda1 | BlockDeviceMappings | AMIの内容を使い容量を指定 |
| データ1 /dev/sdb | BlockDeviceMappings | 容量を指定 |
| データ2 /dev/sdc | BlockDeviceMappings | 容量を指定 |
| データ3 /dev/sdd | 独立したVolume+VolumeAttachment | 対応するスナップショットから復元し個別タグを指定 |
特定のEBSだけにタグを付ける構成例
次はResourcesセクションの抜粋です。参照しているパラメータは別途Parametersに定義します。AmiId、SubnetId、SecurityGroupIdは対象環境の値、容量4項目はNumber、TaggedSnapshotIdはAMIの /dev/sdd に対応するスナップショットIDを指定します。起動先サブネットとセキュリティグループは同じVPCのものを使います。
Resources:
Server:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref AmiId
InstanceType: !Ref InstanceType
SubnetId: !Ref SubnetId
SecurityGroupIds:
- !Ref SecurityGroupId
BlockDeviceMappings:
- DeviceName: /dev/sda1
Ebs:
VolumeSize: !Ref RootSize
VolumeType: gp3
- DeviceName: /dev/sdb
Ebs:
VolumeSize: !Ref Data1Size
VolumeType: gp3
- DeviceName: /dev/sdc
Ebs:
VolumeSize: !Ref Data2Size
VolumeType: gp3
- DeviceName: /dev/sdd
NoDevice: {}
TaggedVolume:
Type: AWS::EC2::Volume
DeletionPolicy: Snapshot
UpdateReplacePolicy: Snapshot
Properties:
AvailabilityZone: !GetAtt Server.AvailabilityZone
SnapshotId: !Ref TaggedSnapshotId
Size: !Ref TaggedSize
VolumeType: gp3
Tags:
- Key: Purpose
Value: business-data
TaggedAttachment:
Type: AWS::EC2::VolumeAttachment
Properties:
Device: /dev/sdd
InstanceId: !Ref Server
VolumeId: !Ref TaggedVolume
この例は構成を説明するための抜粋です。暗号化スナップショットを利用する場合は、作成・起動に使う権限とKMSキーへのアクセスも確認します。Snapshotポリシーで保存されたスナップショットには、保持中のストレージ料金が発生します。
NoDeviceが必要なのは、同じディスクを二重に作らないため
AMIに /dev/sdd が含まれたまま別のVolumeを作成すると、AMI由来のディスクと独立したディスクを両方作成することになります。NoDevice: {}でAMI側の対象マッピングを除外してから、対応するスナップショットを使った独立ボリュームを接続します。これはデータディスクを分離する例であり、ルートディスクを同じ方法で後付けする構成ではありません。
独立ボリュームはEC2と同じAZに置く必要があります。例では!GetAtt Server.AvailabilityZoneを使い、EC2が配置されたAZに合わせています。AZ移動との関係は、EC2を別AZへ移動する方法も参照してください。
全ディスクに共通タグを付けるだけなら別の方法もある
EC2のPropagateTagsToVolumeOnCreation: trueを利用すると、インスタンスのTagsをBlockDeviceMappingsで作成するボリュームへ伝播できます。そのため「CloudFormationのEC2定義からはEBSへ一切タグを付けられない」という理解は正確ではありません。
共通タグの伝播と、1本だけに異なるタグを指定する要件を区別します。独立したVolumeAttachment経由のボリュームにはこの伝播は適用されないため、必要な共通タグもTaggedVolume側へ明示します。
EBSの容量を増やしても、OSの領域は別に確認する
スナップショットから作成するボリュームの容量は、元のスナップショットの容量以上にします。小さくする用途には使えません。また、EBS容量とパーティション・ファイルシステムの容量は別です。AMIに保存されていたパーティション構成を引き継いだ結果、増やした領域が未使用のままになる場合があります。
Linuxではlsblkとdf -hTで確認し、必要に応じてパーティションやファイルシステムを拡張します。LVMを使っている場合はPV・LVなどの確認も必要です。既存データを持つ復元ボリュームへ、初期化用のmkfsを実行しないでください。拡張方法はXFS、ext4、LVMの有無で分かれます。
追加ディスクの接続完了とUserDataの実行順序に注意する
独立したVolumeAttachmentは、EC2作成後に処理されます。UserDataが実行される時点で追加ディスクが接続済みとは限りません。必要なディスクを識別して待機する処理や、接続完了後に実行する構成管理処理を用意します。
OS上のデバイス名がテンプレートの指定名と一致するとは限らないため、対象ボリュームの識別とマウント状態を確認してからアプリケーションを開始します。パラメータを初期化処理へ渡す書き方は、CloudFormationのパラメータをEC2 UserDataで使う方法で解説しています。
新規作成時のサイズ指定と、運用中のサイズ変更を分ける
この構成例は新規作成時の容量指定です。EC2のBlockDeviceMappings内でVolumeSizeなどを更新すると、CloudFormationではインスタンス置換につながるため、変更セットで影響を確認します。EBS自体の容量変更機能と、CloudFormationリソースの更新動作を同一視しないことが重要です。
運用中に頻繁に拡張するデータボリュームは、独立したAWS::EC2::Volumeとして管理する設計も検討します。削除・置換時の保存方針、アプリケーション停止、アンマウント、復旧手順まで決めておきます。
参考資料
AWS公式:BlockDeviceMappingとNoDevice
AWS公式:EC2とタグ伝播
AWS公式:AWS::EC2::Volume
AWS公式:Ebsプロパティと更新動作
AWS公式:Linuxファイルシステムの拡張
