Lambda Tidak Bisa Konek ke RDS Private Subnet: Konfigurasi VPC yang Wajib Dipahami

Skenario ini muncul hampir di setiap tim yang baru memindahkan database ke private subnet: Lambda function berjalan normal, RDS instance statusnya available, tapi koneksi selalu timeout. Tidak ada error message yang jelas, tidak ada log di CloudWatch yang menunjukkan RDS menolak koneksi — hanya diam, lalu timeout. Masalah ini hampir selalu berakar pada satu hal: Lambda function tidak dikonfigurasi untuk berjalan di dalam VPC yang sama dengan RDS.

TL;DR: Lambda ke RDS Private Subnet

Aspek Detail
Apakah Lambda perlu VPC config? Ya, wajib jika RDS berada di private subnet
Parameter yang dibutuhkan Subnet IDs dan Security Group IDs
Subnet yang dipilih Private subnet di VPC yang sama dengan RDS
Security Group Lambda Harus diizinkan sebagai sumber di inbound rule SG RDS
IAM Permission tambahan ec2:CreateNetworkInterface, ec2:DescribeNetworkInterfaces, ec2:DeleteNetworkInterface
Risiko umum Cold start lebih lambat, NAT Gateway diperlukan untuk akses internet

Bagaimana Lambda Terhubung ke Resource di VPC

Secara default, Lambda function berjalan di lingkungan komputasi yang dikelola AWS — bukan di dalam VPC milik akun kamu. Ini berarti Lambda tidak memiliki akses jaringan langsung ke resource yang berada di private subnet, termasuk RDS instance.

Ketika kamu mengaktifkan VPC configuration pada Lambda, AWS akan membuat Elastic Network Interface (ENI) di subnet yang kamu tentukan. ENI inilah yang menjadi 'kaki' Lambda di dalam VPC kamu. Traffic dari Lambda ke RDS mengalir melalui ENI ini, mengikuti routing table dan security group rules yang berlaku di subnet tersebut.

Satu hal yang sering disalahpahami: Lambda tidak 'pindah' ke VPC kamu. Execution environment Lambda tetap dikelola AWS, tapi koneksi jaringannya di-proxy melalui ENI yang ada di VPC kamu.

graph LR LE["Lambda Execution Environment"] -->|traffic melalui| ENI["ENI di Private Subnet (dibuat otomatis AWS)"] ENI -->|melewati| SGLA["Security Group Lambda (outbound: allow port DB)"] SGLA -->|diperiksa oleh| SGRDS["Security Group RDS (inbound: allow dari SG Lambda)"] SGRDS --> RDS["RDS Instance di Private Subnet"] style LE fill:#FF9900,color:#fff style ENI fill:#232F3E,color:#fff style SGLA fill:#1A73E8,color:#fff style SGRDS fill:#1A73E8,color:#fff style RDS fill:#2E7D32,color:#fff
  1. Lambda Execution Environment — berjalan di infrastruktur AWS yang dikelola, bukan di VPC akun kamu.
  2. ENI (Elastic Network Interface) — dibuat otomatis oleh AWS di private subnet yang kamu konfigurasi. Ini adalah titik koneksi Lambda ke VPC kamu.
  3. Security Group Lambda — dikaitkan ke ENI. Outbound rule SG ini harus mengizinkan traffic ke port RDS (default 5432 untuk PostgreSQL, 3306 untuk MySQL).
  4. Security Group RDS — inbound rule-nya harus mengizinkan traffic dari Security Group Lambda (bukan dari IP address).
  5. RDS di Private Subnet — tidak memiliki public IP, hanya bisa diakses dari dalam VPC melalui jalur jaringan yang valid.

Langkah Diagnosis: Kenapa Koneksi Lambda ke RDS Gagal

Langkah 1: Verifikasi VPC Configuration pada Lambda

Titik awal yang paling sering terlewat — banyak engineer mengasumsikan Lambda sudah terkonfigurasi VPC karena function-nya sudah ada di region yang sama dengan RDS. Cek dulu apakah Lambda function kamu benar-benar memiliki VPC config yang aktif.

