# Hadoop分布式集群搭建


<!--more-->


依赖: java环境, jdk8

Hadoop搭建方式

- 单机模式：单节点模式，非集群，生产不会使用这种方式
- 单机伪分布式模式：单节点，多线程模拟集群的效果，生产不会使用这种方式
- 完全分布式模式：多台节点，真正的分布式Hadoop集群的搭建（生产环境建议使用这种方式）

## 1. 环境准备

- 准备三台虚拟机

  ```
  10.211.55.7  hadoop1
  10.211.55.8  hadoop2
  10.211.55.9  hadoop3
  
  关闭防火墙,修改主机名,配置免密登录,集群时间同步
  ```

- 创建以下目录

  ```shell
  mkdir -p /opt/hadoop/software #存放安装包目录
  mkdir -p /opt/hadoop/servers #软件安装目录
  ```

- hadoop下载 到software目录

  ```http
  https://archive.apache.org/dist/hadoop/common/hadoop-2.9.2/hadoop-2.9.2.tar.gz
  ```

## 2. 集群规划

|      | hadoop1              | haddop2     | Hadoop3                        |
| ---- | -------------------- | ----------- | ------------------------------ |
| HDFS | NameNode<br>DataNode | DataNode    | Secondary NameNode<br>DataNode |
| YARN | NodeManager          | NodeManager | NodeManager<br>ResourceManager |

## 3. 安装hadoop

- 解压

  ```shell
  tar -zxvf hadoop-2.9.2.tar.gz -C /opt/hadoop/servers
  ```

- 添加hadoop到环境变量

  ```shell
  vim /etc/profile
  
  export HADOOP_HOME=/opt/hadoop/servers/hadoop-2.9.2 
  export PATH=$PATH:$HADOOP_HOME/bin 
  export PATH=$PATH:$HADOOP_HOME/sbin
  
  source /etc/profile #使配置生效
  ```

- 验证hadoop

  ```shell
  hadoop version
  
  #会出现以下 
  Hadoop 2.9.2
  Subversion https://git-wip-us.apache.org/repos/asf/hadoop.git -r 826afbeae31ca687bc2f8471dc841b66ed2c6704
  Compiled by ajisaka on 2018-11-13T12:42Z
  Compiled with protoc 2.5.0
  From source with checksum 3a9939967262218aa556c684d107985
  This command was run using /opt/hadoop/servers/hadoop-2.9.2/share/hadoop/common/hadoop-common-2.9.2.jar
  ```

- hadoop目录

  ```
  1. bin目录:对Hadoop进行操作的相关命令，如hadoop,hdfs等
  2. etc目录：Hadoop的配置文件目录，入hdfs-site.xml,core-site.xml等 
  3. lib目录：Hadoop本地库（解压缩的依赖）
  4. sbin目录：存放的是Hadoop集群启动停止相关脚本，命令 
  5. share目录：Hadoop的一些jar,官方案例jar，文档等
  ```

### 3.1 集群配置

Hadoop集群配置 = HDFS集群配置 + MapReduce集群配置 + Yarn集群配置

```
HDFS集群配置
	1.将JDK路径明确配置给HDFS（修改hadoop-env.sh）
	2.指定NameNode节点以及数据存储目录（修改core-site.xml）
	3.指定Secondary NameNode节点（修改hdfs-site.xml）
	4.指定DataNode从节点（修改etc/hadoop/slaves文件，每个节点配置信息占一行）

MapReduce集群配置
	1.将JDK路径明确配置给MapReduce（修改mapred-env.sh）
	2.指定MapReduce计算框架运行Yarn资源调度框架（修改mapred-site.xml）

Yarn集群配置
	1.将JDK路径明确配置给Yarn（修改yarn-env.sh）
	2.指定ResourceManager老大节点所在计算机节点（修改yarn-site.xml）
	3.指定NodeManager节点（会通过slaves文件内容确定）
```

