पाइथन और टेराफॉर्म का उपयोग करके एक डुअल-मोड AWS लैम्ब्डा बनाना

चरण-दर-चरण उदाहरण

Page content

इस पेज में हमने एक Python Lambda उदाहरण SQS संदेश प्रोसेसर + REST API के साथ API Key सुरक्षा + Terraform स्क्रिप्ट शामिल किया है, जो इसे सर्वरलेस एक्सीक्यूशन के लिए डिप्लॉय करने के लिए है।

AWS Lambda आपको हल्के सर्वरलेस फंक्शंस लिखने की अनुमति देता है जो लगभग किसी भी इवेंट के प्रति प्रतिक्रिया कर सकते हैं — SQS संदेशों से HTTP रिक्वेस्ट्स तक। इस गाइड में, हम एक एकल Python Lambda बनाएंगे जो दो मोड्स में काम करता है:

  1. SQS मोड: जब एक SQS संदेश जैसे { "par": 10 } द्वारा ट्रिगर किया जाता है, यह { "res": 11 } को दूसरे क्यू में प्रकाशित करता है।
  2. HTTP मोड: जब API Gateway द्वारा GET /lam?par=10 के माध्यम से कॉल किया जाता है, यह { "res": 11 } को क्लाइंट को वापस करता है।

हम HTTP एंडपॉइंट को एक सरल हार्डकोडेड API key — "testkey" का उपयोग करके सुरक्षित भी करेंगे। पूरे सेटअप को Terraform का उपयोग करके डिप्लॉय किया जाएगा।

आर्किटेक्चर ओवरव्यू

हम जो बना रहे हैं, उसे देखें:

python lambda on aws sqs with api diagram

एक ही Lambda दोनों के प्रति प्रतिक्रिया करता है:

  • SQS इवेंट्स, एक इवेंट सोर्स मैपिंग के माध्यम से, और
  • API Gateway रिक्वेस्ट्स, एक RESTful HTTP इंटीग्रेशन के माध्यम से।

चरण 1: Python में Lambda बनाना

एक बहुत ही सरल हैंडलर बनाएं Python जो एक SQS इवेंट और एक HTTP API कॉल के बीच अंतर कर सकता है।

फाइल: lambda_function.py

import json
import os
import boto3

sqs = boto3.client("sqs")

OUTPUT_QUEUE_URL = os.environ.get("OUTPUT_QUEUE_URL")
API_KEY = os.environ.get("API_KEY", "testkey")  # हार्डकोडेड डिफ़ॉल्ट

def lambda_handler(event, context):
    # इवेंट प्रकार का पता लगाएं
    if "Records" in event:  # SQS इवेंट
        return handle_sqs(event["Records"])
    else:                   # HTTP इवेंट
        return handle_http(event)

def handle_sqs(records):
    for record in records:
        body = json.loads(record["body"])
        par = int(body["par"])
        res = par + 1
        message = json.dumps({"res": res})
        sqs.send_message(QueueUrl=OUTPUT_QUEUE_URL, MessageBody=message)
    return {"status": "processed", "count": len(records)}

def handle_http(event):
    headers = {k.lower(): v for k, v in (event.get("headers") or {}).items()}
    if headers.get("x-api-key") != API_KEY:
        return {
            "statusCode": 403,
            "headers": {"Content-Type": "application/json"},
            "body": json.dumps({"error": "Forbidden"})
        }

    params = event.get("queryStringParameters") or {}
    if "par" not in params:
        return {
            "statusCode": 400,
            "headers": {"Content-Type": "application/json"},
            "body": json.dumps({"error": "Missing par"})
        }

    par = int(params["par"])
    return {
        "statusCode": 200,
        "headers": {"Content-Type": "application/json"},
        "body": json.dumps({"res": par + 1})
    }

