Docker配置Airflow与Spark遇HADOOP_CONF_DIR未定义问题求助
解决方案:Airflow 2.7.3 与 Spark 3.5.0 Docker集成问题
核心问题分析
报错HADOOP_CONF_DIR和YARN_CONF_DIR未定义,本质是Spark默认依赖Hadoop客户端库处理S3这类分布式存储,哪怕使用独立模式,也需要基础配置路径来加载必要的存储驱动,而非必须部署完整Hadoop/YARN集群。
模式选择建议
你的业务仅需单节点Spark处理S3数据,优先采用Spark独立模式(local模式或单节点standalone集群),依赖最少,无需额外部署Hadoop集群。
方案1:扩展官方Airflow镜像(最少依赖)
修改Dockerfile
基于官方Airflow镜像,仅安装Spark及必要配置,避免冗余:
# 基于官方Airflow 2.7.3 Python3.11镜像 FROM apache/airflow:2.7.3-python3.11 # 提前定义Hadoop配置目录,避免未定义报错 ENV HADOOP_CONF_DIR=/opt/hadoop-conf ENV YARN_CONF_DIR=$HADOOP_CONF_DIR # 创建配置目录 RUN mkdir -p $HADOOP_CONF_DIR # 安装Spark 3.5.0(自带Hadoop3客户端,无需单独装Hadoop) RUN curl -O https://archive.apache.org/dist/spark/spark-3.5.0/spark-3.5.0-bin-hadoop3.tgz && \ tar -xzf spark-3.5.0-bin-hadoop3.tgz && \ mv spark-3.5.0-bin-hadoop3 /opt/spark && \ rm spark-3.5.0-bin-hadoop3.tgz # 设置Spark环境变量 ENV SPARK_HOME=/opt/spark ENV PATH=$PATH:$SPARK_HOME/bin:$SPARK_HOME/sbin # 安装AWS依赖与匹配版本的PySpark RUN pip install boto3 pyspark==3.5.0
修改docker-compose.yaml
在Airflow服务中添加环境变量与挂载:
version: '3.8' services: airflow-webserver: build: . environment: - AIRFLOW__CORE__EXECUTOR=LocalExecutor - SPARK_HOME=/opt/spark - HADOOP_CONF_DIR=/opt/hadoop-conf - YARN_CONF_DIR=/opt/hadoop-conf # AWS密钥可改用Airflow Secrets管理,此处为示例 - AWS_ACCESS_KEY_ID=your-access-key - AWS_SECRET_ACCESS_KEY=your-secret-key volumes: - ./dags:/opt/airflow/dags - ./logs:/opt/airflow/logs # 可选:挂载自定义Spark配置 - ./spark-conf:/opt/spark/conf airflow-scheduler: build: . environment: - AIRFLOW__CORE__EXECUTOR=LocalExecutor - SPARK_HOME=/opt/spark - HADOOP_CONF_DIR=/opt/hadoop-conf - YARN_CONF_DIR=/opt/hadoop-conf - AWS_ACCESS_KEY_ID=your-access-key - AWS_SECRET_ACCESS_KEY=your-secret-key volumes: - ./dags:/opt/airflow/dags - ./logs:/opt/airflow/logs - ./spark-conf:/opt/spark/conf
关键说明
- 提前定义
HADOOP_CONF_DIR:即使目录为空,也能规避未定义报错,后续可在此添加core-site.xml优化S3访问。 - 选择
spark-3.5.0-bin-hadoop3.tgz:自带Hadoop3客户端,减少依赖层级。 - 匹配PySpark版本:确保与Spark安装版本一致,避免版本冲突。
方案2:Spark独立容器+Airflow容器(分离部署,便于扩展)
若后续需扩展Spark集群,建议分离部署,通过Docker网络通信:
docker-compose.yaml新增Spark服务
services: # 保留原有Airflow服务... spark-master: image: bitnami/spark:3.5.0 environment: - SPARK_MODE=master - SPARK_RPC_AUTHENTICATION_ENABLED=no - SPARK_RPC_ENCRYPTION_ENABLED=no - SPARK_LOCAL_STORAGE_ENCRYPTION_ENABLED=no - SPARK_SSL_ENABLED=no ports: - "7077:7077" - "8080:8080" networks: - airflow-network spark-worker: image: bitnami/spark:3.5.0 environment: - SPARK_MODE=worker - SPARK_MASTER_URL=spark://spark-master:7077 - SPARK_WORKER_MEMORY=1G - SPARK_WORKER_CORES=1 - SPARK_RPC_AUTHENTICATION_ENABLED=no - SPARK_RPC_ENCRYPTION_ENABLED=no - SPARK_LOCAL_STORAGE_ENCRYPTION_ENABLED=no - SPARK_SSL_ENABLED=no networks: - airflow-network # 统一Docker网络 networks: airflow-network: driver: bridge
Airflow DAG中提交Spark任务
使用SparkSubmitOperator连接Spark集群:
from airflow.providers.apache.spark.operators.spark_submit import SparkSubmitOperator from airflow.models.dag import DAG from datetime import datetime default_args = { 'owner': 'airflow', 'start_date': datetime(2024, 1, 1), } with DAG('spark_s3_processing', default_args=default_args, schedule_interval='@daily') as dag: spark_transform = SparkSubmitOperator( task_id='transform_s3_data', application='/opt/airflow/dags/spark_transform_script.py', conn_id='spark_default', verbose=True, conf={ 'spark.hadoop.fs.s3a.access.key': 'your-access-key', 'spark.hadoop.fs.s3a.secret.key': 'your-secret-key', 'spark.hadoop.fs.s3a.impl': 'org.apache.hadoop.fs.s3a.S3AFileSystem' } ) # 前置API取数任务 >> spark_transform
配置Airflow Spark连接
在Airflow UI中添加spark_default连接:
- 连接类型:Spark
- 主机:spark-master
- 端口:7077
- Extra:
{"spark.home": "/opt/spark"}(若Airflow容器内安装了Spark客户端)
验证与调试
- 启动容器后,进入Airflow容器执行
spark-submit --version,确认Spark正常安装。 - 测试S3读取:在容器内启动
pyspark,执行以下代码:
from pyspark.sql import SparkSession spark = SparkSession.builder.appName("s3-test").getOrCreate() df = spark.read.csv("s3a://your-bucket/path/to/data.csv") df.show()
- 若仍有Hadoop配置报错,可在
$HADOOP_CONF_DIR下创建core-site.xml:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <property> <name>fs.s3a.access.key</name> <value>your-access-key</value> </property> <property> <name>fs.s3a.secret.key</name> <value>your-secret-key</value> </property> <property> <name>fs.s3a.impl</name> <value>org.apache.hadoop.fs.s3a.S3AFileSystem</value> </property> </configuration>
内容的提问来源于stack exchange,提问作者Sheitak
相关产品推荐
相关产品推荐