aws lambda get-function-configuration \
  --function-name nama-function-kamu \
  --query 'VpcConfig' \
  --region us-east-1

Jika output menunjukkan VpcId kosong atau SubnetIds adalah array kosong, Lambda kamu belum dikonfigurasi untuk berjalan di dalam VPC. Ini adalah penyebab paling umum dari connection timeout ke RDS private subnet.

Langkah 2: Pastikan Subnet yang Dipilih Berada di VPC yang Sama dengan RDS

Setelah konfirmasi VPC config ada, langkah berikutnya adalah memastikan subnet yang dikonfigurasi di Lambda adalah subnet yang berada di VPC yang sama dengan RDS — bukan hanya region yang sama. VPC yang berbeda tidak bisa saling berkomunikasi tanpa VPC Peering atau Transit Gateway.

aws rds describe-db-instances \
  --db-instance-identifier nama-rds-kamu \
  --query 'DBInstances[0].{VpcId:DBSubnetGroup.VpcId,Subnets:DBSubnetGroup.Subnets[*].SubnetIdentifier}' \
  --region us-east-1

Bandingkan VpcId dari output di atas dengan VpcId yang dikonfigurasi di Lambda. Keduanya harus identik.

Langkah 3: Periksa Security Group Rules — Ini yang Paling Sering Salah

Ini adalah titik kegagalan nomor satu di lapangan. Lambda dan RDS masing-masing memiliki Security Group, dan keduanya harus dikonfigurasi dengan benar. Connection timeout tanpa error di sisi aplikasi hampir selalu berarti traffic diblokir di layer Security Group atau Network ACL — bukan karena RDS menolak koneksi.

Cek Security Group yang dikaitkan ke Lambda function:

aws lambda get-function-configuration \
  --function-name nama-function-kamu \
  --query 'VpcConfig.SecurityGroupIds' \
  --region us-east-1

Cek inbound rules pada Security Group RDS:

aws ec2 describe-security-groups \
  --group-ids sg-xxxxxxxx \
  --query 'SecurityGroups[0].IpPermissions' \
  --region us-east-1

Yang harus ada di inbound rule Security Group RDS: izin traffic pada port database (misalnya 5432 untuk PostgreSQL) dengan sumber berupa Security Group ID Lambda, bukan CIDR block. Menggunakan Security Group sebagai sumber lebih aman dan tidak bergantung pada IP address yang bisa berubah.

graph TD A["Koneksi Lambda ke RDS Timeout"] --> B{"Apakah Lambda punya VPC Config?"} B -->|Tidak| C["Tambahkan VPC Config: Subnet IDs + SG IDs"] B -->|Ya| D{"Apakah VPC Lambda sama dengan RDS?"} D -->|Tidak| E["Gunakan subnet di VPC yang sama dengan RDS"] D -->|Ya| F{"Apakah SG RDS izinkan SG Lambda?"} F -->|Tidak| G["Tambahkan inbound rule di SG RDS dari SG Lambda"] F -->|Ya| H{"Apakah IAM Role punya EC2 ENI permission?"} H -->|Tidak| I["Attach AWSLambdaVPCAccessExecutionRole atau tambahkan custom policy"] H -->|Ya| J["Cek Network ACL dan routing table subnet"] style A fill:#D32F2F,color:#fff style C fill:#2E7D32,color:#fff style E fill:#2E7D32,color:#fff style G fill:#2E7D32,color:#fff style I fill:#2E7D32,color:#fff style J fill:#FF9900,color:#fff

Langkah 4: Verifikasi IAM Role Lambda Memiliki Permission untuk Membuat ENI

Lambda membutuhkan permission EC2 untuk membuat dan mengelola ENI di VPC kamu. Tanpa permission ini, Lambda tidak bisa attach ke VPC sama sekali — dan error-nya sering muncul saat deployment, bukan saat runtime, sehingga mudah terlewat jika kamu tidak memantau deployment logs.

aws iam get-role-policy \
  --role-name nama-execution-role-lambda \
  --policy-name nama-policy \
  --region us-east-1

Atau cek managed policies yang di-attach ke role:

aws iam list-attached-role-policies \
  --role-name nama-execution-role-lambda

