LoginSignup
1
0

More than 1 year has passed since last update.

【AWS】手動作成した既存のVPCをCloudFormationスタックにインポートする + EC2作成【CloudFormation】

Posted at

CloudFormation - 既存リソースのインポート方法メモ

概要

  • すでに手動で作成してあるVPCをyamlファイル化(?)する
  • CloudFormationを使って新たにEC2インスタンスをVPC上に構築する

参考

ドキュメント
インポートがサポートされているリソース

検証用に用意したもの

  • 手動作成リソース

    • VPC
    • インターネットゲートウェイ
    • サブネット
    • ルートテーブル
    • セキュリティグループ
  • 各リソースの識別子(ID)をメモしておく(インポート実行時に指定することになる)

    • VPC : vpc-xxxxxxxxxxxx
    • rtb : rtb-xxxxxxxxx
    • igw : igw-xxxxxxxxx
    • sg : sg-xxxxxxxxx
    • sub : subnet-xxxxxxxxxxx

手順

1. 既存リソースからのスタック作成(VPC,igw,subnet,rt,sg)

  • まずインポートするためのyamlファイルを作る
AWSTemplateFormatVersion: "2010-09-09"
Description: my imported VPC resources

Resources:
  # VPC
  myVPC:
    Type: AWS::EC2::VPC
    DeletionPolicy: Retain
    Properties: 
      CidrBlock: 192.168.0.0/16
      EnableDnsHostnames: false
      EnableDnsSupport: true
      InstanceTenancy: Default
      Tags: 
        - Key: Name
          Value: vpcName

  # InternetGateway
  myInternetGateway:
    Type: AWS::EC2::InternetGateway
    DeletionPolicy: Retain
    Properties: 
      Tags: 
        - Key: Name
          Value: igwName

  # Subnet
  mySubnet1:
    Type: AWS::EC2::Subnet
    DeletionPolicy: Retain
    Properties: 
      AvailabilityZone: ap-northeast-1a
      CidrBlock: 192.168.1.0/24
      MapPublicIpOnLaunch: false
      Tags: 
        - Key: Name
          Value: publicSubnetName1
      VpcId:
        Ref: myVPC
  mySubnet2:
    Type: AWS::EC2::Subnet
    DeletionPolicy: Retain
    Properties: 
      AvailabilityZone: ap-northeast-1d
      CidrBlock: 192.168.2.0/24
      MapPublicIpOnLaunch: false
      Tags: 
        - Key: Name
          Value: publicSubnetName2
      VpcId:
        Ref: myVPC

  # Routetable
  myRoutetablePublic:
    Type: AWS::EC2::RouteTable
    DeletionPolicy: Retain
    Properties:
      Tags: 
        - Key: Name
          Value: publicRouteName
      VpcId:
        Ref: myVPC
  myRoutetablePrivate:
    Type: AWS::EC2::RouteTable
    DeletionPolicy: Retain
    Properties:
      Tags: 
        - Key: Name
          Value: privateRouteName
      VpcId:
        Ref: myVPC

  # SecuriryGroup
  mySecuritygroup:
    Type: AWS::EC2::SecurityGroup
    DeletionPolicy: Retain
    Properties:
        GroupDescription: allow-all-from-my-vm
        VpcId:
          Ref: myVPC
        SecurityGroupIngress:
        - IpProtocol: -1
          FromPort: -1
          ToPort: -1
          CidrIp: ssh元のIP
        SecurityGroupEgress:
        - IpProtocol: -1
          FromPort: -1
          ToPort: -1
          CidrIp: 0.0.0.0/0

インポートしたいリソースの設定内容をとりあえず入れていく
作成時デフォルトで作った場合、必須項目以外は記載無しでもデフォルトでインポートされる(...はず)

==Point==

DeletionPolicy: Retain をすべてのリソースに設定する

これはスタックを削除しても実際のリソースはそのまま残るようにする設定
インポートに関してはこの設定がついてないとエラーで実行できない

セキュリティグループで「すべて」を指定したい場合

FromPortとかに「すべて」を指定したい場合は、"-1" にする
all とかにすると実行したときにFAILEDになる (Non numeric は サポートされていません みたいなエラー文だった)

インポートできないリソースもある

今回の場合、AWS::EC2::Routeはインポート対象外といわれてインポートできなかった
他のリソースをインポートした後Routeの宣言を追加して、変更セット実行したらどうなる??→要検証

2. スタック作成実行

  1. スタックの作成プルダウンから、既存リソースを使用(リソースをインポート)を選択する

  2. 必要なものを教えてくれる 次へ をクリック

  3. テンプレートの指定でさっき作ったyamlファイルをアップロードする
    事前にS3にアップしておいてURL指定すると余計なバケットが作成されなくて済む

  4. インポートするリソースのリソースIDの入力を求められたら、実際のリソースをコンソールなどで確認して、正しく入力する

  5. スタックの名前 好きな名前を適当につけてOK

  6. 「変更」欄で変更内容を確認して(importがずらっと並ぶはず) 「リソースをインポート」をクリック

  7. 普通にスタック作成したときみたいにステータスが流れ始める
    エラーが出た場合はエラー文読んでデバッグしていく