- HDFS集群配置

  切换到hadoop安装目录下` cd etc/hadoop`

  - 配置hadoop-env.sh

    ```shell
    vim hadoop-env.sh
    
    # 将jdk路径明确配置 可以使用${JAVA_HOME}查看, 我的是/usr/local/jdk1.8.0_231
    export JAVA_HOME=/usr/local/jdk1.8.0_231
    ```

  - 指定NameNode节点以及数据存储目录

    ```xml
    vim core-site.xml #在hadoop1
    
    <!-- 指定HDFS中NameNode的地址 -->
    <property> 
      <name>fs.defaultFS</name>
      <!-- 此处hadoop1为你指定的服务器别名(自定义), 端口号我们用9000 -->
      <value>hdfs://hadoop1:9000</value> 
    </property> 
    
    <!-- 指定Hadoop运行时产生文件的存储目录 --> 
    <property> 
      <name>hadoop.tmp.dir</name> 
      <value>/opt/hadoop/servers/hadoop-2.9.2/data/tmp</value> 
    </property>
    ```

    > core-site.xml的默认配置：
    >
    > ```http
    > https://hadoop.apache.org/docs/r2.9.2/hadoop-project-dist/hadoop-common/core- default.xml
    > ```

  - 指定Secondary NameNode节点

    ```xml
    vim hdfs-site.xml
    
    <!-- 指定Hadoop辅助名称节点主机配置 --> 
    <property> 
      <name>dfs.namenode.secondary.http-address</name> 
      <value>hadoop3:50090</value> 
    </property> 
    
    <!--副本数量 --> 
    <property>
      <name>dfs.replication</name> 
      <value>3</value> 
    </property>
    ```

    > 官方默认配置:
    >
    > ```http
    > https://hadoop.apache.org/docs/r2.9.2/hadoop-project-dist/hadoop-hdfs/hdfs- default.xml
    > ```

  - 指定DataNode从节点

    ```shell
    vim slaves
    
    #添加3台机器 
    hadoop1
    hadoop2
    hadoop3
    ```

    > **注意：该文件中添加的内容结尾不允许有空格，文件中不允许有空行**

- MapReduce集群配置

  - 指定MapReduce使用的jdk路径

    ```properties
    vim mapred-env.sh

    export JAVA_HOME=/usr/local/jdk1.8.0_231
    ```

  - 指定MapReduce计算框架运行Yarn资源调度框架(修改mapred-site.xml)

    ```xml
    mv mapred-site.xml.template mapred-site.xml 
    vim mapred-site.xml
    
    <!-- 指定MR运行在Yarn上 -->
    <property>
      <name>mapreduce.framework.name</name> 
      <value>yarn</value> 
    </property>
    ```

    > 官方默认配置:
    >
    > ```http
    > https://hadoop.apache.org/docs/r2.9.2/hadoop-mapreduce-client/hadoop-mapreduce- client-core/mapred-default.xml
    > ```
    >
  
- Yarn集群配置

  - 指定jdk路径

    ```properties
    vim yarn-env.sh
    
    export JAVA_HOME=/usr/local/jdk1.8.0_231
    ```

  - 指定ResourceMnager的master节点信息(修改yarn-site.xml)

    ```xml
    vim yarn-site.xml
    
    <!-- 指定YARN的ResourceManager的地址 --> 
    <property>
      <name>yarn.resourcemanager.hostname</name> 
      <value>hadoop3</value> 
    </property> 
    <!-- Reducer获取数据的方式 --> 
    <property>
      <name>yarn.nodemanager.aux-services</name> 
      <value>mapreduce_shuffle</value> 
    </property>
    ```
  
    > Yarn-site.xml的默认配置:
    >
    > ```http
    > https://hadoop.apache.org/docs/r2.9.2/hadoop-yarn/hadoop-yarn-common/yarn- default.xml
    > ```
  
  - 指定NodeManager节点（slaves文件已修改）
  
    与hadoop集群共用
  

**Hadoop安装目录所属用户和所属用户组信息，默认是501 dialout，而我们操作Hadoop集群的用户使用的是虚拟机的root用户，所以为了避免出现信息混乱，修改Hadoop安装目录所属用户和用户组！！**

