Lambda Kết Nối RDS Private Subnet: Cấu Hình VPC, Subnet và Security Group

Lambda không thể kết nối được RDS trong private subnet là một trong những lỗi phổ biến nhất khi mới bắt đầu làm việc với kiến trúc serverless — và cũng là lỗi dễ mất nhiều giờ nhất vì nó thường không trả về thông báo lỗi rõ ràng, chỉ là timeout. Bài viết này giải thích cơ chế hoạt động, lý do tại sao cần cấu hình VPC cho Lambda khi kết nối RDS private subnet, và từng bước cấu hình chính xác.

TL;DR — Lambda Kết Nối RDS Private Subnet

Vấn đềNguyên nhânGiải pháp
Lambda timeout khi kết nối RDSLambda chạy ngoài VPC, không thể reach private subnetGắn Lambda vào VPC, đúng subnet và Security Group
Lambda trong VPC mất internetPrivate subnet không có NAT GatewayDùng VPC Endpoint hoặc thêm NAT Gateway
Vẫn timeout dù đã cấu hình VPCSecurity Group inbound rule thiếu hoặc sai portCho phép inbound từ Lambda SG đến RDS SG trên port DB
RDS không nhận kết nốiRDS Security Group chưa có rule cho LambdaThêm inbound rule trên RDS SG tham chiếu Lambda SG

Cơ Chế Hoạt Động: Tại Sao Lambda Cần VPC Để Kết Nối RDS Private

Mặc định, Lambda function chạy trong một môi trường compute do AWS quản lý — nằm ngoài VPC của bạn. Điều này có nghĩa là nó có thể gọi các AWS service endpoint công khai và internet, nhưng hoàn toàn không thể reach bất kỳ resource nào trong private subnet của VPC bạn, bao gồm RDS instance.

Khi bạn bật VPC configuration cho Lambda, AWS sẽ tạo một Elastic Network Interface (ENI) trong subnet bạn chỉ định. ENI này là 'chân' của Lambda trong VPC — mọi traffic từ Lambda đến RDS đều đi qua ENI này, tuân theo đầy đủ routing rules, Network ACL, và Security Group của VPC.

