Creating a Launch Template in AWS of a single EC2 instance with multiple elastic network interfaces (ENIs) is quite straightforward. How about the Autoscaling Group and Multiple Availability Zones.
What if a launch template must be used by the Auto Scaling Group, spinning up EC2 instances in multiple Availability Zones and attaching multiple ENIs in defined subnets? Here is how to do it with user data script a bit of shell scripting, and without Lambda functions.
Deploy Bastion Host cluster consisting of 2 EC2 instances in multiple AZs (1a and 1b) and attach 2 additional elastic network interfaces (ENI) to each EC2 instance in desired subnets. Assuming all required ENIs have been created. The primary network interface (eth0) is created automatically, we are attaching eth1, eth2, ethn.
ENIs | AZ | ENI ID |
---|---|---|
ENI_1_BH_1a (eth1) | eu-west-1a | eni-01fd164d37e9399b6 |
ENI_2_BH_1a (eth2) | eu-west-1a | eni-0e65371003fb3eec7 |
ENI_1_BH_1b (eth1) | eu-west-1b | eni-01e64d711a9ff7f88 |
ENI_2_BH_1b (eth2) | eu-west-1b | eni-09329d7d425e30303 |
Add to IAM role the following policy with these minimum privileges:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:DescribeNetworkInterfaces",
"ec2:AttachNetworkInterface"
],
"Resource": "*"
}
]
}
First, we have to make our EC2 instances aware of a couple of things during the boot time:
Next we create a bash function, which will be used in IF statements…
Below user data shell script can be used in launch template.
Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0
--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"
#cloud-config
cloud_final_modules:
- [scripts-user, always]
--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"
#!/bin/bash
## ========= ENI Variables ===========================================
ENI_1_BH_1a="eni-01fd164d37e9399b6"
ENI_2_BH_1a="eni-0e65371003fb3eec7"
ENI_1_BH_1b="eni-01e64d711a9ff7f88"
ENI_2_BH_1b="eni-09329d7d425e30303"
# Ensure latest version of awscli
/bin/curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
/bin/unzip -o awscliv2.zip > /dev/null 2>&1
./aws/install --update
# Required variables
AWS_REGION=$(/bin/curl -s http://169.254.169.254/latest/meta-data/placement/region)
INSTANCE_ID=$(/bin/curl -s http://169.254.169.254/latest/meta-data/instance-id)
AZ=$(/bin/curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone)
## ========= ENIs Attachment =====================================
# Main function
attach_eni () {
/usr/local/bin/aws ec2 attach-network-interface \
--device-index $1 \
--network-interface-id $2 \
--instance-id $INSTANCE_ID \
--region $AWS_REGION
}
## AZ1
if [[ $AZ = "eu-west-1a" ]]; then
attach_eni 1 $ENI_1_BH_1a
attach_eni 2 $ENI_2_BH_1a
fi
## AZ2
if [[ $AZ = "eu-west-1b" ]]; then
attach_eni 1 $ENI_1_BH_1b
attach_eni 2 $ENI_2_BH_1b
fi
This way we can easily control the assignment of ENIs within desired subnets to EC2 instances created by the autoscaling group.
I hope this simple tutorial is helpful. If have any further questions, share with me in the comments section below.