使用 Docker 部署 Hadoop 集群

使用 Docker 部署 Hadoop 集群

一、前言

本文基于虚拟机中的 Docker 引擎部署 Hadoop 集群,适合入门用户参考。Docker 官网提供了详细的安装教程(Docker 安装教程),本文将逐步讲解具体操作流程。

二、知识准备

1. 什么是虚拟机?

虚拟机(Virtual Machine, VM)是通过软件模拟物理计算机硬件运行环境的程序或系统,允许多个操作系统在同一物理机上同时运行。其通过虚拟化技术抽象物理资源(CPU、内存等),为每个虚拟机提供独立环境,彼此隔离。

  • 类型:系统虚拟机(如 VMware、VirtualBox,可运行完整操作系统)和进程虚拟机(如 Java 虚拟机,用于特定应用)。
  • 优势:资源利用率高、灵活性强、易于管理,适用于服务器虚拟化、开发测试等场景。
  • 本文使用 VMware,参考安装教程:VMware 安装保姆级教程

2. 什么是 Docker?

在这里插入图片描述

Docker 是开源的应用开发、交付和运行平台,支持在 Windows、macOS、Linux 上运行,将应用及依赖打包到容器中,实现跨环境一致运行。

核心概念:
  • 容器(Container):镜像的运行实例,轻量级可执行软件包,包含代码、运行时、系统工具等,确保应用在任何环境运行一致。
  • 镜像(Image):构建容器的只读模板,通过 Dockerfile 定义构建指令。
  • 仓库(Registry):存储和分发镜像的平台(如公共 Docker Hub)。
特点:
  • 可移植性:跨平台运行,部署迁移简单。
  • 隔离性:容器间相互隔离,互不影响。
  • 轻量级:无需启动完整操作系统,启动快、资源占用少。
  • 安全性:隔离环境限制资源访问,提供额外安全层。
工作流程:
  1. 编写 Dockerfile(定义依赖、环境等);
  2. 构建镜像;
  3. 运行容器实例;
  4. 管理容器(启动、停止等);
  5. 推送镜像到仓库供其他机器使用。

3. 什么是 Hadoop?

Hadoop 是 Apache 基金会的分布式系统基础架构,简化分布式程序开发,利用集群进行高速运算和存储。核心组件包括:

  • HDFS(Hadoop Distributed File System):高容错的分布式文件系统,适合部署在低成本硬件,提供高吞吐量访问,放宽 POSIX 要求以支持流式数据访问。
  • MapReduce:分布式计算框架,处理海量数据。

三、所需软件清单

软件名称作用下载 / 安装地址
VMware虚拟化硬件和操作系统VMware 安装教程
CentOS操作系统百度网盘:CentOS-7.5-x86_64-DVD-1804.iso(提取码:udwy)
JDK + Hadoop运行环境和框架百度网盘:资料包(提取码:h2xv)

四、详细步骤

1. 安装 VMware 并创建虚拟机

参考VMware 安装教程完成安装,然后新建虚拟机,硬件配置及操作系统安装步骤如下:(注:原文图片展示了虚拟机配置流程,实际操作中需根据向导完成磁盘、内存等设置,并加载 CentOS 镜像文件)

