Deploy a Django application to AWS with support for zero downtime rolling updates.
- Python >= 3.5
- VirtualBox >= 6.0.0
- Vagrant >= 2.2.0
- Packer >= 1.4.0
Create and provision the virtual machine.
vagrant up
vagrant reloadThe 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 -- -ACreate a python virtualenv.
virtualenv -p $(which python3) env
source env/bin/activateNavigate to the /vagrant folder which is synchronized with the top-level
project folder. Install python dependencies.
cd /vagrant
pip install -r requirements.txtHere'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 IdPrimarySubnetId(String) AWS VPC Primary Subnet IdSecondarySubnetId(String) AWS VPC Secondary Subnet IdCertificateArn(String) Wildcard SSL Certificate ARN (*.example.com)HostedZoneId(String) Route53 hosted zone for top-level domainDomainName(String) Second level domain (i.e.demo.example.com)WebImageId(String) Web ASG AMI Id (i.e.ami-ABCDWXYZ)KeyName(String) SSH KeyPair NameSecretKey(SecureString) DjangoSECRET_KEYsettingDatabaseMasterPassword(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.yamlBuild a new AMI using Packer:
packer validate packer/web.json
packer build packer/web.jsonUpdate the WebImageId parameter in SSM:
aws ssm put-parameter --name '/Frontdesk/WebImageId' \
--value 'ami-ABCDWXYZ' \
--type 'String' \
--overwriteTrigger 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.yamlUpdate the frontdesk application and the version in setup.py to reflect the
changes made. Create a build:
./create_build.py --project-path pkg/frontdeskDeploy a build:
./deploy_build.py --app-build ./frontdesk-0.1.pexGenerally 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
Tools and frameworks:
AWS: