[PYTHON] code-server online environment (3) Launch an EC2 instance with Boto3

This is the 14th day article of Advent Calender on the 2019 code-server.

Continuing from the last time, I would like to launch EC2 Instance.

table of contents Local environment 1st day Online environment version 1st day Improve work environment

Online environment, day 2 Create a virtual network

Online environment 3rd day Launch an EC2 instance with Boto3

Online environment 4th day Try running Code-Server in the cloud

Online environment 5th day Launch code-server on Docker

Online environment, day 6 Let's automate

Online environment 7th day Deploy compute on git on EC2

... Online version .. Built with Coompose file

Online .. Try K8S

...

Demon remodeling

Introduction

I didn't set the RouteTable. It works in the time environment, Maybe it doesn't work ...

So let's start by setting up the Route Table

What is a Route Table?

You set the Gateway last time !!, you can set which Gateway to use for each IP accessed from the VPC.

In this case, all you have to do is connect to the Internet Gateway, You can set it frequently, such as between VPCs and Subnets.

Creating a network # 2

Create a Route Table

Create



def create_route_table(vpc_id:str):
    res = ec2client.create_route_table(VpcId=vpc_id)
    print("{}".format(res))
    route_table_id = res['RouteTable']['RouteTableId']
    attach_tag(route_table_id)
    return route_table_id

The Route Table is a VPC. Of course ..

You can go

Create a Route

Let's specify in RouteTable that all IPs can connect to the Internet

Create a Route


def create_route(route_table_id:str, gateway_id:str):
    resp = ec2client.create_route(RouteTableId=route_table_id,DestinationCidrBlock="0.0.0.0/0",GatewayId=gateway_id)
    print("{}".format(resp))

0.0.0.0/0 means all IPs. From 0.0.0.0 to 255.255.255.255

Associate with Subnet

python


def associate_route_table(route_table_id:str, subnet_id:str):
    res = ec2client.associate_route_table(RouteTableId=route_table_id,SubnetId=subnet_id)
    print("{}".format(res))
    associate_id = res['AssociationId']
    return associate_id

Delete Route Table

def delete_route_table():
    print(">>> Delete Route Table")
    res = ec2client.describe_route_tables(Filters=[{"Name":"tag:Name","Values":[instance_name]}])
    print("{}".format(res))
    for route_table in res["RouteTables"]:
        for association in route_table.get('Associations',[]):
            ec2client.disassociate_route_table(AssociationId = association['RouteTableAssociationId'])
        res = ec2client.delete_route_table(RouteTableId=route_table['RouteTableId'])
        print("{}".format(res))

