結論
AWSでLambdaをVPCに配置して、エンドポイント経由でboto3 SQSを使用する際にはendpoint_urlオプションが必要。
import boto3
sqs = boto3.client("sqs", endpoint_url="https://sqs.ap-northeast-1.amazonaws.com")
sqs.send_message(...)
このオプションを付けないと、接続できなくてタイムアウトします。
詳細
AWSでLambaをVPCに配置してプライベート接続でSQSを使用する際にめちゃはまったので注意点をメモします。
詳細は以下のサイトが詳しいのでそちらを参照して下さい。私が試した時はLambda上でboto3を使用した際にのみ現象が発生しました。
私の発生条件ではLambdaのboto3はバージョン1.14.48でした。また、EC2を立てて試したバージョンは1.16.8でしたが、こちらでも同様の現象が発生しました。
- AWS CLI等でSQS VPC Endpointを利用するときの注意点 -- https://blog.serverworks.co.jp/tech/2019/03/18/sqsvpcendpoint/
- Unable Connect do SQS if using a VPC -- https://github.com/boto/boto3/issues/1900
1.の記事によると、AWS CLI(今回の現象をみるにboto3も含む)ではSQSに接続する際にQueueUrlを指定していても、レガシーエンドポイントに接続しようとするというのが問題になっているようです。
VPCでSQSのエンドポイントを作成すると、sqs.ap-northeast-1.amazonaws.com (現行エンドポイント)はプライベートIPが割り当てられるのですが、ap-northeast-1.queue.amazonaws.com (レガシーエンドポイント)はパブリックIPのままとなります。
その状態で、boto3でSQSを使用しようとすると、接続する際にレガシーエンドポイントを使用しようとして、接続できずにタイムアウト、というのが原因のようです。
2.のGitHubの中ではSessionを使った解決方法が示されていますが、boto3.client()
を実行する際に上記のようにendpoint_url
オプションに現行エンドポイントを指定すれば問題は解決しました。
参考までにGitHubの記事中のSessionによる解決コードは以下です。
import boto3
session = boto3.Session()
sqs_client = session.client(
service_name='sqs',
endpoint_url='https://sqs.ap-northeast-1.amazonaws.com',
)
sqs_client.send_message(...)
…2時間ぐらいはまりました。