graph TD A["Lambda Function
(không có VPC config)"] -->|"Không thể reach"| B["RDS trong Private Subnet"] C["Lambda Function
(có VPC config)"] -->|"Traffic qua ENI"| D["ENI trong Private Subnet"] D -->|"Security Group check"| E["RDS Security Group"] E -->|"Inbound rule: allow từ Lambda SG"| F["RDS Instance"] G["Lambda SG"] -.->|"source-group reference"| E style A fill:#f66,color:#fff style B fill:#f66,color:#fff style C fill:#6a6,color:#fff style D fill:#69b,color:#fff style E fill:#f90,color:#fff style F fill:#6a6,color:#fff style G fill:#69b,color:#fff
  1. Lambda không có VPC config: Function chạy trong AWS-managed network, không thể reach private subnet. Mọi kết nối đến RDS đều bị drop ngay từ network layer.
  2. Lambda có VPC config: AWS tạo ENI trong subnet được chỉ định. Lambda traffic đi qua ENI, tuân theo Security Group rules.
  3. Security Group chain: RDS Security Group phải có inbound rule cho phép traffic từ Lambda Security Group — không phải từ IP cụ thể.
  4. Subnet routing: Lambda và RDS phải ở trong subnet có thể route đến nhau (thường là cùng VPC, cùng AZ hoặc AZ khác trong cùng VPC).

Lambda Kết Nối RDS Private Subnet: Từng Bước Cấu Hình

Bước 1: Xác Định Subnet và Security Group Của RDS

Trước khi cấu hình Lambda, cần biết chính xác RDS đang nằm ở subnet nào và đang dùng Security Group nào. Đây là bước nhiều người bỏ qua, dẫn đến việc đặt Lambda vào subnet không thể route đến RDS.

# Lấy thông tin subnet và security group của RDS instance
aws rds describe-db-instances \
  --db-instance-identifier ten-rds-cua-ban \
  --query 'DBInstances[0].{VpcId:DBSubnetGroup.VpcId,Subnets:DBSubnetGroup.Subnets[*].SubnetIdentifier,SGIds:VpcSecurityGroups[*].VpcSecurityGroupId}' \
  --output json

Ghi lại VPC ID, danh sách Subnet ID, và Security Group ID của RDS. Lambda phải được đặt vào cùng VPC.

Bước 2: Tạo Security Group Riêng Cho Lambda

Không nên dùng chung Security Group giữa Lambda và RDS. Tạo một SG riêng cho Lambda — điều này cho phép bạn tham chiếu Lambda SG trong inbound rule của RDS SG một cách rõ ràng, thay vì phải quản lý IP range.

# Tạo Security Group cho Lambda
aws ec2 create-security-group \
  --group-name lambda-rds-sg \
  --description 'Security Group cho Lambda ket noi RDS' \
  --vpc-id vpc-0xxxxxxxxxxxxxxxx

# Lưu lại GroupId từ output, ví dụ: sg-0aaaaaaaaaaaaaaa1

Lambda Security Group không cần inbound rule nào — chỉ cần outbound rule (mặc định đã cho phép tất cả outbound). Đây là điểm nhiều người nhầm: Lambda SG không cần inbound, RDS SG mới cần inbound từ Lambda SG.

Bước 3: Thêm Inbound Rule Vào RDS Security Group

Đây là bước quan trọng nhất và cũng là nơi hay bị bỏ sót. RDS Security Group phải cho phép inbound traffic từ Lambda Security Group trên đúng port của database engine.

# Thêm inbound rule cho RDS Security Group
# Cho phép traffic từ Lambda SG trên port MySQL/Aurora (3306)
aws ec2 authorize-security-group-ingress \
  --group-id sg-0rdsrdsrdsrdsrds2 \
  --protocol tcp \
  --port 3306 \
  --source-group sg-0aaaaaaaaaaaaaaa1

# Nếu dùng PostgreSQL, thay port 3306 bằng 5432
# Nếu dùng SQL Server, thay bằng 1433

Lưu ý: --source-group nhận Security Group ID của Lambda, không phải CIDR block. Cách này tốt hơn dùng IP range vì ENI của Lambda có thể thay đổi IP.

Bước 4: Gắn VPC Configuration Vào Lambda Function

Bây giờ cấu hình Lambda để chạy trong VPC. Chọn subnet trong cùng VPC với RDS — nên chọn ít nhất 2 subnet ở các AZ khác nhau để đảm bảo availability. Các subnet này phải có thể route đến RDS (thường là private subnet trong cùng VPC là đủ).

# Cập nhật VPC config cho Lambda function
aws lambda update-function-configuration \
  --function-name ten-lambda-cua-ban \
  --vpc-config SubnetIds=subnet-0xxxxxxxx1,subnet-0xxxxxxxx2,SecurityGroupIds=sg-0aaaaaaaaaaaaaaa1

Sau lệnh này, AWS sẽ tạo ENI trong các subnet được chỉ định. Quá trình này có thể mất vài phút. Kiểm tra trạng thái:

# Kiểm tra VPC config đã được áp dụng
aws lambda get-function-configuration \
  --function-name ten-lambda-cua-ban \
  --query 'VpcConfig'

Bước 5: Cấp IAM Permission Cho Lambda Để Quản Lý ENI

Lambda cần quyền tạo và xóa ENI trong VPC của bạn. Nếu thiếu permission này, Lambda sẽ không thể khởi động trong VPC và bạn sẽ thấy lỗi liên quan đến ec2:CreateNetworkInterface. AWS cung cấp managed policy AWSLambdaVPCAccessExecutionRole bao gồm các quyền cần thiết.

# Gắn managed policy vào Lambda execution role
aws iam attach-role-policy \
  --role-name ten-execution-role-cua-lambda \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole

Policy này bao gồm các quyền: ec2:CreateNetworkInterface, ec2:DescribeNetworkInterfaces, và ec2:DeleteNetworkInterface. Đây là minimum required permissions cho Lambda VPC access.

Bước 6: Kiểm Tra Kết Nối

Sau khi cấu hình xong, test bằng cách invoke Lambda và kiểm tra log. Nếu vẫn timeout, kiểm tra theo thứ tự: Network ACL của subnet (thường bị bỏ qua), sau đó route table của subnet, cuối cùng là Security Group rules.

# Invoke Lambda và xem log ngay
aws lambda invoke \
  --function-name ten-lambda-cua-ban \
  --log-type Tail \
  --payload '{}' \
  --query 'LogResult' \
  --output text \
  response.json | base64 --decode

Vấn Đề Phổ Biến: Lambda Trong VPC Mất Kết Nối Internet

Khi Lambda chạy trong VPC, nó mất khả năng truy cập internet mặc định — trừ khi subnet có route đến NAT Gateway hoặc Internet Gateway. Đây là trade-off quan trọng cần hiểu trước khi deploy.

graph LR subgraph VPC subgraph PrivateSubnet["Private Subnet"] L["Lambda ENI"] R["RDS Instance"] end NAT["NAT Gateway
(Public Subnet)"] VPE["VPC Endpoint
(Secrets Manager)"] end IGW["Internet Gateway"] EXT["External API / Internet"] AWS["AWS Services"] L -->|"DB query"| R L -->|"Cần internet"| NAT NAT --> IGW IGW --> EXT L -->|"AWS service call
(không qua internet)"| VPE VPE --> AWS style L fill:#6a6,color:#fff style R fill:#69b,color:#fff style NAT fill:#f90,color:#fff style VPE fill:#f90,color:#fff style IGW fill:#aaa,color:#fff style EXT fill:#ccc style AWS fill:#f90,color:#fff
  1. Lambda trong private subnet không có NAT: Chỉ có thể reach resource trong VPC. Không thể gọi API bên ngoài, không thể download package.
  2. Lambda trong private subnet có NAT Gateway: Có thể reach internet qua NAT. Phù hợp khi Lambda cần cả RDS lẫn external API.
  3. VPC Endpoint: Cho phép Lambda trong private subnet gọi AWS services (S3, Secrets Manager, v.v.) mà không cần NAT Gateway. Đây là cách tiết kiệm chi phí hơn cho AWS-to-AWS traffic.

Nghĩ về Lambda VPC config như việc cắm một dây mạng vào switch của VPC. Trước khi cắm, Lambda có wifi riêng ra internet. Sau khi cắm vào switch nội bộ, nó chỉ thấy mạng nội bộ — muốn ra internet phải đi qua cổng của mạng nội bộ đó (NAT Gateway).

Kinh Nghiệm Thực Tế: Lỗi Timeout Sau Khi Đã Cấu Hình Đúng

Có một tình huống khá phổ biến: cấu hình VPC, subnet, Security Group đều đúng, nhưng Lambda vẫn timeout khi kết nối RDS. Log không có gì ngoài Task timed out after X seconds.

Chẩn đoán sai đầu tiên: Hầu hết mọi người sẽ kiểm tra lại Security Group — thêm rule, xóa rule, thử lại. Không có gì thay đổi.

Nguyên nhân thực sự: Network ACL của subnet đang block traffic. Network ACL là stateless — không giống Security Group (stateful), Network ACL cần cả inbound outbound rule cho cả hai chiều của kết nối. Nếu Network ACL của subnet chứa Lambda hoặc subnet chứa RDS có deny rule, kết nối sẽ bị drop ở tầng subnet trước khi Security Group có cơ hội xử lý.

# Kiểm tra Network ACL của subnet Lambda đang dùng
aws ec2 describe-network-acls \
  --filters Name=association.subnet-id,Values=subnet-0xxxxxxxx1 \
  --query 'NetworkAcls[0].{Inbound:Entries[?Egress==`false`],Outbound:Entries[?Egress==`true`]}' \
  --output json

Kiểm tra xem có rule nào với RuleAction: deny đang match port database (3306, 5432) không. Default Network ACL cho phép tất cả traffic, nhưng custom ACL thường có deny rules.

Đây là ví dụ điển hình của việc Security Group và Network ACL là hai lớp kiểm soát độc lập — pass được SG không có nghĩa là pass được ACL.

Cấu Hình Bảo Mật: Dùng Secrets Manager Thay Vì Hardcode Credentials

Khi Lambda đã kết nối được RDS, bước tiếp theo là đảm bảo credentials không bị hardcode trong code hoặc environment variable. AWS Secrets Manager tích hợp trực tiếp với RDS và hỗ trợ rotation tự động.

# IAM policy cho phép Lambda đọc secret
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "secretsmanager:GetSecretValue",
      "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:rds-credentials-xxxxxx"
    }
  ]
}