The deletion looks like this. Before removing it, you need to call ʻassociate_route_table ()` to disassociate it.

Filters=[{"Name":"vpc-id","Values":[vpc_id]}]

Security Group fix

The last code forgot to set up a VPC ..

Create


def create_security_group(vpc_id):
    print(">>> CREATE SECURITY GROUP")
    res = ec2client.create_security_group(Description="AdventCodeServer",GroupName=instance_name,VpcId=vpc_id)
    print("{}".format(res))
    group_id = res['GroupId']
    attach_tag(group_id)
    return group_id

The code written so far is as follows

https://github.com/kyorohiro/advent-2019-code-server/blob/master/remote_cs01/for_aws/main.py

Create an Instance

Create a PEM file

It is assumed that you will connect to the Instance using the SSH key. Let's create a private key and a public key

PEM creation


def create_pem():
    pem_file = open("{}.pem".format(instance_name),"w")
    pem_file.write("")
    try:
        print(">>> CREATE KEY_PAIR")
        res = ec2client.create_key_pair(KeyName=instance_name)
        print("{}".format(res))
        pem_file.write(res['KeyMaterial'])
    finally:
        pem_file.close()
    return instance_name

PEM deleted


def delete_pem():
    print(">>>> DELETE KeyPair")
    ec2client.delete_key_pair(KeyName=instance_name)

Launch Instance

Create


def create_instance(subnet_id:str, group_id:str):
    print(">>>> CREATE INSTANCE")
    res = ec2client.run_instances(ImageId="ami-0cd744adeca97abb1",#KeyName="xx",
        InstanceType='t2.micro',
        MinCount=1,MaxCount=1,KeyName=instance_name,
        TagSpecifications=[
            {
                'ResourceType': 'instance',
                'Tags': [{
                    'Key': 'Name',
                    'Value': instance_name
                }]
            }
        ],NetworkInterfaces=[{"SubnetId":subnet_id,'AssociatePublicIpAddress': True,'DeviceIndex':0,'Groups': [group_id]}]
        )
    print("{}".format(res))

Specify the subnet and group_id you created.

This time I specified Ubuntu. https://aws.amazon.com/jp/amazon-linux-ami/

Delete



def delete_instance():
    print(">>>> ec2client.describe_instances")
    res = ec2client.describe_instances(
        Filters=[{"Name":"tag:Name","Values":[instance_name]}]
        )
    print("{}".format(res))

    print(">>>> DELETE Instance")
    for reservation in res['Reservations']:
        for instance in reservation['Instances']:
            instance_id = instance['InstanceId']
            res = ec2client.terminate_instances(InstanceIds=[instance_id])

    print("{}".format(res))

The deletion is the same as before.

Now, let's connect the ones we have created so far.

Run the script, before that

Let's also write a script that waits for the instance to be deleted.

python


def wait_instance_is_terminated():
    while(True):
        res = ec2client.describe_instances(
            Filters=[{"Name":"tag:Name","Values":[instance_name]}]
            )
        terminated = False
        for reservation in res['Reservations']:
            for instance in reservation['Instances']:
                instance_state = instance['State']['Name']
                print("------{}".format(instance_state))
                if instance_state != 'terminated':
                    terminated = True
        if terminated == False:
            break
        time.sleep(6)

Summary

main.py


import boto3
from boto3_type_annotations import ec2
from botocore.exceptions import ClientError
from typing import Dict, List 
import time
import network

instance_name= "advent-code-server"
ec2client:ec2.Client = boto3.client("ec2")


def create_pem():
    pem_file = open("{}.pem".format(instance_name),"w")
    pem_file.write("")
    try:
        print(">>> CREATE KEY_PAIR")
        res = ec2client.create_key_pair(KeyName=instance_name)
        print("{}".format(res))
        pem_file.write(res['KeyMaterial'])
    finally:
        pem_file.close()
    return instance_name

def delete_pem():
    print(">>>> DELETE KeyPair")
    ec2client.delete_key_pair(KeyName=instance_name)

def create_instance(subnet_id:str, group_id:str):

    print(">>>> CREATE INSTANCE")
    # Ubuntu Server 18.04 LTS (HVM), SSD Volume Type - ami-0cd744adeca97abb1 (64-bit x86) / ami-0f0dcd3794e1da1e1 (64-bit Arm)
    # https://aws.amazon.com/jp/amazon-linux-ami/
    res = ec2client.run_instances(ImageId="ami-0cd744adeca97abb1",#KeyName="xx",
        InstanceType='t2.micro',
        MinCount=1,MaxCount=1,KeyName=instance_name,
        TagSpecifications=[
            {
                'ResourceType': 'instance',
                'Tags': [
                {
                    'Key': 'Name',
                    'Value': instance_name
                }
                ]
            }
        ],NetworkInterfaces=[{"SubnetId":subnet_id,'AssociatePublicIpAddress': True,'DeviceIndex':0,'Groups': [group_id]}]
        )
    print("{}".format(res))

    return instance_name


def delete_instance():
    print(">>>> ec2client.describe_instances")
    res = ec2client.describe_instances(
        Filters=[{"Name":"tag:Name","Values":[instance_name]}]
        )
    print("{}".format(res))

    print(">>>> DELETE Instance")
    for reservation in res['Reservations']:
        for instance in reservation['Instances']:
            print("------{}".format(instance))
            instance_id = instance['InstanceId']
            print(">>>> {}".format(instance_id))
            res = ec2client.terminate_instances(InstanceIds=[instance_id])

    print("{}".format(res))

def wait_instance_is_terminated():
    while(True):
        res = ec2client.describe_instances(
            Filters=[{"Name":"tag:Name","Values":[instance_name]}]
            )
        terminated = False
        for reservation in res['Reservations']:
            for instance in reservation['Instances']:
                instance_state = instance['State']['Name']
                print("------{}".format(instance_state))
                if instance_state != 'terminated':
                    terminated = True
        if terminated == False:
            break
        time.sleep(6)

if __name__ == "__main__":
    res = network.create()
    create_pem()
    create_instance(res["subnet_id"], res["group_id"])
    delete_instance()
    wait_instance_is_terminated()
    delete_pem()
    network.delete()

The whole code is below

https://github.com/kyorohiro/advent-2019-code-server/tree/master/remote_cs02/for_aws

next time

Let's operate the created virtual instance !!

code

https://github.com/kyorohiro/advent-2019-code-server/tree/master/remote_cs02

Recommended Posts

code-server online environment (3) Launch an EC2 instance with Boto3
code-server online environment (4) Launch code-server on the EC2 instance
code-server Online environment (2) Create a virtual network with Boto3
code-server online environment (5) Launch code-server on Docker
code-server online environment (1)
code-server online environment (7) Deploy compute on git on EC2
Stop an instance with a specific tag in Boto3
Create an environment with virtualenv
code-server online environment (6) Let's automate
ruby environment construction with aws EC2
Create an AWS Cloud9 development environment on your Amazon EC2 instance
Get information about EC2 instances with arbitrary prefixes in instance names with boto
Prepare the environment of Chainer on EC2 spot instance with AWS Lambda
[Python] Building an environment with Anaconda [Mac]
Note when creating an environment with python
AWS EC2 instance launch and ssh connection
Create an add-in-enabled Excel instance with xlwings
Launch environment with LineBot + Heroku + Docker + Python
Join an online judge with Python 3.x
Build python environment with pyenv on EC2 (ubuntu)
Building an Anaconda environment for Python with pyenv
Various commands for building an environment with Apache
Creating an AWS EC2 EC2 Instance (Amazon Linux AMI) 2
Security settings required after launching an EC2 instance
Describe ec2 with boto3 and retrieve the value
Try building an environment for MayaPython with VisualStudioCode