Course-এর সূচি

15.3

VPC-র ভেতরে Lambda, RDS Proxy আর Database Trigger

private resource-এ পৌঁছানো, হাজারো connection-এর ঝড় আর RDS Proxy, RDS থেকে Lambda চালানো বনাম RDS event notification।

20 মিনিট পড়া + Animation

টিপস: ডটেড-আন্ডারলাইন করা যেকোনো শব্দে ট্যাপ বা Hover করলে তার অর্থ দেখবে।

এই lesson শেষে তুমি পারবে

  • বুঝিয়ে বলতে, default অবস্থায় একটা Lambda function আসলে কোথায় চলে (AWS-এর নিজের একটা VPC-তে), সেখান থেকে সে কোথায় যেতে পারে (internet আর AWS-এর public endpoint) আর কোথায় পারে না (তোমার private RDS, ElastiCache, internal load balancer)।
  • Function-কে তোমার VPC-তে জুড়তে: দুই বা তার বেশি AZ-এর subnet, একটা security group, AWSLambdaVPCAccessExecutionRole-এ থাকা execution role-এর অনুমতি, আর Hyperplane ENI কীভাবে তৈরি হয়, ভাগাভাগি হয়, আবার ফেরত যায়।
  • ব্যাখ্যা করতে, VPC-তে জোড়া function-এর কেন internet থাকে না, public subnet-এ রাখলেও না, আর সেটা ঠিক করতে NAT gateway (internet-এর জন্য) বা VPC endpoint (AWS service-এর জন্য) দিয়ে।
  • Relational database-এর ওপর Lambda যে connection-এর ঝড় তোলে সেটা বর্ণনা করতে, RDS Proxy কীভাবে সেটা সামলায় (pooling, দ্রুত failover, IAM authentication, Secrets Manager), আর কেন তখন function-কে VPC-তে থাকতেই হয়।
  • আলাদা করতে database-এর ভেতর থেকে Lambda ডাকা (RDS for PostgreSQL, Aurora PostgreSQL, Aurora MySQL: data-র ঘটনা) আর RDS event notification (instance-এর নিজের খবর, data নেই), আর কোনো চাহিদার জন্য ঠিকটা, বা একটা change-data-capture tool, বেছে নিতে।

#Default অবস্থায় Lambda function কোথায় চলে

Lesson 15.1-এ বলেছিলাম “সামলানোর মতো কোনো server নেই”। Server কিন্তু আছেই, network-ও আছে: প্রতিটা Lambda function চলে Lambda service-এর নিজের মালিকানার, নিজের সামলানো একটা VPC-তে। ওই VPC তুমি কখনো দেখতে পাও না, তার route table বদলাতে পারো না, আর তোমার account-এর কিছুই সেদিকে দেখায় না।

সেখান থেকে একটা function-এর নাগাল internet-এর যেকোনো machine-এর মতোই:

  • Internet চলে। Payment gateway, weather API বা GitHub-এ call সোজা বেরিয়ে যায়।
  • AWS-এর public endpoint চলে। DynamoDB, S3, SQS, SNS, Secrets Manager সহ বাকিরা HTTPS দিয়ে তাদের public Regional endpoint-এ পৌঁছায়, আর কী করা যাবে সেটা ঠিক করে IAM (execution role)।
  • তোমার private resource চলে না। Publicly accessible = No দেওয়া একটা RDS database, একটা ElastiCache cluster, একটা internal ALB, 10.0.2.40-এ বসা একটা EC2 instance: এদের সবার আছে শুধু তোমার VPC-র ভেতরের private address, আর Lambda-র VPC থেকে সেখানে যাওয়ার কোনো route নেই। Connection কখনো পৌঁছায় না; function timeout পর্যন্ত বসে থাকে।

#Function-কে তোমার VPC-তে জোড়া

তুমি function-কে একটা VPC configuration দাও:

  • Subnet: যেসব private subnet-এ resource-গুলো আছে, কমপক্ষে আলাদা দুটো AZ-এ দুটো, যাতে একটা AZ-এ গোলমাল হলে function থেমে না যায়। (VPC-টা subnet থেকেই বোঝা যায়।)
  • Security group: এক বা একাধিক, যেমন lambda-sg। এরা function-এর বাইরে যাওয়া traffic নিয়ন্ত্রণ করে, আর তোমার database-এর security group এদেরকেই উল্লেখ করে।
  • চাইলে Ipv6AllowedForDualStack, যাতে dual-stack subnet-এ function IPv6 connection খুলতে পারে (default-এ বন্ধ; শুধু-IPv6 subnet চলে না)।

Execution role-এর network interface বানানো আর সামলানোর অনুমতি লাগে: ec2:CreateNetworkInterface, ec2:DescribeNetworkInterfaces, ec2:DescribeSubnets, ec2:DeleteNetworkInterface, ec2:AssignPrivateIpAddresses আর ec2:UnassignPrivateIpAddresses। AWS managed policy AWSLambdaVPCAccessExecutionRole-এ এগুলো আছে (সাথে CloudWatch Logs-এর অনুমতি), আর console নিজেই এটা লাগিয়ে দেয়। যে মানুষটা পরিবর্তনটা করছে, তারও লাগে ec2:DescribeSecurityGroups, ec2:DescribeSubnets আর ec2:DescribeVpcs।

Lambda function-এর traffic আসলে কোথা থেকে বের হয়

ঢাকার একটা e-commerce shop-এর order function-কে internet-এর একটা payment gateway ডাকতে হয়, DynamoDB-তে লিখতে হয়, আর private একটা RDS for PostgreSQL database থেকে stock পড়তে হয়। VPC-তে জোড়ার আগে আর পরে এই তিনটার কোনগুলোতে সে পৌঁছাতে পারে?

