すべてのプロダクト
Search
ドキュメントセンター

Function Compute:RDS MySQL にアクセスするためのベストプラクティス

最終更新日:Apr 30, 2025

Function Compute では、状態は異なる実行環境インスタンス間で共有されません。データベースを使用して構造化データを永続化することで、状態の共有を実現できます。Function Compute を使用すると、クラウドデータベースに対してデータクエリやデータ挿入などの操作を実行できます。このトピックでは、Python 関数を例として使用して、同じ VPC 内または VPC とリージョンを跨いで ApsaraDB RDS for MySQL にアクセスする方法について説明します。

前提条件

手順

ステップ 1: データベースのホワイトリストを構成する

シナリオ 1: 同じ VPC 内の RDS データベースにアクセスする

同じ VPC 内のデータベースにアクセスする場合、データベースインスタンスと関数が同じリージョンにあることを確認してください。Function Compute がサポートするゾーンにデータベースインスタンスを作成することをお勧めします。詳細については、「Function Compute がサポートするゾーン」をご参照ください。データベースインスタンスが Function Compute でサポートされていないゾーンにある場合は、Function Compute と同じゾーンの VPC に vSwitch を作成し、関数の VPC 構成でこの vSwitch ID を使用できます。同じ VPC 内の vSwitch はプライベートネットワークを介して相互に通信できます。そのため、Function Compute は vSwitch を使用して、他のゾーンにある VPC のリソースにアクセスできます。詳細については、「vSwitch がサポートされていないゾーンにある場合のエラーが発生した場合の対処方法」をご参照ください。

  1. Function Compute コンソール にログインし、Python Web 関数を作成し、関数の VPC アクセスを有効にして、ターゲット VPC リソースを構成します。

    説明

    関数に構成された VPC が、データベースインスタンスが接続されている VPC と同じであることを確認してください。

    image

  2. 関数の詳細ページで、[構成] > [ネットワーク] を選択し、[ネットワーク] ページで、関数構成の vSwitch の CIDR ブロックを取得します。

    image

  3. 前のステップで取得した vSwitch の CIDR ブロックをデータベースアクセスホワイトリストに追加します。

    重要

    IP アドレスホワイトリストを使用して、関数がデータベースにアクセスすることを承認します。セキュリティグループモードを使用しないでください。そうしないと、関数がデータベースに接続できない場合があり、ビジネスに影響します。

    1. RDS インスタンスリスト にアクセスし、上部でリージョンを選択して、ターゲットインスタンス ID をクリックします。

    2. 左側のナビゲーションバーで、ホワイトリストとセキュリティグループ をクリックします。

      ホワイトリストの設定 ページで、現在の IP ホワイトリストモードを表示できます。

      説明

      既存の RDS インスタンスは、拡張ホワイトリストモードで実行される場合があります。すべての新しい RDS インスタンスは、標準ホワイトリストモードで実行されます。

    3. [変更] グループの右側にある [デフォルト] をクリックします。表示される [ホワイトリストグループの変更] ダイアログボックスで、ステップ 2 で取得した vSwitch の IPv4 CIDR ブロックをホワイトリストに構成し、[OK] をクリックします。

      image

    構成が完了すると、関数はデータベースの内部エンドポイントを介して RDS データベースにアクセスできます。

シナリオ 2: VPC またはリージョンを跨いで RDS データベースにアクセスする

異なる VPC とリージョンは、互いに完全に論理的に分離されています。一般に、VPC やリージョンを跨いでデータベースにアクセスすることはできません。 VPC またはリージョンを跨いでデータベースにアクセスする必要がある場合は、関数に固定パブリック IP アドレスを構成できます。この場合、システムは関数が接続されている VPC にパブリック NAT ゲートウェイを作成します。パブリックゲートウェイを使用して、パブリック IP アドレスを介してデータベースにアクセスできます。

  1. Function Compute コンソール にログインします。左側のナビゲーションウィンドウで、[関数] をクリックし、リージョンを選択して、プロンプトに従って 関数を作成 します。

  2. 関数の詳細ページで、[構成] > [ネットワーク] を選択します。[ネットワーク] パネルで、関数の固定パブリック IP アドレスを構成し、[デプロイ] をクリックします。

    image

  3. 表示される [固定パブリック IP 構成] ダイアログボックスで、プロンプトのチェックボックスをオンにして、[OK] をクリックします。構成が完了したら、[デフォルトの NIC がインターネットにアクセスすることを許可する] パラメーターを [いいえ] に設定して、構成済みの固定パブリック IP アドレスを有効にします。

  4. 関数の詳細ページで、[構成] > [ネットワーク] を選択し、[ネットワーク] ページで、関数に構成されている固定パブリック IP アドレスを取得します。

    image

  5. 前のステップで取得した関数の固定パブリック IP アドレスをデータベースアクセスホワイトリストに追加します。

    重要

    IP アドレスホワイトリストを使用して、関数がデータベースにアクセスすることを承認します。セキュリティグループモードを使用しないでください。そうしないと、関数がデータベースに接続できない場合があり、ビジネスに影響します。

    1. RDS インスタンスリスト にアクセスし、上部でリージョンを選択して、ターゲットインスタンス ID をクリックします。

    2. 左側のナビゲーションバーで、ホワイトリストとセキュリティグループ をクリックします。

      ホワイトリストの設定 ページで、現在の IP ホワイトリストモードを表示できます。

      説明

      既存の RDS インスタンスは、拡張ホワイトリストモードで実行される場合があります。すべての新しい RDS インスタンスは、標準ホワイトリストモードで実行されます。

    3. [変更] グループの右側にある [デフォルト] をクリックします。表示される [ホワイトリストグループの変更] ダイアログボックスで、ステップ 2 で取得した vSwitch の IPv4 CIDR ブロックをホワイトリストに構成し、[OK] をクリックします。

      image

    構成が完了すると、関数はデータベースのパブリックエンドポイントを介して RDS データベースにアクセスできます。