AWS Managed Policy AWSLambdaVPCAccessExecutionRole sudah mencakup permission yang dibutuhkan untuk VPC access. Jika kamu menggunakan custom policy, pastikan policy tersebut mengizinkan ec2:CreateNetworkInterface, ec2:DescribeNetworkInterfaces, dan ec2:DeleteNetworkInterface.

Konfigurasi VPC pada Lambda: Cara yang Benar

Menggunakan AWS CLI

Berikut cara mengkonfigurasi VPC pada Lambda function yang sudah ada:

aws lambda update-function-configuration \
  --function-name nama-function-kamu \
  --vpc-config SubnetIds=subnet-aaaaaaaa,subnet-bbbbbbbb,SecurityGroupIds=sg-xxxxxxxx \
  --region us-east-1

Gunakan minimal dua subnet di Availability Zone yang berbeda untuk ketahanan. Jika satu AZ mengalami gangguan, Lambda masih bisa membuat ENI di AZ lain.

IAM Policy untuk Lambda Execution Role

Jika kamu menggunakan custom IAM policy (bukan AWS Managed Policy), berikut permission minimum yang dibutuhkan:

🔽 Klik untuk melihat IAM Policy JSON
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:CreateNetworkInterface",
        "ec2:DescribeNetworkInterfaces",
        "ec2:DeleteNetworkInterface",
        "ec2:DescribeSubnets",
        "ec2:DescribeSecurityGroups",
        "ec2:DescribeVpcs"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/nama-function-kamu:*"
    }
  ]
}

Perhatikan bahwa action ec2:CreateNetworkInterface dan sejenisnya membutuhkan "Resource": "*" — ini bukan kelalaian, tapi memang requirement dari AWS Service Authorization Reference untuk action-action tersebut.

Security Group Rule untuk RDS

Tambahkan inbound rule ke Security Group RDS yang mengizinkan traffic dari Security Group Lambda:

aws ec2 authorize-security-group-ingress \
  --group-id sg-rds-xxxxxxxx \
  --protocol tcp \
  --port 5432 \
  --source-group sg-lambda-xxxxxxxx \
  --region us-east-1

Ganti port 5432 dengan port yang sesuai engine database kamu (MySQL: 3306, PostgreSQL: 5432, MariaDB: 3306, SQL Server: 1433).

Pola Kegagalan yang Sering Terjadi di Produksi

Ada satu skenario yang berulang kali muncul: engineer mengkonfigurasi VPC pada Lambda dengan benar, Security Group sudah tepat, tapi koneksi tetap timeout secara intermittent — tidak selalu gagal, tapi kadang-kadang.

Gejala: Connection timeout terjadi acak, terutama setelah Lambda tidak dipanggil beberapa menit. CloudWatch tidak menunjukkan error eksplisit dari RDS.

Diagnosis awal yang salah: Tim mengasumsikan ini masalah RDS — mungkin connection pool habis, atau RDS instance perlu di-scale up. Mereka menambah instance size, tapi masalah tetap ada.

Penyebab sebenarnya: Ini adalah efek dari ENI provisioning pada Lambda cold start. Ketika Lambda mengalami cold start di VPC, ada tambahan waktu untuk attach ENI ke execution environment. Jika database connection timeout di sisi aplikasi dikonfigurasi terlalu pendek (misalnya 3 detik), koneksi gagal sebelum ENI selesai di-attach. Solusinya adalah menyesuaikan connection timeout di kode aplikasi, atau menggunakan RDS Proxy yang mengelola connection pooling dan mengurangi dampak cold start.

Bayangkan ENI seperti kabel LAN yang harus dicolokkan setiap kali Lambda 'bangun' dari tidur. Proses colok kabel ini butuh waktu — dan jika aplikasi kamu tidak sabar menunggu, koneksi gagal sebelum kabel terpasang.

Pertimbangan Penting Setelah Lambda Masuk VPC

Akses Internet dari Lambda di VPC

Setelah Lambda dikonfigurasi di VPC, function tersebut kehilangan akses internet langsung — termasuk akses ke AWS public endpoints seperti S3, DynamoDB, atau Secrets Manager melalui jalur publik. Ini bukan bug, ini adalah perilaku yang diharapkan dari private subnet.

