Skip to content

seanlwatson/AWS_CLI

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 

Repository files navigation

Deploying a web application with AWS CLI

Install AWS CLI

Install the AWS CLI, see AWS CLI and [Installing the AWS Command Line Interface]

sean@vubuntu:~$ sudo apt install awscli -y
sean@vubuntu:~$ aws --version
aws-cli/1.14.44 Python/3.6.6 Linux/4.15.0-36-generic botocore/1.8.48

Access keys consist of an access key ID and secret access key, which are used to sign programmatic requests that you make to AWS. The aws configure command will prompt you for four pieces of information. AWS Access Key ID and AWS Secret Access Key are your programatic account credentials. Specify an AWS region and are the same names you see in the mgt. console. The default output can be either json, text, or table, where the default format is json.

sean@vubuntu:~$ aws configure
AWS Access Key ID [None]: 
AWS Secret Access Key [None]: 
Default region name [None]: us-west-2
Default output format [None]: json

Verify operation by listing all IAM users.

sean@vubuntu:~$ aws iam list-users
{
    "Users": [
        {
            "Path": "/",
            "UserName": "sean",
            "UserId": "AIDAJODWTO2Q2GNNXKUMA",
            "Arn": "arn:aws:iam::404297683117:user/sean",
            "CreateDate": "2018-05-08T00:38:00Z",
            "PasswordLastUsed": "2018-09-25T01:22:12Z"
        }
    ]
}

In order to launch a virtual server use the aws ec2 run-instances with the following parameters:

  • AMI ID
  • Instance type
  • Security Group
  • SSH key-pair

AMI

An Amazon Machine Image (AMI) is a package that contains the OS and additional software required to start the system.

  1. Use the aws ec2 describe-images command along with filter options to only include the AMI wanted. In the filter use x84_64 bits version to match the architecture. The virtualization type will be HVM. There are two types of AMI virtualization: Para-Virtual (PV) and Hardware Virtual Machine (HVM). The main difference between them is the boot process and how they take advantage of special hardware extensions like CPU, network, and storage for better performance. The GP2 is for General Purpose SSD (gp2), which is a type of EBS (Elastic Block Store) Volume.
sean@vubuntu:~$ aws ec2 describe-images --filters "Name=description,Values=Amazon Linux AMI * x86_64 HVM GP2" --query 'Images[*].[CreationDate, Description, ImageId]' --output text | sort -k 1 | tail
2018-01-08T18:43:49.000Z	Amazon Linux AMI 2017.09.1.20180108 x86_64 HVM GP2	ami-32cf7b4a
2018-01-10T18:59:11.000Z	Amazon Linux AMI 2017.09.1.20180108 x86_64 HVM GP2	ami-2a853252
2018-01-15T19:13:58.000Z	Amazon Linux AMI 2017.09.1.20180115 x86_64 HVM GP2	ami-f2d3638a
2018-01-18T23:11:52.000Z	Amazon Linux AMI 2017.09.1.20171120 x86_64 HVM GP2	ami-e6f84a9e
2018-03-07T06:59:59.000Z	Amazon Linux AMI 2017.09.1.20180307 x86_64 HVM GP2	ami-d874e0a0
2018-03-07T07:11:48.000Z	Amazon Linux AMI 2017.09.1-testlongids.20180307 x86_64 HVM GP2	ami-0163da89c9a854198
2018-04-13T00:32:56.000Z	Amazon Linux AMI 2018.03.0.20180412 x86_64 HVM GP2	ami-6b8cef13
2018-05-08T18:06:57.000Z	Amazon Linux AMI 2018.03.0.20180508 x86_64 HVM GP2	ami-e251209a
2018-06-22T22:27:00.000Z	Amazon Linux AMI 2018.03.0.20180622 x86_64 HVM GP2	ami-0ad99772
2018-08-11T02:29:45.000Z	Amazon Linux AMI 2018.03.0.20180811 x86_64 HVM GP2	ami-a0cfeed8

--filter allows you to filter the output based on the JSON data which represented in data name/value pairs.