ステップ 2: 関数で RDS にアクセスする

  1. Function Compute コンソール にログインし、関数リストでターゲット関数を見つけ、関数の詳細ページで [コード] タブをクリックし、コードエディターで次のサンプルコードを記述します。

    from flask import Flask, jsonify
    import pymysql
    import os
    from datetime import datetime
    import logging
    
    app = Flask(__name__)
    
    # MySQL シングルトン接続を格納するグローバル変数
    _mysql_connection = None
    
    # データベース接続を作成する(シングルトンパターン)
    def getConnection():
        global _mysql_connection
        try:
            # 接続が既に存在し、切断されていない場合は、それを直接返す
            if _mysql_connection is not None:
                try:
                    # 接続が有効かどうかをテストする(簡単なコマンドテスト)
                    with _mysql_connection.cursor() as cursor:
                        cursor.execute("SELECT 1")  # 接続状態をテストするための簡単なクエリ
                        result = cursor.fetchone()
                        if result and result[0] == 1:
                            return _mysql_connection
                except pymysql.OperationalError:
                    # 接続が切断されている場合は、リセットする
                    _mysql_connection = None
    
            # 接続が存在しないか、切断されている場合は、再作成する
            _mysql_connection = pymysql.connect(
                host=os.environ['MYSQL_HOST'],
                port=int(os.environ['MYSQL_PORT']),
                user=os.environ['MYSQL_USER'],
                password=os.environ['MYSQL_PASSWORD'],
                db=os.environ['MYSQL_DBNAME']
            )
            return _mysql_connection
        except Exception as e:
            logging.error(f"データベース接続中にエラーが発生しました: {e}")
            raise
    
    
    @app.route('/', defaults={'path': ''})
    @app.route('/<path:path>', methods=['GET', 'POST', 'PUT', 'DELETE'])
    def hello_world(path):
        conn = getConnection()
        try:
            with conn.cursor() as cursor:
                # users テーブルのすべてのレコードをクエリする。users テーブルは実際のテーブル名に応じて変更する
                sql = "SELECT * FROM users"
                cursor.execute(sql)
                result = cursor.fetchall()
                
                columns = [desc[0] for desc in cursor.description]  # フィールド名リストを取得する
    
                # クエリ結果を辞書リストに変換する
                users = []
                for row in result:
                    user = {}
                    for idx, column_name in enumerate(columns):
                        value = row[idx]
                        if isinstance(value, datetime):  # 日付タイプのフィールドを処理する
                            user[column_name] = value.strftime('%Y-%m-%d %H:%M:%S')
                        else:
                            user[column_name] = value
                    users.append(user)
                    
                if users:
                    # すべてのユーザーの JSON レスポンスを返す
                    return jsonify(users), 200
                else:
                    # ユーザーが見つからない場合は、404 エラーを返す
                    return jsonify({'error': 'ユーザーが見つかりません'}), 404
    
        except Exception as e:
            logging.error(f"データベース操作中にエラーが発生しました: {e}")
            return jsonify({'error': 'データベースエラー'}), 500
    
    
    if __name__ == '__main__':
        app.run(host='0.0.0.0', port=9000)
    
    
  2. 関数の詳細ページで、[構成] > [環境変数] を選択し、[編集] をクリックして、[環境変数] パネルで次の環境変数を構成します。

    環境変数名

    環境変数値

    説明

    MYSQL_HOST

    rm-bp19u8e76ae****.mysql.rds.aliyuncs.com

    データベースインスタンスのエンドポイント。

    • 同じ VPC 内の RDS データベース シナリオを選択した場合は、この環境変数をデータベースの内部エンドポイントに設定します。

    • VPC またはリージョンを跨いで RDS データベースにアクセスする シナリオを選択した場合は、この環境変数をデータベースのパブリックエンドポイントに設定します。

    RDS インスタンスリスト で、ターゲット RDS インスタンス ID をクリックします。左側のナビゲーションウィンドウで、[データベース接続] をクリックします。[データベース接続] ページで、データベースの内部エンドポイントまたはパブリックエンドポイントを取得します。

    MYSQL_DBNAME

    db_test

    RDS インスタンスに作成されたデータベースの名前。

    MYSQL_PASSWORD

    *****

    データベースアカウントのパスワード。

    MYSQL_PORT

    3306

    データベースインスタンスのプライベートポート。

    MYSQL_USER

    dms_user_****

    RDS インスタンスへの接続に使用するアカウントのユーザー名。

  3. 関数の詳細ページで、[コード] タブをクリックし、[関数のテスト] をクリックして、正常に実行された後に返された結果を表示します。テーブルクエリ操作は正常に完了しました。

    image