इस Lambda फंक्शन में हमने क्या रखा है:

  • SQS संदेशों को JSON के रूप में पार्स किया जाता है।
  • जब API Gateway द्वारा ट्रिगर किया जाता है, तो फंक्शन API key और क्वेरी पैरामीटर को वैलिडेट करता है।
  • आउटपुट क्यू URL और API key को एन्वायरनमेंट वेरिएबल्स के माध्यम से पास किया जाता है।

चरण 2: Terraform के साथ डिप्लॉय करना

Terraform हमें AWS इन्फ्रास्ट्रक्चर — Lambda, SQS क्यूज़, API Gateway, और परमिशन्स — को एक साथ सेटअप करने की अनुमति देता है।

प्रोजेक्ट संरचना:

project/
├── lambda/
│   └── lambda_function.py
└── infra/
    └── main.tf

Terraform कॉन्फ़िगरेशन (infra/main.tf)

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
    archive = {
      source  = "hashicorp/archive"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

locals {
  project = "lambda-sqs-api"
}

# Lambda पैकेज
data "archive_file" "lambda_zip" {
  type        = "zip"
  source_dir  = "../lambda"
  output_path = "lambda.zip"
}

# SQS क्यूज़
resource "aws_sqs_queue" "input" {
  name = "${local.project}-input"
}

resource "aws_sqs_queue" "output" {
  name = "${local.project}-output"
}

# Lambda के लिए IAM रोल
data "aws_iam_policy_document" "assume_role" {
  statement {
    actions = ["sts:AssumeRole"]
    principals {
      type        = "Service"
      identifiers = ["lambda.amazonaws.com"]
    }
  }
}

resource "aws_iam_role" "lambda_role" {
  name               = "${local.project}-role"
  assume_role_policy = data.aws_iam_policy_document.assume_role.json
}

resource "aws_iam_policy" "lambda_policy" {
  name = "${local.project}-policy"
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = [
          "sqs:SendMessage",
          "sqs:ReceiveMessage",
          "sqs:DeleteMessage",
          "sqs:GetQueueAttributes"
        ]
        Resource = "*"
      },
      {
        Effect = "Allow"
        Action = [
          "logs:CreateLogGroup",
          "logs:CreateLogStream",
          "logs:PutLogEvents"
        ]
        Resource = "*"
      }
    ]
  })
}

resource "aws_iam_role_policy_attachment" "lambda_policy_attach" {
  role       = aws_iam_role.lambda_role.name
  policy_arn = aws_iam_policy.lambda_policy.arn
}

# Lambda फंक्शन
resource "aws_lambda_function" "func" {
  filename         = data.archive_file.lambda_zip.output_path
  function_name    = local.project
  role             = aws_iam_role.lambda_role.arn
  handler          = "lambda_function.lambda_handler"
  runtime          = "python3.12"
  environment {
    variables = {
      OUTPUT_QUEUE_URL = aws_sqs_queue.output.id
      API_KEY          = "testkey"
    }
  }
}

# इवेंट सोर्स मैपिंग (SQS → Lambda)
resource "aws_lambda_event_source_mapping" "sqs_trigger" {
  event_source_arn  = aws_sqs_queue.input.arn
  function_name     = aws_lambda_function.func.arn
  batch_size        = 1
  enabled           = true
}

# API Gateway
resource "aws_api_gateway_rest_api" "api" {
  name = "${local.project}-api"
}

resource "aws_api_gateway_resource" "lam" {
  rest_api_id = aws_api_gateway_rest_api.api.id
  parent_id   = aws_api_gateway_rest_api.api.root_resource_id
  path_part   = "lam"
}

resource "aws_api_gateway_method" "get_lam" {
  rest_api_id   = aws_api_gateway_rest_api.api.id
  resource_id   = aws_api_gateway_resource.lam.id
  http_method   = "GET"
  authorization = "NONE"
  api_key_required = true
}

