Unable to locate credentials
のエラーで、SageMaker instanceのlocal training jobが実行できないときの対処法をまとめます。
はじめに
SageMakerでは、SageMaker Python SDKを利用して簡単にtraining job/学習ジョブを実行することができます。
SageMaker SDKのtraining jobには、
- オンデマンドに別インスタンスが立ち上がってジョブを実行する通常ジョブ
- 作業中のNotebookインスタンス上でジョブを実行するlocalジョブ
の2種類があります。
この後者、local training jobを実行する際に、Unable to locate credentials
エラーが発生してジョブが実行できない現象に遭遇しました。
対処法を見つけたので、備忘録としてまとめておきます。
SageMakerでlocal training jobが実行できない時の対処法
事象
- SageMaker instanceでlocal training jobを実行した際に、ジョブコンテナで
Unable to locate credentials
エラーが発生してジョブが異常終了する
ただし、私はまだ確実なエラー再現手順を特定できてません。
同様の現象は下記のようにいくつか報告があがっています:
- Local mode: role chaining/assumed role on notebook instances does not forward correct credentials · Issue #3464 · aws/sagemaker-python-sdk · GitHub
- amazon web services - Assume Sagemaker Notebook instance role from Docker container with default network mode - Stack Overflow
原因
- ジョブ実行コンテナからインスタンスメタデータエンドポイント(
169.254.169.254
)にアクセスできていないこと
インスタンスメタデータエンドポイント(169.254.169.254
)は、インスタンスのメタデータを取得するためのリンクローカルアドレスです。
Localのジョブ実行コンテナがインスタンスに付与されたIAM権限を参照/Token取得する際に、このエンドポイントにアクセスする必要があります。
しかし、このエンドポイントにアクセスできていないことで、ジョブ実行コンテナがIAMのTokenを取得できない = 権限を取得できない = Unable to locate credentials
、という状況です。
対処法
- 下記のようなスクリプトを実行し、ジョブ実行コンテナから
169.254.169.254
へアクセスできるように設定変更する
#!/bin/bash # check if we need to configure our docker interface SAGEMAKER_NETWORK=`docker network ls | grep -c sagemaker-local` if [ $SAGEMAKER_NETWORK -eq 0 ]; then docker network create --driver bridge sagemaker-local fi # Get the Docker Network CIDR and IP for the sagemaker-local docker interface. SAGEMAKER_INTERFACE=br-`docker network ls | grep sagemaker-local | cut -d' ' -f1` DOCKER_NET=`ip route | grep $SAGEMAKER_INTERFACE | cut -d" " -f1` DOCKER_IP=`ip route | grep $SAGEMAKER_INTERFACE | cut -d" " -f9` # check if both IPTables and the Route Table are OK. IPTABLES_PATCHED=`sudo iptables -S PREROUTING -t nat | grep -c $SAGEMAKER_INTERFACE` ROUTE_TABLE_PATCHED=`sudo ip route show table agent | grep -c $SAGEMAKER_INTERFACE` if [ $ROUTE_TABLE_PATCHED -eq 0 ]; then # fix routing sudo ip route add $DOCKER_NET via $DOCKER_IP dev $SAGEMAKER_INTERFACE table agent echo "route tables for Docker setup done" else echo "SageMaker instance route table setup is ok. We are good to go." fi if [ $IPTABLES_PATCHED -eq 0 ]; then # fix ip table sudo iptables -t nat -A PREROUTING -i $SAGEMAKER_INTERFACE -d 169.254.169.254/32 -p tcp -m tcp --dport 80 -j DNAT --to-destination 169.254.0.2:9081 echo "iptables for Docker setup done" else echo "SageMaker instance routing for Docker is ok. We are good to go!" fi
重要なのは下記2つの設定変更部分です。
# fix routing sudo ip route add $DOCKER_NET via $DOCKER_IP dev $SAGEMAKER_INTERFACE table agent # fix ip table sudo iptables -t nat -A PREROUTING -i $SAGEMAKER_INTERFACE -d 169.254.169.254/32 -p tcp -m tcp --dport 80 -j DNAT --to-destination 169.254.0.2:9081
SageMaker SDKのlocal training jobでは、sagemaker-local
という名前のdocker networkが利用されます (存在しない場合は作成する処理をスクリプト冒頭で行っています)。
このsagemaker-local
を変更(ip routeの追加とiptablesのdestination変更)することによって、ジョブ実行コンテナから169.254.169.254
へアクセスできるようになる -> インスタンスメタデータ取得できるようになる -> IAM権限Tokenを取得できるようになる、で、エラーを解消できました。
※上記スクリプトは、AWS公式が提供しているSageMaker examples内で見つけたセットアップスクリプトから一部を抽出/改変したものです。
おわりに
以上、Unable to locate credentials
エラーでSageMakerのlocal training jobが実行できないときの対処法をまとめました。
再現方法が特定できていないなどモヤモヤが残る部分はありますが、取り急ぎ解決にたどり着くことができました。
思わぬハマりポイントだったので、この記事が同じ目に遭ったどなたかの参考になれば幸いです。
[関連記事]
参考
Access instance metadata for an EC2 instance - Amazon Elastic Compute Cloud