পরিস্থিতি

Internet আর AWS-এর public endpoint চলে; তোমার VPC-র private IP-তে যাওয়া যায় না।

তোমার VPC10.0.0.0/16
Private subnet
Payment APIinternet
Order functionLambda-র নিজের VPC
Stock DB10.0.2.40
DynamoDBRegional
ধাপ 1 / 4
1

প্রতিটা Lambda function চলে AWS-এর নিজের মালিকানার, নিজের সামলানো একটা VPC-তে, তোমারটায় না। সেটা তুমি কখনো দেখতেই পাও না। Default অবস্থায় সেখান থেকে internet-এ যাওয়ার রাস্তা আছে, তাই public address আছে এমন যেকোনো কিছুকে function ডাকতে পারে।

#Hyperplane ENI: প্রতিটা subnet আর security group জোড়ার জন্য একটা

Lambda প্রতিটা execution environment-এর জন্য তোমার subnet-এ একটা করে network interface বসায় না। সে প্রতিটা subnet আর security group-এর combination-এর জন্য একটা Hyperplane ENI বানায়, আর account-এর যত function একই combination ব্যবহার করে, সবাই সেটা ভাগ করে নেয়। একটা Hyperplane ENI ৬৫,০০০টা পর্যন্ত connection সামলাতে পারে; traffic বাড়লে Lambda নিজেই আরও যোগ করে।

ওই ENI-র জীবনচক্র বুঝলে console-এ দেখা কয়েকটা জিনিসের মানে পরিষ্কার হয়:

কখনকী ঘটে
তুমি নতুন VPC configuration save করলেLambda ENI বানায় (বা আগেরটা ব্যবহার করে)। নতুন function তৈরি না হওয়া পর্যন্ত Pending থাকে, invoke করা যায় না, আর এতে কয়েক মিনিট লাগতে পারে। পুরোনো function এর মধ্যে আগের version দিয়ে কাজ চালিয়ে যায়।
সাধারণ invocationবাড়তি কিছু না। ENI আগে থেকেই আছে, তাই আজকাল VPC-তে জুড়লে cold start একটুও বাড়ে না।
Function ১৪ দিন অলস পড়ে থাকলেLambda অব্যবহৃত ENI ফেরত নেয় আর function-কে Inactive দাগায়। পরের invocation ফেল করে, আর ENI তৈরি না হওয়া পর্যন্ত function আবার Pending।
তুমি VPC configuration সরিয়ে দিলেENI মুছতে Lambda ২০ মিনিট পর্যন্ত সময় নেয়, আর মোছে তখনই যখন অন্য কোনো function বা version সেটা ব্যবহার করছে না। আগে execution role মুছে ফেললে ENI পড়ে থাকে, তখন হাতে মুছতে হয়।

Code কিন্তু তখনো চলে Lambda-র নিজের VPC-তে। শুধু তার network traffic ENI দিয়ে তোমার VPC-তে ঢোকে, ENI-র private IP আর তোমার security group নিয়ে। ENI-টা একমুখী দরজার মতো: function তোমার VPC-র ভেতরে connection খুলতে পারে, কিন্তু তোমার VPC-র কেউ ওই ENI দিয়ে function-এর দিকে connection খুলতে পারে না। Function-কে তুমি আগের মতোই ডাকো (API Gateway, S3 event, SDK), Lambda service-এর মাধ্যমে।

#Security group: address না, group-কে উল্লেখ করো

Database-এর security group-কে তার port (PostgreSQL-এ 5432, MySQL-এ 3306) খুলতে হবে lambda-sg থেকে, কোনো IP range থেকে না: Lambda ENI আবার বানালে বা নতুন যোগ করলে তার address বদলে যেতে পারে, আর group নিজে থেকেই তাদের অনুসরণ করে (security group আছে lesson 3.5-এ)। Function-এর নিজের group-এ সাধারণত কোনো inbound rule-ই থাকে না, কারণ কেউ function-এ connect করে না; তার outbound rule-এ database-এর port আর AWS API-র জন্য 443 খোলা থাকতে হয়।

ভুল security group কোনো error বার্তা দেয় না। Packet চুপচাপ ফেলে দেওয়া হয়, আর function শেষ হয় “Task timed out” দিয়ে। Timeout মানে সমস্যা network-এ (route, security group, NACL); “password authentication failed”-এর মতো error মানে network ঠিক আছে, credential ঠিক নেই।

#IAM দিয়ে শক্ত করে বাঁধা

দুটো IAM কৌশল আসল account-এ আর পরীক্ষায় দুই জায়গাতেই আসে:

  • Role-এ দেওয়া EC2 অনুমতি function-এর code-ও পায়, তাই কেউ function-টা দখল করলে network interface বানাতে পারবে। ওই EC2 action-গুলোর ওপর lambda:SourceFunctionArn condition key দিয়ে একটা deny যোগ করো: এটা মেলে শুধু function-এর code যে call করে সেগুলোর সাথে, তাই Lambda service ঠিকই ENI সামলে যেতে পারে।
  • প্রতিটা function-কে VPC-তে রাখতে বাধ্য করো (বা অনুমোদিত VPC, subnet আর security group-এ), lambda:CreateFunction আর lambda:UpdateFunctionConfiguration-এর ওপর lambda:VpcIds, lambda:SubnetIds আর lambda:SecurityGroupIds condition key দিয়ে। "Null": {"lambda:VpcIds": "true"} দিয়ে deny করলে VPC configuration ছাড়া কোনো function বানানো যায় না; SCP হিসেবে দিলে পুরো organization-এ খাটে (chapter 20)।

#VPC-র function-এর internet নেই

