Deploy Django on AWS with Terraform and Ansible — Part 1

Jose Guevarra
6 min readApr 1, 2021

--

Photo by Power Lai on Unsplash

In today’s infinitely scalable world, it is not enough to run just one Django server. If you are going to run one server you might as well put the infrastructure in place to run a dozen. In this tutorial, I am going to guide you thru deploying a Django site behind an Application Load Balancer(ALB) and in an AutoScaling Group(ASG) in Amazon Web Services(AWS).

Who is this tutorial intended for

If you are a web developer or aspiring DevOps engineer, you will find guide helpful in learning how to use one of the most popular Infrastructure as Code(IaC) tools, Terraform, to provision your web application infrastructure in the cloud. We will also be using Ansible to help deploy the configuration of the Linux EC2 instances. The code we will employ will give you a great playground for what Terraform and Ansible can do.

What we will have built when we are done

After we are all done with this guide we will have an load balancer passing web traffic to an AutoScaling Group of Linux EC2 Instances configured with Django Page Hit Counter app. We will have a RDS MySQL instance configured as our database. It may be straight forward to build this infrastructure by hand using the AWS Management Console but, where is the fun in that? Instead we will have Terraform provision our whole environment then have Ansible configure our Linux EC2 instances to run Django. Our EC2 Instances will be properly configured to run Nginx with UWSGI to run our Django application like many production environments. Note that this is a quick and dirty example of provisioning this web app and not entirely how you may want to do it in a production situation. At the end of this series, I will offer some ways in which to make this setup more production ready.

Our Final Form.

Prerequisites

  • Linux Environment to run scripts from
  • Terraform installed
  • Ansible installed
  • AWS account (Free Tier works fine)
  • Some understanding of Django, Nginx, UWSGI is helpful
  • Some understanding of AWS — Load Balancers, AutoScaling Groups, EC2, RDS(MySQL), security groups.

Our scripts will be handling provisioning all these things at a snap of the finger, however you may want to Google any items that you don’t have any understanding of. Also, we will be running these scrips from a Linux environment although you should be able to run them from OSX/Windows environment as well.

Setup our Accounts and Environment

We will be using Terraform to provision resources in Amazon Web Services. In order to do this, Terraform needs AWS credentials and permissions to do so. Property EC2 SSH keys will need to be created so we can use Ansible as well. It is out of the scope of this guide to setting up our environment so here is a list and some resources to help you:

1. AWS Free Tier

Terraform will be deploying to AWS as our cloud provider of choice. Setup an AWS Free Tier account. Make sure to also create an Administrator account(account with property privileges) or account that is not the “root” account in order run our Terraform scripts.

2. AWS Command Line Interface

You will want to setup the AWS CLI as Terraform uses this for access to AWS resources. Make sure to configure your default region as well.

3. AWS EC2 Keys Pairs (SSH keys)

Ansible uses SSH keys to login to Linux EC2 Instances. Terraform also uses the SSH key pair “name” to tell AWS to provision the EC2 Instances with those particular SSH keys. So make sure you have downloaded the .pem file and taken note of the SSH key pair name.

Getting the source code

To make things simple, I placed everything you need for this project in a GitHub repository, GET IT HERE. If you have your AWS CLI and SSH keys configured correctly, then it should be just a matter of reading the instructions in the README.md file and running your Terraform and Ansible scripts. You may want to do that now before I go through the scripts in more detail.

Source Code Contents:ansible/                 # Ansible playbooks
config/ # Config files to deploy
django-hitcount/ # Django app source
tf/ # Terraform scripts
README.md # Readme file
aws-asg-instances-ip.sh # Gets Public IP Addresses of EC2 Instances
django-hitcount.tar.gz # Packed Django source code

Setup secrets for Terraform

Before we execute our Terraform scripts we will want to set some variables unique to our situation. It is bad practice to hard code confidential information in code so we will be placing them into a file, tf/secret.tfvars, for Terraform to reference. In this instance, we will be setting some database credentials, AWS region, and AWS SSH key name; change these values for your situation as necessary.

db_username = “django”
db_password = “foobarbaz”
ami_key_pair_name = “my-ssh-key1”
aws_region = “us-west-1”

Now we are ready to run our Terraform script, tf/main.tf from within the tf/ directory.

terraform plan -var-file=”secret.tfvars”

If everything was setup correctly, you should see some output similar to the image below. This output basically outlines all the resources that it will create in AWS using Terraform!!! Browse through it and you will see all the things in the tf/main.cf file along with some other supplementary resources.

jose@ragnar:~/src/aws_django/tf$ terraform plan -var-file="secret.tfvars"An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:# aws_autoscaling_group.asg will be created
+ resource "aws_autoscaling_group" "asg" {
+ arn = (known after apply)
+ availability_zones = [
+ "us-west-1a",
+ "us-west-1b",
]
+ default_cooldown = (known after apply)
+ desired_capacity = (known after apply)
+ force_delete = false
+ health_check_grace_period = 300
+ health_check_type = "ELB"
+ id = (known after apply)
+ launch_configuration = (known after apply)
+ load_balancers = [
+ "terraform-elb",
]
+ max_size = 2
+ metrics_granularity = "1Minute"
+ min_size = 2
+ name = (known after apply)
+ protect_from_scale_in = false
+ service_linked_role_arn = (known after apply)
+ vpc_zone_identifier = (known after apply)
+ wait_for_capacity_timeout = "10m"
.....
+ name = "terraform-instance"
+ name_prefix = (known after apply)
+ owner_id = (known after apply)
+ revoke_rules_on_delete = false
+ vpc_id = (known after apply)
}
Plan: 8 to add, 0 to change, 0 to destroy.Changes to Outputs:
+ asg_id = (known after apply)
+ clb_dns_name = (known after apply)
+ db_dns_name = (known after apply)
------------------------------------------------------------------------Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Everything seems to be working. Now we are finally ready to actually create these resources in AWS…FOR REAL! Run the command below and then type “yes” when prompt to actually execute the command against AWS. Note: This may take several minutes to provision EC2 instances and an RDS instance.

terraform apply -var-file="secret.tfvars"

When it finally executes it will print out several values listed in the tf/output.tf file. These values will come into play when we run Ansible.

Go into the AWS Management console and then the EC2 console. You will be able to see two EC2 Linux instances. Go to the RDS console and confirm the database exists. Try logging into them using the web console or SSH. YES, They are REAL! Also, look at the Load Balancer and AutoScaling Group sections. You will see that Terraform successfully provisioned all our Django infrastructure.

Blow it Up!

The great thing about Infrastructure as Code(IaC) is that you can easily run the scripts again. Now that you have confirmed that Terraform successfully provisioned your web app infrastructure, let’s destroy all of it with one command!

terraform destroy -var-file="secret.tfvars"

After it finishes, go back to the AWS Management console and confirm that everything was deleted. Now AWS can’t charge you for any resource usage! If you want to continue playing with the setup, just run terraform apply -var-file="secret.tfvars" again.

Next Steps

In Part 1 of this guide, we got our environment setup and now have the capability to create our Django web app infrastructure by running just a few commands in Terraform. In “Deploy Django on AWS with Terraform and Ansible — Part 2”, we will have Ansible configure our EC2 Linux Instances to run our Django Page Hit Counter app.

--

--

Jose Guevarra
Jose Guevarra

Written by Jose Guevarra

I’m an aspiring DevOps engineer with interests in Data Engineering, Machine Learning, and AI.

No responses yet