0
0

CloudFormationで、EC2に別VPCのENIをアタッチ

Posted at

はじめに

先日、EC2のアップデートで、別のVPCのENIをアタッチできるようになりました。

今回はこれをCloudFormationでやってみました。

概要

AWS::EC2::NetworkInterfaceAttachmentを使います。

  EniAttach:
    Type: AWS::EC2::NetworkInterfaceAttachment
    Properties:
      DeviceIndex: 1
      InstanceId: アタッチされたいEC2
      NetworkInterfaceId: アタッチするENI(別VPC)

また別VPC側のENI経由でもEIPをアタッチすることで、セッションマネージャーで接続できたり、HTTPアクセスできました。

参考

やってみた

以下のものを作ります。

  • 接続元VPC
    • パブリックサブネット
    • EC2
      • セッションマネージャーが使えるロールをアタッチ
  • 接続先VPC
    • パブリックサブネット
    • ENI
  • EC2にENIをアタッチ

以下がCloudFormationテンプレートです。

クリックで表示

パラメータは以下です。

  • 接続元VPC名と、そのCIDR
  • 接続先VPC名と、そのCIDR
  • EC2のイメージID
  • インスタンスタイプ
  • 作るAZ
    • EC2とENIは同じAZである必要があります

一部確認用に、接続元VPCにENIを作った個所をコメントにしています。

AWSTemplateFormatVersion: '2010-09-09'

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Parameters
        Parameters:
          - VpcNameSource
          - VpcCIDRSource
          - VpcNameTarget
          - VpcCIDRTarget
          - ImageId
          - InstanceTypeName
          - AvailabilityZone

Parameters:

  VpcNameSource:
    Type: String
    Default: sourceVpc
    Description: Name of the VPC
  VpcCIDRSource:
    Type: String
    Default: 10.70.0.0/16
    Description: CIDR block for the VPC

  VpcNameTarget:
    Type: String
    Default: targetVpc
    Description: Name of the VPC
  VpcCIDRTarget:
    Type: String
    Default: 10.80.0.0/16
    Description: CIDR block for the VPC

  ImageId:
    Type: String
    Default: ami-098940df4d3292e9a
  InstanceTypeName:
    Type: String
    Default: t3.micro
  AvailabilityZone:
    Type: AWS::EC2::AvailabilityZone::Name

