Deploy a Serverless WSGI App using Zappa, CloudFront, RDS, and VPC
Brian Jinwright, Senior Software Engineer
MetaMetrics Inc.
@brianjinwright
Brian Jinwright (aka Young Python Stacks)
What is Serverless?
TLDR; Refers to using a Function as a Service (FaaS) like AWS’ Lambda offering to handle the bulk of the compute needs for your application. Also, it can be described as using a FaaS in conjunction with other services like API Gateway, SNS, and S3.
Sexy Advantages:
What is WSGI?
WSGI is the Web Server Gateway Interface. It is a Python specification that describes how a web server communicates with web applications, and how web applications can be chained together to process one request.��WSGI is a Python standard described in detail in PEP 3333.
Let’s Get Started
AWS Steps
These steps are AWS focused and I am only adding them to the slides so you know what happens. I recommend that you write a CloudFormation template (use Troposphere) to automate these tasks for future deployments.
Troposphere (https://github.com/cloudtools/troposphere)
You should only have to complete this stage once even if you create a CloudFormation template in the future. We are creating one bucket for Zappa to store our code when deploying and another to store static files (css, images, and js).
Note: By default Zappa will only store your code in the function bucket briefly while deploying (zappa deploy) or updating (zappa update) the Lambda function
2. Configure your VPC
Maybe your app doesn't need a VPC. I personally believe if you are running a database that uses RDS and ElastiCache you need a VPC. Next are a list of things I recommend to get a Zappa powered app working with VPC, RDS, and Elasticache.
2a. Create Public and Private Subnets
Create at least two public and private subnets in different availability zones.
2b. Create a NAT Gateway
This NAT Gateway will enable your Lambda functions in a private subnet to connect to the Internet or other AWS services, but prevent the Internet from initiating a connection with those instances. Associate your NAT Gateway with one of your private subnets. This is needed if you are planning on using any public API (MailChimp, Twilio, etc.) other than S3's.
2c. Route Table
Route tables will control the routing for your subnets. You could setup a different route table for each subnet but for the purposes of this guide we're setting one for the private subnets and one for the public ones. Afterwards you should associate our subnets we will route 0.0.0.0/0 traffic to our NAT Gateway for our private subnets and 0.0.0.0/0 to our Internet Gateway for our public subnets.
2d. Create a VPC Endpoint for S3
This is needed so your Lambda function can communicate with S3's API. This comes in handy later when you run zappa manage "collectstatic --noinput".�
2e. Create a Custom IAM Policy
By default, the Zappa client will create and manage the necessary IAM policies and roles to execute Zappa applications. However, if you're using Zappa in a corporate environment or as part of a continuous integration, you may instead want to manually manage your remote execution policies instead.
Note: PLEASE DO THIS!!!!!!
3. Create a MySQL, Aurora, or MariaDB instance(s)
Create a MySQL instance(s) and associate it with the VPC and subnets you created in the previous step.
4. Create Redis Cluster with ElastiCache
Create a Redis instance(s) and associate it with the VPC and subnets you created in step 2.
Still There?
Code & Local Environment Steps
You got it!! These are the steps that will require a change in your code or your local environment. Mainly the stuff you normally do when you start a new Django project.
This step is only useful if you plan on working on this project locally without something like Docker or Vagrant. If you just install eva it will install the other two.
sudo pip install eva
2. Install zappa, envs, django, django-storages, etc.
pip install zappa envs django mysql-python django-storages boto django-redis
3. Create a project
django-admin startproject yourblog
4. Use environment vars in your settings.py
5. Create a custom storage backend
Partially stolen from Caktus’ Blog https://goo.gl/WLYZD7
Zappa Steps
List of the various Zappa steps that you need to run.
This command just creates a zappa_settings.json configuration file. You will answer questions pertaining to the S3 buckets you created earlier and the default stage for your app. After the initial setup is complete open the settings file to reference the environment variable JSON file you created earlier and the private subnets and security groups you created.
Run zappa deploy dev
This command will deploy the app to Lambda and setup API Gateway. You will only run this command one time. After the first time you will only need to run the update command.
3. Run zappa manage dev migrate
This command is only needed for Django projects. The zappa manage migrate command is the equivalent of python manage.py migrate generally used for Django apps.
Run zappa certify dev
Run this command to request a SSL cert from the Let's Encrypt project and apply it to your API Gateway stage. It uses the domain you entered above in the zappa_settings.json file for the stage you are deploying.
Run zappa manage "collectstatic --noinput"
This command runs another one of Django's management commands, collectstatic. It will gather all of the static files (css, js, images, and videos) and upload them to S3 from inside the Lambda function. Since the files were already uploaded inside of the zip file Zappa deploys the upload to S3 is really fast.�
CloudFront Steps (Optional)
Questions?