Deploy Django on AWS Lambda with SAM: A Step-by-Step Guide
How AWS SAM Fits into the Architecture
By using AWS SAM, you can define all the components of your serverless Django application—including Lambda functions, API Gateway, RDS databases, VPC configurations, and other resources—in a single YAML or JSON template. This approach offers several benefits:
- Infrastructure as Code (IaC): Version control your infrastructure alongside your application code.
- Simplified Deployment: Use
sam buildandsam deploycommands to package and deploy your application. - Local Testing: Test your Lambda functions and API Gateway integrations locally.
- Compatibility with CloudFormation: Since SAM templates are an extension of CloudFormation, you can leverage the full power of CloudFormation’s resource definitions and functionalities.
Implementing the Architecture with AWS SAM
Below is an expanded guide on how to implement the described architecture using AWS SAM.
1. Setup and Prerequisites
- AWS CLI Installed and Configured: Ensure you have the AWS CLI installed and configured with appropriate credentials.
- AWS SAM CLI Installed: Install the SAM CLI for local development and deployment.
- Docker Installed (Optional): Required for local testing of Lambda functions.
2. Project Structure
Organize your Django project to work within the Lambda execution environment:
my-django-app/
├── manage.py
├── my_app/
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── requirements.txt
├── sam-template.yaml
└── src/
└── lambda_function.py
manage.py,my_app/: Standard Django project files.requirements.txt: List of Python dependencies.sam-template.yaml: AWS SAM template file defining the infrastructure.src/lambda_function.py: Entry point for the Lambda function.
3. AWS SAM Template
Create a sam-template.yaml file to define your serverless application.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Serverless Django Application
Globals:
Function:
Timeout: 30 # Adjust as needed
MemorySize: 1024 # Adjust as needed
Runtime: python3.8
Environment:
Variables:
DJANGO_SETTINGS_MODULE: my_app.settings
PYTHONPATH: /var/task
Resources:
DjangoFunction:
Type: AWS::Serverless::Function
Properties:
Handler: lambda_function.lambda_handler
CodeUri: ./ # Points to the root of your project
VpcConfig:
SecurityGroupIds:
- !Ref LambdaSecurityGroup
SubnetIds:
- subnet-xxxxxxxx
- subnet-yyyyyyyy
Policies:
- AWSLambdaVPCAccessExecutionRole
- AmazonRDSFullAccess # Adjust permissions as needed
- AmazonS3FullAccess
- SecretsManagerReadWrite
Events:
ApiEvent:
Type: Api
Properties:
Path: /{proxy+}
Method: ANY
LambdaSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Access to RDS
VpcId: vpc-zzzzzzzz
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 5432 # For PostgreSQL
ToPort: 5432
CidrIp: 0.0.0.0/0 # Restrict in production
Explanation:
- Globals: Sets default properties for all Lambda functions.
- DjangoFunction: Defines the Lambda function that will run your Django application.
- Handler: Points to the
lambda_handlerfunction inlambda_function.py. - CodeUri: Directory where the application code is located.
- VpcConfig: Specifies the VPC, subnets, and security groups for the Lambda function.
- Policies: Grants necessary permissions. Adjust these to follow the principle of least privilege.
- Events: Configures API Gateway to trigger the Lambda function.
4. Lambda Function Handler
Create src/lambda_function.py as the entry point for your Lambda function.
import os
import sys
from django.core.wsgi import get_wsgi_application
# Add your project directory to the system path
sys.path.append('/var/task')
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_app.settings')
application = get_wsgi_application()
def lambda_handler(event, context):
from mangum import Mangum # AWS Lambda adapter for ASGI applications
asgi_handler = Mangum(application)
response = asgi_handler(event, context)
return response
Explanation:
- Mangum: A library that allows running ASGI applications on AWS Lambda. Since Django 3.0+, it supports ASGI.
- Adding Project Directory: Ensures that the Lambda function can find your Django application.
5. Requirements File
Update requirements.txt to include necessary dependencies:
django
mangum
psycopg2-binary
boto3
django-storages[boto3]
6. Database Configuration in Django
Modify your settings.py to use environment variables and AWS Secrets Manager for database credentials.
import os
import json
import boto3
def get_secret():
secret_name = os.environ.get('SECRET_NAME')
region_name = os.environ.get('AWS_REGION')
session = boto3.session.Session()
client = session.client(service_name='secretsmanager', region_name=region_name)
get_secret_value_response = client.get_secret_value(SecretId=secret_name)
secret = get_secret_value_response['SecretString']
return json.loads(secret)
secrets = get_secret()
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': secrets['DB_NAME'],
'USER': secrets['DB_USER'],
'PASSWORD': secrets['DB_PASSWORD'],
'HOST': secrets['DB_HOST'],
'PORT': secrets['DB_PORT'],
}
}
Note: Ensure that SECRET_NAME and AWS_REGION are set in your environment variables or SAM template.
7. Configure Static and Media Files
In settings.py, configure Django to use S3 for static and media files.
INSTALLED_APPS += ['storages']
AWS_STORAGE_BUCKET_NAME = os.environ.get('S3_BUCKET_NAME')
AWS_S3_REGION_NAME = os.environ.get('AWS_REGION')
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
STATIC_URL = f'https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/static/'
MEDIA_URL = f'https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/media/'
8. Build and Deploy with AWS SAM
a. Build the Application
sam build
- This command processes your SAM template and prepares your application for deployment, including installing dependencies.
b. Package the Application
sam package \
--output-template-file packaged.yaml \
--s3-bucket your-deployment-s3-bucket
your-deployment-s3-bucket: An S3 bucket where SAM will upload your deployment package.
c. Deploy the Application
sam deploy \
--template-file packaged.yaml \
--stack-name your-stack-name \
--capabilities CAPABILITY_IAM \
--parameter-overrides \
VpcId=vpc-zzzzzzzz \
SubnetIds="subnet-xxxxxxxx,subnet-yyyyyyyy" \
SecurityGroupIds="sg-zzzzzzzz" \
DBHost=your-db-host \
DBName=your-db-name \
DBUser=your-db-user \
DBPassword=your-db-password \
S3BucketName=your-static-media-bucket \
SecretName=your-secret-name \
AWSRegion=your-aws-region
- Parameters: Replace placeholders with actual values.
- Capabilities:
CAPABILITY_IAMis required to allow SAM to create IAM roles.
9. Running Database Migrations
AWS SAM supports running CloudFormation custom resources, but for simplicity, you can run migrations manually.
Option 1: Run Migrations Locally
- Set up a VPN or SSH tunnel to your RDS instance.
-
Run:
python manage.py migrate
Option 2: Create a Lambda Function for Migrations
- Define a new Lambda function in your SAM template specifically for running migrations.
MigrateFunction:
Type: AWS::Serverless::Function
Properties:
Handler: manage.lambda_handler
CodeUri: ./
Runtime: python3.8
Timeout: 900
VpcConfig:
SecurityGroupIds:
- !Ref LambdaSecurityGroup
SubnetIds:
- subnet-xxxxxxxx
- subnet-yyyyyyyy
Policies:
- AWSLambdaVPCAccessExecutionRole
- AmazonRDSFullAccess
- AmazonS3FullAccess
- SecretsManagerReadWrite
Environment:
Variables:
DJANGO_SETTINGS_MODULE: my_app.settings
COMMAND: migrate
-
manage.pyModification:import os import sys def lambda_handler(event, context): os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_app.settings') from django.core.management import execute_from_command_line execute_from_command_line(['manage.py', os.environ.get('COMMAND')]) -
Invoke the Function:
aws lambda invoke \ --function-name YourStackName-MigrateFunction-XXXXXXXXXXXX \ response.json
10. Networking and VPC Configuration
Ensure your Lambda functions are configured to access the VPC where your RDS instance is deployed.
- VPC ID, Subnets, and Security Groups: Provided as parameters in the SAM template.
- Security Group Rules: Configure security groups to allow traffic between Lambda functions and RDS.
11. Managing Secrets with AWS Secrets Manager
- Store Secrets: In AWS Secrets Manager, create a secret containing your database credentials.
- Access Policy: Ensure your Lambda function’s IAM role has permissions to access the secret.
- Environment Variables: Set
SECRET_NAMEandAWS_REGIONto enable your application to retrieve secrets.
12. Testing Locally
You can test your Lambda function locally using the SAM CLI.
sam local start-api
- This command starts a local API Gateway and Lambda environment.
- Note: You may need to adjust configurations or use local mocks for AWS services.
13. Monitoring and Logging
- CloudWatch Logs: By default, Lambda writes logs to CloudWatch Logs.
- X-Ray (Optional): Use AWS X-Ray for distributed tracing.
14. Permissions and IAM Roles
- Adjust IAM policies in your SAM template to follow the principle of least privilege.
- Policies to Consider:
AWSLambdaVPCAccessExecutionRoleAWSSecretsManagerReadOnlyAccess- Custom policies for S3 and RDS access.
Considerations and Best Practices
a. Layer Dependencies
- AWS Lambda Layers: Use layers to package dependencies separately from your code to reduce package size.
b. Optimizing Cold Starts
- Provisioned Concurrency: Configure your Lambda function with provisioned concurrency to reduce cold start latency.
c. Security
- Restrict Security Group Access: Limit ingress and egress rules to only necessary ports and IP ranges.
- Encrypt Data: Use SSL/TLS for connections to RDS and S3.
d. Scalability
- Database Connection Limits: Be mindful of the maximum number of connections your RDS instance can handle.
- Use RDS Proxy: Implement RDS Proxy to manage connection pooling.
e. Environment Variables
- Use the
Parameterssection in your SAM template to manage environment variables and make your template reusable.
Sample SAM Template with Parameters
Here’s an updated version of the SAM template using parameters:
Parameters:
VpcId:
Type: String
Description: VPC ID where resources are deployed
SubnetIds:
Type: CommaDelimitedList
Description: Subnets for Lambda function
SecurityGroupIds:
Type: CommaDelimitedList
Description: Security groups for Lambda function
SecretName:
Type: String
Description: Name of the AWS Secrets Manager secret
AWSRegion:
Type: String
Default: us-east-1
S3BucketName:
Type: String
Description: S3 bucket for static and media files
Resources:
DjangoFunction:
Type: AWS::Serverless::Function
Properties:
Handler: lambda_function.lambda_handler
CodeUri: ./
VpcConfig:
SecurityGroupIds: !Ref SecurityGroupIds
SubnetIds: !Ref SubnetIds
Policies:
- AWSLambdaVPCAccessExecutionRole
- Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- s3:*
Resource: "*"
- Effect: Allow
Action:
- secretsmanager:GetSecretValue
Resource: !Sub arn:aws:secretsmanager:${AWSRegion}:${AWS::AccountId}:secret:${SecretName}*
Environment:
Variables:
DJANGO_SETTINGS_MODULE: my_app.settings
SECRET_NAME: !Ref SecretName
AWS_REGION: !Ref AWSRegion
S3_BUCKET_NAME: !Ref S3BucketName
Using AWS SAM Accelerate
AWS SAM Accelerate allows for rapid development and testing by syncing your code changes directly to the cloud.
-
Enable Accelerate:
sam sync --stack-name your-stack-name --watch -
Benefits:
- Faster iterations during development.
- Automatic detection of code changes.
Conclusion
Implementing your serverless Django application using AWS SAM is not only feasible but also offers a structured and scalable approach to managing your infrastructure as code. AWS SAM integrates seamlessly with other AWS services, providing a cohesive environment for deploying and managing serverless applications.
Key Benefits:
- Simplified Management: Define and manage all AWS resources in a single template.
- Local Development: Test functions locally, reducing deployment cycles.
- Extensibility: Leverage the full range of AWS services and CloudFormation features.
- Community Support: As an AWS-supported framework, SAM has extensive documentation and community resources.
Next Steps
- Review AWS SAM Documentation:
- Explore Examples:
- Check out sample serverless applications using AWS SAM on GitHub.
- Optimize Your Application:
- Continuously monitor performance and costs.
- Implement best practices for security and scalability.