এবার visitor pass-এর দাম। জোড়ার পর function-এর সব বাইরে যাওয়া traffic ENI দিয়ে বের হয় আর তোমার subnet-এর route table মেনে চলে। সাধারণ একটা private subnet-এর route একটাই: 10.0.0.0/16 → local। ফলে:

  • Internet-এর payment gateway: timeout;
  • DynamoDB, S3, SQS, Secrets Manager, এমনকি Lambda API নিজেও: এরাও timeout, কারণ এদের endpoint তোমার VPC-র বাইরের public address।

দ্বিতীয়টাই মানুষকে অবাক করে। “RDS পড়ার জন্য VPC যোগ করলাম, এখন Secrets Manager থেকে database password পড়তে গিয়ে function আটকে যাচ্ছে” একেবারে চেনা ticket।

#Public subnet-এর ফাঁদ

সহজ রাস্তা মনে হয় function-কে একটা public subnet-এ জোড়া, যার route table 0.0.0.0/0 পাঠায় internet gateway-তে। ওখানকার EC2 instance তো internet পায়, Lambda কেন পাবে না? কারণ internet gateway শুধু তাদের traffic-এর address বদলায় যাদের একটা public IP আছে (lesson 3.3), আর Lambda তার ENI-কে কখনো public IP দেয় না; Elastic IP-ও লাগানো যায় না। AWS সোজাসুজি লিখে দিয়েছে: function-কে public subnet-এ জুড়লে সে internet access-ও পায় না, public IP-ও পায় না।

#সমাধান ১: internet-এর জন্য NAT gateway

Lesson 3.4-এর চেনা নকশা:

  1. Function-কে private subnet-এ জোড়ো।
  2. একই AZ-এর একটা public subnet-এ একটা NAT gateway বসাও (Elastic IP সহ)।
  3. Private subnet-এর route table-এ যোগ করো 0.0.0.0/0 → nat-gateway।

NAT gateway private source address সরিয়ে নিজের public address বসায়, আর internet gateway packet বাইরে পাঠায়। বাড়তি একটা লাভ: সব function-এর সব call বের হয় একটাই নির্দিষ্ট public IP থেকে, যেটা কোনো ব্যাংক বা payment partner তাদের allow-list-এ রাখতে পারে। High availability-র জন্য প্রতি AZ-এ একটা করে NAT gateway রাখো, প্রতিটা private subnet নিজের AZ-এরটার দিকে। NAT gateway-র bill হয় ঘণ্টা ধরে আর প্রতি GB process ধরে, তাই ভারী S3 বা DynamoDB traffic ওর ভেতর দিয়ে পাঠানো মানে অকারণে টাকা খরচ।

#সমাধান ২: AWS service-এর জন্য VPC endpoint

Function যদি শুধু AWS service-এর সাথে কথা বলে, তাহলে হয়তো তার internet লাগেই না। VPC endpoint (lesson 22.2) private পথ দেয়:

  • S3 আর DynamoDB-র জন্য gateway endpoint তোমার route table-এ একটা route (prefix list) যোগ করে। বিনা খরচে, কোনো ENI নেই।
  • প্রায় বাকি সবকিছুর জন্য interface endpoint (AWS PrivateLink): SQS, SNS, Secrets Manager, KMS, STS, Step Functions, Lambda নিজেও… প্রতিটা তোমার subnet-এ private IP-ওয়ালা একটা ENI, আর private DNS-এর কারণে service-এর চেনা নামটাই (secretsmanager.ap-southeast-1.amazonaws.com) ওই IP-তে resolve হয়, তাই code বদলাতে হয় না। ঘণ্টা ধরে প্রতি AZ আর প্রতি GB হিসেবে bill হয়।

Endpoint দিয়ে কখনো internet-এ যাওয়া যায় না, আর NAT gateway কখনো S3 বা DynamoDB traffic সস্তা করে না। বেশিরভাগ production VPC দুটোই রাখে: AWS service-এর জন্য endpoint, বাকিদের জন্য NAT gateway।

VPC-র function-এর internet নেই, যতক্ষণ না তুমি বের হওয়ার রাস্তা বানাও

সেই একই order function, এখন VPC-তে জোড়া। তার এখনো লাগবে internet-এর payment gateway, DynamoDB, আর Secrets Manager-এ রাখা database password।

পরিস্থিতি

Private subnet, NAT নেই, endpoint নেই: VPC-র বাইরের প্রতিটা call timeout হয়।

তোমার VPC
Private subnet
Public subnet
DynamoDB
Secrets Manager
Function ENI10.0.2.15
Payment API
ধাপ 1 / 3
1

Private subnet-এ জোড়ার পর function-এর traffic এখন ওই subnet-এর route table মেনে চলে: 10.0.0.0/16 local, আর কিছুই না। তার ENI-র আছে শুধু একটা private address।

#আদৌ VPC লাগবে কি?

Function-এর দরকার…VPC-তে জুড়বে?বাড়তি কী লাগবে
শুধু internet আর AWS service (S3, DynamoDB, SQS…)না। Default-ই রাখো।কিছু না
Private RDS, Aurora, ElastiCache, internal ALB বা EC2হ্যাঁ, ২+ AZ-এর private subnetResource-এর security group-এ rule
Private resource আর AWS serviceহ্যাঁGateway endpoint (S3, DynamoDB), interface endpoint, বা NAT gateway
Private resource আর internetহ্যাঁPublic subnet-এ NAT gateway, private subnet থেকে route
Partner-এর allow-list-এর জন্য নির্দিষ্ট public IPহ্যাঁ, private resource না থাকলেওElastic IP-ওয়ালা NAT gateway

