Amazon Redshift でクエリを実行する AWS Lambda 関数を作成したいと考えています。
解決策
**前提条件: ** Amazon Virtual Private Cloud エンドポイントを設定するには、次の手順を実行します。
- プライベートサブネットを持つ VPC を作成する。
- サブネットグループを作成する。先ほど作成した VPC とサブネットを追加する。
- プライベート Amazon Redshift クラスターを作成する。先ほど作成した VPC とサブネットグループを選択する。
- AWS Secrets Manager で Amazon Redshift 用の新しいシークレットを作成する。シークレットネームとして redshift を入力する。
Lambda 関数を作成する
Amazon Redshift クラスターにクエリを実行する Lambda 関数を作成するには、次の手順を実行します。
- Lambda コンソールを開く。
- [Create function] (関数の作成) を選択する。
- [Author from Scratch] (一から作成) オプションを選択する。
- 次のフィールドを更新します。
[Function name] (関数名) に、カスタム名を入力する。
[Runtime] (ランタイム) に、コード環境を入力する。
**注: ** この解決策の例は Python 3.9 に対応しています。
[Architecture] (アーキテクチャ) に、システムアーキテクチャを入力する。
**注: ** この解決策の例は x86_64 に対応しています。
[Permissions] (アクセス許可) で [Create a new role with basic Lambda permissions] (基本的な Lambda アクセス許可を持つ新しいロールを作成) を選択する。
- [Create function] (関数の作成) を選択する。
Lambda 関数にアクセス許可を設定する
次の手順を実行します。
- Lambda コンソールを開く。
- [Configuration] (設定) を選択する。
- [Permissions] (アクセス許可) を選択する。
- Lambda 関数用に作成されたロールを選択する。
- [Add Permissions] (アクセス許可を追加) を選択する。
- [Attach policies] (ポリシーをアタッチ) を選択する。
- AmazonRedshiftDataFullAccess および SecretsManagerReadWrite ポリシーを Lambda 実行ロールに追加します。
**注: ** タスクの実行に必要なアクセス許可のみを最小特権で付与することはベストプラクティスです。
Python コードを Lambda 関数に追加する
次の例では、Lambda が Amazon Redshift データベースに接続し、public スキーマに lambda_func テーブルを作成します。
次の手順を実行します。
-
Lambda コンソールを開く。
-
[Code] (コード) を選択する。
-
[Code] (コード) ボックスに次のコードを入力する。
import os
import json
import boto3
import botocore
import botocore.session as bc
from botocore.client import Config
print('Loading function')
secret_name=os.environ['SecretId'] # getting SecretId from Environment varibales
session = boto3.session.Session()
region = session.region_name
# Initializing Secret Manager's client
client = session.client(
service_name='secretsmanager',
region_name=region
)
get_secret_value_response = client.get_secret_value(
SecretId=secret_name
)
secret_arn=get_secret_value_response['ARN']
secret = get_secret_value_response['SecretString']
secret_json = json.loads(secret)
cluster_id=secret_json['dbClusterIdentifier']
# Initializing Botocore client
bc_session = bc.get_session()
session = boto3.Session(
botocore_session=bc_session,
region_name=region
)
# Initializing Redshift's client
config = Config(connect_timeout=5, read_timeout=5)
client_redshift = session.client("redshift-data", config = config)
def lambda_handler(event, context):
print("Entered lambda_handler")
query_str = "create table public.lambda_func (id int);"
try:
result = client_redshift.execute_statement(Database= 'dev', SecretArn= secret_arn, Sql= query_str, ClusterIdentifier= cluster_id)
print("API successfully executed")
except botocore.exceptions.ConnectionError as e:
client_redshift_1 = session.client("redshift-data", config = config)
result = client_redshift_1.execute_statement(Database= 'dev', SecretArn= secret_arn, Sql= query_str, ClusterIdentifier= cluster_id)
print("API executed after reestablishing the connection")
return str(result)
except Exception as e:
raise Exception(e)
return str(result)
**注: ** dev をデータベース名に置き換えてください。
-
Lambda 関数の設定セクションに、キー SecretId と secret_name の環境変数を追加してください。