こんにちは!イーゴリです。
以前、以下の記事で既存EC2のENIを置き換えるためのCloudFormationテンプレート生成ツールを紹介しました。 この方法では、既存のENIをそのまま利用します。
ただし、AWSの仕様上、既存のENIを持つEC2を削除してから、新しいEC2にENIをアタッチするという手順になります。

今回はそれとは少し異なり、既存EC2の情報をもとに「新しいEC2インスタンス」をCloudFormationで作成するためのテンプレートを自動生成するツールを紹介します。
この方法では新しいENIが作成されるため、新しいIPを使用する場合は既存のEC2を削除する必要はありません。

背景

AWS環境の運用をしていると、以下のようなケースがあります。
- 既存EC2の設定をベースにして新しいEC2を構築したい
- OSを更新したEC2を新しく作り直したい
- Golden AMIを利用して再構築したい
- 既存設定(タグ、SG、Subnetなど)をなるべくそのまま再現したい
このような場合、手動でCloudFormationテンプレートを書くのはかなり手間がかかります。
例えばEC2が1台だけの場合でも、以下のような情報を確認する必要があり、 お客様から一つ一つヒアリングしなければなりません。
- InstanceType
- Subnet
- SecurityGroup
- Tags
- EBS設定
- IMDS設定
- IAMロール
- Monitoring
- SourceDestCheck
さらに複数台ある場合、これを毎回手作業で作成するのは現実的ではありません。
そこで、既存EC2の情報からCloudFormationテンプレートを自動生成するスクリプトを作成してみました。
前提条件
以下の環境が必要です。
Python 3
boto3 (boto3 は Python から AWS API を呼び出すための公式ライブラリです)
AWS CLI
対象AWSアカウントへ接続済みのAWS CLIプロファイル
EC2情報を参照できる権限
やりたいこと
今回のツールで実現したいことはシンプルです。
既存EC2の情報
↓
ec2_parameters_to_csv.py(対象アカウントのすべてのEC2情報が出力される)
↓
出力結果:Parameter.csv、describe-instances.json、describe-network-interfaces.json、describe-volumes.json
↓
Parameter.csvの整理(不要なEC2を削除し、対象のEC2のみ残す)
↓
create_cfn_yaml.py
↓
CloudFormation YAML生成
↓
CloudFormationテンプレートを展開→新しいEC2作成
つまり、既存EC2の設定をテンプレート化して再利用できるようにするというものです。
注意事項
①このスクリプトについては、一切の責任を負えませんので、ご自身で十分にご検証した上で、このスクリプトを使ってもよいかご判断ください。
②下記のスクリプトは私にとって必要なEC2パラメーターのみ取得されているので、他のパラメーターが必要な場合、ご自身で修正してください。
EC2情報の取得
まず、既存EC2の情報を取得して Parameter.csv を作成します。
ROロール(AWS CLI)で対象AWSアカウントにログインする。 $ export AWS_DEFAULT_PROFILE=<AWSアカウントプロファイル名> 対象アカウントがROロールでログインされていることを確認する。 $ aws sts get-caller-identity $ cd <スクリプトのディレクトリ>
以下のスクリプトを使用して、対象アカウント内のEC2情報をCSVとして出力します。
$ python3 ec2_parameters_to_csv.py
import boto3 import json import csv from datetime import datetime # AWSクライアントの設定 ec2 = boto3.client('ec2') # EC2インスタンス情報の取得 instances = ec2.describe_instances() volumes = ec2.describe_volumes() network_interfaces = ec2.describe_network_interfaces() # カスタム関数: datetimeオブジェクトを文字列に変換 def custom_converter(o): if isinstance(o, datetime): return o.isoformat() # JSONファイルに保存 with open('describe-instances.json', 'w') as f: json.dump(instances, f, indent=4, default=custom_converter) with open('describe-volumes.json', 'w') as f: json.dump(volumes, f, indent=4, default=custom_converter) with open('describe-network-interfaces.json', 'w') as f: json.dump(network_interfaces, f, indent=4, default=custom_converter) # CSVフォーマットの定義 csv_data = [] csv_headers = [ 'InstanceId', 'InstanceName', 'AvailabilityZone', 'PrivateIpAddress', 'InstanceType', 'AMI_ID', 'IamInstanceProfile', 'IMDSv2', 'EBS_Volume_Type', 'EBS_Volume_Size', 'IOPS', 'Throughput', 'EBS_Encrypted', 'KeyName', 'SubnetId', 'SecurityGroupIds', 'Monitoring', 'SourceDestCheck' ] # Max counts max_instance_tags = 0 max_ebs_tags = 0 max_eni_tags = 0 # Step 1: Calculate max tags for reservation in instances['Reservations']: for instance in reservation['Instances']: max_instance_tags = max(max_instance_tags, len(instance.get('Tags', []))) for bd in instance.get('BlockDeviceMappings', []): if 'Ebs' in bd: volume_id = bd['Ebs']['VolumeId'] for vol in volumes['Volumes']: if vol['VolumeId'] == volume_id: max_ebs_tags = max(max_ebs_tags, len(vol.get('Tags', []))) for eni in instance.get('NetworkInterfaces', []): for net_if in network_interfaces['NetworkInterfaces']: if net_if['NetworkInterfaceId'] == eni['NetworkInterfaceId']: max_eni_tags = max(max_eni_tags, len(net_if.get('TagSet', []))) # Step 2: Populate data rows for reservation in instances['Reservations']: for instance in reservation['Instances']: instance_id = instance['InstanceId'] instance_type = instance['InstanceType'] ami_id = instance['ImageId'] iam_instance_profile_arn = instance.get('IamInstanceProfile', {}).get('Arn', 'N/A') iam_instance_profile = iam_instance_profile_arn.split('/')[-1] if iam_instance_profile_arn != 'N/A' else 'N/A' imdsv2 = 'Enabled' if instance.get('MetadataOptions', {}).get('HttpTokens') == 'required' else 'Disabled' availability_zone = instance['Placement']['AvailabilityZone'] private_ip = instance.get('PrivateIpAddress', 'N/A') monitoring_state = instance.get('Monitoring', {}).get('State', 'disabled') source_dest_check = instance.get('SourceDestCheck', True) instance_name = next((tag['Value'] for tag in instance.get('Tags', []) if tag['Key'] == 'Name'), '') ebs_volume_type = '' ebs_volume_size = '' ebs_encrypted = '' iops = 3000 throughput = 125 if 'BlockDeviceMappings' in instance: for bd in instance['BlockDeviceMappings']: if 'Ebs' in bd: volume_id = bd['Ebs']['VolumeId'] for vol in volumes['Volumes']: if vol['VolumeId'] == volume_id: ebs_volume_type = vol['VolumeType'] ebs_volume_size = vol['Size'] ebs_encrypted = 'true' if vol.get('Encrypted') else 'false' ebs_volume_type = 'gp3' # スループットを計算: # ボリュームサイズが170 GiB未満の場合、スループットは125 MiB/s # ボリュームサイズが170 GiBから300 GiBの間では、スループットはボリュームサイズ * 0.75 (最大250 MiB/s) # ボリュームサイズが300 GiB以上の場合、スループットは250 MiB/s if ebs_volume_size <= 170: throughput = 125 elif ebs_volume_size <= 300: throughput = min(250, ebs_volume_size * 0.75) else: throughput = 250 # IOPS計算 if ebs_volume_size <= 1000: iops = 3000 else: iops = min(16000, 3000 + (ebs_volume_size - 1000) * 3) instance_tags = instance.get('Tags', []) ebs_tags = [] eni_tags = [] for bd in instance.get('BlockDeviceMappings', []): if 'Ebs' in bd: volume_id = bd['Ebs']['VolumeId'] for vol in volumes['Volumes']: if vol['VolumeId'] == volume_id: ebs_tags.extend(vol.get('Tags', [])) for eni in instance.get('NetworkInterfaces', []): for net_if in network_interfaces['NetworkInterfaces']: if net_if['NetworkInterfaceId'] == eni['NetworkInterfaceId']: eni_tags.extend(net_if.get('TagSet', [])) key_name = instance.get('KeyName', 'N/A') subnet_id = instance.get('SubnetId', 'N/A') security_groups = [sg['GroupId'] for sg in instance.get('SecurityGroups', [])] security_group_ids = ','.join(security_groups) row = [ instance_id, instance_name, availability_zone, private_ip, instance_type, ami_id, iam_instance_profile, imdsv2, ebs_volume_type, ebs_volume_size, iops, throughput, ebs_encrypted, key_name, subnet_id, security_group_ids, monitoring_state, source_dest_check ] def extend_with_tags(row, tags, max_tags): data = [] for tag in tags: data.append(tag['Key']) data.append(tag['Value']) data.extend(['', ''] * (max_tags - len(tags))) row.extend(data) extend_with_tags(row, instance_tags, max_instance_tags) extend_with_tags(row, ebs_tags, max_ebs_tags) extend_with_tags(row, eni_tags, max_eni_tags) csv_data.append(row) # Dynamic headers for i in range(1, max_instance_tags + 1): csv_headers.append(f'Instance_Tag{i}_Key') csv_headers.append(f'Instance_Tag{i}_Value') for i in range(1, max_ebs_tags + 1): csv_headers.append(f'EBS_Tag{i}_Key') csv_headers.append(f'EBS_Tag{i}_Value') for i in range(1, max_eni_tags + 1): csv_headers.append(f'ENI_Tag{i}_Key') csv_headers.append(f'ENI_Tag{i}_Value') # Save to CSV with open('Parameter.csv', 'w', newline='', encoding='latin-1') as f: writer = csv.writer(f) writer.writerow(csv_headers) writer.writerows(csv_data)
このスクリプトを実行すると、アカウント内のEC2インスタンスの情報が Parameter.csv として出力されます。