নিজে combination-গুলো চেষ্টা করে দেখো। Function-এর traffic কোথা দিয়ে বের হয় আর VPC-তে কী আছে বেছে নাও, তারপর প্রতিটা পথ যাচাই করো:

আমার function কি সেখানে পৌঁছাবে?

ঢাকার shop-এর order function-এর চারটা জিনিস লাগে: 10.0.2.40-এ stock database (private), internet-এর একটা payment gateway, DynamoDB, আর Secrets Manager-এ রাখা একটা password। Function-এর traffic কোথা দিয়ে বের হয় আর VPC-তে কী কী আছে বেছে নাও, তারপর প্রতিটা পথ যাচাই করো।

Function-এর networking

VPC-তে কী আছে

ফল দেখতে “পথ যাচাই করো” চাপো।

#Lambda আর relational database: connection-এর ঝড়

একদল web server database-এর সাথে কথা বলে প্রতিটা server-এর ভেতরের একটা connection pool দিয়ে: ১০টা server × ২০টা connection = ২০০, সবসময় স্থির। Lambda এই ছকটা ভেঙে দেয়, যেটা lesson 7.4 database-এর দিক থেকে দেখিয়েছিল:

  • প্রতিটা execution environment একবারে একটাই request সামলায় আর নিজেই আলাদা একটা ছোট process, তাই তার থাকে নিজের connection, সাধারণত init code-এ (handler-এর বাইরে) খোলা, আর environment যতক্ষণ বাঁচে ততক্ষণ সেটাই বারবার ব্যবহার হয়।
  • Concurrency মানে environment-এর সংখ্যা, আর সেটা দ্রুত বাড়ে: প্রতি function প্রতি ১০ সেকেন্ডে ১,০০০টা পর্যন্ত নতুন environment, account-এর সীমা পর্যন্ত (default-এ প্রতি Region-এ ১,০০০; lesson 15.2)।
  • Relational database-এর max_connections নির্দিষ্ট, memory দিয়ে ঠিক হয়: ছোট instance-এ কয়েকশো।

তাই হঠাৎ ভিড় মানে connection-এর ঝড়: ১,০০০ environment একই মুহূর্তে ১,০০০টা connection খোলে, সীমার ওপরের সবাইকে database ফিরিয়ে দেয় “too many connections” বলে, আর সবচেয়ে জরুরি request-গুলোই ফেল করে। CPU প্রায়ই ঠিক থাকে; database-এর শুধু connection-এর জায়গা ফুরিয়ে গেছে। অলস environment বন্ধ হয় না, জমে থাকে, তাই ভিড়ের পরেও কিছুক্ষণ তাদের connection খোলা থাকে।

একটা চটজলদি হিসাব: একসাথে চলা environment ≈ প্রতি সেকেন্ডে request × গড় সময় (সেকেন্ডে)। প্রতি সেকেন্ডে ২,৫০০ request আর প্রতিটা ৪০০ ms হলে ১,০০০টা environment, মানে সরাসরি ১,০০০টা connection।

#Database-এর সামনে RDS Proxy

Amazon RDS Proxy হলো RDS (MySQL, PostgreSQL, MariaDB, SQL Server) আর Aurora (MySQL, PostgreSQL)-এর জন্য পুরোপুরি managed, serverless, highly available একটা connection pooler। Function-রা database-এর বদলে proxy-র endpoint-এ connect করে, code-এ আর কিছু বদলাতে হয় না:

  • Scalability (pooling)। Proxy অল্প কয়েকটা আসল database connection-এর একটা pool রাখে, আর কোনো client-কে একটা ধার দেয় শুধু তার transaction চলার সময়টুকু (multiplexing)। একটা request-এ ২০০ ms লাগলে আর তার ২০ ms যায় transaction-এ, তাহলে ১,০০০টা একসাথে চলা function-এর লাগে মোটামুটি ১,০০০ × ২০ ÷ ২০০ = ১০০টা database connection। Pool-এর বাইরের request লাইনে অপেক্ষা করে, ফিরিয়ে দেওয়া হয় না (তোমার ঠিক করা সীমা পেরোলেই কেবল proxy load ফেলে দেয়)।
  • Availability। Function-দের connection শেষ হয় proxy-তে, তাই সেগুলো Multi-AZ failover পেরিয়েও টিকে থাকে; proxy DNS-এর অপেক্ষা না করে সরাসরি instance-গুলো দেখে আর নতুন primary-তে আবার connect করে। AWS বলে failover-এ ৬৬% পর্যন্ত কম সময় লাগে।
  • Security। Client-দের জন্য IAM authentication বাধ্যতামূলক করা যায়: function তার execution role দিয়ে একটা স্বল্প-মেয়াদি token সই করে (rds-db:connect), তাই code বা environment variable-এ কোনো password থাকে না। Proxy database-এ ঢোকে Secrets Manager থেকে পড়া credential দিয়ে (বা ২০২৫-এর সেপ্টেম্বর থেকে MySQL আর PostgreSQL engine-এ পুরো পথেই IAM database authentication দিয়ে, তখন কোনো secret-ই লাগে না)।
  • Network। Proxy থাকে database-এর একই VPC-তে, আর কখনো publicly accessible হতে পারে না। তাই যে function এটা ব্যবহার করে, তাকে ওই VPC-তে জোড়া থাকতেই হবে (বা জোড়া লাগানো অন্য VPC-তে), আর proxy-র security group-এ function-এর group থেকে port খোলা থাকতে হবে।

Multiplexing, pinning, endpoint আর দামের খুঁটিনাটি lesson 7.4-এ; এখানে আমাদের নজর Lambda-র দিকটায়।

Connection-এর ঝড় আর RDS Proxy