(1) 硬件配置

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(2)操作系统安装,[安装包附上](通过网盘分享的文件:CentOS-7.5-x86_64-DVD-1804.iso链接: https://pan.baidu.com/s/17IDhheZHzKiKSTbXIiBxyA 提取码: udwy --来自百度网盘超级会员v3的分享)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(3)打开虚拟机进行初始化(时间较长,耐心等待)
配置完成后,点击“安装”

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 在 CentOS 中安装 Docker 引擎

(1)更新 yum 到最新
sudo yum update -y
  • yum:CentOS 包管理器;-y:自动确认所有操作。
(2)卸载旧版本 Docker
sudo yum remove docker \
    docker-client \
    docker-client-latest \
    docker-common \
    docker-latest \
    docker-latest-logrotate \
    docker-logrotate \
    docker-engine
(3)安装依赖工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
  • device-mapper-persistent-data:Docker 管理支持;lvm2:逻辑卷管理工具。
(4)添加阿里云 Docker 源
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
(5)安装 Docker 社区版
sudo yum install -y docker-ce
(6)配置镜像加速器(解决下载慢问题)

编辑配置文件:

sudo vim /etc/docker/daemon.json

添加内容:

{
  "registry-mirrors": [
    "https://docker.m.daocloud.io",
    "https://docker.jianmuhub.com",
    "https://huecker.io",
    "https://dockerhub.timeweb.cloud",
    "https://dockerhub1.beget.com",
    "https://noohub.ru"
  ],
  "dns": ["114.15.15.114", "8.8.8.8"]
}

重启 Docker 服务:

sudo systemctl daemon-reload  # 重新加载配置
sudo systemctl start docker   # 启动Docker
sudo systemctl restart docker # 重启Docker(如需)
(7)设置 Docker 开机启动
sudo systemctl enable docker
(8)验证 Docker 安装
systemctl status docker  # 查看状态(应显示active)
docker -v                # 查看版本

3. 部署 Hadoop 集群

A. 构建基础 CentOS 镜像(含 SSH 服务)

(1)拉取 CentOS 基础镜像

docker pull centos:7.9.2009

(2)编写 Dockerfile 配置 SSH

vim Dockerfile  # 创建并编辑文件

内容如下

# 基础镜像
FROM centos:centos7.9.2009

# 创建目录
RUN mkdir -p /opt/software && mkdir -p /opt/module

# 更换阿里云yum源
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo && \
    sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo && \
    yum makecache

# 安装工具和中文支持
RUN yum -y install kde-l10n-Chinese glibc-common vim openssh-server openssh-clients net-tools lrzsz && \
    localedef -c -f UTF-8 -i zh_CN zh_CN.utf8 && \
    echo "LANG=zh_CN.UTF-8" >> /etc/locale.conf

# 配置SSH服务
RUN sed -i '/^HostKey/'d /etc/ssh/sshd_config && \
    echo 'HostKey /etc/ssh/ssh_host_rsa_key' >> /etc/ssh/sshd_config && \
    echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config && \
    echo 'PasswordAuthentication yes' >> /etc/ssh/sshd_config

# 生成SSH密钥
RUN ssh-keygen -t rsa -b 2048 -f /etc/ssh/ssh_host_rsa_key -N "" 

# 设置root密码(123456)
RUN echo 'root:123456' | chpasswd

# 暴露SSH端口
EXPOSE 22

# 启动命令
CMD ["/usr/sbin/init"]

保存退出(Esc + :wq)。

(3)构建镜像

docker build -t="centos7-ssh" .  # 镜像名自定义
docker images  # 查看是否构建成功
B. 集成 JDK 和 Hadoop 到镜像

(1)上传 JDK 和 Hadoop 安装包

  • 通过 Xshell 连接虚拟机(IP 获取命令:ip -4 addr show | grep inet | awk '{print $2}' | cut -d'/' -f1)。
  • 使用 Xftp 将下载的jdk-8u212-linux-x64.tar.gzhadoop-3.1.3.tar.gz上传到虚拟机。
  • 在这里插入图片描述
    )

(2)编写 Dockerfile 集成环境

vim Dockerfile  # 编辑文件(可覆盖之前的)

内容如下:

FROM centos7-ssh  # 基于之前的镜像

# 安装JDK
ADD jdk-8u212-linux-x64.tar.gz /usr/local/  
RUN mv /usr/local/jdk1.8.0_212 /usr/local/jdk1.8
ENV JAVA_HOME /usr/local/jdk1.8
ENV PATH $JAVA_HOME/bin:$PATH