その後、不要なEC2の行を削除し、対象となるEC2のみを残します。
次は下記の流れになります。
create_cfn_yaml.py
↓
Parameter.csvを参照
↓
CloudFormationテンプレートの出力
Parameter.csv
Parameter.csv には EC2構築に必要な情報が入っています。 基本的には、AWS CLI の describe コマンドで取得した情報がそのまま出力されます。 設定を変更したい場合は、CSVの内容を手動で編集することで調整できます。
主な項目は以下です。
| 項目 | 内容 | 説明 |
|---|---|---|
| InstanceId | 元となるEC2 | 構築元となるEC2インスタンスのIDです。 |
| InstanceName | インスタンス名 | 新規EC2の Name タグの値です。既存インスタンスと同じ名前になるため、必要に応じて新しいインスタンス名を指定してください。 |
| AvailabilityZone | アベイラビリティゾーン | 既存EC2が配置されているAZです。 |
| PrivateIpAddress | 固定IP | 既存のプライベートIPです。変更も可能です。値を削除した場合は、新しいプライベートIPが自動で割り当てられます。※既存のIPから変更しない場合は、そのIPを保持しているENIを削除する必要があります。 |
| InstanceType | インスタンスタイプ | 新しく作成するEC2のインスタンスタイプです。必要に応じて変更できます。 |
| AMI_ID | 使用するAMI | 新しいEC2で使用するAMIです。ゴールデンイメージや希望するAMI IDを指定できます。 |
| IamInstanceProfile | IAMプロファイルの指定 | EC2に関連付けるIAMインスタンスプロファイルです。不要な場合は環境に応じて調整します。 |
| IMDSv2 | IMDS設定 | IMDSv2を有効化する場合は Enabled を指定します。不要な場合は Disabled を指定します。 |
| EBS_Volume_Type | EBSタイプ | ルートボリュームのタイプです。本スクリプトでは gp2 / gp3 を想定しています。 |
| EBS_Volume_Size | EBSサイズ | ルートボリュームのサイズ(GiB)です。必要に応じて変更できます。 |
| IOPS | EBS IOPS | EBSのIOPS値です。ボリュームサイズをもとにスクリプト内で計算されます。必要に応じて調整してください。 |
| Throughput | EBSスループット | gp3利用時のスループット値です。ボリュームサイズをもとにスクリプト内で計算されます。 |
| EBS_Encrypted | EBS暗号化設定 | EBSの暗号化する場合は true を指定します。 |
| KeyName | EC2キーペア | EC2に設定するキーペア名です。 |
| SubnetId | サブネット | 新しいEC2を配置するサブネットです。 |
| SecurityGroupIds | セキュリティグループ | EC2に関連付けるセキュリティグループIDです。複数ある場合はカンマ区切りで指定されます。 |
| Monitoring | 詳細モニタリング設定 | EC2の詳細モニタリング設定です。enabled の場合は CloudWatch の詳細モニタリング(1分間隔)が有効になります。disabled の場合は標準モニタリング(5分間隔)になります。 |
| SourceDestCheck | 送信元/送信先チェック | EC2の Source/Destination Check の設定です。NATインスタンスなどでは無効化が必要な場合があります。 |
| Instance_TagX_Key | EC2タグキー | EC2インスタンスに設定されているタグのキーです。 |
| Instance_TagX_Value | EC2タグ値 | EC2インスタンスに設定されているタグの値です。 |
| EBS_TagX_Key | EBSタグキー | EBSボリュームに設定されているタグのキーです。 |
| EBS_TagX_Value | EBSタグ値 | EBSボリュームに設定されているタグの値です。 |
| ENI_TagX_Key | ENIタグキー | ENIに設定されているタグのキーです。 |
| ENI_TagX_Value | ENIタグ値 | ENIに設定されているタグの値です。 |
上記のCSVでは、InstanceType の変更や AMI の指定、既存の Private IP をそのまま利用するか、新しい Private IP を割り当てるかといった調整が可能です。
必要に応じてCSVの内容を修正し、不要なEC2の行を削除した上で、次のステップに進みます。
実行方法
スクリプトは以下のように実行します。
$ python3 create_cfn_yaml.py
import csv import os def read_userdata_csv(file_path): userdata = [] with open(file_path, 'r', encoding='latin-1') as csvfile: reader = csv.DictReader(csvfile) for row in reader: userdata.append({ 'InstanceID': row['Instance ID'], # 'Username': row['Username'], # 'Sudo': row['sudo'].strip().upper() == 'TRUE', 'PublicKey': row['public-key'] }) return userdata def read_parameter_csv(file_path): parameters = [] with open(file_path, 'r', encoding='latin-1') as csvfile: reader = csv.DictReader(csvfile) for row in reader: # データを不正な文字からクリーニングします cleaned_row = {key: value.replace('Â', '').strip() if value else None for key, value in row.items()} parameters.append(row) return parameters def generate_userdata_section(userdata, instance_id): useradd_section = """ timedatectl set-timezone Asia/Tokyo """ useradd_commands = [] settingsudo_commands = [] for user in userdata: if user['InstanceID'] == instance_id: # username = user['Username'] ssh_key = user['PublicKey'] # useradd_commands.append(f'create_user {username} "{ssh_key}"') useradd_commands.append(f'register_publickey_ec2-user "{ssh_key}"') # if user['Sudo']: # settingsudo_commands.append(f'settingsudo "{username}"') return useradd_section\ + "\n".join(useradd_commands) # + "\n" + "\n".join(settingsudo_commands) def format_tags(tags, indent=8): indent_space = " " * indent return "\n".join([f"{indent_space}- Key: {tag['Key']}\n{indent_space} Value: {tag['Value']}" for tag in tags]) def generate_cloudformation_template(parameters, userdata, output_dir): templates = [] for parameter in parameters: instance_id = parameter["InstanceId"] name_tag = parameter.get("InstanceName", "") private_ip = parameter.get("PrivateIpAddress", "").strip() # IMDSv2に基づいてHttpTokensの値を設定します http_tokens = "required" if parameter.get("IMDSv2", "").strip().lower() == "enabled" else "optional" userdata_script = generate_userdata_section(userdata, instance_id) userdata_script = userdata_script.replace("\n", "\n ") security_group_ids = "\n".join([f" - {sg.strip()}" for sg in parameter["SecurityGroupIds"].split(',')]) # EC2インスタンスのタグを生成します instance_tags = [] for i in range(1, 101): tag_key = parameter.get(f"Instance_Tag{i}_Key") tag_value = parameter.get(f"Instance_Tag{i}_Value") if tag_key and tag_value: # aws: から始まるタグと TestTag タグを除外 if not tag_key.strip().startswith("aws:") and tag_key.strip() != "TestTag": instance_tags.append({"Key": tag_key.strip(), "Value": tag_value.strip()}) # InstanceNameが空でない場合は、Nameタグを追加します if name_tag and not any(tag['Key'] == 'Name' for tag in instance_tags): instance_tags.append({"Key": "Name", "Value": name_tag.strip()}) # 起動テンプレート用のタグを生成します ebs_tags = [] eni_tags = [] for i in range(1, 101): ebs_tag_key = parameter.get(f"EBS_Tag{i}_Key") ebs_tag_value = parameter.get(f"EBS_Tag{i}_Value") if ebs_tag_key and ebs_tag_value: ebs_tags.append({"Key": ebs_tag_key.strip(), "Value": ebs_tag_value.strip()}) eni_tag_key = parameter.get(f"ENI_Tag{i}_Key") eni_tag_value = parameter.get(f"ENI_Tag{i}_Value") if eni_tag_key and eni_tag_value: eni_tags.append({"Key": eni_tag_key.strip(), "Value": eni_tag_value.strip()}) # 動的なタグを含むEC2インスタンスの基本テンプレートを生成します template = f"""AWSTemplateFormatVersion: "2010-09-09" Description: "{name_tag}" Resources: EC2Instance: Type: AWS::EC2::Instance Properties: ImageId: {parameter.get("AMI_ID")} InstanceType: {parameter.get("InstanceType")} KeyName: {parameter.get("KeyName")} SubnetId: {parameter.get("SubnetId")} """ # private_ipが存在するか確認し、値が空でない場合に行を追加します if private_ip: template += f" PrivateIpAddress: {private_ip}\n" source_dest_check = parameter.get("SourceDestCheck", "true").strip().lower() monitoring = "true" if parameter.get("Monitoring", "disabled").strip().lower() == "enabled" else "false" # テンプレートの生成を続けます template += f""" SecurityGroupIds: {security_group_ids} EbsOptimized: true SourceDestCheck: {source_dest_check} DisableApiTermination: true UserData: Fn::Base64: Fn::Sub: | #!/bin/bash -v sleep 10 exec > >(tee /var/log/user-data.log | logger -t user-data -s 2> /dev/console) 2>&1 {userdata_script.strip()} reboot IamInstanceProfile: {parameter.get("IamInstanceProfile")} Monitoring: {monitoring} Tags: {format_tags(instance_tags)} LaunchTemplate: LaunchTemplateId: !Ref LaunchTemplate01 Version: 1 LaunchTemplate01: Type: AWS::EC2::LaunchTemplate Properties: LaunchTemplateData: MetadataOptions: HttpTokens: {http_tokens} TagSpecifications: - ResourceType: volume Tags: {format_tags(ebs_tags, indent=12)} - ResourceType: network-interface Tags: {format_tags(eni_tags, indent=12)} BlockDeviceMappings: - DeviceName: "/dev/xvda" Ebs: Encrypted: {str(parameter.get("EBS_Encrypted", "false")).lower()} VolumeSize: {parameter.get("EBS_Volume_Size", "30")} VolumeType: {parameter.get("EBS_Volume_Type", "gp3")} DeleteOnTermination: true Iops: {parameter.get("IOPS", "3000")} Throughput: {parameter.get("Throughput", "125")} """ if name_tag: filename = f"{name_tag}({instance_id}).yaml" else: filename = f"({instance_id}).yaml" filename = os.path.join(output_dir, filename) templates.append((filename, template)) return templates def main(): parameter_file = 'Parameter.csv' userdata_file = 'userdata.csv' # ディレクトリ 'yaml' が存在しない場合は作成します output_dir = 'yaml' os.makedirs(output_dir, exist_ok=True) parameters = read_parameter_csv(parameter_file) userdata = read_userdata_csv(userdata_file) templates = generate_cloudformation_template(parameters, userdata, output_dir) if templates: for filename, template in templates: with open(filename, 'w') as yaml_file: yaml_file.write(template) print(f"CloudFormation template saved to '{filename}'.") else: print("Error generating CloudFormation templates.") if __name__ == "__main__": main()
※1 上記のスクリプトでは、「TestTag」や「aws」から始まるタグ情報はコピーされないようになっています。必要に応じて修正してください。
※2 この記事では、下記のユーザーデータをスクリプトに設定しています。必要に応じて修正してください。
#!/bin/bash -v sleep 10 exec > >(tee /var/log/user-data.log | logger -t user-data -s 2> /dev/console) 2>&1 timedatectl set-timezone Asia/Tokyo reboot
なお、EC2構築と同時に Linux 内の ec2-user に公開鍵を追加したい場合は、以下の設定を追記することで対応できます。
以前のバージョンのスクリプトでは、userdata.csv にデータを追加することで、Public Key の登録だけでなく新しいユーザーの作成にも対応していました。 本記事では説明をシンプルにするため、該当する処理はコメントアウトしています。 必要に応じてスクリプトを修正することで、この機能を利用することも可能です。
create_user() {
useradd $1
mkdir /home/$1/.ssh
chmod 700 /home/$1/.ssh
chown $1:$1 /home/$1/.ssh
echo $2 > /home/$1/.ssh/authorized_keys
chmod 600 /home/$1/.ssh/authorized_keys
chown $1:$1 /home/$1/.ssh/authorized_keys
}
settingsudo() {
echo "$1 ALL = NOPASSWD: ALL" >> /etc/sudoers.d/$1
chmod 440 /etc/sudoers.d/$1
chown root:root /etc/sudoers.d/$1
}
実行すると「yaml/」ディレクトリに{インスタンス名(インスタンスID)}のファイルが生成されます。
CloudFormation template saved to 'yaml/Bastion(i-0606f85f472df06ba).yaml'. CloudFormation template saved to 'yaml/DC1.test.local(i-01c7fd724682ffe9a).yaml'. CloudFormation template saved to 'yaml/DC2.test.local(i-0160d258bd82a9356).yaml'. CloudFormation template saved to 'yaml/DC3.test.local(i-00f31a7ac8e70017f).yaml'. CloudFormation template saved to 'yaml/onpremDNS(i-0ae18790cf80003f7).yaml'. CloudFormation template saved to 'yaml/testwin(i-086610811b0ba8b87).yaml'.
つまり、EC2インスタンスごとに1つのCloudFormationテンプレートが作成されます。
CFnテンプレートの出力例を紹介します。
AWSTemplateFormatVersion: "2010-09-09"
Description: "Bastion"
Resources:
EC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-051cf04206
InstanceType: t2.micro
KeyName: ke
SubnetId: subnet-09
PrivateIpAddress: 10.123.10.15
SecurityGroupIds:
- sg-01f249b28e
- sg-028744e32
EbsOptimized: true
SourceDestCheck: true
DisableApiTermination: true
UserData:
Fn::Base64:
Fn::Sub: |
#!/bin/bash -v
sleep 10
exec > >(tee /var/log/user-data.log | logger -t user-data -s 2> /dev/console) 2>&1
timedatectl set-timezone Asia/Tokyo
reboot
IamInstanceProfile: base
Monitoring: false
Tags:
- Key: insttag7
Value: 7
- Key: insttag4
Value: 4
- Key: insttag5
Value: 5
- Key: Name
Value: Bastion
- Key: insttag2
Value: 2
- Key: insttag3
Value: 3
- Key: insttag8
Value: 8
- Key: insttag1
Value: 1
- Key: insttag6
Value: 6
LaunchTemplate:
LaunchTemplateId: !Ref LaunchTemplate01
Version: 1
LaunchTemplate01:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateData:
MetadataOptions:
HttpTokens: optional
TagSpecifications:
- ResourceType: volume
Tags:
- Key: ebsttag5
Value: 5
- Key: ebsttag3
Value: 3
- Key: ebsttag6
Value: 6
- Key: ebsttag1
Value: 1
- Key: ebsttag4
Value: 4
- Key: Name
Value: bastion-root
- Key: TestEBSTags
Value: EBSTags
- Key: ebsttag2
Value: 2
- ResourceType: network-interface
Tags:
- Key: env
Value: test
- Key: enitag4
Value: 4
- Key: enitag1
Value: 1
- Key: enitag2
Value: 2
- Key: enitag5
Value: 5
- Key: enitag6
Value: 6
- Key: testenitag
Value: testtag
- Key: enitag3
Value: 3
- Key: name
Value: bastion
BlockDeviceMappings:
- DeviceName: "/dev/xvda"
Ebs:
Encrypted: false
VolumeSize: 8
VolumeType: gp3
DeleteOnTermination: true
Iops: 3000
Throughput: 125
ユーザーデータのログは /var/log/user-data.log に出力されます。
EC2展開後は /var/log/user-data.log を確認することでログを確認できます。
CloudFormationでEC2作成
生成されたテンプレートをCloudFormationでデプロイすることで新しいEC2インスタンスを作成できます。
EBS、ENIタグやEBSやIMDS等の詳細設定のために LaunchTemplate01 が作成されるため、不要なリソースを残さないようLaunchTemplate01を削除しておくことをおすすめします。

この方法を使うことで既存設定を再利用や再構築などが効率よく実施できます。
以上、御一読ありがとうございました。
本田 イーゴリ (記事一覧)
カスタマーサクセス部
・2024 Japan AWS Top Engineers (Security)
・AWS SAP, DOP, SCS, DBS, SAA, DVA, COA, CLF, ANS, AIF, MLS, MLA, DEA
・Azure AZ-900
・EC-Council CCSE
趣味:日本国内旅行(47都道府県制覇)・ドライブ・音楽