Shop-এ ঈদের flash sale। API Gateway-র পেছনের order API কয়েক সেকেন্ডে Lambda-কে ২০ থেকে ১,০০০ execution environment-এ নিয়ে যায়। PostgreSQL database নিতে পারে মোটামুটি ৪০০টা connection।

পরিস্থিতি

প্রতিটা execution environment-এর নিজের connection: ১,০০০ environment, জায়গা ৪০০টা।

তোমার VPC
Private subnet
API Gateway
Order function
Orders DBসর্বোচ্চ ≈ ৪০০২০ / ৪০০
২০ conn
ধাপ 1 / 4
1

প্রতিটা execution environment আলাদা ছোট্ট একটা process, তার নিজের database connection থাকে, সাধারণত init code-এ খোলা, আর environment যতক্ষণ বাঁচে ততক্ষণ সেটাই আবার আবার ব্যবহার হয়। ২০টা environment মানে ২০টা connection: কোনো সমস্যা নেই।

#Database বাঁচানোর আরও উপায়

  • Connection handler-এর বাইরে খোলো, যাতে গরম environment প্রতিটা request-এ নতুন না খুলে আগেরটাই ব্যবহার করে; প্রতি request-এ কিছু বন্ধ কোরো না।
  • Function-এর concurrency-তে সীমা টানো (reserved concurrency, lesson 15.2) যখন সব request একসাথে সামলানোর চেয়ে database বাঁচানো বেশি জরুরি। এটা RDS Proxy-র সাথে চলে; তার জায়গা নেয় না।
  • RDS Data API (Aurora PostgreSQL আর Aurora MySQL, provisioned আর Serverless v2): IAM আর একটা Secrets Manager secret দিয়ে HTTPS API-র মাধ্যমে SQL চালাও। সামলানোর মতো কোনো database connection নেই, function-কে VPC-তেও থাকতে হয় না। কম থেকে মাঝারি traffic-এ ভালো; API আলাদা, তাই code বদলাতে হয়।
  • DynamoDB-তে (lesson 15.4 আর 15.5) connection বলে কিছুই নেই: প্রতিটা request একটা HTTPS call। এজন্যই serverless design-এ Lambda-র স্বাভাবিক জুটি DynamoDB।

#যখন database নিজেই Lambda ডাকে

এতক্ষণ function ডাকছিল database-কে। তীর উল্টো দিকেও যেতে পারে, আর এখানে দুটো feature আছে যারা দেখতে একরকম, কিন্তু আলাদা প্রশ্নের উত্তর দেয়।

#Database-এর ভেতর থেকে Lambda ডাকা

RDS for PostgreSQL, Aurora PostgreSQL আর Aurora MySQL SQL থেকে একটা Lambda function ডাকতে পারে, তাই database-এর ভেতরেই data-র ঘটনায় সাড়া দেওয়া যায়, data যে application-ই বদলাক:

  • PostgreSQL: aws_lambda extension বসাও, তারপর SELECT aws_lambda.invoke(...), প্রায়ই একটা trigger থেকে। Default invocation_type হলো RequestResponse (synchronous): SQL statement function-এর উত্তরের জন্য অপেক্ষা করে। ফল না লাগলে 'Event' (asynchronous) দাও, তাহলে insert আটকে থাকে না।
  • Aurora MySQL: native function lambda_sync আর lambda_async (পুরোনো mysql.lambda_async stored procedure deprecated, version 3-এ নেই-ই)।

দুটো জিনিস সবসময় লাগে:

  1. Database থেকে Lambda service পর্যন্ত একটা network পথ। Public subnet-এ publicly accessible instance নিজেই বের হতে পারে (তার security group-এ outbound 443 খোলা থাকতে হবে)। Private instance-এর লাগে একটা NAT gateway বা Lambda-র একটা VPC interface endpoint। এমন endpoint-এর পেছনে RDS for PostgreSQL হলে endpoint-এর private DNS ব্যবহারের আগে তার rds.custom_dns_resolution = 1 parameter-ও লাগে (custom parameter group-এ, তারপর reboot)।
  2. অনুমতি। একটা IAM role, যে rds.amazonaws.com-কে বিশ্বাস করে আর lambda:InvokeFunction অনুমতি দেয়, instance-এ লাগানো (aws rds add-role-to-db-instance --feature-name Lambda) বা Aurora cluster-এ। Lambda-র resource-based policy লাগে শুধু function অন্য account-এ থাকলে।

সাধারণ ব্যবহার: row insert হলে welcome বা confirmation email, দাম বদলালে search index-এ পাঠানো, বাইরের কোনো fraud check ডাকা। কাজটা ছোট আর asynchronous রাখো; trigger-এ ভারী logic রাখলে প্রতিটা insert ধীর আর ভঙ্গুর হয়ে যায়।

#RDS event notification

RDS event notification তোমাকে জানায় database resource-এর নিজের খবর, তোমার row-এর না: একটা instance তৈরি হলো, বন্ধ হলো, চালু হলো, reboot হলো, failover হলো, storage কমে আসছে, একটা backup বা snapshot শুরু বা শেষ হলো, একটা parameter group বদলাল। তুমি এই source type-গুলোর event category-তে subscribe করো: DB instance, DB cluster, DB snapshot, DB cluster snapshot, DB parameter group, DB security group, RDS Proxy, custom engine version।

  • গন্তব্য: একটা SNS topic (email, SMS, HTTPS, SQS, Lambda), event subscription-এর মাধ্যমে; আর EventBridge, যেখানে কোনো subscription ছাড়াই default-এ সব RDS event আসে, আর rule দিয়ে ছেঁকে Lambda, SQS, Step Functions সহ আরও অনেক জায়গায় পাঠানো যায় (chapter 19, lesson 19.5)।
  • পৌঁছায় প্রায় সাথে সাথে: পাঁচ মিনিট পর্যন্ত লাগতে পারে, আর ক্রমের কোনো নিশ্চয়তা নেই।
  • প্রতিটা event-এর একটা ID থাকে, যেমন RDS-EVENT-0049, “A Multi-AZ failover has completed.”
