别再手动配环境了!用Docker Compose一键部署Hadoop 3.x集群(附完整YAML文件)
告别手工配置:用Docker Compose三分钟部署Hadoop集群
记得第一次接触Hadoop时,光是搭建一个三节点的测试集群就花了我整整两天时间。从虚拟机配置、网络设置到各个组件的参数调优,每一步都可能遇到意想不到的坑。直到发现Docker Compose这个神器,我才意识到原来集群部署可以如此优雅简单。今天要分享的这套方案,已经在我们团队内部迭代了十几个版本,现在只需一个YAML文件就能拉起完整的Hadoop 3.x环境。
1. 为什么选择Docker Compose方案
传统手工部署Hadoop集群的痛点,每个过来人都深有体会。需要逐台机器安装JDK、配置SSH免密登录、修改数十个XML配置文件,稍有不慎就会陷入排错地狱。而Docker Compose带来的变革体现在三个维度:
- 环境一致性:所有节点基于同一镜像启动,彻底杜绝"在我机器上是好的"这类问题
- 秒级重置:测试完成后
docker-compose down即可销毁集群,不会留下任何痕迹 - 版本控制:YAML文件纳入Git管理,随时可复现特定版本的集群配置
对比常见的部署方式:
| 方案类型 | 准备时间 | 复杂度 | 可移植性 | 适合场景 |
|---|---|---|---|---|
| 物理机部署 | 天级别 | ★★★★★ | ★☆☆☆☆ | 生产环境 |
| 虚拟机部署 | 小时级别 | ★★★★☆ | ★★☆☆☆ | 传统企业环境 |
| 纯Docker部署 | 分钟级别 | ★★★☆☆ | ★★★★☆ | 开发测试 |
| Docker Compose | 分钟级别 | ★★☆☆☆ | ★★★★★ | 本地开发/CI测试 |
提示:生产环境仍建议使用Kubernetes等专业编排工具,本文方案主要面向开发测试场景
2. 准备工作:构建自定义镜像
虽然可以直接使用官方镜像,但自定义镜像能让我们更好地控制组件版本和预装工具。下面是优化后的Dockerfile:
FROM ubuntu:20.04 # 安装基础工具 RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \ openssh-server \ openjdk-8-jdk \ vim \ net-tools \ iputils-ping && \ rm -rf /var/lib/apt/lists/* # 配置SSH RUN mkdir /var/run/sshd RUN echo 'root:root' | chpasswd RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config RUN ssh-keygen -A # 安装Hadoop 3.3.4 ENV HADOOP_VERSION 3.3.4 ENV HADOOP_HOME /opt/hadoop ENV PATH $HADOOP_HOME/bin:$PATH RUN wget -q https://archive.apache.org/dist/hadoop/core/hadoop-$HADOOP_VERSION/hadoop-$HADOOP_VERSION.tar.gz && \ tar -xzf hadoop-$HADOOP_VERSION.tar.gz -C /opt && \ mv /opt/hadoop-$HADOOP_VERSION $HADOOP_HOME && \ rm hadoop-$HADOOP_VERSION.tar.gz && \ mkdir -p $HADOOP_HOME/logs # 暴露常用端口 EXPOSE 22 9870 8088 9864 9866 9867 CMD ["/usr/sbin/sshd", "-D"]构建命令很简单:
docker build -t hadoop-base:3.3.4 .这个镜像做了几点关键优化:
- 使用更轻量的Ubuntu基础镜像
- 通过环境变量管理Hadoop版本
- 预配置SSH服务方便节点间通信
- 暴露所有必要的服务端口
3. 编写Docker Compose编排文件
接下来是核心的docker-compose.yml文件,我们采用1个NameNode + 2个DataNode + 1个ResourceManager的架构:
version: '3.7' services: namenode: image: hadoop-base:3.3.4 hostname: namenode ports: - "9870:9870" # HDFS Web UI - "8020:8020" # HDFS服务端口 volumes: - ./config/core-site.xml:/opt/hadoop/etc/hadoop/core-site.xml - ./config/hdfs-site.xml:/opt/hadoop/etc/hadoop/hdfs-site.xml environment: - CLUSTER_NAME=hadoop-cluster command: > bash -c ' $HADOOP_HOME/bin/hdfs namenode -format $$CLUSTER_NAME && $HADOOP_HOME/bin/hdfs --daemon start namenode && tail -f /dev/null' datanode1: image: hadoop-base:3.3.4 hostname: datanode1 depends_on: - namenode volumes: - ./config/core-site.xml:/opt/hadoop/etc/hadoop/core-site.xml - ./config/hdfs-site.xml:/opt/hadoop/etc/hadoop/hdfs-site.xml command: > bash -c ' $HADOOP_HOME/bin/hdfs --daemon start datanode && tail -f /dev/null' datanode2: image: hadoop-base:3.3.4 hostname: datanode2 depends_on: - namenode volumes: - ./config/core-site.xml:/opt/hadoop/etc/hadoop/core-site.xml - ./config/hdfs-site.xml:/opt/hadoop/etc/hadoop/hdfs-site.xml command: > bash -c ' $HADOOP_HOME/bin/hdfs --daemon start datanode && tail -f /dev/null' resourcemanager: image: hadoop-base:3.3.4 hostname: resourcemanager ports: - "8088:8088" # YARN Web UI depends_on: - namenode - datanode1 - datanode2 volumes: - ./config/yarn-site.xml:/opt/hadoop/etc/hadoop/yarn-site.xml command: > bash -c ' $HADOOP_HOME/bin/yarn --daemon start resourcemanager && tail -f /dev/null' nodemanager1: image: hadoop-base:3.3.4 hostname: nodemanager1 depends_on: - resourcemanager volumes: - ./config/yarn-site.xml:/opt/hadoop/etc/hadoop/yarn-site.xml command: > bash -c ' $HADOOP_HOME/bin/yarn --daemon start nodemanager && tail -f /dev/null' nodemanager2: image: hadoop-base:3.3.4 hostname: nodemanager2 depends_on: - resourcemanager volumes: - ./config/yarn-site.xml:/opt/hadoop/etc/hadoop/yarn-site.xml command: > bash -c ' $HADOOP_HOME/bin/yarn --daemon start nodemanager && tail -f /dev/null' networks: default: driver: bridge ipam: config: - subnet: 172.20.0.0/16这个配置有几个精妙之处:
- 使用
depends_on确保服务启动顺序 - 通过
command实现自动格式化NameNode - 挂载配置文件实现动态修改
- 固定子网段避免IP变化导致的问题
4. 关键配置文件详解
配置文件存放在项目config目录下,下面是三个核心配置的优化版本:
core-site.xml- 集群全局配置:
<configuration> <property> <name>fs.defaultFS</name> <value>hdfs://namenode:8020</value> </property> <property> <name>hadoop.tmp.dir</name> <value>/tmp/hadoop</value> </property> <property> <name>hadoop.proxyuser.root.hosts</name> <value>*</value> </property> <property> <name>hadoop.proxyuser.root.groups</name> <value>*</value> </property> </configuration>hdfs-site.xml- HDFS专用配置:
<configuration> <property> <name>dfs.replication</name> <value>2</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>/hadoop/dfs/name</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>/hadoop/dfs/data</value> </property> <property> <name>dfs.client.use.datanode.hostname</name> <value>true</value> </property> </configuration>yarn-site.xml- YARN资源管理配置:
<configuration> <property> <name>yarn.resourcemanager.hostname</name> <value>resourcemanager</value> </property> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <property> <name>yarn.nodemanager.env-whitelist</name> <value>JAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,CLASSPATH_PREPEND_DISTCACHE,HADOOP_YARN_HOME,HADOOP_MAPRED_HOME</value> </property> </configuration>注意:生产环境需要调整
dfs.replication参数,通常设置为3以上
5. 集群操作与验证
启动集群只需一条命令:
docker-compose up -d等待约1分钟后,可以通过以下方式验证集群状态:
检查HDFS:
docker exec -it hadoop_namenode_1 hdfs dfsadmin -report预期输出应显示2个活动的DataNode:
Live datanodes (2): Name: 172.20.0.3:9866 (datanode1) ... Name: 172.20.0.4:9866 (datanode2)运行MapReduce测试任务:
docker exec -it hadoop_namenode_1 \ hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.4.jar \ pi 10 100访问Web界面:
- HDFS状态: http://localhost:9870
- YARN资源管理: http://localhost:8088
常见问题排查技巧:
- 如果Web界面无法访问,先检查端口映射是否正确
- 查看容器日志:
docker-compose logs [服务名] - DataNode无法注册时,检查
core-site.xml中的NameNode地址 - 资源不足时可调整
docker-compose.yml中的资源限制
6. 高级配置技巧
对于需要更复杂配置的场景,可以考虑以下优化:
资源限制:
services: namenode: deploy: resources: limits: cpus: '2' memory: 2G reservations: memory: 1G数据持久化:
volumes: hadoop_data: driver: local services: namenode: volumes: - hadoop_data:/hadoop/dfs/name集成其他组件:
services: historyserver: image: hadoop-base:3.3.4 hostname: historyserver command: > bash -c ' $HADOOP_HOME/bin/mapred --daemon start historyserver && tail -f /dev/null' ports: - "19888:19888"这套方案最让我满意的是它的扩展性。上周需要测试Hive集成,只需在原有基础上添加MySQL和Hive服务定义,半小时就搭好了测试环境。相比从前动辄数天的环境准备,现在所有时间都可以专注在业务逻辑验证上。