sean@vubuntu:~$ aws ec2 describe-images --filters "Name=image-id,Values=ami-a0cfeed8"
{
    "Images": [
        {
            "Architecture": "x86_64",
            "CreationDate": "2018-08-11T02:29:45.000Z",
            "ImageId": "ami-a0cfeed8",
            "ImageLocation": "amazon/amzn-ami-hvm-2018.03.0.20180811-x86_64-gp2",
            "ImageType": "machine",
            "Public": true,
            "OwnerId": "137112412989",
            "State": "available",
            "BlockDeviceMappings": [
                {
                    "DeviceName": "/dev/xvda",
                    "Ebs": {
                        "Encrypted": false,
                        "DeleteOnTermination": true,
                        "SnapshotId": "snap-0b9ac5da0147e5eb2",
                        "VolumeSize": 8,
                        "VolumeType": "gp2"
                    }
                }
            ],
            "Description": "Amazon Linux AMI 2018.03.0.20180811 x86_64 HVM GP2",
            "EnaSupport": true,
            "Hypervisor": "xen",
            "ImageOwnerAlias": "amazon",
            "Name": "amzn-ami-hvm-2018.03.0.20180811-x86_64-gp2",
            "RootDeviceName": "/dev/xvda",
            "RootDeviceType": "ebs",
            "SriovNetSupport": "simple",
            "VirtualizationType": "hvm"
        }
    ]
}

tail is a command-line utility for outputting the last part of files given to it via standard input and writes results to standard output. By default tail returns the last ten lines of each file that it is given.

sort is a command-line utility for sorting with the -k 1 option sorts the data fields using the 1st column number (the newest being on the bottom).

--query supplements commands to filter only information wanted and uses the JMESPath query language for JSON. The Images[*] uses an Index Expression, which is used to access elements in a list by indexing - in this case all Images. .[CreationDate, Description, ImageId] is part of a subexpression, which is a combination of two expressions separated by the . char. The brackets [ ...] is a MultiSelect List, which extracts a subset of elements separated by a , from a JSON hash. See JMESPath for more information.

Instance type

Instance type comprise varying combinations of CPU, memory, storage, and networking capacity and each instance type includes one or more instance sizes.

The t2.micro includes the following:

Model vCPU CPU Credits / hour Mem (GiB) Storage
t2.micro 1 6 1 EBS-Only

Security Group

Security Groups act as a virtual firewall (stateful) for your instance to control inbound and outbound traffic. The small web application will run on TCP/3000 and we want to support SSH TCP/22. Security Groups are tied to subnets within a Virtual Private Cloud (VPC).

  1. Run the following command to find the default VPC ID.
sean@vubuntu:~$ aws ec2 describe-vpcs
{
    "Vpcs": [
        {
            "CidrBlock": "172.31.0.0/16",
            "DhcpOptionsId": "dopt-b0dbadc9",
            "State": "available",
            "VpcId": "vpc-b3b5feca",
            "InstanceTenancy": "default",
            "CidrBlockAssociationSet": [
                {
                    "AssociationId": "vpc-cidr-assoc-a7c0ddcc",
                    "CidrBlock": "172.31.0.0/16",
                    "CidrBlockState": {
                        "State": "associated"
                    }
                }
            ],
            "IsDefault": true,
            "Tags": [
                {
                    "Key": "Name",
                    "Value": "Default VPC"
                }
            ]
        }
    ]
}
  1. Create a Security Group for the default VPC ID.
sean@vubuntu:~$ aws ec2 create-security-group --group-name HelloWorld --description "Hello World Demo" --vpc-id vpc-b3b5feca
{
    "GroupId": "sg-0e2799ad580df135d"
}
  1. By default Security Groups allow all outbound traffic from the instance but deny all inbound traffic. Open up SSH TCP/22 & TCP/3000 for inbound connectivity.

:::info You can get your public IP address with the following command:

sean@vubuntu:~$ dig +short myip.opendns.com @resolver1.opendns.com
75.166.145.22

Or install curl and try this:

sean@vubuntu:~$ sudo apt install curl -y
sean@vubuntu:~$ curl https://api.ipify.org
75.166.145.22

:::

sean@vubuntu:~$ aws ec2 authorize-security-group-ingress --group-name HelloWorld --protocol tcp --port 22 --cidr 75.166.145.22/32
sean@vubuntu:~$ aws ec2 authorize-security-group-ingress --group-name HelloWorld --protocol tcp --port 3000 --cidr 75.166.145.22/32

  1. Verify the Security Group.
