Disclaimer: If you want to finish the challenge on your own DO NOT read this post. It'll spoil the fun ;)
This is a requirement of the challenge and it was easy for me as I already obtained the AWS Certified Solutions Architect Associate Certification in December 2020 and pursued this challenge to gain hands on experience on the AWS cloud.
- Why serverless?
- Website Architecture
- Choosing a source control
- Choosing a CI/CD mechanism
- Infrastructure as code with terraform
- CI/CD for terraform
- Implementing backend with python
- CI/CD for backend
- Building the frontend
- CI/CD for frontend
The primary reasons are:
The serverless paradigm offers a way to pay only for what you use. Moreover, the developer need not provision anything beforehand, amazon takes care of that. With low costs it still offers scalability to varying workloads on demand. This makes it very suitable to experiment with cloud technologies out of an enterprise organization and also meet real world challenges. I literally pay 0$ a month for the entire website. My only cost is a custom domain (1.5$/year) and hosted zone on route53 (0.5$/month).
The only downside of it is the infrastructure gets increasingly complex and becomes difficult to manage. However, it is still growing and the future may hold something promising. There is also a possibility that it may succumb to the containerization paradigm (highly debatable).
The above architecture works as follows:
- Users request the webpages to the browser.
- The browser sends request to Route53 which resolves the DNS to reach nearest cloudfront edge location.
- CloudFront forwards the request to S3 bucket which contains the website files and retrieves its contents.
- The S3 bucket with frontend code is protected with Origin Access Identity (OAI) which prevents direct access to the bucket.
- The API Gateway forwards the request to lambda as JSON.
- Lambda identifies the type of request and performs a get/put operation on DynamoDB to store/retrieve the number of visitors.
- The visitor count is then displayed on the website.
- A git repository on Github provides code version control and CI/CD through Github actions.
- Terraform deploys the AWS infrastructure.
The version control system used for this project is github. The development workflow consists of two branches master and dev.
The continuous integration and continuous delivery (CI/CD) is achieved using github actions. It consists of yml files which are used to automate the build, test and deploy phases of the development process.
The infrastructure required to host the website on AWS is built using Terraform.
Before getting started it is important to take care of the following aspects:
- Security: Terraform needs permission to deploy infrastructure on aws. Therefore, a user is created who has access only to STS (Secure Token Service) and nothing else. A role is created which has the IAM permissions to perform actions on the required AWS services.
- Terraform State: A remote backend is configured using an s3 bucket to store the Terraform state file and dynamodb is used to store the state lock. This ensures that the infrastructure declared in the tf files and the actual infrastructure deployed is always the same.
The following infrastructure components are deployed using Terraform:
- Private S3 bucket which hosts the frontend code of website.
- A new table is created in dynamodb with on demand capacity and a primary key ID. A default item is created to store the value of the number of visitors.
- A lambda function with python runtime. The code is retrieved from s3 bucket.
- An API Gateway configured as lambda proxy is created which sends GET and POST requests to lambda in the form of JSON and the lambda function also responds in JSON.
The Terraform code must be pushed to dev. Creating a pull request results in the triggering of a github action which generates a plan and posts a comment as shown below
Merging the pull request to master applies the plan and deploys the infrastructure as shown below.
The backend code is written in python. This code is deployed to lambda through CI/CD. The backend code uses Boto3 SDK to communicate with DynamoDB. The Lambda function has an IAM Role to perform actions on DynamoDB.
Dealing with CORS: The lambda response contains the header Access-Control-Allow-Origin for * to allow cross origin requests for GET, POST and OPTIONS requests.
A github action is configured to do the following when code is pushed to /backend on the master branch:
- Run tests on the python code to report bugs.
- Zip the python code
- Upload the zip file to s3 bucket
- Update the lambda function code by retrieving the zip from the S3 bucket.
This process is shown below:
A github action is configured to do the following when code is pushed to /frontend on the master branch:
- Upload the code to S3 bucket.
- Invalidate the cloudfront cache to get the latest contents from the bucket.
This process is shown below:
It has been an amazing experience completing this challenge. I have learnt a ton from Terraform to CI/CD to AWS. It is definitely worth it for anyone who is serious about a career and cloud. Thanks to @forrestbrazeal for this amazing challenge. As for me I'm on to the next challenge, Stay tuned for another Blog post on a serverless project to automate an ETL pipeline on AWS using python.