Fargateタスクからgsutil
コマンドを実行し、S3にアクセスする際、Caught exception reading instance data
というエラーが出て、認証に失敗する事象についてです。
結論
gsutil
コマンドの仕様です(執筆時点)- タスクロールではなく環境変数でAWSの認証情報を指定することで対応可能です
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- AWS_DEFAULT_REGION
以下、詳細です。
事象詳細
S3に対する適切な権限を付与しているIAMロールをFargateタスクのタスクロールに指定している状態にも関わらず、gsutil
コマンドを利用してS3にアクセスすると、下記のようなエラーが発生するといった事象です。
権限設定、シンタックス等に間違いはないため、例えば、EC2上で同じことを行った場合は処理が正常に完了します。つまり、Fargateタスクで実行する際に特有の事象です。
エラー
ERROR 0904 05:23:14.152952 utils.py] Caught exception reading instance data
Traceback (most recent call last):
File "/usr/lib/python3.7/urllib/request.py", line 1324, in do_open
encode_chunked=req.has_header('Transfer-encoding'))
File "/usr/lib/python3.7/http/client.py", line 1244, in request
self._send_request(method, url, body, headers, encode_chunked)
File "/usr/lib/python3.7/http/client.py", line 1290, in _send_request
self.endheaders(body, encode_chunked=encode_chunked)
File "/usr/lib/python3.7/http/client.py", line 1239, in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
File "/usr/lib/python3.7/http/client.py", line 1026, in _send_output
self.send(msg)
File "/usr/lib/python3.7/http/client.py", line 966, in send
self.connect()
File "/usr/lib/python3.7/http/client.py", line 938, in connect
(self.host,self.port), self.timeout, self.source_address)
File "/usr/lib/python3.7/socket.py", line 727, in create_connection
raise err
File "/usr/lib/python3.7/socket.py", line 716, in create_connection
sock.connect(sa)
OSError: [Errno 22] Invalid argument
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/google-cloud-sdk/platform/gsutil/gslib/vendored/boto/boto/utils.py", line 220, in retry_url
r = opener.open(req, timeout=timeout)
File "/usr/lib/python3.7/urllib/request.py", line 525, in open
response = self._open(req, data)
File "/usr/lib/python3.7/urllib/request.py", line 543, in _open
'_open', req)
File "/usr/lib/python3.7/urllib/request.py", line 503, in _call_chain
result = func(*args)
File "/usr/lib/python3.7/urllib/request.py", line 1352, in http_open
return self.do_open(http.client.HTTPConnection, req)
File "/usr/lib/python3.7/urllib/request.py", line 1326, in do_open
raise URLError(err)
urllib.error.URLError: <urlopen error [Errno 22] Invalid argument>
ERROR 0904 05:23:14.154281 utils.py] Unable to read instance data, giving up
Caught non-retryable exception while listing s3://XXXXX/YYYYY/ZZZZZ/: No handler was ready to authenticate. 1 handlers were checked. ['S3HmacAuthV4Handler'] Check your credentials
CommandException: Caught non-retryable exception - aborting rsync
原因
gsutil
コマンドの仕様です(執筆時点)。
下記のように関連Issuesがあります。初回報告が2016年で、現在オープン中のものは2020年に報告されたものなので、対応としては優先順位が低いものと想定されます。したがって、修正されるまで待つというよりも、後述の対応を行った方がよろしいかと存じます。
- gsutil has no handler when accessing s3 bucket.
- AWS Fargate Task – Caught exception reading instance data
対応
環境変数を利用する
AWS Fargate Task – Caught exception reading instance dataにも記載がありますが、AWSの認証情報をIAMロールではなく環境変数で指定することで対応可能です。
なお、上記Issueに記載された環境変数ではなく、AWS CLI を設定する環境変数に記載のある次の3つの環境変数を指定することでも動作することが確認できました。つまり、上記のIssueに記載のあるAWS_SECURITY_TOKEN
は明示的に指定していません。
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- AWS_DEFAULT_REGION
また、上記のIssueではFargateタスクのコンテナ内部でコマンドを実行することで対応を行っていますが、Fargateはパラメータストアに保存した機密情報を簡単に環境変数に指定する機能があります。
好みの問題かもしれませんが、自前で実装するよりも簡単なので、次のページを参照してパラメータストアから情報を渡す構成をお勧め致します。
Amazon ECS タスクで秘密情報や機密情報をコンテナに安全に渡す方法を教えてください。
ローカルストレージを利用する
gsutil
コマンドでS3にアクセスするということは、GCSとS3間でファイルを連携するといった実装を行っているものと思われます。
セキュリティポリシー的にAWS側でキーの発行ができないといったような場合、一時的にローカルストレージにファイルをダウンロードするといった方式も考えられます。
例: GCS→ローカル→S3 or S3→ローカル→GCS
その場合、ファイルが200 GiB未満ならば、ローカルストレージ上で対応可能です。
デフォルトでは、プラットフォームバージョン 1.4.0 以降を使用して Fargate でホストされる Amazon ECS タスクは、後に最低 20 GiB のエフェメラルストレージを受け取ります。エフェメラルストレージの総量は、タスク定義で ephemeralStorage パラメータを指定することで、最大 200 GiB まで増やすことができます。
Fargate タスクストレージ
ファイルが200 GiB以上の場合は、次のようにEFSをFargateにマウントし、その領域を利用するといった方法が考えられます。
Fargate で実行されている Amazon ECS コンテナまたはタスクに Amazon EFS ファイルシステムをマウントする方法を教えてください。
コメント