# 安装Hadoop
ADD hadoop-3.1.3.tar.gz /usr/local
RUN mv /usr/local/hadoop-3.1.3 /usr/local/hadoop
ENV HADOOP_HOME /usr/local/hadoop
ENV PATH $HADOOP_HOME/bin:$PATH

# 安装额外工具
RUN yum install -y which sudo

(3)构建 Hadoop 镜像

docker build -t="hadoop" .  # 镜像名自定义

在这里插入图片描述

C. 配置集群网络

(1)创建 Docker 网桥(用于容器通信)

在这里插入图片描述

docker network create --driver bridge hadoop-net

(2)启动 3 个容器(1 主 2 从)
在这里插入图片描述

docker run -itd --name hadoop1 --network hadoop-net --hostname hadoop1 hadoop
docker run -itd --name hadoop2 --network hadoop-net --hostname hadoop2 hadoop
docker run -itd --name hadoop3 --network hadoop-net --hostname hadoop3 hadoop

(3)检查网络

在这里插入图片描述

docker network inspect hadoop-net  # 查看容器IP(如172.18.0.2、172.18.0.3、172.18.0.4)
D. 配置 SSH 免密登录

(1)分别进入 3 个容器并配置 hosts

在这里插入图片描述

在这里插入图片描述

# 打开3个终端,分别执行
docker exec -it hadoop1 bash
docker exec -it hadoop2 bash
docker exec -it hadoop3 bash

# 每个容器中编辑hosts文件
vi /etc/hosts
# 添加以下内容(IP替换为实际查看到的地址)
172.18.0.2 hadoop1
172.18.0.3 hadoop2
172.18.0.4 hadoop3

(2)配置免密登录(3 个容器均执行)

# 安装SSH客户端
yum install -y openssh-clients

# 生成密钥(一路回车)
ssh-keygen

# 分发公钥到所有节点(密码为123456)
ssh-copy-id -i /root/.ssh/id_rsa root@hadoop1
ssh-copy-id -i /root/.ssh/id_rsa root@hadoop2
ssh-copy-id -i /root/.ssh/id_rsa root@hadoop3
E. 配置 Hadoop 集群
部署规划:
  • 主节点(hadoop1):NameNode、ResourceManager
  • 从节点(hadoop2、hadoop3):DataNode、NodeManager
  • SecondaryNameNode 部署在 hadoop1(测试环境简化,生产环境建议分离)
配置文件(在 hadoop1 上操作,后拷贝到从节点)

core-site.xml(核心配置)

vi /usr/local/hadoop/etc/hadoop/core-site.xml

添加内容:

<property>
    <name>fs.defaultFS</name>
    <value>hdfs://hadoop1:9000</value>
</property>
<property>
    <name>hadoop.tmp.dir</name>
    <value>file:/home/hadoop/tmp</value>
</property>
<property>
    <name>io.file.buffer.size</name>
    <value>131702</value>
</property>

hdfs-site.xml(HDFS 配置)

vi /usr/local/hadoop/etc/hadoop/hdfs-site.xml

添加内容:

<property>
    <name>dfs.namenode.name.dir</name>
    <value>file:/home/hadoop/hdfs_name</value>
</property>
<property>
    <name>dfs.datanode.data.dir</name>
    <value>file:/home/hadoop/hdfs_data</value>
</property>
<property>
    <name>dfs.replication</name>
    <value>2</value>  <!-- 副本数,与从节点数量一致 -->
</property>
<property>
    <name>dfs.namenode.secondary.http-address</name>
    <value>hadoop1:9001</value>
</property>
<property>
    <name>dfs.webhdfs.enabled</name>
    <value>true</value>
</property>

mapred-site.xml(MapReduce 配置)

vi /usr/local/hadoop/etc/hadoop/mapred-site.xml

添加内容:

<property>
    <name>mapreduce.framework.name</name>
    <value>yarn</value>  <!-- 指定使用YARN框架 -->
