课程 6:Hadoop 回顾与 Docker化集群搭建
本课程简要回顾 Apache Hadoop 的核心组件,并指导您使用 Docker 和 Docker Compose 搭建一个简化的 Hadoop 集群。这种方法非常适合学习和开发目的。
1. Hadoop 生态系统回顾
Apache Hadoop 是一个开源框架,设计用于在商用硬件构建的计算机集群上进行大规模数据集(大数据)的分布式存储和分布式处理。
HDFS (Hadoop Distributed File System)
作用:HDFS 是 Hadoop 的主要存储系统。它是一个设计用于在商用硬件上运行的分布式文件系统。
- 主要特性:
- 可伸缩性:可以存储 PB 级别的数据。
- 容错性:数据在多台机器(DataNode)上复制,以防止硬件故障时数据丢失。默认情况下,数据块复制3次。
- 数据局部性:通过将计算移动到数据所在位置,而不是将大量数据移动到计算位置,来优化计算。
- 核心组件:
- NameNode:管理文件系统命名空间(元数据,如文件名、目录结构、数据块位置)并规定客户端对文件的访问的主服务器。它不存储实际数据。
- DataNode:存储实际数据块的从节点。它们负责根据客户端或 NameNode 的请求读取和写入数据块,并向 NameNode 报告其状态。
YARN (Yet Another Resource Negotiator)
作用:YARN 是 Hadoop 的集群资源管理框架。它负责为 Hadoop 集群中运行的各种应用程序分配系统资源,并调度任务在不同的集群节点上执行。
- 核心组件:
- ResourceManager (RM):管理整个集群全局资源分配的主守护进程。它有两个主要组件:调度器(根据配置的策略为应用程序分配资源)和 ApplicationManager(管理正在运行的 ApplicationMaster)。
- NodeManager (NM):在集群中每个工作节点上运行的从守护进程。它负责管理该节点上的资源、监控其使用情况并向 ResourceManager 报告。它还管理在该节点上执行任务。
- ApplicationMaster (AM):一个特定框架库的实例,它从 ResourceManager 协商资源,并与 NodeManager 一起执行和监控任务。
MapReduce
作用:MapReduce 是一种用于大型数据集分布式计算的编程模型和处理引擎。它通过抽象分布式系统的复杂性来简化并行处理。
- 阶段:
- Map 阶段:输入数据被分割并通过并行运行的 map 任务进行处理。每个 map 任务将其用户定义的 map 函数应用于其输入数据部分,以产生中间键/值对。
- Shuffle 和 Sort 阶段:来自 map 阶段的中间结果按键排序和分组。
- Reduce 阶段:Reduce 任务处理分组的中间数据。每个 reduce 任务将其用户定义的 reduce 函数应用于聚合与键关联的值,从而产生最终输出。
它们如何协同工作
数据被加载到 HDFS 中进行分布式存储。当提交 MapReduce 作业(或其他处理框架如 Spark)时,YARN 会在 DataNode 上分配资源(CPU、内存)。然后,处理任务(例如 mapper 和 reducer)由 YARN 调度在这些节点上运行,理想情况下是在数据所在的位置(数据局部性),以处理来自 HDFS 的数据并将结果存回 HDFS。
2. 搭建 Docker化的 Hadoop 集群
手动搭建 Hadoop 集群可能很复杂。Docker 显著简化了此过程,使其非常适合学习和开发。
使用 Docker 搭建 Hadoop 的好处
- 易于搭建:无需在多台机器或复杂的虚拟机上手动安装和配置 Hadoop 组件。
- 隔离性:可以在本地机器上运行不同的 Hadoop 版本或配置而不会发生冲突。
- 可复现性:Dockerfile 和 Docker Compose 文件确保您的环境易于复现。
- 清洁的环境:可以轻松启动、停止和重置您的 Hadoop 环境,而不会影响您的主机系统。
前提条件:
- Docker 引擎:确保 Docker 已在您的系统上安装并正在运行。(请参考课程 5 或 Docker 官方文档)。
- Docker Compose:强烈建议使用 Docker Compose 来管理像 Hadoop 集群这样的多容器应用程序。安装说明可以在 Docker 官方网站上找到。(通常包含在 Windows/Mac 的 Docker Desktop 中)。
步骤 1:创建 `docker-compose.yml` 文件
我们将使用 `bigdataeurope/hadoop-*` 系列镜像,它们为多容器设置提供了良好的基础。为您的 Hadoop 设置创建一个目录(例如 `my_hadoop_cluster`),并在其中创建一个名为 `docker-compose.yml` 的文件,内容如下:
version: '3.8'
services:
namenode:
image: bigdataeurope/hadoop-namenode:2.0.0-hadoop3.2.1-java8
container_name: namenode
hostname: namenode
volumes:
- namenode_data:/hadoop/dfs/name
environment:
- CLUSTER_NAME=testcluster
ports:
- "9870:9870" # NameNode Web UI
- "9000:9000" # NameNode RPC (供 DataNode 和 HDFS 客户端使用)
networks:
- hadoop_network
datanode1:
image: bigdataeurope/hadoop-datanode:2.0.0-hadoop3.2.1-java8
container_name: datanode1
hostname: datanode1
depends_on:
- namenode
volumes:
- datanode1_data:/hadoop/dfs/data
environment:
- CORE_CONF_fs_defaultFS=hdfs://namenode:9000
ports:
- "9864:9864" # DataNode Web UI (可选)
networks:
- hadoop_network
# 可选:添加第二个 DataNode 以获得更真实的设置
# datanode2:
# image: bigdataeurope/hadoop-datanode:2.0.0-hadoop3.2.1-java8
# container_name: datanode2
# hostname: datanode2
# depends_on:
# - namenode
# volumes:
# - datanode2_data:/hadoop/dfs/data
# environment:
# - CORE_CONF_fs_defaultFS=hdfs://namenode:9000
# ports:
# - "9865:9864" # 如果运行多个 datanode,则映射到不同的主机端口
# networks:
# - hadoop_network
resourcemanager: # YARN ResourceManager
image: bigdataeurope/hadoop-resourcemanager:2.0.0-hadoop3.2.1-java8
container_name: resourcemanager
hostname: resourcemanager
depends_on:
- namenode
- datanode1 # 如果使用,则添加 datanode2
ports:
- "8088:8088" # YARN ResourceManager Web UI
networks:
- hadoop_network
nodemanager1: # YARN NodeManager
image: bigdataeurope/hadoop-nodemanager:2.0.0-hadoop3.2.1-java8
container_name: nodemanager1
hostname: nodemanager1
depends_on:
- namenode
- resourcemanager
environment:
- YARN_CONF_yarn_resourcemanager_hostname=resourcemanager
ports:
- "8042:8042" # NodeManager Web UI
networks:
- hadoop_network
volumes:
namenode_data:
datanode1_data:
# datanode2_data:
networks:
hadoop_network:
driver: bridge
说明:
namenode:配置 HDFS NameNode。端口 9870 用于其 Web UI,9000 用于 HDFS 通信。datanode1:配置一个 HDFS DataNode。它依赖于 NameNode。resourcemanager:配置 YARN ResourceManager。端口 8088 用于其 Web UI。nodemanager1:配置一个 YARN NodeManager,它在工作节点上运行(此处与 datanode 一起模拟)。volumes:定义命名卷以持久化 HDFS 数据,即使容器被移除和重新创建。networks:创建一个自定义桥接网络 `hadoop_network`,以便容器之间使用其服务名作为主机名轻松通信。
步骤 2:启动 Hadoop 集群
在终端中导航到您的 `my_hadoop_cluster` 目录并运行:
docker-compose up -d
此命令将下载镜像(如果尚不存在)并在分离模式 (-d) 下启动所有定义的服务。
检查容器状态:
docker-compose ps
# 或者直接使用 docker 命令
docker ps
您应该看到 namenode、datanode1、resourcemanager 和 nodemanager1 正在运行。
步骤 3:访问 Web UI
一旦容器启动并运行(给它们一两分钟完全初始化):
- HDFS NameNode UI:打开浏览器并转到 http://localhost:9870。您应该会看到 NameNode 仪表板,包括有关活动 DataNode 的信息。
- YARN ResourceManager UI:打开浏览器并转到 http://localhost:8088。您可以看到集群指标、正在运行的应用程序和节点信息。
- DataNode UI (可选):对于
datanode1,映射到 http://localhost:9864。 - NodeManager UI (可选):对于
nodemanager1,映射到 http://localhost:8042。
所有服务可能需要一些时间来初始化,DataNode 也需要时间向 NameNode 注册。如果 UI 没有立即显示 DataNode,请稍等片刻并刷新。
步骤 4:基本 HDFS 命令
要与 HDFS 交互,您将使用 docker exec 在 namenode 容器内运行 HDFS 命令(因为它配置了 HDFS 客户端工具)。
- 列出根目录:
docker exec namenode hdfs dfs -ls /您可能会看到一些默认目录。
- 创建用户目录(常见做法):
docker exec namenode hdfs dfs -mkdir -p /user/myuser(将
myuser替换为您想要的用户名或任何目录名)。 - 创建一个本地测试文件:
echo "你好 Docker化的 Hadoop!" > mytestfile.txt - 将本地文件复制到 NameNode 容器中:
docker cp mytestfile.txt namenode:/tmp/mytestfile.txt - 将文件从容器的本地文件系统放入 HDFS:
docker exec namenode hdfs dfs -put /tmp/mytestfile.txt /user/myuser/ - 验证 HDFS 中的文件:
docker exec namenode hdfs dfs -ls /user/myuser/您应该会看到列出的
mytestfile.txt。 - 查看 HDFS 中的文件内容:
docker exec namenode hdfs dfs -cat /user/myuser/mytestfile.txt - 将文件从 HDFS 获取回 NameNode 容器的本地文件系统:
docker exec namenode hdfs dfs -get /user/myuser/mytestfile.txt /tmp/mytestfile_from_hdfs.txt - 将文件从 NameNode 容器复制回您的主机:
docker cp namenode:/tmp/mytestfile_from_hdfs.txt ./现在您应该在主机的当前目录中拥有
mytestfile_from_hdfs.txt。
步骤 5:停止集群
要停止并移除 `docker-compose.yml` 中定义的所有容器、网络和卷:
docker-compose down
如果您想停止而不移除卷(以便数据持久化):
docker-compose stop
结论
使用 Docker 和 Docker Compose 搭建 Hadoop 集群为学习和开发提供了一个易于管理和可复现的环境。您可以轻松地试验 HDFS 命令,提交 MapReduce 作业(尽管运行作业是一个更高级的步骤,此处未完全涵盖),并了解 Hadoop 组件如何交互,而无需手动安装的开销。此设置为探索分布式数据处理奠定了良好的基础。