Resources:
  ##################################################
  # Source VPC
  ##################################################
  VPCSource:
    Type: 'AWS::EC2::VPC'
    Properties:
      CidrBlock: !Ref VpcCIDRSource
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Ref VpcNameSource

  InternetGatewaySource:
    Type: 'AWS::EC2::InternetGateway'
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${VpcNameSource}-igw

  VPCGatewayAttachmentSource:
    Type: 'AWS::EC2::VPCGatewayAttachment'
    Properties:
      VpcId: !Ref VPCSource
      InternetGatewayId: !Ref InternetGatewaySource

  PublicSubnetSource:
    Type: 'AWS::EC2::Subnet'
    Properties:
      VpcId: !Ref VPCSource
      AvailabilityZone: !Ref AvailabilityZone
      CidrBlock: !Select [ 0, !Cidr [ !Ref VpcCIDRSource, 24, 8 ] ]
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub ${VpcNameSource}-subnet

  PublicRouteTableSource:
    Type: 'AWS::EC2::RouteTable'
    Properties:
      VpcId: !Ref VPCSource
      Tags:
        - Key: Name
          Value: !Sub ${VpcNameSource}-rtb-public
  PublicRouteSource:
    Type: 'AWS::EC2::Route'
    DependsOn: VPCGatewayAttachmentSource
    Properties:
      RouteTableId: !Ref PublicRouteTableSource
      DestinationCidrBlock: '0.0.0.0/0'
      GatewayId: !Ref InternetGatewaySource

  SubnetRouteTableAssociationSource:
    Type: 'AWS::EC2::SubnetRouteTableAssociation'
    Properties:
      SubnetId: !Ref PublicSubnetSource
      RouteTableId: !Ref PublicRouteTableSource

  SecurityGroupForSource:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !Ref VPCSource
      GroupDescription: "Source VPC SG"

  # EniSource:
  #   Type: AWS::EC2::NetworkInterface
  #   Properties:
  #     Tags:
  #       - Key: Name
  #         Value: SourceEni
  #     GroupSet:
  #       - !GetAtt SecurityGroupForSource.GroupId
  #     SubnetId: !Ref PublicSubnetSource

  # EC2
  SessionManagerRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: 'Allow'
            Principal:
              Service:
                - 'ec2.amazonaws.com'
            Action:
              - 'sts:AssumeRole'
      Path: '/'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
  InstanceProfile:
    DependsOn: SessionManagerRole
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: '/'
      Roles:
        - !Ref SessionManagerRole
  InstanceOnSource:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref ImageId
      InstanceType: !Ref InstanceTypeName
      IamInstanceProfile: !Ref InstanceProfile
      SubnetId: !Ref PublicSubnetSource
      SecurityGroupIds:
        - !GetAtt SecurityGroupForSource.GroupId
      Tags:
        - Key: Name
          Value: sourceInstance
          
  ##################################################
  # Target VPC
  ##################################################
  VPCTarget:
    Type: 'AWS::EC2::VPC'
    Properties:
      CidrBlock: !Ref VpcCIDRTarget
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Ref VpcNameTarget

  InternetGatewayTarget:
    Type: 'AWS::EC2::InternetGateway'
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${VpcNameTarget}-igw

  VPCGatewayAttachmentTarget:
    Type: 'AWS::EC2::VPCGatewayAttachment'
    Properties:
      VpcId: !Ref VPCTarget
      InternetGatewayId: !Ref InternetGatewayTarget

  PublicSubnetTarget:
    Type: 'AWS::EC2::Subnet'
    Properties:
      VpcId: !Ref VPCTarget
      AvailabilityZone: !Ref AvailabilityZone
      CidrBlock: !Select [ 0, !Cidr [ !Ref VpcCIDRTarget, 24, 8 ] ]
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub ${VpcNameTarget}-subnet

  PublicRouteTableTarget:
    Type: 'AWS::EC2::RouteTable'
    Properties:
      VpcId: !Ref VPCTarget
      Tags:
        - Key: Name
          Value: !Sub ${VpcNameTarget}-rtb-public
  PublicRouteTarget:
    Type: 'AWS::EC2::Route'
    DependsOn: VPCGatewayAttachmentTarget
    Properties:
      RouteTableId: !Ref PublicRouteTableTarget
      DestinationCidrBlock: '0.0.0.0/0'
      GatewayId: !Ref InternetGatewayTarget

  SubnetRouteTableAssociationTarget:
    Type: 'AWS::EC2::SubnetRouteTableAssociation'
    Properties:
      SubnetId: !Ref PublicSubnetTarget
      RouteTableId: !Ref PublicRouteTableTarget

  SecurityGroupForTarget:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !Ref VPCTarget
      GroupDescription: "Target VPC SG"

  EniTarget:
    Type: AWS::EC2::NetworkInterface
    Properties:
      Tags:
        - Key: Name
          Value: TargetEni
      GroupSet:
        - !GetAtt SecurityGroupForTarget.GroupId
      SubnetId: !Ref PublicSubnetTarget

  EniAttach:
    Type: AWS::EC2::NetworkInterfaceAttachment
    Properties:
      DeviceIndex: 1
      InstanceId: !Ref InstanceOnSource
      # NetworkInterfaceId: !Ref EniSource
      NetworkInterfaceId: !Ref EniTarget

実行して、作られたEC2のネットワークを確認すると、以下のように複数のVPCにアタッチされていることが確認できます。
image.png

別VPCのENIを使う

セッションマネージャーを使う

このままセッションマネージャーで接続すると、接続元VPCのENI経由で接続になります。
接続先VPCのENIでもできるかやってみました。

以下の事をやります。

  1. セッションマネージャーで接続します
  2. EC2のルート情報を変更して、接続先VPCのENI側に向けます
    • ここで接続が切れます
  3. 接続先VPCのENIにEIPをアタッチします

まずセッションマネージャーで接続して、ルート情報を見てみます。
image.png

ルート情報を変更します。面倒なのですべて接続先VPCのENIに向けます。
以下のコマンドを実行すると、ルート情報が変更されるため、コマンドの実行結果が返ってこなくなりますが、エラーになっていないので問題ないです。

sudo route add -net 0.0.0.0 netmask 0.0.0.0 metric 100 ens6

次にEIPを割り当てて、ENIに関連付けします。
image.png

再度、セッションマネージャーで接続します。ルート情報を見てみると、追加している情報を確認できます。

image.png

HTTPでアクセス

上記に引き続き、httpdをインストールしてアクセスしてみます。

sudo yum -y update
sudo yum -y install httpd
sudo systemctl start httpd.service
sudo systemctl enable httpd.service

次にセキュリティグループにインバウンドルールを追加します。

image.png

EIPでHTTPアクセスして、画面が表示されることが確認できました。

image.png

おわりに

今回はCloudFormationを使って、EC2に別VPCのENIをアタッチさせてみました。
巨大なLANを持っていて、WWWとつなげたい場合は中継サーバーを建ててNICを2つ使って両方に接続、という仕事をやっていた自分にとっては、大変刺さるアップデートでした。

この記事がどなたかのお役に立てれば幸いです。

0
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
0
0