SQL থেকে Lambda ডাকাRDS event notification
কী নিয়েতোমার data: একটা row insert, update, deleteResource: failover, backup, reboot, storage, parameter
ভেতরে কী থাকেSQL যা পাঠায় (নতুন row-টা JSON হিসেবে)Event ID, category, বার্তা, source; data নেই
EngineRDS for PostgreSQL, Aurora PostgreSQL, Aurora MySQLসব RDS engine আর Aurora
শুরু হয়Database-এর একটা trigger বা query থেকেRDS নিজে থেকে
যায়একটা Lambda function-এSNS topic, EventBridge (তারপর যেকোনো জায়গায়)
লাগেবাইরে যাওয়ার network পথ + DB-তে IAM roleএকটা event subscription (SNS) বা EventBridge rule
সময়Statement চলার মধ্যেই (synchronous) বা ঠিক পরে (async)৫ মিনিট পর্যন্ত, ক্রমহীন

Database নিজে Lambda ডাকে, নাকি RDS নিজের খবর জানায়

দুটো আলাদা feature, দুটোই শুরু হয় একটা database থেকে। SQL থেকে Lambda ডাকা তোমার data নিয়ে (নতুন একটা order-এর row)। RDS event notification instance নিয়ে (একটা failover, একটা backup), তাতে data একটুও থাকে না।

পরিস্থিতি

Orders table-এর একটা trigger প্রতিটা নতুন row-এর জন্য একটা function ডাকে।

তোমার VPC
Private subnet
Shop app
Orders DBPostgreSQL
Lambda endpoint
Email function
Email service
নতুন order
ধাপ 1 / 4
1

যে অর্ডারের row যোগ হলো, সেই মুহূর্তেই shop একটা confirmation email চায়, পাঁচটা app-এর যেকোনোটাই row-টা যোগ করুক না কেন। Logic-টা database-এ রাখলে সবগুলোই ধরা পড়ে।

#Data-র পরিবর্তন অন্য উপায়ে ধরা

তুমি যদি আসলে চাও “data-র প্রতিটা পরিবর্তনের একটা ধারা”, analytics বা অন্য service-এর জন্য, তার জন্য বানানো tool আছে, যেগুলো নিজেদের lesson-এ আছে:

  • DynamoDB Streams বা Kinesis Data Streams for DynamoDB → Lambda (lesson 15.5): item-পর্যায়ের পরিবর্তনের জন্য serverless-এর স্বাভাবিক পছন্দ।
  • Zero-ETL integration (Aurora MySQL আর Aurora PostgreSQL, সাথে RDS for MySQL, RDS for PostgreSQL আর RDS for Oracle) কোনো pipeline ছাড়াই প্রায় সাথে সাথে পরিবর্তনগুলো Amazon Redshift-এ পৌঁছে দেয় (lesson 17.2)।
  • Change data capture (CDC) সহ AWS DMS পরিবর্তনগুলো Kinesis, S3 বা অন্য database-এ পাঠায় (lesson 23.3)।

#কোথায় কী ভুল হয়

লক্ষণসম্ভাব্য কারণসমাধান
Private RDS বা ElastiCache-এ connect করতে গিয়ে function timeoutVPC-তে জোড়াই হয়নিSecurity group সহ private subnet-এ জোড়ো
জোড়া হয়েছে, তবু database-এ timeoutDatabase-এর security group function-এর group-কে ঢুকতে দেয় না (বা NACL আটকায়)lambda-sg থেকে DB port-এর inbound rule
VPC-তে জোড়ার পর DynamoDB, S3, Secrets Manager বা internet-এর call আটকে যায়VPC থেকে বের হওয়ার route নেইAWS service-এর জন্য gateway / interface endpoint, internet-এর জন্য NAT gateway
Public subnet-এর function internet-এ যেতে পারে নাLambda ENI কখনো public IP পায় নাPrivate subnet + public subnet-এ NAT gateway
VPC configuration save করতে EC2 permission errorExecution role-এর network interface-এর অনুমতি নেইAWSLambdaVPCAccessExecutionRole লাগাও
নতুন function কয়েক মিনিট PendingHyperplane ENI তৈরি হচ্ছেঅপেক্ষা করো; আগে থেকে থাকা subnet + security group combination ব্যবহার করো
মাসে একবার চলা function প্রথম call-এ ফেল১৪ দিন অলস → Inactive, ENI ফেরত গেছেRetry (EventBridge, SQS আর async invocation নিজেরাই retry করে), ENI টিকে থাকবে ধরে নিও না
একটা AZ-এ গোলমাল হলেই সব বন্ধসব function-এর জন্য একটাই subnet, বা একটাই NAT gateway২+ AZ-এ subnet আর প্রতি AZ-এ একটা NAT gateway
ভিড়ের সময় “too many connections”, database-এর CPU কমConnection-এর ঝড়, প্রতি environment-এ একটা connectionRDS Proxy; connection handler-এর বাইরে খোলো; দরকারে concurrency-তে সীমা
Function RDS Proxy-র endpoint-এ connect করতে পারে নাFunction VPC-তে নেই, বা proxy-র security group-এ rule নেইProxy-র VPC-তে জোড়ো; তার group থেকে port খোলো
Proxy-তে IAM auth ফেলExecution role-এর rds-db:connect নেই, বা TLS নেইProxy resource-এর ওপর অনুমতি দাও; TLS দিয়ে connect করো
Private DB থেকে aws_lambda.invoke ফেল করে বা আটকে থাকেNAT gateway বা Lambda endpoint নেই, বা rds.custom_dns_resolution এখনো 0পথ যোগ করো, parameter বদলাও, reboot করো
Trigger যোগ করার পর insert ধীর হয়ে গেছেTrigger Lambda-কে synchronous ভাবে ডাকে (RequestResponse default)'Event' দাও, function দ্রুত রাখো
Team ভেবেছিল RDS event subscription থেকে “row insert হলো” event আসবেEvent notification শুধু resource-এর খবর দেয়SQL থেকে Lambda ডাকো, বা CDC (DMS, zero-ETL)
NAT gateway-র bill Lambda-র bill-এর চেয়েও বেশিভারী S3/DynamoDB traffic NAT দিয়ে যাচ্ছেGateway endpoint (বিনা খরচে)