</property>
<property>
    <name>mapreduce.jobhistory.address</name>
    <value>hadoop1:10020</value>
</property>
<property>
    <name>mapreduce.jobhistory.webapp.address</name>
    <value>hadoop1:19888</value>
</property>
<property>
    <name>yarn.app.mapreduce.am.env</name>
    <value>HADOOP_MAPRED_HOME=${HADOOP_HOME}</value>
</property>
<property>
    <name>mapreduce.map.env</name>
    <value>HADOOP_MAPRED_HOME=${HADOOP_HOME}</value>
</property>
<property>
    <name>mapreduce.reduce.env</name>
    <value>HADOOP_MAPRED_HOME=${HADOOP_HOME}</value>
</property>

yarn-site.xml(YARN 配置)

vi /usr/local/hadoop/etc/hadoop/yarn-site.xml

添加内容:

<property>
    <name>yarn.resourcemanager.hostname</name>
    <value>hadoop1</value>  <!-- 资源管理器部署在主节点 -->
</property>
<property>
    <name>yarn.nodemanager.aux-services</name>
    <value>mapreduce_shuffle</value>  <!-- 启用Shuffle服务 -->
</property>
<property>
    <name>yarn.log-aggregation-enable</name>
    <value>true</value>  <!-- 启用日志聚合 -->
</property>
<property>
    <name>yarn.log-aggregation.retain-seconds</name>
    <value>604800</value>  <!-- 日志保留7天 -->
</property>

workers(从节点列表)

vi /usr/local/hadoop/etc/hadoop/workers

添加内容:

hadoop2
hadoop3
配置环境变量(hadoop1 上操作)
修改 Hadoop 启动脚本
# 编辑start-dfs.sh和stop-dfs.sh
cd /usr/local/hadoop/sbin
vi start-dfs.sh  # 在第二行添加
vi stop-dfs.sh   # 在第二行添加

添加内容:

HDFS_DATANODE_USER=root
HADOOP_SECURE_DN_USER=hdfs
HDFS_NAMENODE_USER=root
HDFS_SECONDARYNAMENODE_USER=root
# 编辑start-yarn.sh和stop-yarn.sh
vi start-yarn.sh  # 在第二行添加
vi stop-yarn.sh   # 在第二行添加

添加内容:

YARN_RESOURCEMANAGER_USER=root
HADOOP_SECURE_DN_USER=yarn
YARN_NODEMANAGER_USER=root
配置 Hadoop 环境变量
vi /usr/local/hadoop/etc/hadoop/hadoop-env.sh

添加:

export JAVA_HOME=/usr/local/jdk1.8
配置系统环境变量
vi ~/.bashrc

添加:

export JAVA_HOME=/usr/local/jdk1.8
export HADOOP_HOME=/usr/local/hadoop
export PATH=$PATH:/bin:/usr/bin:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
生效配置:
source ~/.bashrc
同步配置到从节点
scp -r /usr/local/hadoop/ hadoop2:/usr/local/
scp -r /usr/local/hadoop/ hadoop3:/usr/local/

4. 启动并测试集群

(1)格式化 HDFS(仅首次启动时执行)

hdfs namenode -format

(2)启动集群

start-all.sh

