All in One: Four ways of creating a website in AWS
Development of a website can vary according to the system requirements, and sometimes a single static page can be a solution such as running an HTML file on Apache server, whereas in some cases a complex architecture might be necessary such as websites where data is processed. If it is possible to define the correct requirements, we can claim in which direction the development will be proceeded. Before describing the missing points, allow me to show what AWS solutions are available on the market and how they can be used.
AWS offers four different ways to develop a website, as listed below, and our target in this tutorial to see how they can be utilized.
- Building a static s3 site on AWS
- Building a serverless website on AWS lambda
- Building a website on an EC2 virtual machine
- Building a website using PaaS AWS beanstalk
Building Static AWS S3 Website
AWS S3 is the most popular file storage service, and it can contain any kind of data object, this is at least what AWS claims. As long as you give enough IAM permission to your S3 Bucket, all data can be publicly accessible and reachable from all internet users, e.g. we can download the files directly from S3 and access other permitted files, etc. The same concept is applicable to a website, instead of calling a Word document or any other data type, this time we will be requesting an HTML page.
The easiest way to do this is to create a S3 with the public access and upload the website folder in it. Below we create a bucket with the name “singularitywebsite” and turn of Block all public access, so that this bucket can be accessed by all people.
After the bucket creation, in the bucket under the properties static website hosting
will be edited.
As seen below, index document and error document are defined. In this example, error.html will not be added.
A bucket policy is a must and define how to access the bucket with which permission. In this case, it is enough for us to get object, therefore in teh action field s3:GetObject
is added. This permission is valid for all data under the singularitywebsite
folder.
After the completion of the bucket policy creation, a simple index.html
file can be uploaded as below.
In order to access the web page, as highlighted in the following figure, the object URL is the URL address of the static webpage.
Once this URL address is called, we see the content of the index.html.
Improving Website Performance via S3+CloudFront
As the content is static, AWS has a nice service called CloudFront based on content-delivery-network concept that allows us to serve a website near to the end user by caching the website content on the edge servers. This would improve the performance of the webpage and reduce the network data traffic. This article, deploying a static website using AWS s3 and CloudFront, gives us enough detailed information about its usage.
Building Serverless Website on AWS Lambda
AWS lambda is designed to define a function, sometimes it is called also FaaS (Function as a Service), and it plays a crucial role for the AWS serveless architecture. Designing an AWS lambda as a website or a rest interface can be established through an AWS API Gateway. In this section, there is two different way to create a serverless website on AWS lambda, either we will create an API Gateway and Lambda manually, or we will use the facility of Cloud9 environment. Once the code is ready and tested, it will be deployed directly on the AWS services. We prefer first the manual approach, i.e. create AWS lambda, add the API Gateway trigger.
We create below a function called returnhello
and the runtime is python3.8
. The rest configuration is untouched and just create it.
AWS lambda is created, and simple code should be automatically generated for us, which returns Hello from Lambda!
.
To make this lambda function accessible, it should be connected to an API Gateway, which is doable by clicking Add trigger
the button shown below.
Once the related button is clicked, we will be navigated to the trigger configuration page, and API Gateway should be selected.
During the API GW configuration, we will keep it as simple as possible, and the final configuration should look like below
And this trigger will be listed under the Configuration/Triggers
in AWS lambda as seen below
whenever we click the API endpoint depicted in the figure above, it will call the lambda and lambda will return the following message.
And the final visualization of the lambda from the function view
Notice that all these steps can be also done in AWS Cloud9 environment as mentioned before. The difference is, the manual creation of API gateway and many inter-steps will be performed by Cloud9 itself, which eases the development.
Building Website on EC2 Virtual Machine
We proceed one step further and increase our control level on the system, which might be a good or bad sign. In this part, we develop an HTTP based web server running on an EC2 default and spot instance. Please remember that EC2 has different instance types, and spot instance is the cheapest one due to its underlying concept. The following steps will be applied:
- Create an EC2 instance and PEM key that allow accessing to VM
- Create security group that allows HTTP (8080) port
- Accessing EC2 VM using PEM key
- Developing a Python App
Create an EC2 instance and PEM key that allow accessing to VM
What is needed is to create an EC2 VM and generate a PEM key that would give access to it. In the following figure, only the name is put, the rest is kept the same.
Instance type is selected for free version, and in the network settings SSH and HTTP are activated.
Key pair creation is shown as below, which is pretty simple, just a name of the key pair is enough.
After performing all these steps, our EC2 VM is up and running as shown in the instances page.
Create security group that allows HTTP (8080) port
All network configurations are default provided by AWS, however, we need to be sure the web page to be configured on this EC2 can be reachable or not. Especially, if another port is selected such as {IP}:8080 for the test purposes, this port number should be added to the security groups. In this example, we add a custom TCP
with 8080
port for all IP network. If we do not add it, most probably your web page will not be accessible over the URL address.
Accessing EC2 VM using PEM key
In the previous state we generated a PEM key pair, now our intention is to use it and connect to the instance on the terminal. One of the easiest ways is to connect via SSH client. By clicking connect
under Actions and then selecting SSH Client tab, give insights how to perform these steps:
Based on the config above, the following command are executed to log in the EC2 instance.
chmod 400 ec2-tutorial-key.cerssh -i "ec2-tutorial-key.cer" ec2-user@ec2-34-224-27-214.compute-1.amazonaws.com
The result of these commands ends up with the following figure, we are now on EC2 instance.
Developing a Python App
The easiest way to initiate a web server is to utilize HTTP Apache server, however, a simple flask python app can be also tested. To perform it, we need to install some python packages:
- python-pip
- flask
The actual python version on the platform is 2.7.18 as shown below, however, for our example this is also enough
# install python-pip and flask
sudo yum install python-pip
pip install flask# create a simple python file for flask
touch app.py # to edit it, call nano or another editor
nano app.py
Paste the following code in the app.py
file:
from flask import Flaskapp = Flask(__name__)@app.route("/")
def hello_world():
return "<p>Hello, World!</p>"
To run the flask application, you can simply call the command below on the EC2:
flask run --host=0.0.0.0 --port=8080
The result on the EC2 console:
The last point is indeed just to use the Public IPv4 DNS
address, which is available under the instance details:
By adding the port
number, in case the following URL address is called, the hello world
page will be reachable.
http://ec2-34-224-27-214.compute-1.amazonaws.com:8080/
Building Website using PaaS AWS Beanstalk
AWS describes “Elastic Beanstalk is a service for deploying and scaling web applications and services. Upload your code and Elastic Beanstalk automatically handles the deployment — from capacity provisioning, load balancing, and auto-scaling to application health monitoring.”
In other words, as a developer we need to just write the code and the rest operations, deployment, infrastructure provisioning, load balancer, etc. will be ready to execute the code. Similar approach exists also in other cloud platforms such as GCP has Google App Engine, and Azure App Services. In short, these platforms abstract all underlying components, and allow us to focus on our business web application. In order to use EB, we will perform the following steps:
- Prepare Cloud9 environment and Install Elastic Beanstalk Client
- Creating a Flask Python App
- Defining IAM roles for Elastic Beanstalk
- Deploy Python App to Elastic Beanstalk and Testing
- Cleaning Elastic Beanstalk Environment
- (Optional) Analyzing Errors in Logs
The following tutorial is mainly constructed on the links: eb-cli-setup, eb-cli-install, python-flask-app.
Prepare Cloud9 environment and Install Elastic Beanstalk Client
Using EB on Cloud9 reduces many steps to perform during the development process, therfore Cloud9 is our development enviroment in this tutorial. If you don’t know how to create it, you can look at this Cloud9 tutorial. The next step is to install elastic beanstalk directly on Cloud9 environment. There are three steps to perform, first clone the gitlab project as below:
git clone https://github.com/aws/aws-elastic-beanstalk-cli-setup.git
execute the ebcli_installer.py
python ./aws-elastic-beanstalk-cli-setup/scripts/ebcli_installer.py
and finally, eb
command should be executable, therefore it has to be added to the PATH as below.
echo 'export PATH="/home/ec2-user/.ebcli-virtual-env/executables:$PATH"' >> ~/.bash_profile && source ~/.bash_profile
once you are done, eb --help
command should result as seen below:
Creating a Flask Python App
The next step after the installation of elastic beanstalk is to implement a flask python project to be deployed. We create a folder named eb-app
on the console, and inside folder create and activate the virtual environment as below:
mkdir eb-app
cd eb-app
python3 -m venv venv
source venv/bin/activate
After the virtual environment activation, the necessary libraries are installed:
pip install flask==2.2.2
Many other application is also installed while installing Flask application, via pip freeze
we can list those packages and save in the requirement file.
pip freeze > requirements.txt
Now, the environment is ready, and we create and application.py
file that will include the all logic of the web application. We use the same application content from this link, and paste in the code below in the file.
from flask import Flask# print a nice greeting.
def say_hello(username = "World"):
return '<p>Hello %s!</p>\n' % username# some bits of text for the page.
header_text = '''
<html>\n<head> <title>EB Flask Test</title> </head>\n<body>'''
instructions = '''
<p><em>Hint</em>: This is a RESTful web service! Append a username
to the URL (for example: <code>/Thelonious</code>) to say hello to
someone specific.</p>\n'''
home_link = '<p><a href="/">Back</a></p>\n'
footer_text = '</body>\n</html>'application = Flask(__name__)application.add_url_rule('/', 'index', (lambda: header_text +
say_hello() + instructions + footer_text))application.add_url_rule('/<username>', 'hello', (lambda username:
header_text + say_hello(username) + home_link + footer_text))# run the app.
if __name__ == "__main__":
# Setting debug to True enables debug output. This line should be
# removed before deploying a production app.
application.debug = True
application.run()
In the end, you will see the following picture as a result. Notice that the name of the file and the flask application is same, so that elastic beanstalk can start the application. Using a different name will result in ModuleNotFound
failure in the logs, which will be also shown later in this tutorial.
To prevent any side effect of the virtual enviroment codes on the elastic beanstalk, we should hinder importing venv
folder in the EB environment. Therefore we create a .ebignore
file and add venv
folder name as below:
touch .ebignore
vi .ebignore
venv
In the absence of .ebignore
most probably .gitignore
file will be considered by EB, however, this is not testet.
Defining IAM roles for Elastic Beanstalk
This is probably most critical part and without the required IAM permissions, the code deployment will not be succesfull, which is proven with many deployment trials. Why these IAM permissions are required, because some of them are required for starting operations from Cloud9, others are necessary to be able to realize the deployment. Two necessary roles aws-elasticbeanstalk-ec2-role
and aws-elasticbeanstalk-service-role
should be seperatly created and the following picture ought to be seen in the final IAM roles page.
First create a role by selecting the configuration below for aws-elasticbeanstalk-ec2-role
For aws-elasticbeanstalk-ec2-role
role is the required policies are depicted in the picture.
For aws-elasticbeanstalk-service-role
role, the required policies are depicted in the picture.
An unsuccessfull configuration, you may see the following warnings.
WARNING: Insufficient IAM privileges. Unable to determine if instance profile 'aws-elasticbeanstalk-ec2-role' exists, assuming that it exists.
this can be also displayed directly under the application environment in the elastic beanstalk.
Deploying Python App to Elastic Beanstalk and Testing
Once we are sure about the IAM roles and policies, it is time to deploy the code on Elastic Beanstalk environment. First the environment along with the application name, python version and region is initiated and then the environment is created as seen below:
eb init -p python-3.7 flask-eb-app --region us-east-1
eb create flask-eb-app-env
A successfull installation will be ending up with the message Successfuly launched environment:...
as shown in the following image.
Behind the scene of this deployment, as detailed above, all required componets such as security groups. load balancer, EC2 instances, Cloud Watch alamrs and many other things are step by step are created.
To be 100% sure, the health of the application environment should be dsplayed as OK
as depicted below and the URL
address should reflect the python application.
Once the URL
address is clicked, it is cleary seen below, the flask python application is running in the elastic beanstalk environment.
Cleaning Elastic Beanstalk Environment
ev terminate flask-eb-app-env
Elastic Beanstalk is not a cheap service, therefore it is recommeded to shut down if it is not needed anymore. The command below helps terminating the environment, and deletes all related AWS resources created during the deployment as given below.
Analyzing Errors in Logs
It might be not easy to first understand and then find the potential issues during the deployment process. Elastic Beanstalk aids us through the following interface, where all details such as health of the application, logs, monitoring, alamrs, etc. are provided.
For example, one of my error discovery was related to the python module name and I could discover it by downloading logs under the Logs
section in the figure above and opening the message
file in the following image.
As highligted below, elastic beanstalk cannot find the module name in this case. All occured errors can be easily seen in detail.
Summary
In this tutorial, our intention is to discover different ways of the web application development via AWS services starting from the most easy one to the last most complex one. I hope, some of them can be helpful and faciliate to understand various AWS concepts.
References
- https://github.com/aws/aws-elastic-beanstalk-cli-setup
- https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/eb-cli3-install.html
- https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create-deploy-python-flask.html
- https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/eb-cli-troubleshooting.html
- https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/iam-servicerole.html
- https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/iam-instanceprofile.html