EMR on EKS中PySpark读取s3a路径遇证书错误求助
问题场景
在EMR on EKS托管端点的PySpark内核中运行代码读取S3数据时,出现SSL证书匹配错误,已配置部分S3a参数但未生效:
from pyspark.sql import SparkSession # Create a SparkSession spark = SparkSession.builder \ .appName("S3 Read Example") \ .getOrCreate() spark.conf.set("spark.hadoop.fs.s3a.path.style.access", "true") spark.conf.set("fs.s3a.acl.default", "BucketOwnerFullControl") spark.conf.set("spark.hadoop.fs.s3a.aws.credentials.provider", "com.amazonaws.auth.WebIdentityTokenCredentialsProvider") # Read data from S3 using the s3a path s3_path = "s3a://bucket/file.parquet" df = spark.read \ .format("parquet") \ .load(s3_path) spark.stop()
错误信息
Py4JJavaError: An error occurred while calling o119.load.
: org.apache.hadoop.fs.s3a.AWSClientIOException: getFileStatus on s3a://com.bucket.name/file-path/file.snappy.parquet: com.amazonaws.SdkClientException: Unable to execute HTTP request: Certificate for <com.bucket.name.s3.amazonaws.com> doesn't match any of the subject alternative names: [.s3.amazonaws.com, s3.amazonaws.com]: Unable to execute HTTP request: Certificate for <com.bucket.name.s3.amazonaws.com> doesn't match any of the subject alternative names: [.s3.amazonaws.com, s3.amazonaws.com]
用户额外尝试的配置:
spark.conf.set("spark.hadoop.fs.s3a.path.style.access", "true") spark.conf.set("fs.s3a.acl.default", "BucketOwnerFullControl") spark.conf.set("spark.hadoop.fs.s3a.aws.credentials.provider", "com.amazonaws.auth.WebIdentityTokenCredentialsProvider") spark.conf.set("fs.s3a.impl","com.amazon.ws.emr.hadoop.fs.EmrFileSystem")
错误原因
证书不匹配的核心原因是路径样式访问配置未生效:
- 当Bucket名称包含点(如
com.bucket.name)时,若使用S3默认的虚拟主机样式访问(bucket.s3.amazonaws.com),AWS的SSL证书(仅匹配*.s3.amazonaws.com和s3.amazonaws.com)会验证失败。 - 部分配置参数缺少
spark.hadoop前缀,导致Hadoop无法识别这些S3a配置;且在SparkSession创建后才设置参数,部分Hadoop配置已加载完成,无法覆盖生效。
解决方案
1. 正确配置SparkSession参数(构建阶段设置)
所有Hadoop S3a相关参数必须以spark.hadoop为前缀,且在SparkSession构建时配置,确保Hadoop加载时生效:
from pyspark.sql import SparkSession # 在SparkSession初始化阶段配置所有必要的S3参数 spark = SparkSession.builder \ .appName("S3 Read Example") \ # 强制开启路径样式访问,避免虚拟主机证书问题 .config("spark.hadoop.fs.s3a.path.style.access", "true") \ # 设置默认ACL为桶所有者完全控制 .config("spark.hadoop.fs.s3a.acl.default", "BucketOwnerFullControl") \ # 使用EMR on EKS的Web身份令牌凭证提供者 .config("spark.hadoop.fs.s3a.aws.credentials.provider", "com.amazonaws.auth.WebIdentityTokenCredentialsProvider") \ # 指定EMR专属的S3文件系统实现 .config("spark.hadoop.fs.s3a.impl", "com.amazon.ws.emr.hadoop.fs.EmrFileSystem") \ .getOrCreate() # 读取目标S3路径(替换为实际bucket和文件路径) s3_path = "s3a://com.bucket.name/file-path/file.snappy.parquet" df = spark.read.format("parquet").load(s3_path) # 可选:验证数据读取结果 df.show(5) spark.stop()
2. 额外排查点
- IAM权限验证:确保EMR on EKS的执行角色拥有目标S3 bucket的
s3:GetObject、s3:ListBucket等必要权限。 - 集群级配置检查:若集群级
spark-defaults.conf中设置了spark.hadoop.fs.s3a.path.style.access=false,会覆盖会话级配置,需确保集群级配置未冲突。 - 托管端点角色关联:确认EMR Studio托管端点已正确关联具备S3访问权限的IAM角色。
内容的提问来源于stack exchange,提问作者Trupal Patel

