Sunday, 16 March 2025

FastAPI for Redpanda

# Step-by-Step Instructions to Deploy FastAPI on AWS Lambda with ALB


## Step 1: Prepare FastAPI App


1. **Install Dependencies:**

```bash

pip install fastapi uvicorn confluent_kafka protobuf mangum

pip freeze > requirements.txt

```


2. **Create FastAPI App:**

   - Save the following code as `app.py`.


```python

from fastapi import FastAPI

from confluent_kafka import Consumer

from datetime import datetime, timedelta, timezone

import my_protobuf_pb2  # Import your Protobuf message definition

from mangum import Mangum


app = FastAPI()


consumer_conf = {

    'bootstrap.servers': 'your-redpanda-broker:9092',

    'group.id': 'fastapi-group',

    'auto.offset.reset': 'earliest'

}

consumer = Consumer(consumer_conf)

topic = 'your-topic'

consumer.subscribe([topic])


@app.get("/gool-tickets")

def get_gool_tickets():

    now = datetime.now(timezone.utc)

    last_24_hours = now - timedelta(hours=24)

    messages = []


    while True:

        msg = consumer.poll(1.0)  # Poll for 1 second

        if msg is None:

            break

        if msg.error():

            continue


        msg_timestamp = msg.timestamp()[1]

        msg_time = datetime.fromtimestamp(msg_timestamp / 1000, tz=timezone.utc)


        if msg_time >= last_24_hours:

            proto_msg = my_protobuf_pb2.Ticket()  # Adjust according to your message type

            proto_msg.ParseFromString(msg.value())


            if proto_msg.ticket_type == "Gool":

                messages.append({

                    "ticket_type": proto_msg.ticket_type,

                    "timestamp": msg_time.isoformat()

                })


    return {"gool_tickets": messages}


handler = Mangum(app)

```


## Step 2: Package the Application


1. **Create Deployment Package:**

```bash

mkdir package

pip install -r requirements.txt -t package/

cp app.py my_protobuf_pb2.py package/

cd package

zip -r ../fastapi_lambda.zip .

cd ..

```


## Step 3: Upload to S3


1. **Create S3 Bucket (if needed):**

```bash

aws s3 mb s3://your-s3-bucket-name

```


2. **Upload the Package:**

```bash

aws s3 cp fastapi_lambda.zip s3://your-s3-bucket-name/

```


## Step 4: Deploy with CloudFormation


1. **Validate the Template:**

```bash

aws cloudformation validate-template --template-body file://template.yaml

```


2. **Deploy the Stack:**

```bash

aws cloudformation create-stack \

  --stack-name FastAPIAppStack \

  --template-body file://template.yaml \

  --capabilities CAPABILITY_IAM

```


3. **Check Deployment Status:**

```bash

aws cloudformation describe-stacks --stack-name FastAPIAppStack

```


4. **Get the ALB URL:**

After deployment, get the ALB URL from the CloudFormation outputs and access your FastAPI app at:

```plaintext

http://your-alb-dns-name/gool-tickets

```


# CloudFormation Template (template.yaml)


AWSTemplateFormatVersion: '2010-09-09'

Description: FastAPI on Lambda with ALB


Resources:

  FastAPILambdaFunction:

    Type: AWS::Lambda::Function

    Properties:

      FunctionName: FastAPIHandler

      Runtime: python3.11

      Handler: app.handler

      Timeout: 30

      MemorySize: 256

      Role: !GetAtt LambdaExecutionRole.Arn

      Code:

        S3Bucket: your-s3-bucket-name

        S3Key: fastapi_lambda.zip


  LambdaExecutionRole:

    Type: AWS::IAM::Role

    Properties:

      RoleName: FastAPIExecutionRole

      AssumeRolePolicyDocument:

        Version: '2012-10-17'

        Statement:

          - Effect: Allow

            Principal:

              Service: [lambda.amazonaws.com]

            Action: ['sts:AssumeRole']

      Policies:

        - PolicyName: FastAPIPolicy

          PolicyDocument:

            Version: '2012-10-17'

            Statement:

              - Effect: Allow

                Action:

                  - 'logs:CreateLogGroup'

                  - 'logs:CreateLogStream'

                  - 'logs:PutLogEvents'

                Resource: 'arn:aws:logs:*:*:*'


  ALB:

    Type: AWS::ElasticLoadBalancingV2::LoadBalancer

    Properties:

      Name: FastAPIALB

      Subnets:

        - subnet-xxxxxxxx  # Replace with your subnet IDs

        - subnet-yyyyyyyy

      SecurityGroups:

        - !Ref ALBSecurityGroup

      Scheme: internet-facing

      LoadBalancerAttributes:

        - Key: idle_timeout.timeout_seconds

          Value: '60'

      Type: application


  ALBSecurityGroup:

    Type: AWS::EC2::SecurityGroup

    Properties:

      GroupDescription: Allow HTTP and HTTPS

      SecurityGroupIngress:

        - IpProtocol: tcp

          FromPort: 80

          ToPort: 80

          CidrIp: 0.0.0.0/0


  Listener:

    Type: AWS::ElasticLoadBalancingV2::Listener

    Properties:

      LoadBalancerArn: !Ref ALB

      Protocol: HTTP

      Port: 80

      DefaultActions:

        - Type: forward

          TargetGroupArn: !Ref LambdaTargetGroup


  LambdaTargetGroup:

    Type: AWS::ElasticLoadBalancingV2::TargetGroup

    Properties:

      Name: FastAPILambdaTargetGroup

      TargetType: lambda

      Targets:

        - Id: !GetAtt FastAPILambdaFunction.Arn


  LambdaInvokePermission:

    Type: AWS::Lambda::Permission

    Properties:

      Action: 'lambda:InvokeFunction'

      FunctionName: !GetAtt FastAPILambdaFunction.Arn

      Principal: elasticloadbalancing.amazonaws.com

      SourceArn: !GetAtt ALB.Arn


Outputs:

  ALBUrl:

    Value: !Sub "http://${ALB.DNSName}"

    Description: URL of the ALB


No comments:

Post a Comment