はじめに
先日、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にアタッチされていることが確認できます。
別VPCのENIを使う
セッションマネージャーを使う
このままセッションマネージャーで接続すると、接続元VPCのENI経由で接続になります。
接続先VPCのENIでもできるかやってみました。
以下の事をやります。
- セッションマネージャーで接続します
- EC2のルート情報を変更して、接続先VPCのENI側に向けます
- ここで接続が切れます
- 接続先VPCのENIにEIPをアタッチします
まずセッションマネージャーで接続して、ルート情報を見てみます。
ルート情報を変更します。面倒なのですべて接続先VPCのENIに向けます。
以下のコマンドを実行すると、ルート情報が変更されるため、コマンドの実行結果が返ってこなくなりますが、エラーになっていないので問題ないです。
sudo route add -net 0.0.0.0 netmask 0.0.0.0 metric 100 ens6
再度、セッションマネージャーで接続します。ルート情報を見てみると、追加している情報を確認できます。
HTTPでアクセス
上記に引き続き、httpdをインストールしてアクセスしてみます。
sudo yum -y update
sudo yum -y install httpd
sudo systemctl start httpd.service
sudo systemctl enable httpd.service
次にセキュリティグループにインバウンドルールを追加します。
EIPでHTTPアクセスして、画面が表示されることが確認できました。
おわりに
今回はCloudFormationを使って、EC2に別VPCのENIをアタッチさせてみました。
巨大なLANを持っていて、WWWとつなげたい場合は中継サーバーを建ててNICを2つ使って両方に接続、という仕事をやっていた自分にとっては、大変刺さるアップデートでした。
この記事がどなたかのお役に立てれば幸いです。