resource "aws_api_gateway_integration" "lambda_integration" {
  rest_api_id = aws_api_gateway_rest_api.api.id
  resource_id = aws_api_gateway_resource.lam.id
  http_method = aws_api_gateway_method.get_lam.http_method

  integration_http_method = "POST"
  type                    = "AWS_PROXY"
  uri                     = aws_lambda_function.func.invoke_arn
}

resource "aws_lambda_permission" "api_gateway" {
  statement_id  = "AllowAPIGatewayInvoke"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.func.function_name
  principal     = "apigateway.amazonaws.com"
  source_arn    = "${aws_api_gateway_rest_api.api.execution_arn}/*/*"
}

# API Key और यूज़ेज़ प्लान
resource "aws_api_gateway_api_key" "key" {
  name    = "testkey"
  value   = "testkey"
  enabled = true
}

resource "aws_api_gateway_usage_plan" "plan" {
  name = "basic"
  api_stages {
    api_id = aws_api_gateway_rest_api.api.id
    stage  = aws_api_gateway_deployment.deploy.stage_name
  }
}

resource "aws_api_gateway_usage_plan_key" "plan_key" {
  key_id        = aws_api_gateway_api_key.key.id
  key_type      = "API_KEY"
  usage_plan_id = aws_api_gateway_usage_plan.plan.id
}

resource "aws_api_gateway_deployment" "deploy" {
  depends_on = [aws_api_gateway_integration.lambda_integration]
  rest_api_id = aws_api_gateway_rest_api.api.id
  stage_name  = "v1"
}

output "api_url" {
  value = "${aws_api_gateway_deployment.deploy.invoke_url}/lam"
}

चरण 3: डिप्लॉय और टेस्ट करना

  1. Terraform को इनिशियलाइज़ करें:
cd infra
terraform init
  1. कॉन्फ़िगरेशन लागू करें:
terraform apply
  1. API Gateway एंडपॉइंट को टेस्ट करें:
curl -H "x-api-key: testkey" "<API_URL>?par=10"
# अपेक्षित प्राप्त करना: {"res": 11}
  1. SQS को टेस्ट करें:

इनपुट क्यू में एक संदेश भेजें:

aws sqs send-message --queue-url <input-queue-url> --message-body '{"par": 5}'

फिर आउटपुट क्यू को चेक करें:

aws sqs receive-message --queue-url <output-queue-url>
# अपेक्षित प्राप्त करना: {"res": 6}

चरण 4: क्लीन अप

सभी संसाधनों को हटाने के लिए:

terraform destroy

सारांश

[SQS इनपुट क्यू] ─▶ [Lambda फंक्शन] ─▶ [SQS आउटपुट क्यू]
                           ▲
                           │
                 [API Gateway /lam?par=N]
                           │
                     API Key द्वारा सुरक्षित

आपने अभी एक मल्टी-ट्रिगर Lambda बनाया है जो:

  • SQS क्यूज़ से कंस्यूम करता है और प्रकाशित करता है।
  • API Gateway के माध्यम से HTTP रिक्वेस्ट्स का जवाब देता है।
  • एक सरल हेडर चेक का उपयोग करके API key लागू करता है।
  • Terraform के माध्यम से पूरी तरह से प्रबंधित किया जाता है, जो पुन: उत्पादन योग्य serverless इन्फ्रास्ट्रक्चर के लिए है।

थंब्स अप!

यह पैटर्न हल्के संदेश ट्रांसफॉर्मर्स, हाइब्रिड माइक्रोसर्विसेज़, या असिंक्रोनस और सिंक्रोनस AWS सिस्टम्स को ब्रिज करने के लिए अच्छा है — सभी कुछ कुछ लाइन्स के Python और Terraform के साथ।

अगर आप AWS SAM का उपयोग करके एक थोड़ा अधिक उन्नत Lambda उदाहरण देखना चाहते हैं - तो कृपया इस पोस्ट को देखें: AWS SAM + AWS SQS + Python PowerTools का उपयोग करके Lambda कोडिंग

उपयोगी लिंक्स