EMR上Spark作业无法写入AWS Glue Catalog元存储问题求助
问题背景
已在EMR配置中勾选"AWS Glue Data Catalog设置"下的"Use for Spark table metadata"复选框,Spark代码在主节点spark-shell中执行正常,能成功创建Glue Catalog表,但提交成作业时却无法识别Glue数据库,反而写入Spark默认元存储。尝试过添加fileFormat=hive选项,以及在SparkSession中配置Glue相关参数,但问题依旧。
解决步骤
1. 确认EMR集群的Spark默认配置
登录EMR主节点,检查/etc/spark/conf/spark-defaults.conf文件,确认以下两个配置存在:
spark.sql.catalogImplementation=hive hive.metastore.client.factory.class=com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory
如果不存在,说明EMR的Glue Catalog配置未正确生效,需重新创建集群并确保勾选对应选项,或手动修改配置后重启Spark服务。
2. 提交作业时显式传递Glue配置参数
spark-shell会自动继承主节点的Spark配置,但spark-submit提交作业时可能丢失部分配置,建议在提交命令中显式指定Glue相关参数:
spark-submit \ --class GlueCatalogTableWriter \ --conf spark.sql.catalogImplementation=hive \ --conf hive.metastore.client.factory.class=com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory \ --master yarn \ your-application.jar
3. 修正代码中的SparkSession构建
确保代码中的SparkSession启用Hive支持,必须添加enableHiveSupport(),否则Spark不会使用Hive兼容的元存储(包括Glue Catalog):
import org.apache.spark.sql.{DataFrame, SparkSession} object GlueCatalogTableWriter { def main(args: Array[String]): Unit = { val spark = SparkSession.builder() .appName("GlueCatalogTableWriter") .config("spark.sql.catalogImplementation", "hive") .config("hive.metastore.client.factory.class", "com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory") .enableHiveSupport() // 关键:启用Hive支持 .getOrCreate() // 确保目标数据库存在 val databaseName = "your_database_name" spark.sql(s"CREATE DATABASE IF NOT EXISTS $databaseName") val data = Seq(("John", 25), ("Alice", 30), ("Bob", 35)) val columns = Seq("Name", "Age") val df = spark.createDataFrame(data).toDF(columns: _*) val tableName = "your_table_name" val catalogTablePath = "s3://your-bucket/path/to/parquet/file" df.write .mode("overwrite") .format("parquet") .option("path", catalogTablePath) .saveAsTable(s"$databaseName.$tableName") spark.stop() } }
4. 验证EMR角色的Glue权限
检查EMR集群使用的EC2实例角色(默认是EMR_EC2_DefaultRole)是否拥有Glue Catalog的操作权限,需要包含至少以下权限:
glue:CreateTableglue:GetDatabaseglue:GetTableglue:UpdateTable
如果权限不足,需在IAM控制台给角色添加对应的Glue权限策略。
5. 测试验证
提交作业前,先在spark-shell中执行spark.sql("SHOW DATABASES"),确认能看到Glue Catalog中的数据库,再提交作业,对比两者的配置差异。
内容的提问来源于stack exchange,提问作者karthik

