Search code examples
amazon-web-servicesamazon-ec2nataws-vpc

How to put a NAT-Instance in auto scaling?


I wanted to create a fault tolerant website and was trying to create an autoscaling group.NAT-instance was used instead of NAT-Gateway. I experienced the following issues.

When a NAT instance gets terminated [for some reason].The auto-scaling group will launch the respective NAT image, but it would not have disabled the Source/destination check. That has to be done manually and as a result, the private subnet which is connected to the nat-instance will have the status message "Black-hole". Unless until the source destination check is manually changed, the private subnet won't even have the new NAT-instance displayed.

Does anybody have a solution to this problem?


Solution

  • You could use the AWS CLI to modify the sourceDestCheck attribute of the network interface. You could launch this from the User Data of the instance. Other methods are a custom python program or even PowerShell (included below).

    aws ec2 modify-instance-attribute --instance-id i-1234567890abcdef0 --source-dest-check "{\"Value\": true}"
    

    Or by changing the network interace.

    aws ec2 modify-network-interface-attribute --network-interface-id eni-686ea200 --no-source-dest-check
    

    This Stack Overflow question covers doing the same in Python.

    Disable Source/Destination Check AWS Python Boto

    This document shows how to do this in PowerShell.

    Edit-EC2NetworkInterfaceAttribute Cmdlet

    My preferred method would be Python or PowerShell. These methods are the easiest way to get the parameters that you need (instanceId or networkId).

    [EDIT: Example programs]

    Both examples below require either credentials installed on the instance or an IAM role. This is necessary to modify the source/destination flag.

    Here is an example shell script.

    EC2_INSTANCE_ID="`wget -q -O - http://169.254.169.254/latest/meta-data/instance-id`"
    EC2_AVAIL_ZONE="`wget -q -O - http://169.254.169.254/latest/meta-data/placement/availability-zone`"
    EC2_REGION="`echo \"$EC2_AVAIL_ZONE\" | sed -e 's:\([0-9][0-9]*\)[a-z]*\$:\\1:'`"
    echo "Region:" $EC2_REGION
    
    aws ec2 modify-instance-attribute --instance-id $EC2_INSTANCE_ID --source-dest-check "{\"Value\": false}" --region $EC2_REGION
    
    rc=$?; if [[ $rc != 0 ]]; then echo "Failure:" $rc; exit $rc; fi
    
    echo "Success"
    

    Here is an example Python 2 program using boto3 (change the region to yours):

    #!/usr/bin/python
    import boto3
    import requests
    import sys
    
    # install boto3
    # sudo pip install boto3
    
    # Disable stack trace on failure
    sys.tracebacklimit = 0
    
    # Specify the URL for the instance metadata
    url = 'http://169.254.169.254/latest/meta-data/instance-id'
    
    # Specify the region where our instance is at
    region = 'us-west-2'
    
    # Make a request to get the contents of the URL
    r = requests.get(url)
    
    if r.ok != True:
        print "Error: Failed to get instance-id from metadata:", r.reason
        print "Status Code:", r.status_code
        sys.exit(1)
    
    # Get the instance ID from the return response
    instance_id = r.text
    
    print "Instance ID:", instance_id
    
    if instance_id[0] != 'i':
        print "Error: Does not look like a valid instance ID: ", instance_id
        sys.exit(1)
    
    client = boto3.client('ec2', region_name=region)
    
    r = client.modify_instance_attribute(InstanceId=instance_id, SourceDestCheck={'Value': False})
    
    code = r['ResponseMetadata']['HTTPStatusCode']
    
    if code != 200:
        print "Error: Cannot change SourceDestCheck: ", code
        sys.exit(1)
    
    print "Success: SourceDestCheck disabled"