詳細情報

  • RDS MySQL データベースにアクセスするその他の例については、「Function Compute Python が MySQL データベースにアクセスする」をご参照ください。

  • データベースアクセスに失敗した場合は、問題の症状に基づいてトラブルシューティングを行う必要があります。詳細については、「データベースアクセス失敗の一般的な原因」をご参照ください。

  • ApsaraDB RDS は、MySQL、SQL Server、PostgreSQL、および MariaDB データベースエンジンをサポートしています。詳細については、「ApsaraDB RDS とは」をご参照ください。

  • Serverless Devs コマンドラインツールを使用して関数を作成し、RDS MySQL データベースにアクセスする場合は、次の手順に従います。

    ここをクリックして Serverless Devs の手順を表示する

    1. Serverless Devs と Docker をインストールし、キー情報を追加します。 詳細については、「クイックスタート」をご参照ください。

    2. コードディレクトリ mycode を作成し、s.yaml ファイルとコードファイル app.py を準備します。以下は、s.yaml ファイルの例です。サンプルコードについては、ステップ 2: 関数で RDS にアクセスする で提供されているサンプルコードを参照してください。

      次の s.yaml の例は、同じ VPC 内の RDS データベースにアクセスするシナリオに適用されます。 VPC またはリージョンを跨いでデータベースにアクセスする必要がある場合は、「シナリオ 2: VPC またはリージョンを跨いで RDS データベースにアクセスする」をご参照ください。

      # ------------------------------------
      #   公式マニュアル: https://manual.serverless-devs.com/user-guide/aliyun/#fc3
      #   ヒント: https://manual.serverless-devs.com/user-guide/tips/
      #   ご質問がある場合は、DingTalk グループ 33947367 に参加してください
      # ------------------------------------
      edition: 3.0.0
      name: hello-world-app
      access: "default"
      
      vars: # グローバル変数
        region: "cn-hangzhou"  # 同じ VPC 内の RDS データベースにアクセスすることを選択した場合は、RDS データベースと同じリージョンに関数がデプロイされていることを確認してください
      
      resources:
        hello_world:
          component: fc3 
          actions:       
            pre-${regex('deploy|local')}: 
              - component: fc3 build 
          props:
            region: ${vars.region}              
            functionName: "start-python-0t1m"
            runtime: custom.debian10
            description: 'hello world by serverless devs'
            timeout: 10
            memorySize: 512
            cpu: 0.5
            diskSize: 512
            code: ./code
            customRuntimeConfig:
              port: 9000
              command:
                - python3
                - app.py
            internetAccess: true
            vpcConfig:
             vpcId: vpc-bp1dxqii29fpkc8pw**** # データベースインスタンスが存在する VPC の ID
             securityGroupId: sg-bp12ly2ie92ixrfc**** # セキュリティグループ ID
             vSwitchIds: 
              - vsw-bp1ty76ijntee9z83**** # この vSwitch の CIDR ブロックがデータベースインスタンスアクセスホワイトリストに構成されていることを確認してください
            environmentVariables:
              PYTHONPATH: /code/python
              PATH: /code/python/bin:/var/fc/lang/python3.10/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin
              MYSQL_HOST: rm-bp1j1y7657640z5****.mysql.rds.aliyuncs.com  # データベースインスタンスの内部エンドポイント
              MYSQL_PORT: "3306"  # データベースインスタンスのプライベートポート
              MYSQL_USER: dms_user_****  # データベースインスタンスに作成されたデータベース
              MYSQL_PASSWORD: ****   # データベースインスタンスのパスワード
              MYSQL_DBNAME: db_test  # データベースインスタンスに作成されたデータベースの名前
    3. 次のコマンドを実行して、プロジェクトをビルドします。

      sudo s build --use-docker
    4. 次のコマンドを実行して、プロジェクトをデプロイします。

      sudo s deploy -y
    5. 次のコマンドを実行して、関数を呼び出します。

      説明

      関数に構成した vSwitch の CIDR ブロックまたは固定パブリック IP アドレスが、データベースインスタンスアクセスホワイトリストに追加されていることを確認してください。詳細については、ステップ 3 を参照してください。

      sudo s invoke -e "{}"