(3)验证进程(在各节点执行jps

  • hadoop1 应包含:NameNode、ResourceManager、SecondaryNameNode
  • hadoop2、hadoop3 应包含:DataNode、NodeManager
同步配置到从节点
scp -r /usr/local/hadoop/ hadoop2:/usr/local/
scp -r /usr/local/hadoop/ hadoop3:/usr/local/

4. 启动并测试集群

(1)格式化 HDFS(仅首次启动时执行)

hdfs namenode -format

(2)启动集群

start-all.sh

(3)验证进程(在各节点执行jps

  • hadoop1 应包含:NameNode、ResourceManager、SecondaryNameNode
  • hadoop2、hadoop3 应包含:DataNode、NodeManager

五、Docker 安装与直接虚拟机安装的深度差异及亲手实践细节(附问题排查与数据记录)

一、Docker 与直接虚拟机安装的底层差异(附实操数据支撑)

Docker 的 “进程级虚拟化” 与虚拟机的 “硬件级虚拟化”,并非简单的 “轻量” 与 “重量级” 区别,而是从架构设计、资源调度到环境管理的全维度差异。以下结合我在 Hadoop 部署中的实际测试数据(宿主机配置:CPU i5-1035G1,内存 16GB,磁盘 512GB SSD),从 6 个核心维度展开对比:
对比维度Docker(容器化)直接虚拟机(以 VMware 为例)我的实操细节与数据记录
底层架构共享宿主机 Linux 内核(如 CentOS 7 的 3.10 内核),容器仅包含应用及依赖(无独立 OS 内核)通过 Hypervisor(VMware Workstation 16)模拟 x86 硬件,每个虚拟机运行完整 OS(如 CentOS 7,含独立内核、驱动、系统进程)1. Docker 容器内执行uname -r,输出与宿主机一致(3.10.0-1160.el7.x86_64);2. 虚拟机内执行uname -r,输出相同内核版本,但通过ls /boot可见独立的 vmlinuz(内核文件)和 initramfs(初始化镜像),占用约 500MB 磁盘空间。
资源占用无 OS 开销,仅占用应用运行资源(MB 级)需预分配固定硬件资源(GB 级),含 OS 后台进程开销1. Docker 部署 Hadoop(1 主 2 从):- 启动前:Docker 服务占用内存≈200MB;- 启动后:3 个容器共占用内存≈1.2GB(hadoop1:500MB,hadoop2:350MB,hadoop3:350MB),CPU 使用率≈5%;2. 虚拟机部署 Hadoop(1 主 2 从):- 每台虚拟机预分配 2GB 内存、2 核 CPU;- 启动后:每台虚拟机 OS 后台进程(如 sshd、rsyslog、NetworkManager)已占用≈800MB 内存,3 台共占用≈6.8GB 内存,CPU 使用率≈15%(开机后无任务状态)。
启动速度秒级启动(容器创建→SSH 可连接)分钟级启动(开机自检→OS 加载→服务初始化)1. Docker 启动流程计时:- docker run -itd hadoop1:2 秒创建容器;- docker exec -it hadoop1 bash:1 秒进入容器;- 启动 SSH 服务(systemctl start sshd):3 秒;- 总计:≤6 秒可操作;2. 虚拟机启动流程计时:- 开机自检:15 秒;- CentOS 加载内核与 init 进程:25 秒;- 启动 NetworkManager、sshd 等服务:20 秒;- 总计:60-80 秒才可通过 Xshell 连接。
隔离性进程级隔离(PID、网络、文件系统隔离),共享内核,无硬件隔离系统级隔离(CPU、内存、磁盘、网络完全独立),OS 级故障不扩散1. Docker 隔离性测试:- 在 hadoop2 容器中执行kill -9 1(尝试终止容器 init 进程),仅 hadoop2 容器退出,hadoop1、hadoop3 正常运行;- 但容器无法修改内核参数(如sysctl -w net.ipv4.ip_forward=1需宿主机授权);2. 虚拟机隔离性测试:- 故意在 hadoop2 虚拟机中执行rm -rf /boot(破坏系统引导),仅 hadoop2 无法启动,hadoop1、hadoop3 不受影响;- 每台虚拟机可独立修改内核参数(如调整 swap 分区大小),不影响其他虚拟机。
环境一致性镜像打包 “应用 + 依赖 + 配置 + 系统库”,一次构建可跨环境复用依赖虚拟机快照,快照含完整 OS 状态,跨硬件易出兼容问题1. Docker 复用测试:- 在宿主机 A 构建的hadoop:3.1.3镜像(大小 820MB),导出为hadoop.tar(压缩后 380MB);- 拷贝到宿主机 B(CPU i7-1265U,内存 32GB),导入镜像(docker load -i hadoop.tar)后,直接启动容器,Hadoop 集群 10 分钟内正常运行,无任何配置修改;2. 虚拟机复用测试:- 导出 hadoop1 虚拟机快照(大小 12GB),拷贝到宿主机 B;- 导入后启动报错:“VMware Workstation 无法使用此虚拟机,因为它是在不同的硬件版本上创建的”,需手动升级虚拟机硬件版本(耗时 20 分钟),且启动后网卡无法识别(需重新配置ifcfg-ens33文件)。
存储与数据持久化容器默认存储为 “临时层”,需手动挂载宿主机目录或使用数据卷虚拟机磁盘为独立文件(.vmdk),数据默认存储在虚拟机内部1. Docker 数据持久化实操:- 启动 hadoop1 时挂载数据目录:docker run -itd --name hadoop1 -v /home/myhadoop/data:/home/hadoop/hdfs_data hadoop;- 测试:在容器内hdfs dfs -put test.txt /,删除容器后重新启动,挂载目录下仍能找到test.txt(数据未丢失);2. 虚拟机数据处理:- 若需备份 Hadoop 数据,需通过 Xftp 从虚拟机内下载(1GB 文件需 10 分钟);- 曾因虚拟机快照损坏(.vmdk 文件出错),导致 3 天的测试数据全部丢失,重新部署耗时 4 小时。

二、亲手实践过程:从虚拟机踩坑到 Docker 高效部署(附错误日志与解决步骤)

我先后用虚拟机部署 3 次(前 2 次失败,第 3 次成功)、Docker 部署 2 次(1 次成功,1 次因镜像缓存问题调试),整个过程累计耗时约 20 小时,以下是详细的实践细节、踩坑记录与解决思路:

(一)直接虚拟机安装 Hadoop 的踩坑与解决(2 次失败复盘)

失败案例 1:虚拟机分区配置错误导致磁盘不足
  • 操作细节:首次创建 VM 时,为图方便选择 “自动分区”,仅给/分区分配 20GB 空间;安装 Hadoop(解压后约 800MB)和 JDK(约 300MB)后,执行hdfs namenode -format时突然报错:No space left on device(设备无剩余空间)。

  • 排查过程

    1. 执行df -h查看磁盘使用:/分区已用 100%(日志文件/var/log/messages因 SSH 连接失败日志占了 15GB);
    2. 原因:自动分区未单独划分/var分区,SSH 多次连接失败的日志(sshd[1234]: Connection closed by 192.168.6.1 port 54321 [preauth])填满了/分区。
  • 解决方法

    1. 删除旧虚拟机,重新创建时选择 “手动分区”:

      /boot:200MB(引导分区);

      swap:4GB(内存 2 倍,用于内存溢出时临时存储);

      /var:10GB(日志与临时文件);

      /home:20GB(Hadoop 数据存储);

      /:剩余空间(系统文件);

    2. 配置 SSH 连接超时时间:vi /etc/ssh/sshd_config,添加ClientAliveInterval 60(每 60 秒发送心跳包),避免频繁断连产生冗余日志。

失败案例 2:静态 IP 配置错误导致集群节点无法通信
  • 操作细节:为避免 DHCP 导致 IP 变化,给 3 台虚拟机配置静态 IP(hadoop1:192.168.6.128,hadoop2:192.168.6.129,hadoop3:192.168.6.130);修改/etc/sysconfig/network-scripts/ifcfg-ens33后,执行systemctl restart network报错:Job for network.service failed because the control process exited with error code

  • 排查过程

    1. 查看网络日志:journalctl -u network,发现错误:Invalid IP address '192.168.6.128/24'(IP 格式错误);
    2. 检查配置文件:发现将IPADDR=192.168.6.128误写为IPADDR=192.168.6.128/24(子网掩码应单独用PREFIX=24配置)。
  • 解决方法

    1. 修正ifcfg-ens33配置:

      IPADDR=192.168.6.128;

      PREFIX=24;

      GATEWAY=192.168.6.1(与宿主机 VMnet8 网卡网关一致);

      DNS1=114.114.114.114;

    2. 重启网络服务:systemctl restart network,执行ping 192.168.6.129(hadoop2),丢包率 0%,通信正常。

虚拟机部署成功后的痛点:效率极低

即使第 3 次成功部署,仍遇到 2 个难以解决的问题:

  1. 资源占用过高:3 台虚拟机运行 Hadoop 时,宿主机内存占用达 85%(≈13.6GB),打开浏览器就卡顿,无法同时进行代码编写;
  2. 配置同步繁琐:修改core-site.xml后,需通过 Xshell 分别登录 3 台虚拟机,手动替换文件(曾因 hadoop3 忘记替换,导致 DataNode 无法加入集群,排查 2 小时才发现)。

(二)Docker 部署 Hadoop 的实践细节(从镜像构建到集群验证)

1. 镜像构建:解决 “缓存失效” 与 “依赖缺失” 问题
  • 初始问题:首次编写 Dockerfile 时,将ADD jdk-8u212.tar.gz /usr/local/放在yum install之后,导致每次修改yum相关命令时,JDK 解压步骤都要重新执行(Docker 构建按层缓存,前层修改后后续层缓存失效),构建时间从 10 分钟延长到 25 分钟。

  • 优化方案:调整 Dockerfile 指令顺序,将 “不变的步骤”(如 JDK/Hadoop 解压)放在前面,“易变的步骤”(如yum install)放在后面:

    dockerfile

    # 先解压JDK(仅首次构建时执行,后续缓存复用)
    ADD jdk-8u212-linux-x64.tar.gz /usr/local/  
    RUN mv /usr/local/jdk1.8.0_212 /usr/local/jdk1.8
    # 再执行yum安装(修改时仅重新执行这层)
    RUN yum install -y which sudo openssh-clients
    
  • 验证结果:修改yum命令后,重新构建镜像仅需 5 分钟(复用前层缓存),效率提升 60%。

2. 网络配置:自定义网桥与端口映射的实操
  • 问题场景:首次用 Docker 默认bridge网络启动容器,执行ssh hadoop2时报错:ssh: Could not resolve hostname hadoop2: Name or service not known(无法解析主机名)。

  • 解决步骤

    1. 创建自定义网桥并指定子网:

      docker network create --driver bridge --subnet 172.18.0.0/16 hadoop-net
      

      (子网 172.18.0.0,确保容器 IP 固定段);

    2. 启动容器时指定 IP(避免 DHCP 分配变化):

      docker run -itd --name hadoop1 --network hadoop-net --ip 172.18.0.2 hadoop
      
      docker run -itd --name hadoop2 --network hadoop-net --ip 172.18.0.3 hadoop
      
      docker run -itd --name hadoop3 --network hadoop-net --ip 172.18.0.4 hadoop
      
    3. 配置宿主机端口映射(方便浏览器访问 Hadoop Web 界面):

      启动 hadoop1 时添加

      -p 9870:9870 -p 8088:8088
      

      (将容器 9870 端口映射到宿主机 9870,8088 同理);

  • 验证:宿主机浏览器输入http://127.0.0.1:9870,成功打开 HDFS 管理界面,查看 DataNode 状态:hadoop2、hadoop3 均在线(副本数 2,符合配置)。

3. SSH 免密登录:权限与密钥分发的细节排查
  • 问题现象:在 hadoop1 执行ssh-copy-id hadoop2,输入密码 123456 后报错:Permission denied, please try again(权限拒绝)。

  • 排查过程

    1. 进入 hadoop2 容器,查看/etc/ssh/sshd_config:发现PasswordAuthentication no(默认禁用密码登录);
    2. 检查/root/.ssh目录权限:ls -ld /root/.ssh显示drwxrwxrwx(权限过宽,SSH 要求.ssh 目录权限必须为 700)。
  • 解决方法

    1. 在 Dockerfile 中添加权限配置:

      RUN chmod 700 /root/.ssh && echo 'PasswordAuthentication yes' >> /etc/ssh/sshd_config
      
    2. 重新构建镜像并启动容器,再次执行ssh-copy-id hadoop2,成功分发密钥;

    3. 验证:ssh hadoop2无需输入密码,直接进入 hadoop2 容器,免密配置生效。

4. Hadoop 启动:进程缺失与日志排查
  • 问题场景:执行start-all.sh后,在 hadoop2 执行jps,发现缺少 DataNode 进程(仅显示 NodeManager 和 Jps)。

  • 排查步骤

    1. 查看 DataNode 日志:cd /usr/local/hadoop/logs,打开hadoop-root-datanode-hadoop2.log,发现错误:

      Incompatible clusterIDs: namenode clusterID = CID-xxx; datanode clusterID = CID-yyy
      

      (DataNode 与 NameNode 的 clusterID 不一致);

    2. 原因:首次格式化 HDFS 后,删除过 hadoop2 容器,重新启动后 DataNode 保留了旧的 clusterID(存储在/home/hadoop/hdfs_data/current/VERSION文件中);

  • 解决方法

    1. 在 hadoop2、hadoop3 容器中删除旧数据目录:

      rm -rf /home/hadoop/hdfs_data/* /home/hadoop/tmp/*
      
    2. 在 hadoop1 重新格式化 HDFS:hdfs namenode -format(注意:仅首次启动或 clusterID 不一致时执行,重复格式化会导致数据丢失);

    3. 重启集群:stop-all.sh && start-all.sh,再次执行jps,hadoop2、hadoop3 的 DataNode 进程正常显示。

三、实践总结:从 “会部署” 到 “懂原理” 的认知升级

  1. 对 “虚拟化” 的理解深化:最初以为虚拟机和 Docker 只是 “大小区别”,直到亲手排查clusterID错误时发现:虚拟机的 DataNode 数据存储在独立 OS 中,删除虚拟机后数据彻底消失;而 Docker 容器的数据默认在临时层,但通过挂载宿主机目录可实现持久化 —— 这让我明白:容器化的核心是 “隔离应用而非隔离 OS”,虚拟机则是 “隔离完整 OS 环境”。
  2. 效率意识的建立:虚拟机部署时,仅 “重复配置 3 台机器” 就耗时 8 小时;而 Docker 通过镜像复用,第二次部署仅用 30 分钟(含启动集群)。这让我意识到:开发测试环境中,“可复用性” 比 “强隔离性” 更重要,容器化技术正是解决了 “环境一致性” 和 “部署效率” 的痛点。
  3. 问题排查能力的提升:从最初遇到错误就 “百度复制命令”,到后来学会查看日志(如hadoop logsjournalctl)、分析配置文件(如sshd_configcore-site.xml),再到理解底层原理(如 Docker 分层缓存、HDFS 的 clusterID 机制)—— 每一次踩坑都是对 “原理” 的具象化理解,比如知道Dockerfile指令顺序影响缓存,本质是 “分层构建” 的设计逻辑。
如果用一句话总结:虚拟机让我 “学会了部署 Hadoop”,而 Docker 让我 “懂了为什么这么部署”,也让我真正体会到:技术选型不是 “哪个更好”,而是 “哪个更适合场景”—— 对于需要快速迭代、频繁部署的学习场景,Docker 无疑是更优解。

版权声明

本文部分内容参考自 CSDN 博主「吾仄 lo 咚锵」的原创文章(原文链接:https://blog.csdn.net/qq_45034708/article/details/115413751),遵循 CC 4.0 BY-SA 版权协议。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值