```sh
chown -R root:root /opt/hadoop/servers/hadoop-2.9.2
```



### 3.2 分发配置

**编写集群分发脚本rsync-script**

- rsync远程同步工具

  rsync主要用于备份和镜像。具有速度快、避免复制相同内容和支持符号链接的优点。

  rsync和scp区别：用rsync做文件的复制要比scp的速度快，rsync只对差异文件做更新。scp是把所有文件都复制过去。

  - 基本语法 

    ```sh
    rsync -rvl $pdir/$fname $user@$host:$pdir/$fname
    #命令 选项参数 要拷贝的文件路径/名称 目的用户@主机:目的路径/名称
    ```

  - 参数说明

    ```sh
    -r 递归
    -v 显示复制过程
    -l 拷贝符号连接
    ```

- rsync案例

  - 3台虚拟机安装rsync

    `yum install -y rsync`

  - 把/opt/hadoop/software目录同步到其他服务器的root用户下的/opt/hadoop/software目录

    ```sh
     rsync -rvl /opt/hadoop/software/ root@hadoop2:/opt/hadoop/software
    ```

- 集群分发脚本编写

  - 需求: 循环复制文件到集群所有节点的相同目录下

  - 期望脚本: 脚本+要同步的文件名称

  - 说明: 在/usr/local/bin这个目录下存放脚本, root用户可以在系统任何地方直接执行

  - 脚本实现

    - 在/usr/local/bin目录下创建rsync-script

      ```sh
      touch rsync-script
      vim rsync-script
      ```

      编写脚本如下

      ```shell
      #!/bin/bash 
      #1 获取命令输入参数的个数，如果个数为0，直接退出命令 
      paramnum=$# 
      if((paramnum==0)); then 
      echo no params; 
      exit; 
      fi
      #2 根据传入参数获取文件名称 
      p1=$1 
      file_name=`basename $p1` 
      echo fname=$file_name 
      #3 获取输入参数的绝对路径 
      pdir=`cd -P $(dirname $p1); pwd` 
      echo pdir=$pdir 
      #4 获取用户名称 
      user=`whoami` 
      #5 循环执行rsync 
      for((host=1; host<4; host++)); do 
      echo ------------------- hadoop$host -------------- 
      rsync -rvl $pdir/$file_name $user@hadoop$host:$pdir 
      done
      ```

    - 修改脚本 rsync-script 具有执行权限

      ```sh
      chmod 777 rsync-script
      ```

    - 调用脚本形式：rsync-script 文件名称

      ```sh
      rsync-script /home/root/bin
      ```

    - 调用脚本 分发hadoop安装目录到其他节点

      ```sh
      rsync-script /opt/hadoop/servers/hadoop-2.9.2
      ```

## 4. 启动集群

**如果集群是第一次启动，需要在Namenode所在节点格式化NameNode，非第一次不用执行格式化Namenode操作！**

### 4.1 单节点启动

```sh
 #格式化namenode
 hadoop namenode -format
```

