- 公開日
- 最終更新日
【CloudFormation】既存のVPCをCloudFormationにインポートしてみた
この記事を共有する

目次
はじめに
こんにちは!パーソル&サーバーワークスの野間です。
普段AWSで新しくリソースを作成する際はCloudFormationを使って管理をすることが多いですが、
今回、過去に手動で作成されたリソースをCloudFormationに取り込む機会がありました。
今後の参考として、手順とポイントをまとめてみました。
インポート用のリソースの準備
まずはCloudFormationにインポートする対象となるVPCを手動で作成します。
今回は、以下のような構成でVPCを構築しました。
パブリック/プライベートサブネット、NATゲートウェイなども含めており、実運用に近い構成です。
作成したリソースの構成
VPC名:import-test-vpc
CIDR:10.0.0.0/16
アベイラビリティゾーン(AZ)の数:2
パブリックサブネットの数:2(各AZに1つずつ)
プライベートサブネットの数:2(各AZに1つずつ)
NATゲートウェイ:1
VPCエンドポイント:なし
CloudFormationにインポートするためのテンプレート作成
次に、手動で作成したリソースと完全に一致するCloudFormationテンプレートを用意します。
テンプレート作成時に重要なのは、以下の2点です。
① 既存リソースと一致したテンプレートを作成する
CloudFormationにインポートするには、テンプレートに記載するリソースと実際のリソースの設定が一致している必要があります。
例えば、VPCのCIDRやタグ情報などに差異があるとインポート処理は失敗してしまいます。
また、仮にインポートに成功しても、CloudFormationの管理対象と実際の状態にズレがあると「ドリフト検出」に引っかかる可能性があります。
事前にマネジメントコンソールやCLIを使って、対象リソースの設定を正確に確認しておきましょう。
テンプレート作成を効率化したい場合は、AWSのIaCジェネレーターを使うのもおすすめです。
参考:IaC ジェネレーターを使用して既存のリソースからテンプレートを生成する
② Deletion Policy を設定する
CloudFormationにインポートするリソースには、DeletionPolicyの設定が必須です。
これは、スタック削除時にリソースを保持(Retain)するか削除(Delete)するかを指定するためのプロパティです。
今回は誤って既存リソースを削除しないよう、すべてのリソースに DeletionPolicy: Retain
を指定しました。
参考:AWS リソースを CloudFormation スタックに手動でインポートする
今回作成したテンプレート
SecurityGroup:
AWSTemplateFormatVersion: 2010-09-09
Parameters:
SystemName:
Type: String
Default: vpc-import
Resources:
#------------------------------------------------------
# Create VPC
#------------------------------------------------------
VPC01:
Type: AWS::EC2::VPC
DeletionPolicy: Retain
Properties:
CidrBlock: 10.0.0.0/0
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub ${SystemName}-vpc
#------------------------------------------------------
# Create InternetGateway
#------------------------------------------------------
InternetGateway01:
Type: AWS::EC2::InternetGateway
DeletionPolicy: Retain
Properties:
Tags:
- Key: Name
Value: !Sub ${SystemName}-igw
#------------------------------------------------------
# Create NatGateway
#------------------------------------------------------
NatGateway01:
Type: AWS::EC2::NatGateway
DeletionPolicy: Retain
Properties:
AllocationId: !GetAtt NATGatewayEIP.AllocationId
SubnetId: !Ref PublicSubnet01
Tags:
- Key: Name
Value: !Sub ${SystemName}-ngw
NATGatewayEIP:
Type: AWS::EC2::EIP
DeletionPolicy: Retain
Properties:
Domain: vpc
#------------------------------------------------------
# Create Subnet
#------------------------------------------------------
PublicSubnet01:
Type: AWS::EC2::Subnet
DeletionPolicy: Retain
Properties:
AvailabilityZone: !Select
- 0
- Fn::GetAZs: ""
CidrBlock: 10.0.0.0/20
MapPublicIpOnLaunch: false
VpcId: !Ref VPC01
Tags:
- Key: Name
Value: !Sub ${SystemName}-subnet-public1-ap-northeast-1a
PublicSubnet02:
Type: AWS::EC2::Subnet
DeletionPolicy: Retain
Properties:
AvailabilityZone: !Select
- 0
- Fn::GetAZs: ""
CidrBlock: 10.0.16.0/20
MapPublicIpOnLaunch: false
VpcId: !Ref VPC01
Tags:
- Key: Name
Value: !Sub ${SystemName}-subnet-public2-ap-northeast-1c
PrivateSubnet01:
Type: AWS::EC2::Subnet
DeletionPolicy: Retain
Properties:
AvailabilityZone: !Select
- 0
- Fn::GetAZs: ""
CidrBlock: 10.0.128.0/20
MapPublicIpOnLaunch: false
VpcId: !Ref VPC01
Tags:
- Key: Name
Value: !Sub ${SystemName}-subnet-private1-ap-northeast-1a
PrivateSubnet02:
Type: AWS::EC2::Subnet
DeletionPolicy: Retain
Properties:
AvailabilityZone: !Select
- 0
- Fn::GetAZs: ""
CidrBlock: 10.0.144.0/20
MapPublicIpOnLaunch: false
VpcId: !Ref VPC01
Tags:
- Key: Name
Value: !Sub ${SystemName}-subnet-private2-ap-northeast-1c
#------------------------------------------------------
# Create RouteTable
#------------------------------------------------------
PublicRouteTable01:
Type: AWS::EC2::RouteTable
DeletionPolicy: Retain
Properties:
VpcId: !Ref VPC01
Tags:
- Key: Name
Value: !Sub ${SystemName}-rtb-public
PrivateRouteTable01:
Type: AWS::EC2::RouteTable
DeletionPolicy: Retain
Properties:
VpcId: !Ref VPC01
Tags:
- Key: Name
Value: !Sub ${SystemName}-rtb-private1-ap-northeast-1a
PrivateRouteTable02:
Type: AWS::EC2::RouteTable
DeletionPolicy: Retain
Properties:
VpcId: !Ref VPC01
Tags:
- Key: Name
Value: !Sub ${SystemName}-rtb-private2-ap-northeast-1c
#------------------------------------------------------
# Create Route
#------------------------------------------------------
PublicRoute01:
Type: AWS::EC2::Route
DeletionPolicy: Retain
Properties:
RouteTableId: !Ref PublicRouteTable01
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway01
PrivateRoute01:
Type: AWS::EC2::Route
DeletionPolicy: Retain
Properties:
RouteTableId: !Ref PrivateRouteTable01
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway01
PrivateRoute02:
Type: AWS::EC2::Route
DeletionPolicy: Retain
Properties:
RouteTableId: !Ref PrivateRouteTable02
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway01
CloudFormationにインポートする
テンプレートが準備できたら、いよいよリソースのインポートです。
AWS CloudFormation コンソールから、[スタックの作成] > [既存のリソースを使用(リソースのインポート)] を選択します。
テンプレートをアップロードし、インポート対象のリソースID(VPC IDやサブネットIDなど)を指定します。
プレビュー画面で、各リソースが「import」と表示されているかを確認します。
入力するパラメータを間違えていたり、テンプレートに不備があるとこの画面でエラーが表示されます。
問題がなければそのままインポートを実行します。
これで、手動で作成したリソースをIaCの管理下に置くことができました!
まとめ
今回は、手動で作成されたVPC環境をCloudFormationに取り込む手順を紹介しました。
インポート作業は準備に時間がかかりますが、一度インポートを行えばその後の運用管理がとても楽になります。
なお、CloudFormationのインポートには非対応のリソースも存在するため、事前に下記の公式リストで対応状況を確認しておくと安心です。
参考:リソースタイプのサポート
この記事は私が書きました
野間 太一
記事一覧猫とCloudFormationが好きです。
