Amazon Redshift からデータを挿入または抽出するときに、AWS Glue ジョブが「一時ディレクトリが指定されていません」というエラーで失敗します。
簡単な説明
AWS Glue ジョブが Amazon Redshift からデータを書き込んだり読み込んだりするときに覚えておくべき点をいくつか挙げます。
- **AWS Glue ジョブが Amazon Redshift クラスターにデータを書き込む場合:**ジョブは、最初に CSV 形式で Amazon Simple Storage Service (Amazon S3) バケットにデータを書き込みます。次に、ジョブは Amazon Redshift に COPY コマンドを発行します。
- **AWS Glue ジョブが Amazon Redshift クラスターからデータを読み取る場合:**ジョブは、最初に UNLOAD コマンドを使用して CSV 形式で Amazon S3 バケットにデータをアンロードします。次に、ジョブはこれらの一時的なバケットファイルから DynamicFrame にデータをロードします。
このエラーは、次のいずれかの条件に当てはまる場合に発生する可能性があります。
- Amazon Redshift から一時的な S3 バケットにデータをアンロードしている。
- COPY または UNLOAD コマンドを使用して S3 バケットから Amazon Redshift にデータをロードしている。
解決方法
このエラーの一般的な原因と解決方法の一部を次に示します。
一時ディレクトリを定義する
このエラーの最も一般的な原因は、AWS Glue ジョブがステージングディレクトリとして使用する一時的な S3 バケットがないことです。したがって、S3 バケットをジョブの一時ディレクトリとして定義してください。一時バケットの定義方法の詳細については、「AWS Glue で使用される特別なパラメータ」を参照してください。
IAM ロールのアクセス許可を確認する
IAM ロールのアクセス許可を確認し、一時的な S3 バケットにアクセスするための適切なアクセス許可があることを確認します。また、AWS Glue IAM ロールの次のポリシーで、バケットに必要なアクセス許可をブロックしていないことを確認してください。
- バケットポリシー
- S3 VPC エンドポイントポリシー
- AWS Organizations ポリシー
- サービスコントロールポリシー
必要なアクセス許可の例としては、ListObjects、GetObject、PutObject などがあります。
一時ディレクトリの名前を確認する
次の例外が発生しないように、一時ディレクトリとして使用される S3 バケットの名前にピリオドが含まれていないことを確認してください。
Caused by: java.sql.SQLException: [Amazon](500310) Invalid operation: UNLOAD destination is not supported.
AWS Key Management Service (AWS KMS) のアクセス許可を確認する
AWS Key Management Service (AWS KMS) のカスタマーマネージドキーを使用してデータを暗号化する場合は、AWS Glue スクリプトの ETL ステートメントの additional_options に必ずextraunloadoptions を含めてください。以下はその例です。
datasource0 = glueContext.create_dynamic_frame.from_catalog(
database = "database-name",
table_name = "table-name",
redshift_tmp_dir = args["TempDir"],
additional_options = {"extraunloadoptions":"ENCRYPTED KMS_KEY_ID 'CMK key ID'"},
transformation_ctx = "datasource0"
)
AWS KMS を使用して S3 データを暗号化し、AWS KMS に関連するアクセス許可の問題に直面している場合は、次の点を確認してください。
- AWS Glue IAM ロールに以下のような AWS KMS アクションのアクセス許可がある。
- AWS Glue IAM ロールを AWS KMS キーに追加してある。
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
]
AWS Glue Python Shell ジョブの IAM ロールのアクセス許可を確認する。
AWS Glue Python Shell ジョブから COPY コマンドまたは UNLOAD コマンドを実行しようとしていて、認証情報をロードできていない場合は、次の点を確認してください。
- AWS Glue IAM ロールを Amazon Redshift に追加してある。
- AWS Glue ジョブロールで、信頼関係ポリシーに Amazon Redshift と AWS Glue が含まれている。以下はその例です。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"glue.amazonaws.com",
"redshift.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
パケットドロップの確認
接続が成功した後でもクエリが Amazon Redshift クラスターに到達できないのは、Amazon Redshift と AWS Glue ネットワークパス間の最大伝送単位 (MTU) サイズの不一致が原因である可能性があります。ICMP の「宛先に到達できない」を許可するように Amazon Redshift セキュリティグループを設定してみてください。詳細については、クエリがハングして、クラスターに達しない場合があるを参照してください。
AWS CloudFormation テンプレートで一時ディレクトリを定義する
CloudFormation を使用して AWS Glue ジョブを作成した場合は、CloudFormation テンプレートの DefaultArguments パラメータで一時ディレクトリの場所を指定していることを確認してください。以下はその例です。
"DefaultArguments": { "--TempDir": "s3://doc-example-bucket/doc-example-folder"}
DynamicFrame で一時ディレクトリを定義する
AWS Glue ジョブで一時ディレクトリを定義した後でもエラーが発生した場合は、Amazon Redshift で読み書きしているかどうかを確認してください。これを行うには、AWS Glue の DynamicFrame メソッドを使用します。この場合、以下を確認します。
一時ディレクトリを DynamicFrame の redshift_tmp_dir プロパティに渡してある。
ETL ジョブの getResolvedOptions 関数で TempDir が指定されている。
次のコマンドを使用して、ジョブ名と TempDir パラメータを取得します。
import sys
from awsglue.utils import getResolvedOptions
args = getResolvedOptions(sys.argv,['JOB_NAME','TempDir'])
TempDir = args['TempDir']
詳細については、「getResolvedOptionsを使用したパラメータへのアクセス」を参照してください。
関連情報
Amazon Redshift との間でデータを移動する