#System design-এ Lambda-র networking

  • Default ধরো VPC ছাড়া। Function-কে জোড়ো শুধু তখনই, যখন তার private resource বা নির্দিষ্ট outbound IP লাগে। কম ঝামেলা, NAT-এর bill নেই।
  • জুড়লে: কমপক্ষে দুটো AZ-এর private subnet, এক ধরনের function-এর জন্য একটা security group (যাতে তারা ENI ভাগ করে), আর database ওই group-কে উল্লেখ করে ঢুকতে দেবে।
  • বের হওয়ার রাস্তা প্রথম দিনেই ঠিক করো: প্রতিটা VPC-তে S3 আর DynamoDB-র gateway endpoint (বিনা খরচে), প্রায়ই ডাকা service-এর জন্য interface endpoint, আর internet লাগলে তবেই প্রতি AZ-এ একটা NAT gateway।
  • Relational database + Lambda = RDS Proxy (বা Data API, বা DynamoDB)। কড়া একটা ওপরের সীমা চাইলে reserved concurrency-র সাথে মেলাও।
  • Secret: proxy-তে IAM authentication, database-এর secret Secrets Manager-এ rotation সহ (chapter 21), interface endpoint দিয়ে পৌঁছানো।
  • Database থেকে আসা event: ছোট row-ভিত্তিক কাজের জন্য SQL থেকে asynchronous ভাবে Lambda; operation-এর জন্য EventBridge দিয়ে RDS event notification; data pipeline-এর জন্য DynamoDB Streams, zero-ETL বা DMS।
  • নিয়ম দিয়ে বাঁধো: যেখানে প্রতিটা function VPC-তে থাকতেই হবে সেখানে lambda:VpcIds দিয়ে SCP, আর least privilege-এর জন্য lambda:SourceFunctionArn দিয়ে EC2 action-এ deny।

#নিজে করে দেখো

ap-southeast-1-এ order function, account 111122223333। ID-গুলো বানানো, output ছোট করা।

# 1. Execution role-কে VPC-র অনুমতি দাও, তারপর function-কে দুটো private subnet-এ জোড়ো
aws iam attach-role-policy --role-name order-fn-role-example \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole

aws lambda update-function-configuration --function-name order-example \
  --vpc-config SubnetIds=subnet-0a1b2c3d4e5f60001,subnet-0a1b2c3d4e5f60002,SecurityGroupIds=sg-0lambda1234example
aws lambda get-function-configuration --function-name order-example \
  --query '{state:State,update:LastUpdateStatus,vpc:VpcConfig.VpcId}'
#   { "state": "Active", "update": "InProgress", "vpc": "vpc-0abc1234def567890" }   # ENI তৈরি হচ্ছে
#   ...এক মিনিট পরে: "update": "Successful"

# 2. Hyperplane ENI দেখো (প্রতিটা subnet + security group জোড়ায় একটা)
aws ec2 describe-network-interfaces --filters Name=interface-type,Values=lambda \
  --query 'NetworkInterfaces[].{id:NetworkInterfaceId,ip:PrivateIpAddress,subnet:SubnetId}'
#   [ { "id": "eni-0f1e2d3c4b5a60001", "ip": "10.0.2.15", "subnet": "subnet-0a1b2c3d4e5f60001" },
#     { "id": "eni-0f1e2d3c4b5a60002", "ip": "10.0.3.22", "subnet": "subnet-0a1b2c3d4e5f60002" } ]

# 3. Database-কে function-এর security group থেকে ঢুকতে দাও
aws ec2 authorize-security-group-ingress --group-id sg-0db12345example \
  --protocol tcp --port 5432 --source-group sg-0lambda1234example

# 4. AWS service-এ private পথ: DynamoDB-র জন্য ফ্রি gateway endpoint, Secrets Manager-এর জন্য interface endpoint
aws ec2 create-vpc-endpoint --vpc-id vpc-0abc1234def567890 \
  --service-name com.amazonaws.ap-southeast-1.dynamodb --route-table-ids rtb-0private1example
aws ec2 create-vpc-endpoint --vpc-id vpc-0abc1234def567890 --vpc-endpoint-type Interface \
  --service-name com.amazonaws.ap-southeast-1.secretsmanager --private-dns-enabled \
  --subnet-ids subnet-0a1b2c3d4e5f60001 subnet-0a1b2c3d4e5f60002 --security-group-ids sg-0endpoints1example

# 5. NAT gateway দিয়ে internet (production-এ প্রতি AZ-এ একটা)
aws ec2 create-nat-gateway --subnet-id subnet-0public1example --allocation-id eipalloc-0abc1234example
aws ec2 create-route --route-table-id rtb-0private1example \
  --destination-cidr-block 0.0.0.0/0 --nat-gateway-id nat-0abc1234example