3. ドリフト検出

ステータスが「IMPORT_COMPLETE」になったら、確認のためにドリフトを検出する

スタックを選択して「スタックアクション」プルダウンから「ドリフトの検出」→「ドリフト結果を表示」

全項目のドリフトステータスが「IN_SYNC」になってたらOK

ドリフトステータス 説明
DELETED リソースが削除されたため、リソースは意図したテンプレート設定と異なります。
MODIFIED リソースは意図したテンプレート設定とは異なります。
NOT_CHECKED CloudFormation は、リソースが意図したテンプレート設定と異なるかどうかを確認していません。
IN_SYNC リソースの現在の設定は、意図したテンプレート設定と一致します。

yamlファイルの中身が間違っている場合

どうなるのか検証してみたところ、
実際のリソースの設定に合わされるようにMODIFYされる
ことがわかった

試しにVPCで EnableDnsSupport: true → false にした(わざと値を間違えた)ものを使ってimport実行してみたところ、
ドリフトを検出→ドリフトの結果→ドリフトの詳細を見ると、自動で true に修正されていることが分かった
これぞフォールトトレランス!!

3. スタックによるリソースの作成(EC2)

ここからおまけ

  # EC2 Instance
  myEC2instance1:
    Type: AWS::EC2::Instance
    Properties: 
      BlockDeviceMappings: 
        - DeviceName: /dev/sda1
          Ebs:
            VolumeType: gp2
            DeleteOnTermination: true
            VolumeSize: 10
      ImageId: ami-0ddf5ff463ff76656
      InstanceType: t2.nano
      KeyName: my-key
      NetworkInterfaces:
        - AssociatePublicIpAddress: true
          DeviceIndex: 0
          SubnetId: !Ref mySubnet1
          GroupSet:
            - !Ref mySecuritygroup
      Tags: 
        - Key: Name
          Value: 
            Ref: InstanceName
  • Ref:
    宣言したリソース名を指定することで特定のパラメータを戻り値で受け取ることができる。
    戻り値の内容はリソースによって変わるので、ドキュメントを見て確認するしかない。
    基本的にIDが返ってくる VPC→VPC ID

  • VolumeType: gp2, gp3, io1, io2 とかを選ぶ gp2が一番標準のSSD

  • gp2はiopsを指定できない (使用要領によってiopsが変動するらしい)

  • ImageId: RockyLinux8を使用 一度インスタンスを作成して、概要からコピってきた
    [求]何もわからない状態からAMIを調べる方法

  • NetworkInterfaces: インターフェース設定 この中でサブネットとセキュリティグループを指定する

  • SubnetId: !Ref mySubnet1

!Ref mySubnet1とすることで SubnetID(subnet-xxxxxx) が Stringで返ってくる
Ref mySubnet1だとエラー起きるので、Stringではない何かが返ってきているようだ

  • GroupSet:
    • !Ref mySecuritygroup

この書き方じゃないとうまくいかなかった
GroupSet(サブネット)はID(String型)じゃなくて、IDのリスト型じゃないとだめらしい(List<AWS::EC2::SecurityGroup::Id>)

エラー起きたときの出力↓
Value of property SecurityGroupIds must be of type List of String

改良

  • Parametersを使ってインスタンス名とセキュリティグループを指定できるようにした
  • EIPをアタッチした
import.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: my imported VPC resources

# Specify Parameter
Parameters:
  InstanceName:
    Description: Specify Instance Name.
    Type: String
  InstanceSecurityGroup:
    Description: Specify Secutiry Group.
    Type: List<AWS::EC2::SecurityGroup::Id>

Resources:

  ## 略 ##

  # EC2 Instance
  myEC2instance1:
    Type: AWS::EC2::Instance
    Properties: 
      BlockDeviceMappings: 
        - DeviceName: /dev/sda1
          Ebs:
            VolumeType: gp2
            DeleteOnTermination: true
            VolumeSize: 10
      ImageId: ami-0ddf5ff463ff76656
      InstanceType: t2.nano
      KeyName: my-key
      NetworkInterfaces:
        - AssociatePublicIpAddress: true
          DeviceIndex: 0
          SubnetId: !Ref mySubnet2
          GroupSet:
            Ref: InstanceSecurityGroup
      Tags: 
        - Key: Name
          Value: 
            Ref: InstanceName

  # Elastic IP
  myElasticIP1:
    Type: AWS::EC2::EIP
    Properties:
      InstanceId:
        Ref: myEC2instance1
      Tags:
        - Key: Name
          Value: !Ref InstanceName

4. スタック更新実行

  1. さっきインポートしたスタックを選択して、更新をクリック

  2. 既存のテンプレートを置き換える → 修正したyamlファイルをアップロードして 次へ

  3. パラメータを指定して 次へ

  4. スタックオプションは特に指定なし 次へ

  5. スタックの更新を実行 (不安なら 変更セットの表示)

5. 問題なければ完成!

EC2に指定したKeypairでsshできたら無事完成!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0