sean@vubuntu:~$ aws ec2 describe-security-groups --group-names HelloWorld --output table
----------------------------------------------------------------------------------------------
|                                   DescribeSecurityGroups                                   |
+--------------------------------------------------------------------------------------------+
||                                      SecurityGroups                                      ||
|+------------------+------------------------+-------------+---------------+----------------+|
||    Description   |        GroupId         |  GroupName  |    OwnerId    |     VpcId      ||
|+------------------+------------------------+-------------+---------------+----------------+|
||  Hello World Demo|  sg-0e2799ad580df135d  |  HelloWorld |  404297683117 |  vpc-b3b5feca  ||
|+------------------+------------------------+-------------+---------------+----------------+|
|||                                      IpPermissions                                     |||
||+----------------------------+----------------------------------+------------------------+||
|||          FromPort          |           IpProtocol             |        ToPort          |||
||+----------------------------+----------------------------------+------------------------+||
|||  22                        |  tcp                             |  22                    |||
||+----------------------------+----------------------------------+------------------------+||
||||                                       IpRanges                                       ||||
|||+--------------------------------------------------------------------------------------+|||
||||                                        CidrIp                                        ||||
|||+--------------------------------------------------------------------------------------+|||
||||  75.166.145.22/32                                                                    ||||
|||+--------------------------------------------------------------------------------------+|||
|||                                      IpPermissions                                     |||
||+----------------------------+----------------------------------+------------------------+||
|||          FromPort          |           IpProtocol             |        ToPort          |||
||+----------------------------+----------------------------------+------------------------+||
|||  3000                      |  tcp                             |  3000                  |||
||+----------------------------+----------------------------------+------------------------+||
||||                                       IpRanges                                       ||||
|||+--------------------------------------------------------------------------------------+|||
||||                                        CidrIp                                        ||||
|||+--------------------------------------------------------------------------------------+|||
||||  75.166.145.22/32                                                                    ||||
|||+--------------------------------------------------------------------------------------+|||
|||                                   IpPermissionsEgress                                  |||
||+----------------------------------------------------------------------------------------+||
|||                                       IpProtocol                                       |||
||+----------------------------------------------------------------------------------------+||
|||  -1                                                                                    |||
||+----------------------------------------------------------------------------------------+||
||||                                       IpRanges                                       ||||
|||+--------------------------------------------------------------------------------------+|||
||||                                        CidrIp                                        ||||
|||+--------------------------------------------------------------------------------------+|||
||||  0.0.0.0/0                                                                           ||||
|||+--------------------------------------------------------------------------------------+|||

Create SSH key

  1. Create an SSH key pair that will be used to access the EC2 instance.
sean@vubuntu:~$ aws ec2 create-key-pair --key-name EffectiveDevOpsAWS
{
    "KeyFingerprint": "99:ee:44:6e:9b:3f:5c:bc:3e:ab:9d:09:d5:c3:6b:28:dc:56:0e:07",
    "KeyMaterial": "-----BEGIN RSA PRIVATE KEY-----\n<...snippped...>\n-----END RSA PRIVATE KEY-----",
    "KeyName": "EffectiveDevOpsAWS"
}

  1. The key is located in the "KeyMaterial": section of the JSON output. Use the echo command to output it to a PEM file.
sean@vubuntu:~$ echo -e "-----BEGIN RSA PRIVATE KEY-----\n<...snippped...>\n-----END RSA PRIVATE KEY-----" > ~/.ssh/EffectiveDevOpsAWS.pem
sean@vubuntu:~$ chmod 600 ~/.ssh/EffectiveDevOpsAWS.pem

Verify the fingerprint is the same as that displayed by the EC2 API. The command essentially just converts the private key from PEM (text) to DER (binary) format.

sean@vubuntu:~$ openssl pkcs8 -in ~/.ssh/EffectiveDevOpsAWS.pem -nocrypt -topk8 -outform DER | openssl sha1 -c
(stdin)= 99:ee:44:6e:9b:3f:5c:bc:3e:ab:9d:09:d5:c3:6b:28:dc:56:0e:07

Launch EC2 instance

  1. Launch EC2 Instance with the following information:
  • AMI ID: ami-a0cfeed8
  • Instance type: t2.micro
  • Security Group: sg-077a84bbc6f365e4c
  • SSH key-pair: EffectiveDevOps
