[PYTHON] Pseudo stop / start NAT gateway

Billing for NAT gateways not using VS

The usage fee for NAT gateway is unexpectedly high, and I want to stop it when I'm not using it in a development environment at night. However, there is no stop function at present, and stop equals deletion. In terms of stopping, it is a good idea to set up a NAT instance and stop it, but that is simply troublesome. I want to use the managed service. Then, create a script that deletes the NAT gateway when it is not in use and recreates it with the necessary information when you want to use it.

Try to figure out what you want to do

gomi.png I haven't officially studied how to write UML, so please forgive me.

Stop (delete) script

import boto3
 
client = boto3.client('ec2')
 
natGateWayList = []
routeTableList = []
subnetList = []
natGateWayNameList = []
iPlist = []

#Get a running NAT gateway
response = client.describe_nat_gateways(
    Filters=[
        {
            'Name': 'state',
            'Values': ['available'],
        },
    ],
)
 
for natgateway in response['NatGateways']:
    natGateWayList.append(natgateway['NatGatewayId'])
    subnetList.append(natgateway['SubnetId'])
    for tag in natgateway['Tags']:
        if tag['Key'] == "Name":
            natGateWayNameList.append(tag['Value'])
        else:
            pass

#Get routing towards NAT gateway
for i in natGateWayList:
    response = client.describe_route_tables(
        Filters=[
            {
                'Name': 'route.nat-gateway-id',
                'Values': [i],
            },
        ],
    )
    for j in response['RouteTables']:
        routeTableList.append(j['RouteTableId'])
 
#Insert the NAT gateway name in the Subnet tag
for sub, nm in zip(subnetList, natGateWayNameList):
    response = client.create_tags(
        Resources=[
            sub,
        ],
        Tags=[
            {
                'Key': 'tempNatName',
                'Value': str(nm)
            },
        ]
    )

#Set a Flag in the route table where the NAT gateway exists
for i in routeTableList:
    response = client.create_tags(
        Resources=[
            i,
        ],
        Tags=[
            {
                'Key': 'routeingToNat',
                'Value': 'True'
            },
        ]
    )

#Collect EIP from the value obtained by the startup script
response = client.describe_addresses(
    Filters=[
        {
            'Name': 'tag:DisFLG',
            'Values': ['True']
        },
    ]
)
#Various deletion processing
for i in response['Addresses']:
    client.release_address(AllocationId=i['AllocationId'])
 
for i in routeTableList:
    response = client.delete_route(
        DestinationCidrBlock='0.0.0.0/0',
        RouteTableId=i,
    )
 
for i in natGateWayList:
    client.delete_nat_gateway(NatGatewayId=i)

Startup script

import boto3
 
client = boto3.client('ec2')
 
subnetLst = []
ipList = []
natGateWayNameList = []
routeTableList = []
natGateWayIdList = []

#Recover NAT Name tag from subnet where NAT gateway was located
response = client.describe_subnets(
    Filters=[
        {
            'Name': 'tag:tempNatName',
            'Values': ['*']
        },
    ],
)

for h in response['Subnets']:
    subnetLst.append(h['SubnetId'])
    for i in h['Tags']:
        if i['Key'] == "tempNatName":
            natGateWayNameList.append(i['Value'])
        else:
            pass

#Flag EIP for deletion
for nat in natGateWayNameList:
    result = client.allocate_address(
        Domain='vpc'
    )
    response = client.create_tags(
        Resources=[
            result['AllocationId'],
        ],
        Tags=[
            {
                'Key': 'Name',
                'Value': str(nat) + '-IsIpAdress'
            },
            {
                'Key': 'DisFLG',
                'Value': 'True'
            },
        ]
    )
    ipList.append(result['AllocationId'])

#Create NAT gateway
for sub, ip, ntnm in zip(subnetLst, ipList, natGateWayNameList):
    response = client.create_nat_gateway(
        AllocationId=ip,
        SubnetId=sub
    )
 
    natid = response['NatGateway']['NatGatewayId']
    natGateWayIdList.append(natid)
    client.get_waiter('nat_gateway_available').wait(NatGatewayIds=[natid])
 
    response = client.create_tags(
        Resources=[
            natid,
        ],
        Tags=[
            {
                'Key': 'Name',
                'Value': str(ntnm)
            },
        ]
    )
 
response = client.describe_route_tables(
    Filters=[
        {
            'Name': 'tag:routeingToNat',
            'Values': ['True']
        },
    ],
)

#Retrieving values from route table tags and routing
for i in response['RouteTables']:
    routeTableList.append(i['RouteTableId'])
 
for natId in natGateWayIdList:
    response = client.describe_nat_gateways(
        Filters=[
            {
                'Name': 'nat-gateway-id',
                'Values': [natId]
            },
        ],
    )
    natVpcId = response['NatGateways'][0]['VpcId']
    for routeTableId in routeTableList:
        rtbrespo = client.describe_route_tables(
            Filters=[
                {
                    'Name': 'route-table-id',
                    'Values': [routeTableId]
                },
            ],
        )
        rtVpcId = rtbrespo['RouteTables'][0]['VpcId']
        if natVpcId == rtVpcId:
            response = client.create_route(
               DestinationCidrBlock='0.0.0.0/0',
                NatGatewayId=natId,
                RouteTableId=routeTableId
            )
 

Something various

--Since it is assumed that there is already NATGW with the Name tag attached, if you move it as it is, it will probably be NG ――If you want to control finely, you can write various things in Tag and describe it. --If you have an Elastic IP that you are not using, you will be charged a little, so we will release and procure addresses one by one. It's a saving script in the first place. --If you want to keep the EIP you are using, you can cut the address procurement process and insert the existing EIP ID. --It is also possible to create NATGW only during working hours if you run it with lambda and CloudWatch Event ――However, since the block is not divided for each function, it is necessary to add it, it works as it is --Since I tried it in an environment with two VPCs, it is such a routing process --For example, if the subnet is cut in AZ, it is necessary to judge that it is added to the routing. --A duck that can be made smarter with List comprehensions instead of for statements ――Momo Asakura is cute, and Shiina Natsukawa can recommend it.

Referenced page

I tried to manage the start / stop of NAT Gateway without a server [Oshinin! Soft Dojo] https://www.ntt-tx.co.jp/column/dojo_aws_blog/20180411/ I want to stop when I'm not using AWS resources! https://qiita.com/atmitani/items/dbb58e820030996b73d9 I want to easily start / stop EC2 with the simplest mechanism possible! | Class method blog https://dev.classmethod.jp/cloud/aws/simple-auto-start-stop-for-ec2/

Recommended Posts

Pseudo stop / start NAT gateway
Start / stop GCE from python