Nếu Lambda đang chạy trong private subnet không có NAT Gateway, cần tạo VPC Endpoint cho Secrets Manager để Lambda có thể reach service này mà không cần internet.

# Tạo VPC Endpoint cho Secrets Manager
aws ec2 create-vpc-endpoint \
  --vpc-id vpc-0xxxxxxxxxxxxxxxx \
  --vpc-endpoint-type Interface \
  --service-name com.amazonaws.us-east-1.secretsmanager \
  --subnet-ids subnet-0xxxxxxxx1 subnet-0xxxxxxxx2 \
  --security-group-ids sg-0aaaaaaaaaaaaaaa1

Tổng Kết và Bước Tiếp Theo

Để Lambda kết nối được RDS trong private subnet, cần đủ bốn yếu tố: Lambda phải có VPC configuration với đúng subnet và Security Group; RDS Security Group phải có inbound rule từ Lambda Security Group; Lambda execution role phải có quyền quản lý ENI; và subnet phải không bị block bởi Network ACL. Thiếu bất kỳ yếu tố nào trong số này đều dẫn đến timeout.

Tài liệu tham khảo chính thức:

Glossary — Thuật Ngữ Chính

Thuật ngữGiải thích
ENI (Elastic Network Interface)Card mạng ảo trong VPC. Lambda tạo ENI trong subnet được chỉ định để có thể giao tiếp với resource trong VPC.
Security GroupStateful firewall ở cấp resource (instance/ENI). Cho phép hoặc từ chối traffic dựa trên rule. Stateful nghĩa là response traffic tự động được cho phép.
Network ACLStateless firewall ở cấp subnet. Cần rule cho cả hai chiều traffic. Được đánh giá trước Security Group.
NAT GatewayCho phép resource trong private subnet gửi traffic ra internet mà không cần public IP. Cần thiết nếu Lambda trong VPC cần gọi API bên ngoài.
VPC EndpointKết nối private từ VPC đến AWS services mà không đi qua internet. Có hai loại: Gateway (S3, DynamoDB) và Interface (hầu hết các service còn lại).

Related Posts

Nhận xét

Bài đăng phổ biến từ blog này

EC2 Không Có Internet Trong Custom VPC: Cách Gắn Internet Gateway và Cập Nhật Route Table

RDS Multi-AZ: Lợi Ích Thực Sự Là Gì và Khi Nào Nên Bật?

Lỗi CORS trên API Gateway: Cách bật CORS và Lambda phải trả về header gì