sean@vubuntu:~$ aws ec2 run-instances --instance-type t2.micro --key-name EffectiveDevOpsAWS --security-group-ids sg-0e2799ad580df135d --image-id ami-a0cfeed8
{
    "Groups": [],
    "Instances": [
        {
            "AmiLaunchIndex": 0,
            "ImageId": "ami-a0cfeed8",
            "InstanceId": "i-079f9ae01c99115a7",
            "InstanceType": "t2.micro",
            "KeyName": "EffectiveDevOpsAWS",
            "LaunchTime": "2018-10-17T22:31:44.000Z",
            "Monitoring": {
                "State": "disabled"
            },
            "Placement": {
                "AvailabilityZone": "us-west-2a",
                "GroupName": "",
                "Tenancy": "default"
            },
            "PrivateDnsName": "ip-172-31-22-252.us-west-2.compute.internal",
            "PrivateIpAddress": "172.31.22.252",
            "ProductCodes": [],
            "PublicDnsName": "",
            "State": {
                "Code": 0,
                "Name": "pending"
            },
            "StateTransitionReason": "",
            "SubnetId": "subnet-718a3a08",
            "VpcId": "vpc-b3b5feca",
            "Architecture": "x86_64",
            "BlockDeviceMappings": [],
            "ClientToken": "",
            "EbsOptimized": false,
            "Hypervisor": "xen",
            "NetworkInterfaces": [
                {
                    "Attachment": {
                        "AttachTime": "2018-10-17T22:31:44.000Z",
                        "AttachmentId": "eni-attach-063a5cc7d51ce8a90",
                        "DeleteOnTermination": true,
                        "DeviceIndex": 0,
                        "Status": "attaching"
                    },
                    "Description": "",
                    "Groups": [
                        {
                            "GroupName": "HelloWorld",
                            "GroupId": "sg-0e2799ad580df135d"
                        }
                    ],
                    "Ipv6Addresses": [],
                    "MacAddress": "02:38:b1:9e:31:4a",
                    "NetworkInterfaceId": "eni-014e58c52f13fcb97",
                    "OwnerId": "404297683117",
                    "PrivateDnsName": "ip-172-31-22-252.us-west-2.compute.internal",
                    "PrivateIpAddress": "172.31.22.252",
                    "PrivateIpAddresses": [
                        {
                            "Primary": true,
                            "PrivateDnsName": "ip-172-31-22-252.us-west-2.compute.internal",
                            "PrivateIpAddress": "172.31.22.252"
                        }
                    ],
                    "SourceDestCheck": true,
                    "Status": "in-use",
                    "SubnetId": "subnet-718a3a08",
                    "VpcId": "vpc-b3b5feca"
                }
            ],
            "RootDeviceName": "/dev/xvda",
            "RootDeviceType": "ebs",
            "SecurityGroups": [
                {
                    "GroupName": "HelloWorld",
                    "GroupId": "sg-0e2799ad580df135d"
                }
            ],
            "SourceDestCheck": true,
            "StateReason": {
                "Code": "pending",
                "Message": "pending"
            },
            "VirtualizationType": "hvm"
        }
    ],
    "OwnerId": "404297683117",
    "ReservationId": "r-06b2c73070b3687b7"
}
  1. Check the status by getting the InstanceID from the output of the aws ec2 run-instances command. The instance is ready when the Status under SystemStatus changes from initializing to ok.
sean@vubuntu:~$ aws ec2 describe-instance-status --instance-ids i-079f9ae01c99115a7
{
    "InstanceStatuses": [
        {
            "AvailabilityZone": "us-west-2a",
            "InstanceId": "i-079f9ae01c99115a7",
            "InstanceState": {
                "Code": 16,
                "Name": "running"
            },
            "InstanceStatus": {
                "Details": [
                    {
                        "Name": "reachability",
                        "Status": "initializing"
                    }
                ],
                "Status": "initializing"
            },
            "SystemStatus": {
                "Details": [
                    {
                        "Name": "reachability",
                        "Status": "initializing"
                    }
                ],
                "Status": "initializing"
            }
        }
    ]
}

sean@vubuntu:~$ aws ec2 describe-instance-status --instance-ids i-079f9ae01c99115a7 --query "InstanceStatuses[*].SystemStatus.Status"
[
    "ok"
]

Connect to EC2 instance via SSH

  1. Find the DNS name of the EC2 instance.
sean@vubuntu:~$ aws ec2 describe-instances --instance-ids i-079f9ae01c99115a7 --query "Reservations[*].Instances[*].PublicDnsName"
[
    [
        "ec2-54-189-165-229.us-west-2.compute.amazonaws.com"
    ]
]
  1. SSH using the default user account for Amazon Linux is ec2-user.
sean@vubuntu:~$ ssh -i ~/.ssh/EffectiveDevOpsAWS.pem ec2-user@ec2-54-189-165-229.us-west-2.compute.amazonaws.com

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2018.03-release-notes/
11 package(s) needed for security, out of 20 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-172-31-22-252 ~]$
[ec2-user@ip-172-31-22-252 ~]$ ec2-metadata --all
ami-id: ami-a0cfeed8
ami-launch-index: 0
ami-manifest-path: (unknown)
ancestor-ami-ids: not available
block-device-mapping: 
	 ami: /dev/xvda
	 root: /dev/xvda
