How does Function Compute access RDS?

更新时间:
复制 MD 格式

Function Compute accesses Alibaba Cloud Relational Database Service (RDS) through a virtual private cloud (VPC). By placing your function and your RDS instance in the same VPC, you establish a private network path between them without exposing database traffic to the public internet.

Prerequisites

Before you configure access, make sure you have:

  • An RDS instance and a Function Compute function deployed in the same region

  • Both the RDS instance and the function configured to use the same VPC

  • The RDS instance IP address whitelist configured to allow inbound traffic from the function's VPC CIDR block or private IP range

  • A RAM role or RAM user with permissions to read the database credentials (recommended: store credentials in Alibaba Cloud KMS or environment variables, not hardcoded in function code)

Configure VPC access for your function

To connect your function to RDS, configure the function's network settings to use the VPC where your RDS instance runs.

For step-by-step configuration instructions, see Configure network settings.

After the VPC binding is complete, your function can reach the RDS instance using the instance's private endpoint (intranet connection string), available on the RDS console under Database Connection.

Connect to RDS in your function code

Use the RDS private endpoint and port in your connection string. Store credentials as environment variables to avoid hardcoding sensitive information.

Important

Do not hardcode database passwords in your function code or configuration files. Use environment variables or a secrets management service such as Alibaba Cloud KMS to inject credentials at runtime.

The following examples show how to connect to an RDS MySQL instance from a Function Compute function.

Python

import os
import pymysql

def handler(event, context):
    connection = pymysql.connect(
        host=os.environ['RDS_HOST'],        # RDS private endpoint, e.g. rm-xxxx.mysql.rds.aliyuncs.com
        port=int(os.environ['RDS_PORT']),   # Default MySQL port: 3306
        user=os.environ['RDS_USER'],
        password=os.environ['RDS_PASSWORD'],
        database=os.environ['RDS_DB_NAME'],
        connect_timeout=5
    )
    try:
        with connection.cursor() as cursor:
            cursor.execute('SELECT 1')
            result = cursor.fetchone()
        return str(result)
    finally:
        connection.close()

Java

import com.aliyun.fc.runtime.Context;
import com.aliyun.fc.runtime.StreamRequestHandler;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.io.InputStream;
import java.io.OutputStream;

public class RDSHandler implements StreamRequestHandler {
    @Override
    public void handleRequest(InputStream input, OutputStream output, Context context) throws Exception {
        String host = System.getenv("RDS_HOST");
        String port = System.getenv("RDS_PORT");
        String user = System.getenv("RDS_USER");
        String password = System.getenv("RDS_PASSWORD");
        String dbName = System.getenv("RDS_DB_NAME");

        String url = String.format("jdbc:mysql://%s:%s/%s", host, port, dbName);
        try (Connection conn = DriverManager.getConnection(url, user, password);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery("SELECT 1")) {
            if (rs.next()) {
                output.write(rs.getString(1).getBytes());
            }
        }
    }
}

Node.js

const mysql = require('mysql2/promise');

exports.handler = async (event, context) => {
    const connection = await mysql.createConnection({
        host: process.env.RDS_HOST,      // RDS private endpoint
        port: parseInt(process.env.RDS_PORT, 10),
        user: process.env.RDS_USER,
        password: process.env.RDS_PASSWORD,
        database: process.env.RDS_DB_NAME,
        connectTimeout: 5000
    });
    try {
        const [rows] = await connection.execute('SELECT 1');
        return JSON.stringify(rows);
    } finally {
        await connection.end();
    }
};

Go

package main

import (
    "database/sql"
    "fmt"
    "os"

    _ "github.com/go-sql-driver/mysql"
    "github.com/aliyun/fc-runtime-go-sdk/fc"
)

func HandleRequest() (string, error) {
    dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?timeout=5s",
        os.Getenv("RDS_USER"),
        os.Getenv("RDS_PASSWORD"),
        os.Getenv("RDS_HOST"),
        os.Getenv("RDS_PORT"),
        os.Getenv("RDS_DB_NAME"),
    )
    db, err := sql.Open("mysql", dsn)
    if err != nil {
        return "", err
    }
    defer db.Close()

    var result string
    err = db.QueryRow("SELECT 1").Scan(&result)
    if err != nil {
        return "", err
    }
    return result, nil
}

func main() {
    fc.Start(HandleRequest)
}

Set the following environment variables on your function:

VariableDescriptionExample
RDS_HOSTRDS private endpoint (intranet connection string)rm-xxxx.mysql.rds.aliyuncs.com
RDS_PORTDatabase port3306
RDS_USERDatabase usernameappuser
RDS_PASSWORDDatabase passwordSet via KMS or secret injection
RDS_DB_NAMETarget database namemydb

Troubleshoot connection issues

SymptomLikely causeResolution
Connection timeoutFunction and RDS are in different VPCs, or the VPC binding is incompleteVerify that both resources use the same VPC; re-check the function's network configuration
Access deniedIncorrect credentials or missing database user permissionsConfirm the database username and password; grant the user access to the target database
IP address whitelist blocks connectionRDS IP address whitelist does not include the function's private IP rangeAdd the VPC CIDR block to the RDS IP address whitelist
Cannot resolve hostnameFunction is not bound to the VPC where RDS runsComplete VPC configuration as described in Configure network settings