![示意图](https://img.zhaojq.top/20260727091726400.png "示意图")

格式化后创建的文件：/opt/hadoop/servers/hadoop-2.9.2/data/tmp/dfs/name/current

- 在hadoop1上启动NameNode

  ```sh
  hadoop-daemon.sh start namenode
  
  jps
  ```

- 在hadoop1, hadoop2, hadoop3上分别启动DataNode

  ```sh
  hadoop-daemon.sh start datanode
  
  jps
  ```

-  web端查看Hdfs界面

  ```http
  http://10.211.55.7:50070/dfshealth.html#tab-overview
  ```

- yarn集群单点启动

  ```sh
  #hadoop3
  yarn-daemon.sh start resourcemanager
  
  jps
  
  #hadoop2
  yarn-daemon.sh start nodemanager
  
  #hadoop1
  yarn-daemon.sh start nodemanager
  ```

### 4.2 集群群起

先停止之前单节点方式启动

- 启动hdfs

  ```sh
  #hadoop1上执行
  start-dfs.sh
  ```

  ![示意图](https://img.zhaojq.top/20260727091726595.png "示意图")

- 启动yarn

  ```sh
  #hadoop3上执行
  start-yarn.sh
  ```

**注意：NameNode和ResourceManger不是在同一台机器，不能在NameNode上启动YARN，应该在ResouceManager所在的机器上启动YARN**

### 4.3 集群启动停止命令

**各服务组件逐一启动/停止**:

- 分别启动/停止HDFS组件

  ```sh
  hadoop-daemon.sh start/stop namenode/datanode/secondarynamenode
  ```

- 启动/停止yarn

  ```sh
  yarn-daemon.sh start/stop resourcemanager/nodemanager
  ```

**各个模块分开启动/停止（配置ssh是前提）常用**:

- 整体启动/停止HDFS

  ```sh
  start-dfs.sh 
  stop-dfs.sh
  ```

- 整体启动/停止YARN

  ```sh
  start-yarn.sh
  stop-yarn.sh
  ```



## 5. 集群测试

- HDFS 分布式存储测试

  ```sh
  #本地home目录创建一个文件 
  cd /root 
  vim test.txt 
  
  # hdfs创建目录
  hdfs dfs -mkdir -p /test/input
  
  #上传linxu文件到Hdfs 
  hdfs dfs -put /root/test.txt /test/input 
  
  #从Hdfs下载文件到linux本地 
  hdfs dfs -get /test/input/test.txt
  ```

-  MapReduce 分布式计算

  ```sh
  # 在HDFS文件系统根目录下面创建一个wcinput文件夹
  hdfs dfs -mkdir /wcinput
   
  # 在/root/目录下创建一个wc.txt文件(本地文件系统) 
  cd /root/
  touch wc.txt
  vim wc.txt
  # 添加以下内容
  hadoop mapreduce yarn 
  hdfs hadoop mapreduce 
  mapreduce yarn hello 
  hello
  hello
  
  # 上传wc.txt到hdfs目录/wcinput下
  hdfs dfs -put wc.txt /wcinput
  
  # 回到Hadoop目录/opt/lagou/servers/hadoop-2.9.2
  # 执行程序
  hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.9.2.jar wordcount /wcinput /wcoutput
  
  # 查看结果
  hdfs dfs -cat /wcoutput/part-r-00000
  ```

  > tips: 注意yarn-site.xml 如果用服务器别名不行的话, 修改为ip地址

## 6. 配置历史服务器

在Yarn中运行的任务产生的日志数据不能查看，为了查看程序的历史运行情况，需要配置一下历史日志服务器。具体配置步骤如下：

- 配置mapred-site.xml

  ```xml
  <!-- 历史服务器端地址 --> 
  <property> 
    <name>mapreduce.jobhistory.address</name> 
    <value>hadoop1:10020</value> 
  </property> 
  <!-- 历史服务器web端地址 --> 
  <property> 
    <name>mapreduce.jobhistory.webapp.address</name> 
    <value>hadoop1:19888</value> 
  </property>
  ```

- 分发mapred-site.xml到其它节点

  ```sh
  rsync-script mapred-site.xml
  ```

- 启动历史服务器

  ```sh
  mr-jobhistory-daemon.sh start historyserver
  
  jps
  ```

- 查看JobHistory

  ```http
  http://hadoop1:19888/jobhistory
  ```

- 配置日志聚集

  日志聚集：应用(Job)运行完成以后，将应用运行日志信息从各个task汇总上传到HDFS系统上。

  日志聚集功能好处：可以方便的查看到程序运行详情，方便开发调试。

  **注意：开启日志聚集功能，需要重新启动NodeManager 、ResourceManager和HistoryManager**

  ```xml
  # 配置yarn-site.xml
  
  <!-- 日志聚集功能使能 -->
  <property> 
    <name>yarn.log-aggregation-enable</name> 
    <value>true</value> 
  </property>
  <!-- 日志保留时间设置7天 --> 
  <property> 
    <name>yarn.log-aggregation.retain-seconds</name> 
    <value>604800</value> 
  </property>
  ```

  








