instance-id: i-079f9ae01c99115a7
instance-type: t2.micro
local-hostname: ip-172-31-22-252.us-west-2.compute.internal
local-ipv4: 172.31.22.252
kernel-id: not available
placement: us-west-2a
product-codes: not available
public-hostname: ec2-54-189-165-229.us-west-2.compute.amazonaws.com
public-ipv4: 54.189.165.229
public-keys: 
keyname:EffectiveDevOpsAWS
index:0
format:openssh-key
key:(begins from next line)
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCamr79lrbfZBhAHFkqTEgJ7GP6OcCYG0AaojxfBbg4MwNalQ0lGE6k7euFZ/OReIfvFlvthNyIF3gqZnzFsUOkxbHeXVFFGBra3DAEtrbd9xMJGjH47vc6ytiL2+8IgAaIfUa3ec9N1IsFQwrLX/vs3tM/SI5Ld8APkkFChoQbXQPDS4k3AE8wyrSn83Q0+aOAWNXGUdkAWsagMrLhmCSt31AhGdH2hGJE6XZp+XZxNu1c9ThpnTHxvXCznODeonuAKC/acQPigO5fw7DFWITw6oLx5mZfiLNd7U5vyJVQ1J9HzxoMLfA52CcwaJyGLG7wM63BnuHymCwz02YKaK3x EffectiveDevOpsAWS
ramdisk-id: not available
reservation-id: r-06b2c73070b3687b7
security-groups: HelloWorld
user-data: not available

Install node.js

  1. Install node.js. Amazon Linux is based on Red Hat Enterprise Linux (RHEL) and uses yum utility to manage and install packages. The OS comes with Extra Packages for Enterprise Linux (EPEL) pre-configured in it.
[ec2-user@ip-172-31-22-252 ~]$ sudo yum install --enablerepo=epel -y nodejs
[ec2-user@ip-172-31-22-252 ~]$ node -v
v0.10.48

Run node.js Hello World

  1. Download the helloworld code from github.
[ec2-user@ip-172-31-22-252 ~]$ wget http://bit.ly/2vESNuc -O /home/ec2-user/helloworld.js
var http = require("http")

http.createServer(function (request, response) {

   // Send the HTTP header
   // HTTP Status: 200 : OK
   // Content Type: text/plain
   response.writeHead(200, {'Content-Type': 'text/plain'})

   // Send the response body as "Hello World"
   response.end('Hello World\n')
}).listen(3000)

// Console will print the message
console.log('Server running')
  1. Run the code.
[ec2-user@ip-172-31-22-252 ~]$ node helloworld.js Server running
Server running
  1. Navigate to http://ec2-54-189-165-229.us-west-2.compute.amazonaws.com:3000.

  1. Stop execution of helloworld with Ctrl+C in the terminal window.
^C[ec2-user@ip-172-31-22-252 ~]$ 

Turn code into a service using upstart

  1. Turn simple code into a service using upstart. Amazon Linux (unlike RHEL) comes with a system called upstart and provides additional features that System-V boot-up scripts don’t have, such as the ability to re-spawn a process that died unexpectedly. Download the helloworld.conf code from github and add the following code to /etc/init/ on the EC2 instance.
[ec2-user@ip-172-31-22-252 ~]$ sudo wget http://bit.ly/2vVvT18 -O /etc/init/helloworld.conf
description "Hello world Deamon"

# Start when the system is ready to do networking.
start on started elastic-network-interfaces

# Stop when the system is on its way down.
stop on shutdown

respawn
script
    exec su --session-command="/usr/bin/node /home/ec2-user/helloworld.js" ec2-user
end script  
  1. Start the application.
[ec2-user@ip-172-31-22-252 ~]$ sudo start helloworld
helloworld start/running, process 2856
  1. Service should still work at: http://ec2-54-189-165-229.us-west-2.compute.amazonaws.com:3000.

Terminate EC2 instance

  1. Perform a clean shutdown of Hello World service using the stop command, then exit the virtual server.
[ec2-user@ip-172-31-22-252 ~]$ sudo stop helloworld
helloworld stop/waiting
[ec2-user@ip-172-31-22-252 ~]$ ec2-metadata --instance-id
instance-id: i-079f9ae01c99115a7
[ec2-user@ip-172-31-22-252 ~]$ exit
logout
Connection to ec2-54-189-165-229.us-west-2.compute.amazonaws.com closed.
  1. Terminate the EC2 instance.
sean@vubuntu:~$ aws ec2 terminate-instances --instance-ids i-079f9ae01c99115a7
{
    "TerminatingInstances": [
        {
            "CurrentState": {
                "Code": 32,
                "Name": "shutting-down"
            },
            "InstanceId": "i-079f9ae01c99115a7",
            "PreviousState": {
                "Code": 16,
                "Name": "running"
            }
        }
    ]
}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published