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:
sam build and sam deploy commands to package and deploy your application.Below is an expanded guide on how to implement the described architecture using AWS SAM.
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.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:
lambda_handler function in lambda_function.py.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:
Update requirements.txt to include necessary dependencies:
django
mangum
psycopg2-binary
boto3
django-storages[boto3]
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.
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/'
sam build
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.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
CAPABILITY_IAM is required to allow SAM to create IAM roles.AWS SAM supports running CloudFormation custom resources, but for simplicity, you can run migrations manually.
Run:
python manage.py migrate
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.py Modification:
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
Ensure your Lambda functions are configured to access the VPC where your RDS instance is deployed.
SECRET_NAME and AWS_REGION to enable your application to retrieve secrets.You can test your Lambda function locally using the SAM CLI.
sam local start-api
AWSLambdaVPCAccessExecutionRoleAWSSecretsManagerReadOnlyAccessParameters section in your SAM template to manage environment variables and make your template reusable.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
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:
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: