Spark在AWS Batch独立运行时无法访问S3问题求助
我之前也碰到过类似的场景,结合你的测试情况,大概率是依赖缺失、凭证传递逻辑不对,或者Spark配置没跟上这几个点出了问题,给你梳理几个排查方向和解决方案:
1. 先确认Spark S3依赖是否被正确打包
NativePackager打包时很容易漏掉Spark访问S3必需的依赖包,这是最常见的坑。比如用s3a协议的话,必须要有hadoop-aws和aws-java-sdk-bundle这两个核心依赖,而且版本要和你的Spark版本匹配(比如Spark 3.x对应hadoop-aws 3.3.x系列)。
如果是用sbt的NativePackager,你需要在build.sbt里明确添加这些依赖,并且不要用Provided scope(否则打包时会跳过):
libraryDependencies ++= Seq( "org.apache.hadoop" % "hadoop-aws" % "3.3.4", "com.amazonaws" % "aws-java-sdk-bundle" % "1.12.451" )
打包完成后可以解压生成的jar/镜像,检查里面是否包含这些依赖的class文件。
2. 让Spark自动读取ECS任务IAM角色的凭证
你测试2里手动用curl拉取凭证的方式不太对——Spark在ECS容器里可以直接通过任务IAM角色自动获取凭证,不需要手动存文件。你需要给Spark配置正确的凭证提供者:
在Spark代码里添加以下配置,或者提交任务时通过--conf参数传递:
val spark = SparkSession.builder() .appName("S3AccessDemo") // 让Spark自动从ECS任务角色拉取凭证 .config("spark.hadoop.fs.s3a.aws.credentials.provider", "com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper") // 指定s3a文件系统实现类 .config("spark.hadoop.fs.s3a.impl", "org.apache.hadoop.fs.s3a.S3AFileSystem") .getOrCreate()
这样Spark会自动去访问ECS的凭证服务,不需要你手动处理AWS_CONTAINER_CREDENTIALS_RELATIVE_URI环境变量。
3. 检查协议配置的细节
不同协议的要求不一样,推荐优先用s3a(功能最完善),但要注意:
- 如果是AWS中国区或者非标准区域,要额外配置endpoint:
spark.hadoop.fs.s3a.endpoint = s3.cn-north-1.amazonaws.com.cn - 确保ECS任务角色已经被授予了S3的访问权限(比如
s3:GetObject、s3:ListBucket等权限,不要用过于宽泛的权限,但至少要覆盖你要访问的桶路径)
4. 日志排查定位具体问题
如果上面的步骤都没解决,一定要看Spark的详细日志。可以通过以下参数开启debug级别的日志,重点看S3访问相关的报错栈:
spark-submit \ --conf spark.driver.extraJavaOptions="-Dorg.slf4j.simpleLogger.defaultLogLevel=debug" \ --conf spark.executor.extraJavaOptions="-Dorg.slf4j.simpleLogger.defaultLogLevel=debug" \ your-packaged-app.jar
比如如果日志里出现ClassNotFoundException,就是依赖没打包;如果是AccessDenied,就是IAM角色权限不够;如果是NoCredentialsAvailable,就是凭证获取逻辑有问题。
内容的提问来源于stack exchange,提问作者oleber

