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:


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

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

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:

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:

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

b. Package the Application

sam package \
    --output-template-file packaged.yaml \
    --s3-bucket your-deployment-s3-bucket

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

9. Running Database Migrations

AWS SAM supports running CloudFormation custom resources, but for simplicity, you can run migrations manually.

Option 1: Run Migrations Locally

Option 2: Create a Lambda Function for 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

10. Networking and VPC Configuration

Ensure your Lambda functions are configured to access the VPC where your RDS instance is deployed.

11. Managing Secrets with AWS Secrets Manager

12. Testing Locally

You can test your Lambda function locally using the SAM CLI.

sam local start-api

13. Monitoring and Logging

14. Permissions and IAM Roles


Considerations and Best Practices

a. Layer Dependencies

b. Optimizing Cold Starts

c. Security

d. Scalability

e. Environment Variables


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.


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:


Next Steps