Ada dua opsi untuk mengembalikan akses ke layanan AWS dari Lambda yang ada di VPC:

  • NAT Gateway — untuk akses internet umum dan AWS public endpoints. Perlu dikonfigurasi di public subnet dengan route table yang tepat.
  • VPC Endpoints — untuk akses ke layanan AWS spesifik (S3, DynamoDB, Secrets Manager, dll.) tanpa melalui internet. Lebih efisien dari sisi biaya dan latensi untuk traffic ke AWS services.

Jika Lambda kamu perlu mengambil database credentials dari Secrets Manager, pastikan kamu membuat VPC Endpoint untuk Secrets Manager — atau Lambda tidak bisa mengambil credentials tersebut dari dalam VPC.

Verifikasi Akhir: Test Koneksi

Setelah semua konfigurasi selesai, deploy ulang Lambda dan test dengan invocation sederhana. Pantau CloudWatch Logs untuk memastikan tidak ada error ENI creation:

aws lambda invoke \
  --function-name nama-function-kamu \
  --payload '{}' \
  --cli-binary-format raw-in-base64-out \
  --log-type Tail \
  --region us-east-1 \
  output.json

Cek juga ENI yang dibuat oleh Lambda di VPC kamu untuk konfirmasi:

aws ec2 describe-network-interfaces \
  --filters Name=description,Values='AWS Lambda VPC ENI*' \
            Name=vpc-id,Values=vpc-xxxxxxxx \
  --query 'NetworkInterfaces[*].{ENI:NetworkInterfaceId,SubnetId:SubnetId,Status:Status}' \
  --region us-east-1

Wrap-Up: Lambda Connecting to Private RDS — Checklist Final

Menghubungkan Lambda ke RDS di private subnet bukan hal yang rumit, tapi ada beberapa layer yang harus benar semua secara bersamaan. Satu layer yang salah cukup untuk membuat koneksi gagal tanpa pesan error yang jelas.

  • ✅ Lambda VPC config aktif dengan Subnet IDs dan Security Group IDs
  • ✅ Subnet Lambda berada di VPC yang sama dengan RDS
  • ✅ Security Group RDS memiliki inbound rule dari Security Group Lambda
  • ✅ Lambda execution role memiliki permission EC2 untuk ENI management
  • ✅ VPC Endpoint atau NAT Gateway dikonfigurasi jika Lambda perlu akses ke AWS services lain
  • ✅ Connection timeout di kode aplikasi cukup panjang untuk mengakomodasi cold start

Untuk referensi lebih lanjut, lihat dokumentasi resmi AWS: Configuring a Lambda function to access resources in a VPC dan Connecting Lambda to an RDS database.

Glossary: Istilah Kunci

Istilah Penjelasan
ENI (Elastic Network Interface) Interface jaringan virtual di VPC. Lambda membuat ENI di subnet yang dikonfigurasi untuk mendapatkan akses jaringan ke resource di VPC.
Private Subnet Subnet yang tidak memiliki route langsung ke Internet Gateway. Resource di sini tidak bisa diakses dari internet secara langsung.
Security Group Firewall stateful di level instance/ENI. Mengontrol traffic masuk (inbound) dan keluar (outbound) berdasarkan protokol, port, dan sumber/tujuan.
VPC Endpoint Koneksi privat dari VPC ke layanan AWS tanpa melalui internet publik. Menghindari kebutuhan NAT Gateway untuk traffic ke AWS services.
RDS Proxy Managed proxy untuk RDS yang mengelola connection pooling. Mengurangi overhead pembukaan koneksi baru, berguna untuk workload Lambda yang bersifat serverless.

Related Posts

Komentar

Postingan populer dari blog ini

EBS vs EFS untuk Multiple EC2 Instance: Cara Berbagi Folder Antar Instance

Memahami Instance T3 Burstable: Cara Kerja CPU Credits dan Kenapa Server Tiba-tiba Melambat

EC2 Tidak Bisa Akses Internet di Custom VPC: Cara Pasang Internet Gateway dan Update Route Table