1. 为什么选择Docker Compose搭建Hadoop集群

第一次接触Hadoop集群部署时,我像大多数初学者一样被繁琐的配置步骤劝退。直到发现Docker Compose这个神器,才真正体会到什么叫"一键部署"。传统方式需要手动配置每台机器的网络、SSH免密登录、环境变量,而用Docker Compose只需要一个YAML文件就能搞定所有服务编排。

最让我惊喜的是环境隔离性。有次测试MapReduce任务时把DataNode搞崩溃了,直接删除容器重新启动,5分钟就恢复了测试环境。这比物理机时代重装系统要高效太多。另外,用Docker Compose可以轻松实现:

  • 服务依赖管理:确保NameNode先于DataNode启动
  • 端口映射自动化:不用再手动配置50070/8088等端口
  • 配置集中化:所有环境变量在docker-compose.yml中统一管理

实测下来,从零开始搭建一个3节点集群仅需15分钟。下面这个对比表格能直观看出优势:

配置项传统方式Docker Compose方式
环境准备需3台物理机/虚拟机单机运行多个容器
网络配置手动配置静态IP和hosts自动创建自定义网络
服务启动顺序需人工确保启动顺序depends_on自动管理
环境清理需逐个卸载服务docker-compose down一键清除

2. 快速搭建Hadoop容器环境

2.1 准备Docker镜像

我推荐直接使用现成的Hadoop镜像,比如bde2020/hadoop这个维护较活跃的镜像。如果希望自定义,可以参考这个Dockerfile:

FROM centos:7
RUN yum install -y openssh-server java-1.8.0-openjdk
ENV JAVA_HOME /usr/lib/jvm/jre
ADD hadoop-3.3.4.tar.gz /usr/local
RUN mv /usr/local/hadoop-3.3.4 /usr/local/hadoop
ENV HADOOP_HOME /usr/local/hadoop
ENV PATH $PATH:$HADOOP_HOME/bin

构建镜像时有个小技巧:把常用的配置文件提前打包进镜像,比如core-site.xml、hdfs-site.xml等。这样可以减少容器启动后的配置工作量。我通常会准备一个config目录存放这些文件,然后在Dockerfile中添加:

COPY config/* /usr/local/hadoop/etc/hadoop/

2.2 编写docker-compose.yml

下面这个模板是我经过多次优化后的版本,重点解决了几个痛点:

  1. 使用固定IP方便服务发现
  2. 通过volumes挂载配置文件便于修改
  3. 设置合理的资源限制避免容器争抢资源
version: '3'
services:
  namenode:
    image: bde2020/hadoop-namenode:2.0.0-hadoop3.2.1-java8
    container_name: namenode
    ports:
      - "9870:9870"
      - "9000:9000"
    volumes:
      - namenode-data:/hadoop/dfs/name
    environment:
      - CLUSTER_NAME=hadoop-cluster
    networks:
      hadoop-net:
        ipv4_address: 172.18.0.2

  datanode1:
    image: bde2020/hadoop-datanode:2.0.0-hadoop3.2.1-java8
    container_name: datanode1
    depends_on:
      - namenode
    volumes:
      - datanode1-data:/hadoop/dfs/data
    environment:
      - CORE_CONF_fs_defaultFS=hdfs://namenode:9000
    networks:
      hadoop-net:
        ipv4_address: 172.18.0.3

networks:
  hadoop-net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.18.0.0/16

volumes:
  namenode-data:
  datanode1-data:

3. 关键配置详解

3.1 网络配置技巧

在Hadoop集群中,各节点需要通过主机名互相访问。我推荐使用Docker的自定义网络配合静态IP,这样既保证网络性能又便于管理。在docker-compose.yml中这样配置:

networks:
  hadoop-net:
    driver: bridge
    ipam:
      config:
        - subnet: "172.18.0.0/16"

然后在每个服务的配置中添加:

services:
  namenode:
    networks:
      hadoop-net:
        ipv4_address: 172.18.0.2

这样配置后,容器间既可以通过IP直接访问,也能通过服务名(如namenode)进行DNS解析。记得在所有容器的/etc/hosts中添加IP映射:

172.18.0.2 namenode
172.18.0.3 datanode1
172.18.0.4 datanode2

3.2 存储卷的最佳实践

Hadoop集群运行会产生大量数据,一定要用volume持久化存储。我建议为不同类型数据创建独立volume:

volumes:
  namenode-metadata:
  datanode-blockdata:
  yarn-logs:

在服务配置中挂载时要注意路径:

namenode:
  volumes:
    - namenode-metadata:/hadoop/dfs/name
datanode1:
  volumes:
    - datanode-blockdata:/hadoop/dfs/data

曾经踩过一个坑:直接挂载宿主机目录会导致权限问题。解决方法是在Dockerfile中添加:

RUN chmod -R 755 /hadoop

4. 集群运维实战技巧

4.1 一键启停集群

使用Docker Compose管理集群生命周期特别方便:

# 启动集群(-d表示后台运行)
docker-compose up -d

# 停止集群(保留数据卷)
docker-compose stop

# 彻底销毁集群(删除数据卷)
docker-compose down -v

建议把常用操作写成Makefile:

start:
    docker-compose up -d

stop:
    docker-compose stop

clean:
    docker-compose down -v

logs:
    docker-compose logs -f

4.2 常见问题排查

  1. NameNode无法启动:检查端口9000是否被占用,我常用这个命令排查:

    netstat -tulnp | grep 9000
    
  2. DataNode无法连接NameNode:检查防火墙规则和SELinux状态:

    setenforce 0
    systemctl stop firewalld
    
  3. 资源不足问题:在docker-compose.yml中限制资源:

    resources:
      limits:
        cpus: '1'
        memory: 2G
    

记得定期查看容器日志:

docker-compose logs -f datanode1

4.3 性能调优建议

根据服务器配置调整以下参数:

  1. HDFS块大小(hdfs-site.xml):

    <property>
      <name>dfs.blocksize</name>
      <value>256m</value>
    </property>
    
  2. YARN容器内存(yarn-site.xml):

    <property>
      <name>yarn.nodemanager.resource.memory-mb</name>
      <value>4096</value>
    </property>
    
  3. MapReduce任务配置

    hadoop jar job.jar \
      -Dmapreduce.map.memory.mb=1024 \
      -Dmapreduce.reduce.memory.mb=2048
    

对于开发测试环境,我通常会把副本数设为1以节省空间:

<property>
  <name>dfs.replication</name>
  <value>1</value>
</property>

更多推荐