Skip to content

Latest commit

 

History

History
159 lines (116 loc) · 4.06 KB

README.md

File metadata and controls

159 lines (116 loc) · 4.06 KB

proto-aws-django

Deploy a Django application to AWS with support for zero downtime rolling updates.

Requirements

  • Python >= 3.5
  • VirtualBox >= 6.0.0
  • Vagrant >= 2.2.0
  • Packer >= 1.4.0

Vagrant

Create and provision the virtual machine.

vagrant up
vagrant reload

The virtual machine copies your ~/.aws/config and ~/.aws/credentials files to the vagrant user's home folder. However you need to manually start an SSH agent and forward it to the VM if you want to be able to use your SSH key.

ssh-add
vagrant ssh -- -A

Create a python virtualenv.

virtualenv -p $(which python3) env
source env/bin/activate

Navigate to the /vagrant folder which is synchronized with the top-level project folder. Install python dependencies.

cd /vagrant
pip install -r requirements.txt

Provision

Here's what you need to do to start from scratch:

  • Locate the default VPC and Subnets or create them.
  • Locate or create a Route53 hosted zone for a top-level domain.
  • Locate or create a wildcard SSL certificate in the Certificate Manager.
  • Build the Web AMI (packer build packer/web.json).
  • Build the application (in vagrant create_build.py).
  • Set SSM parameters (see below).
  • Create the CloudFormation stack (see below).
  • Deploy the initial build (deploy_build.py).
  • Verify the application is reachable at the configured domain.

Here's how you set secret and plain-text SSM parameters:

aws ssm put-parameter --name '/Frontdesk/DatabaseMasterPassword' \
  --description 'RDS DBInstance MasterUserPassword' \
  --value 'something_secure_and_secret' \
  --type 'SecureString' \
  --tags 'Key=Project,Value=Frontdesk'

aws ssm put-parameter --name '/Frontdesk/WebImageId' \
  --description 'Web ASG AMI ID' \
  --value 'ami-ABCDWXYZ' \
  --type 'String' \
  --tags 'Key=Project,Value=Frontdesk'

Here's the SSM parameters you need to set:

  • VpcId (String) AWS VPC Id
  • PrimarySubnetId (String) AWS VPC Primary Subnet Id
  • SecondarySubnetId (String) AWS VPC Secondary Subnet Id
  • CertificateArn (String) Wildcard SSL Certificate ARN (*.example.com)
  • HostedZoneId (String) Route53 hosted zone for top-level domain
  • DomainName (String) Second level domain (i.e. demo.example.com)
  • WebImageId (String) Web ASG AMI Id (i.e. ami-ABCDWXYZ)
  • KeyName (String) SSH KeyPair Name
  • SecretKey (SecureString) Django SECRET_KEY setting
  • DatabaseMasterPassword (SecureString) Database master user password

Here's how you create the CloudFormation stack:

aws cloudformation create-stack --stack-name Frontdesk \
  --capabilities CAPABILITY_NAMED_IAM \
  --template-body file://cloudformation/frontdesk.yaml

Update Web AMI

Build a new AMI using Packer:

packer validate packer/web.json
packer build packer/web.json

Update the WebImageId parameter in SSM:

aws ssm put-parameter --name '/Frontdesk/WebImageId' \
  --value 'ami-ABCDWXYZ' \
  --type 'String' \
  --overwrite

Trigger a rolling update of web instances by updating the stack:

aws cloudformation update-stack --stack-name Frontdesk \
  --capabilities CAPABILITY_NAMED_IAM \
  --template-body file://cloudformation/frontdesk.yaml

Create Build

Update the frontdesk application and the version in setup.py to reflect the changes made. Create a build:

./create_build.py --project-path pkg/frontdesk

Deploy Build

Deploy a build:

./deploy_build.py --app-build ./frontdesk-0.1.pex

Deprovision

Generally the exact opposite of provisioning with a few extra steps:

  • Delete content of deployment bucket
  • Delete stack
  • Delete SSM parameters
  • Deregister AMIs
  • Delete AMI snapshots

References

Tools and frameworks:

AWS: