AWS EMR PySpark Worker创建Boto3 Client失败(ProfileNotFound)
我搭建了一个AWS EMR集群,使用以下引导脚本安装依赖库:
#!/bin/bash # Install needed libraries sudo pip3 install pandas==1.3.5 awswrangler==2.19.0 boto3==1.26.72
通过SSH登录主节点后,能成功运行pyspark,正常导入boto3连接S3、使用awswrangler读取数据:
>>> import boto3 >>> s3client = boto3.client('s3') >>> import awswrangler as wr >>> src_file = os.environ.get("SRC_FILE") >>> og_df = wr.s3.read_csv("s3://" + src_file) >>> og_df.head(3)
但执行以下命令提交Spark任务时:
[ec2-user@ip-172-31-3-167 ~]$ spark-submit --master yarn \ > --py-files standardize_functions.zip standardize_blocks.py
出现错误:
raise ProfileNotFound(profile=profile_name) botocore.exceptions.ProfileNotFound: The config profile (default) could not be found
触发错误的代码(仅在集群提交Spark任务时报错):
import boto3 # Initialize boto3 resource session = boto3.session.Session()
直接调用boto3 client也会出现相同错误:
import boto3 # Initialize boto3 resource s3 = boto3.client('s3')
注意:在集群的pyspark shell中运行脚本无报错,本地提交脚本(非YARN)也无报错。
关于IAM角色与权限,EMR集群已配置对应角色,且通过临时代码验证集群已正确获取IAM角色凭证:
{'Code': 'Success', 'LastUpdated': '2023-02-22T21:43:49Z', 'InstanceProfileArn': 'arn:aws:iam::XXXXXXX:instance-profile/EMR-can-call-Services-while-in-cluser', 'InstanceProfileId': 'XXXXXXX'} {'Code': 'Success', 'LastUpdated': '2023-02-22T21:44:23Z', 'Type': 'AWS-HMAC', 'AccessKeyId': 'XXXXXX', 'SecretAccessKey': 'XXXXXX', 'Token': 'XXXX', 'Expiration': '2023-02-23T04:03:48Z'}
请问哪里操作有误?为何在EMR的PySpark Worker中通过YARN提交Spark任务时无法创建Boto3会话?如何在EMR集群的Spark任务中访问其他AWS服务?
问题根源
通过YARN提交Spark任务时,Worker节点的执行环境和主节点pyspark shell环境存在差异:
- 主节点pyspark shell以
ec2-user身份运行,该用户目录下可能存在AWS配置文件(~/.aws/config或~/.aws/credentials),boto3可读取这些配置初始化会话。 - YARN Worker进程以
yarn用户身份运行,该用户目录下无AWS配置文件,boto3默认尝试读取default配置时就会报错。 - 虽然集群已绑定IAM角色,凭证可通过元数据服务获取,但部分boto3版本的默认初始化逻辑,在找不到本地配置文件时,无法自动从元数据服务加载凭证。
解决方法
1. 显式指定从EC2元数据服务加载凭证
修改boto3初始化代码,跳过本地配置文件依赖,直接使用实例角色凭证:
import boto3 from botocore.config import Config # 显式创建会话,自动读取实例角色凭证 session = boto3.Session(region_name='你的AWS区域') # 或直接初始化client s3 = boto3.client( 's3', config=Config(region_name='你的AWS区域') )
此方式会让boto3自动从EC2元数据服务获取当前实例角色的临时凭证,无需依赖本地配置文件。
2. 提交任务时传递AWS环境变量
在spark-submit命令中添加--conf参数,传递AWS区域等关键环境变量:
spark-submit --master yarn \ --conf spark.executorEnv.AWS_DEFAULT_REGION=us-east-1 \ --py-files standardize_functions.zip standardize_blocks.py
3. 为YARN用户创建默认AWS配置
修改引导脚本,为yarn用户创建AWS配置文件:
#!/bin/bash # Install needed libraries sudo pip3 install pandas==1.3.5 awswrangler==2.19.0 boto3==1.26.72 # 为yarn用户创建.aws目录及配置 sudo mkdir -p /var/lib/hadoop/.aws sudo echo "[default]" > /var/lib/hadoop/.aws/config sudo echo "region = 你的AWS区域" >> /var/lib/hadoop/.aws/config sudo chown -R yarn:yarn /var/lib/hadoop/.aws
YARN Worker默认使用/var/lib/hadoop作为用户目录,创建该配置后,boto3即可找到default配置。
4. 优先使用Spark原生集成访问AWS服务
对于S3这类服务,优先使用Spark原生的Hadoop集成(直接通过s3://路径读写),避免使用boto3。访问其他AWS服务(如DynamoDB、Redshift)时,使用对应的Spark连接器,减少Worker节点上的boto3会话初始化操作。
内容的提问来源于stack exchange,提问作者Austin Wolff

