AWS newbie here. I'm trying to create a stack with multiple EC2 nodes, each of which should have two network interfaces.
One interface should be public and connected to the Internet, the other interface should be private. The interfaces should belong to different subnets so they can be routed independently (data plane / control plane).
Here is what I've tried in CloudFormation:
Resources:
[.....]
Host1:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: 'ami-02541b8af977f6cdd' # Amazon Linux x86
InstanceType: 't2.micro'
KeyName: !Ref KeyName
NetworkInterfaces:
- SubnetId: !Ref SubnetPublic
AssociatePublicIpAddress: true
DeleteOnTermination: true
DeviceIndex: '0'
GroupSet:
- !Ref SecurityGroup
- SubnetId: !Ref SubnetPrivate
AssociatePublicIpAddress: false
DeleteOnTermination: true
DeviceIndex: '1'
GroupSet:
- !Ref SecurityGroup
This however results in an error:
The associatePublicIPAddress parameter cannot be specified when launching with multiple network interfaces.
Full YAML file available here: https://gist.github.com/kmansoft/39f7be10553195f41b8201e5638073f2
How can I resolve this?
CodePudding user response:
I'm not at all a CloudFormation guy but, I think I see a problem here. There is just one instance being specified. correct? But you're specifying two subnets. An instance can only be in one subnet.
All instances, regardless of whether they are in a public or private subnet, will have a private IP address. If they are in a public subnet, they will also have a public IP. However, the public IP will not be visible at the O/S level, i.e., not visible by ifconfig or ip. The public IP is handled by AWS at the network level, out of sight of you or the O/S.
So, first design a VPC, and the VPC will have both public and private subnets. Any instance launched in a private subnet will automatically only get a private IP address. An instance launched in a public subnet will automatically be assigned a private IP address and a public IP address. Further, for your public IP addresses, if you wish, you can assign an Elastic IP, which will allow you to have a static public IP address. If you don't have an Elastic IP assigned, then every time the instance is stopped/started, it will get a new public IP address, though the private IP address will remain static.
Finally, an instance in the public subnet will, as previously mentioned, have both a public and private IP address. So, if you're copying files from one instance to another in the same VPC, just use the private IP address. To service, for example, web traffic from the Internet, you can use the public IP address. Lastly, you can enhance security by defining that all incoming SSH traffic must come in on the private IP address. That way, you'll either need to be in your local office (which presumably has point-to-point VPN) or you must start VPN to login to an instance via SSH.
How all this translates to CloudFormation, I have no idea.
Hope that helps.
CodePudding user response:
Got things to work.
The trick was to only specify one network interface in the EC2 Instance - then it's possible to set AssociatePublicIpAddress: true
- and add the second network interface separately.
Resources:
[...]
Host1:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: 'ami-02541b8af977f6cdd' # Amazon Linux x86
InstanceType: 't2.micro'
AvailabilityZone: !Select [0, !GetAZs '']
KeyName: !Ref KeyName
NetworkInterfaces:
- SubnetId: !Ref SubnetPublic
AssociatePublicIpAddress: true
DeleteOnTermination: true
DeviceIndex: '0'
GroupSet:
- !Ref SecurityGroup
Tags:
- Key: Name
Value: 'simple - host1'
Host1Eth1:
Type: 'AWS::EC2::NetworkInterface'
Properties:
SubnetId: !Ref SubnetPrivate
GroupSet:
- !Ref SecurityGroup
Tags:
- Key: Name
Value: 'simple - host1 eth1'
Host1Eth1Attachment:
Type: 'AWS::EC2::NetworkInterfaceAttachment'
Properties:
DeleteOnTermination: true
DeviceIndex: 1
NetworkInterfaceId: !Ref Host1Eth1
InstanceId: !Ref Host1
In my config, eth0 is allocated from 30.0.1.0/24, and eth1 is allocated from 30.0.2.0/24.
Here is the routing table right after the Instance is created:
default via 30.0.1.1 dev eth0
default via 30.0.2.1 dev eth1 metric 10001
30.0.1.0/24 dev eth0 proto kernel scope link src 30.0.1.145
30.0.2.0/24 dev eth1 proto kernel scope link src 30.0.2.251
169.254.169.254 dev eth0
This is pretty close to what I need, just needs to be tweaked a little bit with an Instance UserData.
Full YAML script: https://gist.github.com/kmansoft/c490e7958b8ff8f1d2eb14a6cd115f08