diff --git a/spark/spark kerberos认证与 YARN 的代理机制.md b/spark/spark kerberos认证与 YARN 的代理机制.md
new file mode 100644
index 0000000..f5f7655
--- /dev/null
+++ b/spark/spark kerberos认证与 YARN 的代理机制.md
@@ -0,0 +1,177 @@
+## spark kerberos认证与 YARN 的代理机制
+
+在 Spark 中,**自行实现 Kerberos 认证**与依赖**YARN 的代理认证机制**存在本质区别,尤其当 YARN 本身已启用 Kerberos 时,需要明确两者的协作方式。以下是详细说明:
+
+
+### **一、Spark 自行认证 vs YARN 代理认证的核心区别**
+
+| **维度** | **Spark 自行实现认证** | **YARN 代理认证机制** |
+|------------------------|---------------------------------------------------|---------------------------------------------------|
+| **认证主体** | 直接使用 Spark 应用的 Kerberos Principal(如 `spark@EXAMPLE.COM`) | YARN 作为代理,使用 YARN 的 Principal 替 Spark 完成认证 |
+| **凭证管理** | 由 Spark 应用手动加载 Keytab 并定期刷新 TGT(如通过定时任务) | YARN 自动为 Spark 分配临时凭证(Delegation Token),并管理生命周期 |
+| **适用场景** | - 长期运行的应用(如 Streaming)
- 非 YARN 模式(Standalone/K8s)
- 需要细粒度控制认证逻辑 | - 短期批处理作业
- YARN 集群模式
- 依赖 YARN 统一管理凭证 |
+| **配置方式** | 代码中手动调用 `UserGroupInformation.loginUserFromKeytab()`,需指定 Keytab 路径 | 通过 `--keytab` 和 `--principal` 提交参数,依赖 YARN 自动处理 |
+| **凭证分发范围** | 需确保 Keytab 能被 Driver 和 Executor 访问(如通过 `--files` 分发) | YARN 自动将临时凭证分发到所有容器(Container),无需显式处理 |
+
+
+### **二、当 YARN 已启用 Kerberos 时的处理方式**
+
+若 YARN 集群本身启用了 Kerberos 认证(即访问 YARN 资源管理器需要 Kerberos 凭证),Spark 应用需要同时处理**两层认证**:
+1. **Spark 与 YARN 的认证**:证明 Spark 有权限提交作业到 YARN。
+2. **Spark 与其他服务的认证**:证明 Spark 有权限访问 HDFS、Hive、Kafka 等服务。
+
+此时需结合两种认证方式,具体配置如下:
+
+
+#### **1. 提交作业时的基础配置**
+必须通过 `--keytab` 和 `--principal` 告知 YARN 应用的身份,确保 Spark 能成功提交到 YARN 并获取资源:
+```bash
+spark-submit \
+ --master yarn \
+ --deploy-mode cluster \
+ --keytab /path/to/spark.keytab \ # Spark 应用的 Keytab
+ --principal spark@EXAMPLE.COM \ # Spark 应用的 Principal
+ --files /path/to/hive-site.xml \ # 可选:分发 Hive 配置
+ --class com.example.SparkApp \
+ your-application.jar
+```
+
+**核心作用**:
+- YARN 通过 `--keytab` 和 `--principal` 验证 Spark 提交者的身份,允许作业提交。
+- YARN 会自动为 Spark 申请访问 HDFS、Hive 等服务的临时凭证(Delegation Token),并分发给 Executor。
+
+
+#### **2. 长期运行应用的特殊处理**
+对于 Streaming 等长期运行的应用,YARN 自动分配的临时凭证可能过期(默认有效期较短,通常几小时),需结合**自行认证逻辑**刷新凭证:
+
+
+
+```scala
+import org.apache.hadoop.security.UserGroupInformation
+import org.apache.spark.sql.SparkSession
+import org.apache.spark.sql.streaming.Trigger
+import java.util.concurrent.{Executors, TimeUnit}
+import org.slf4j.LoggerFactory
+
+object SparkYARNKerberosApp {
+ private val logger = LoggerFactory.getLogger(SparkYARNKerberosApp.getClass)
+
+ // 从提交参数中获取 Principal(通过 --conf 传递)
+ private def getPrincipal(spark: SparkSession): String = {
+ spark.conf.get("spark.yarn.principal")
+ }
+
+ // 获取 YARN 分发的 Keytab 本地路径(通过 --files 分发)
+ private def getKeytabPath(): String = {
+ val keytabFileName = System.getenv("SPARK_KEYTAB_FILENAME") // 从环境变量传入文件名
+ new java.io.File(keytabFileName).getAbsolutePath
+ }
+
+ def main(args: Array[String]): Unit = {
+ // 1. 创建 SparkSession(已通过 --keytab 和 --principal 完成 YARN 认证)
+ val spark = SparkSession.builder()
+ .appName("Spark on YARN with Kerberos")
+ .enableHiveSupport()
+ .getOrCreate()
+
+ // 2. 获取 YARN 传递的认证信息
+ val principal = getPrincipal(spark)
+ val keytabPath = getKeytabPath()
+ logger.info(s"YARN 认证信息 - Principal: $principal, Keytab: $keytabPath")
+
+ // 3. 启动长期任务的凭证刷新机制(处理 YARN 临时凭证过期问题)
+ startCredentialRefresh(principal, keytabPath)
+
+ // 4. 运行长期 Streaming 任务
+ runStreamingJob(spark)
+
+ spark.stop()
+ }
+
+ /**
+ * 启动凭证刷新任务,同时兼容 YARN 代理凭证和手动认证
+ */
+ private def startCredentialRefresh(principal: String, keytabPath: String): Unit = {
+ val scheduler = Executors.newSingleThreadScheduledExecutor()
+
+ // 每 12 小时刷新一次(短于 YARN 临时凭证有效期)
+ scheduler.scheduleAtFixedRate(() => {
+ try {
+ val currentUser = UserGroupInformation.getCurrentUser()
+
+ // 优先使用 YARN 代理的凭证刷新
+ if (currentUser.hasKerberosCredentials) {
+ currentUser.checkTGTAndReloginFromKeytab()
+ logger.info("通过 YARN 代理刷新凭证成功")
+ } else {
+ // YARN 凭证失效时,手动重新登录
+ logger.warn("YARN 代理凭证失效,尝试手动登录")
+ UserGroupInformation.loginUserFromKeytab(principal, keytabPath)
+ }
+ } catch {
+ case e: Exception =>
+ logger.error("凭证刷新失败,强制重新登录", e)
+ UserGroupInformation.loginUserFromKeytab(principal, keytabPath)
+ }
+ }, 0, 12, TimeUnit.HOURS)
+
+ // 应用退出时关闭线程池
+ sys.addShutdownHook {
+ scheduler.shutdown()
+ }
+ }
+
+ /**
+ * 示例:访问需要认证的服务(Hive/Kafka 等)
+ */
+ private def runStreamingJob(spark: SparkSession): Unit = {
+ import spark.implicits._
+
+ // 从 Hive 读取数据(依赖 YARN 分配的 Hive 凭证)
+ val hiveDF = spark.sql("SELECT * FROM secure_db.secure_table")
+
+ // 写入 HDFS(依赖 YARN 分配的 HDFS 凭证)
+ val query = hiveDF.writeStream
+ .outputMode("append")
+ .format("parquet")
+ .option("path", "hdfs:///user/spark/streaming/output")
+ .trigger(Trigger.ProcessingTime("5 minutes"))
+ .start()
+
+ query.awaitAnyTermination()
+ }
+}
+
+```
+
+
+
+
+
+#### **3. 关键配置说明**
+- **YARN 代理凭证的局限性**:YARN 分配的临时凭证(如 HDFS Delegation Token)有有效期(通常由 `dfs.delegation.token.lifetime` 控制,默认 7 天),长期运行的应用需主动刷新。
+- **双重认证的协作**:
+ - 短期作业:仅依赖 YARN 代理认证即可(无需手动处理)。
+ - 长期作业:需在代码中添加定时刷新逻辑,优先使用 YARN 代理凭证,失效时通过 Keytab 重新登录。
+- **安全配置传递**:确保 `hive-site.xml`、`core-site.xml` 等配置文件通过 `--files` 或 `HADOOP_CONF_DIR` 传递给 Spark,避免认证配置缺失。
+
+
+### **三、常见问题与解决方案**
+
+1. **YARN 提交失败:`No valid credentials`**
+ - 原因:未通过 `--keytab` 和 `--principal` 提供 Spark 应用的身份,或 Keytab 权限错误。
+ - 解决:确保 Keytab 权限为 `600`,且 `--principal` 与 Keytab 中的主体一致。
+
+2. **长期运行后 HDFS 访问失败:`Token expired`**
+ - 原因:YARN 分配的 HDFS 临时凭证过期,且未手动刷新。
+ - 解决:在代码中添加定时刷新逻辑(如示例中的 `startCredentialRefresh` 方法)。
+
+3. **Executor 认证失败:`Keytab not found`**
+ - 原因:Keytab 未通过 `--files` 分发到 Executor,或路径硬编码导致无法访问。
+ - 解决:通过 `--files` 分发 Keytab,代码中通过当前工作目录动态获取路径(如 `new File(keytabFileName).getAbsolutePath`)。
+
+
+### **总结**
+- **短期作业**:直接依赖 YARN 代理认证(`--keytab` + `--principal`),无需额外代码处理。
+- **长期作业**:需结合 YARN 代理认证和手动刷新逻辑,确保凭证不过期。
+- **核心原则**:YARN 负责 Spark 与集群资源的认证,Spark 自行处理与其他服务的长期认证,两者协作实现全链路安全访问。
\ No newline at end of file
diff --git a/spark/spark配置优先级.md b/spark/spark配置优先级.md
new file mode 100644
index 0000000..c559e96
--- /dev/null
+++ b/spark/spark配置优先级.md
@@ -0,0 +1,166 @@
+# Spark 中 Hadoop/Hive 配置文件指定与优先级文档
+
+## 1. 概述
+在 Spark 与 Hadoop、Hive 集成过程中,需通过多种方式指定配置文件(如 `hive-site.xml`、`core-site.xml`、`yarn-site.xml`),不同指定方式存在明确的优先级顺序。本文档系统整理 Spark 中 Hadoop/Hive 配置文件的指定方法及优先级规则,帮助开发者解决配置冲突、确保配置生效。
+
+
+## 2. Spark 中 Hadoop/Hive 配置文件的指定方式
+Spark 支持多种方式指定 Hadoop/Hive 配置文件,适用于不同部署场景(本地模式、集群模式、临时作业等),具体方式如下:
+
+### 2.1 方式 1:通过 `--files` 选项分发(集群临时配置)
+通过 `spark-submit` 的 `--files` 选项,将本地或指定路径的 `hive-site.xml` 等配置文件分发到所有 Executor 工作目录,适用于**不同作业需差异化配置**的场景,无需修改集群全局配置。
+
+**使用示例**:
+```bash
+spark-submit \
+ --files /path/to/local/hive-site.xml # 本地配置文件路径,会分发到Executor
+ --class com.example.SparkHiveApp \
+ ./spark-hive-app.jar
+```
+
+**特点**:
+- 配置文件仅对当前提交的作业生效,不影响其他作业
+- 自动分发到 YARN/K8s 集群所有节点,避免节点间配置不一致
+
+
+### 2.2 方式 2:通过环境变量 `HADOOP_CONF_DIR` 指定(全局统一配置)
+设置 `HADOOP_CONF_DIR` 环境变量,指向包含 Hadoop/Hive 配置文件的目录,Spark 会自动加载该目录下的 `hive-site.xml`、`core-site.xml` 等文件,适用于**集群全局统一配置**场景。
+
+**使用示例**:
+```bash
+# 1. 临时生效(当前终端)
+export HADOOP_CONF_DIR=/path/to/hadoop-conf # 目录需包含hive-site.xml等
+
+# 2. 永久生效(Linux系统,编辑/etc/profile)
+echo "export HADOOP_CONF_DIR=/path/to/hadoop-conf" >> /etc/profile
+source /etc/profile
+
+# 3. 提交作业
+spark-submit --class com.example.SparkHiveApp ./spark-hive-app.jar
+```
+
+**特点**:
+- 配置对所有通过该终端提交的 Spark 作业生效
+- 需确保所有节点的 `HADOOP_CONF_DIR` 指向一致路径(本地路径或共享存储路径)
+
+
+### 2.3 方式 3:放置到默认目录(静态全局配置)
+Spark 会自动扫描以下默认目录,加载 Hadoop/Hive 配置文件,适用于**静态集群配置**(无需频繁修改):
+1. Spark 安装目录的 `conf` 文件夹(`$SPARK_HOME/conf`)
+2. Hadoop 安装目录的 `conf` 文件夹(依赖 `HADOOP_HOME` 环境变量)
+
+**使用示例**:
+```bash
+# 将hive-site.xml复制到Spark默认conf目录
+cp /path/to/hive-site.xml $SPARK_HOME/conf/
+
+# 提交作业(无需额外指定配置路径)
+spark-submit --class com.example.SparkHiveApp ./spark-hive-app.jar
+```
+
+**特点**:
+- 配置长期生效,适合集群基础固定配置
+- 需手动同步所有节点的默认目录配置文件,避免节点间不一致
+
+
+### 2.4 方式 4:代码中显式配置(作业级强制覆盖)
+在 Spark 应用代码中,通过 `SparkSession.builder().config()` 或 `SparkConf` 直接设置 Hadoop/Hive 相关参数,适用于**作业级强制覆盖配置**(优先级最高)。
+
+**使用示例(Scala)**:
+```scala
+import org.apache.spark.sql.SparkSession
+
+object SparkHiveApp {
+ def main(args: Array[String]): Unit = {
+ val spark = SparkSession.builder()
+ .appName("SparkHiveDemo")
+ .enableHiveSupport()
+ // 显式设置Hive Metastore地址(覆盖配置文件)
+ .config("hive.metastore.uris", "thrift://custom-metastore:9083")
+ // 显式设置HDFS默认地址(覆盖core-site.xml)
+ .config("fs.defaultFS", "hdfs://custom-namenode:8020")
+ .getOrCreate()
+
+ // 业务逻辑
+ spark.sql("SELECT * FROM test_db.test_table").show()
+ spark.stop()
+ }
+}
+```
+
+**特点**:
+- 优先级最高,直接覆盖所有配置文件的对应参数
+- 配置与代码绑定,适合作业专属配置
+
+
+### 2.5 方式 5:命令行 `--conf` 参数(提交时临时覆盖)
+通过 `spark-submit` 的 `--conf` 选项,在提交作业时临时指定 Hadoop/Hive 配置,适用于**单次作业临时调整配置**,无需修改代码或配置文件。
+
+**使用示例**:
+```bash
+spark-submit \
+ --conf hive.metastore.uris=thrift://custom-metastore:9083 \ # 临时覆盖Metastore地址
+ --conf fs.defaultFS=hdfs://custom-namenode:8020 \ # 临时覆盖HDFS地址
+ --class com.example.SparkHiveApp \
+ ./spark-hive-app.jar
+```
+
+**特点**:
+- 仅对当前提交的作业生效,灵活性高
+- 适合快速测试不同配置参数的效果
+
+
+### 2.6 方式 6:Spark 配置文件(`spark-defaults.conf`)
+在 Spark 安装目录的 `conf/spark-defaults.conf` 中,通过 `spark.hadoop.` 前缀配置 Hadoop/Hive 参数,适用于**Spark 专属的全局配置**。
+
+**使用示例**:
+```properties
+# $SPARK_HOME/conf/spark-defaults.conf
+spark.hadoop.hive.metastore.uris thrift://custom-metastore:9083 # Hive Metastore地址
+spark.hadoop.fs.defaultFS hdfs://custom-namenode:8020 # HDFS默认地址
+spark.hadoop.yarn.resourcemanager.address yarn-rm:8032 # YARN ResourceManager地址
+```
+
+**特点**:
+- 配置对所有 Spark 作业生效,属于 Spark 层的全局配置
+- 需添加 `spark.hadoop.` 前缀,Spark 会自动传递给 Hadoop 配置系统
+
+
+## 3. Hadoop/Hive 配置文件的优先级顺序
+Spark 加载 Hadoop/Hive 配置时,遵循**高优先级覆盖低优先级**的规则,具体优先级从高到低如下:
+
+| 优先级排序 | 配置方式 | 说明 |
+|------------|------------------------------|----------------------------------------------------------------------|
+| 1 | 代码中显式配置 | 通过 `SparkSession.config()` 或 `SparkConf` 设置的参数,优先级最高 |
+| 2 | 命令行 `--conf` 参数 | `spark-submit` 时通过 `--conf` 指定的参数,覆盖配置文件 |
+| 3 | `--files` 分发的配置文件 | 通过 `--files` 分发的 `hive-site.xml` 等,仅对当前作业生效 |
+| 4 | `spark-defaults.conf` | Spark 配置文件中带 `spark.hadoop.` 前缀的参数 |
+| 5 | `HADOOP_CONF_DIR` 目录配置 | 环境变量指定目录下的 `hive-site.xml`、`core-site.xml` 等 |
+| 6 | Spark 安装目录 `conf` 目录 | `$SPARK_HOME/conf` 下的 Hadoop/Hive 配置文件 |
+| 7 | Hadoop 安装目录 `conf` 目录 | `$HADOOP_HOME/conf` 下的默认配置文件,优先级最低 |
+| 8 | Hadoop/Hive 内置默认配置 | 源代码中定义的默认配置,仅在所有方式未指定时生效 |
+
+
+### 3.1 优先级示例验证
+假设存在以下配置场景:
+1. `HADOOP_CONF_DIR` 下的 `hive-site.xml` 配置 `hive.metastore.uris=thrift://default-ms:9083`
+2. 提交作业时通过 `--files /custom/hive-site.xml` 分发,文件中配置 `hive.metastore.uris=thrift://file-ms:9083`
+3. 提交作业时通过 `--conf hive.metastore.uris=thrift://cmd-ms:9083` 指定
+
+**最终生效的配置**:`thrift://cmd-ms:9083`(遵循优先级 2 > 3 > 5)
+
+
+## 4. 注意事项
+1. **集群模式配置同步**:在 YARN/K8s 集群模式下,`--files` 分发的配置文件会自动同步到所有 Executor,但需确保 Driver 节点也能访问该文件(本地路径或共享存储路径)。
+2. **配置参数冲突**:若不同方式配置了同一参数,以高优先级为准;若未配置,则使用低优先级或内置默认值。
+3. **`enableHiveSupport()` 依赖**:若 Spark 应用需集成 Hive(如访问 Hive 表),必须在创建 `SparkSession` 时调用 `.enableHiveSupport()`,否则 `hive-site.xml` 配置不生效。
+4. **路径一致性**:通过 `HADOOP_CONF_DIR` 或默认目录指定配置时,需确保所有节点的配置文件路径一致(建议使用共享存储如 HDFS 存储配置文件)。
+
+
+## 5. 常见场景配置方案
+| 场景 | 推荐配置方式 | 优势 |
+|--------------------------|----------------------------------|----------------------------------------------------------------------|
+| 作业专属配置(临时) | `--files` 分发 + 命令行 `--conf` | 不影响全局配置,灵活性高 |
+| 集群全局固定配置 | `HADOOP_CONF_DIR` + 默认目录 | 所有作业统一生效,减少重复配置 |
+| 代码绑定配置(强制) | 代码中显式配置 | 配置与代码绑定,避免环境依赖问题 |
+| Spark 专属全局配置 | `spark-defaults.conf` | 仅对 Spark 作业生效,与 Hadoop 配置解耦 |
\ No newline at end of file