# 6. Orders database-এর সামনে RDS Proxy, IAM auth বাধ্যতামূলক, secret Secrets Manager-এ
aws rds create-db-proxy --db-proxy-name orders-proxy-example --engine-family POSTGRESQL \
  --auth '[{"AuthScheme":"SECRETS","SecretArn":"arn:aws:secretsmanager:ap-southeast-1:111122223333:secret:orders-db-example-AbCdEf","IAMAuth":"REQUIRED"}]' \
  --role-arn arn:aws:iam::111122223333:role/orders-proxy-secret-reader-example \
  --vpc-subnet-ids subnet-0a1b2c3d4e5f60001 subnet-0a1b2c3d4e5f60002 \
  --vpc-security-group-ids sg-0proxy1234example --require-tls
aws rds register-db-proxy-targets --db-proxy-name orders-proxy-example --db-instance-identifiers orders-db-example
aws rds describe-db-proxies --db-proxy-name orders-proxy-example --query 'DBProxies[0].[Status,Endpoint]'
#   [ "available", "orders-proxy-example.proxy-c1a2b3c4d5e6.ap-southeast-1.rds.amazonaws.com" ]

# 7. Database-কে Lambda ডাকতে দাও (RDS for PostgreSQL): lambda:InvokeFunction-ওয়ালা role, feature name Lambda
aws rds add-role-to-db-instance --db-instance-identifier orders-db-example --feature-name Lambda \
  --role-arn arn:aws:iam::111122223333:role/rds-invoke-welcome-example

# 8. Failover হলে DBA-কে খবর দাও
aws rds create-event-subscription --subscription-name orders-db-failover-example \
  --sns-topic-arn arn:aws:sns:ap-southeast-1:111122223333:dba-oncall-example \
  --source-type db-instance --source-ids orders-db-example --event-categories failover availability

Database-এর ভেতরে (psql), ধাপ ৭-এর trigger-এর দিকটা:

CREATE EXTENSION IF NOT EXISTS aws_lambda CASCADE;

CREATE OR REPLACE FUNCTION notify_new_order() RETURNS trigger AS $$
BEGIN
  PERFORM aws_lambda.invoke(
    aws_commons.create_lambda_function_arn('arn:aws:lambda:ap-southeast-1:111122223333:function:welcome-email-example'),
    row_to_json(NEW)::json,
    'Event');               -- asynchronous: INSERT email-এর জন্য অপেক্ষা করে না
  RETURN NEW;
END $$ LANGUAGE plpgsql;

CREATE TRIGGER orders_after_insert AFTER INSERT ON orders
  FOR EACH ROW EXECUTE FUNCTION notify_new_order();

তারপর function-কে আবার VPC থেকে খুলে দাও (--vpc-config SubnetIds=[],SecurityGroupIds=[]) আর দেখো মোটামুটি ২০ মিনিটের মধ্যে তার ENI-গুলো উধাও হয়, যদি না অন্য কোনো function সেগুলো ভাগ করে ব্যবহার করে।

#সারসংক্ষেপ

মূল কথা

  • প্রতিটা Lambda function চলে Lambda service-এর নিজের মালিকানার একটা VPC-তে। Default-এ সে পৌঁছায় internet আর AWS-এর public endpoint-এ, কিন্তু তোমার VPC-র private resource-এ না (RDS, ElastiCache, internal ALB, EC2)।
  • VPC-তে জোড়ো subnet (২+ AZ) আর security group দিয়ে; execution role-এর লাগে AWSLambdaVPCAccessExecutionRole-এর ENI-অনুমতি। Lambda প্রতিটা subnet + security group জোড়ায় একটা ভাগাভাগির Hyperplane ENI বানায় (একবার কয়েক মিনিট Pending; cold start বাড়ে না; ১৪ দিন অলস থাকলে ফেরত নেয় → Inactive, প্রথম call ফেল)।
  • Database-এর security group port খোলে function-এর security group থেকে। Timeout মানে network; error বার্তা মানে credential।
  • VPC function-এর internet নেই, AWS-এর public endpoint-ও নেই, public subnet-এ রাখলেও না (তার ENI কখনো public IP পায় না)। Internet-এর জন্য private subnet + public subnet-এ NAT gateway (প্রতি AZ-এ একটা), AWS-এর জন্য gateway endpoint (S3, DynamoDB, বিনা খরচে) আর interface endpoint (বাকি বেশিরভাগ service)।
  • Lambda + relational database = connection-এর ঝড় (প্রতি environment-এ একটা connection)। RDS Proxy connection pool আর multiplex করে, failover পেরিয়েও ধরে রাখে (৬৬% পর্যন্ত দ্রুত), IAM authentication বাধ্যতামূলক করে আর credential রাখে Secrets Manager-এ, আর কখনো public হয় না, তাই function-কে VPC-তে থাকতে হয়। বিকল্প: Data API, DynamoDB, সীমা হিসেবে reserved concurrency।
  • RDS for PostgreSQL, Aurora PostgreSQL আর Aurora MySQL SQL থেকে Lambda ডাকতে পারে (data-র ঘটনা); লাগে বাইরে যাওয়ার পথ (public, NAT, বা Lambda VPC endpoint) আর lambda:InvokeFunction-ওয়ালা IAM role। 'Event' না দিলে aws_lambda.invoke synchronous।
  • RDS event notification জানায় resource-এর খবর (failover, backup, reboot), তাতে data থাকে না, যায় SNS বা EventBridge-এ, আসে মোটামুটি ৫ মিনিটের মধ্যে আর ক্রমহীন। Data-র পরিবর্তনের জন্য DynamoDB Streams, zero-ETL বা DMS CDC।