contos7.9 部署3节点 hadoop3.4 高可用集群

contos7.9 部署3节点 hadoop3.4 高可用集群

环境信息

服务器IP地址配置系统jdkhadoopzookeeper备注
hadoop-0001192.168.0.1412C4GCentOS 7.9 64bitjdk-8u421-linux-x64.tar.gzhadoop-3.4.0.tar.gzapache-zookeeper-3.8.4-bin.tar.gzhadoop和zookeeper均为写文档时的最高版本
hadoop-0002192.168.0.2222C4GCentOS 7.9 64bitjdk-8u421-linux-x64.tar.gzhadoop-3.4.0.tar.gzapache-zookeeper-3.8.4-bin.tar.gzhadoop和zookeeper均为写文档时的最高版本
hadoop-0003192.168.0.2522C4GCentOS 7.9 64bitjdk-8u421-linux-x64.tar.gzhadoop-3.4.0.tar.gzapache-zookeeper-3.8.4-bin.tar.gzhadoop和zookeeper均为写文档时的最高版本

Hadoop与Zookeeper的版本对应关系

Hadoop版本Zookeeper版本
2.7.x3.4.6
2.8.x3.4.6
3.0.x3.5.1
3.1.x3.5.3
3.2.x3.5.6或3.4.14
3.3.x3.5.9或3.7.0

(注意:表格中的版本对应关系可能因具体发布时间和官方更新而有所变化,建议在实际使用时参考Apache官方文档或相关社区的最新信息。)

服务器角色分配

服务器角色hadoop-0001hadoop-0002hadoop-0003
zookeeper
NameNode
ResourceManager
DataNode
NodeManager
JournalNode

比较Hadoop基础集群规划,将Secondary NameNode改为NameNode,最终为双NameNode,双ResourceManager,三个zookeeper三个JournalNode。

JournalNode负责存储NameNode的编辑日志,这些日志记录了HDFS的所有更改。在NameNode故障时,新的NameNode需要这些日志来恢复文件系统的状态。

ZooKeeper和JournalNode在HDFS的HA配置中各自承担着不同的责任。ZooKeeper负责状态管理和故障转移,而JournalNode负责存储和复制编辑日志。这两者的结合使得HDFS能够在出现单点故障时实现快速且可靠的恢复,从而提高了整个集群的高可用性。

使用端口

服务进程端口号端口号用途访问方式使用者
NameNode50070NameNode HTTP UI浏览器管理员、客户端
NameNode9870NameNode HTTPS UI(如果启用)浏览器管理员、客户端
DataNode50010DataNode RPC 服务接口调用内部通信
DataNode50020DataNode HTTP UI浏览器管理员、客户端
DataNode50075DataNode IPC 服务接口调用内部通信
DataNode9864DataNode HTTPS UI(如果启用)浏览器管理员、客户端
Secondary NameNode50090Secondary NameNode HTTP UI浏览器管理员
ResourceManager8088ResourceManager HTTP UI浏览器管理员、客户端
ResourceManager8090ResourceManager Scheduler UI浏览器管理员
ResourceManager9090ResourceManager HTTPS UI(如果启用)浏览器管理员、客户端
NodeManager8040NodeManager HTTP UI浏览器管理员、客户端
NodeManager8042NodeManager Localizer HTTP UI浏览器管理员
NodeManager9042NodeManager HTTPS UI(如果启用)浏览器管理员、客户端
HistoryServer19888HistoryServer HTTP UI浏览器管理员、客户端
ZooKeeper2181ZooKeeper 客户端端口接口调用内部通信、客户端
ZooKeeper2888ZooKeeper 服务器间通信端口接口调用内部通信
ZooKeeper3888ZooKeeper 选举端口接口调用内部通信

服务器配置

配置免密登录

root 对所有节点 (hadoop-0001, hadoop-0002, hadoop-0003)

[root@hadoop-0001 ~]# ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa -N ""

[root@hadoop-0001 ~]# for i in 192.168.0.141 192.168.0.222 192.168.0.252; do ssh-copy-id $i; done

服务器配置初始化 init_server.sh

所有节点执行 (hadoop-0001, hadoop-0002, hadoop-0003)

#!/bin/bash

# 清理旧的YUM源
rm -rf /etc/yum.repos.d/*.repo

# 下载华为云内部使用的YUM源文件
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.myhuaweicloud.com/repo/CentOS-Base-7.repo

# 清理YUM缓存并重新生成
yum clean all
yum makecache

# 安装常用软件包
yum install -y net-tools lftp rsync psmisc vim-enhanced tree vsftpd bash-completion createrepo lrzsz iproute

# 停止不需要的服务
systemctl stop postfix atd tuned

# 卸载不需要的软件包
yum remove -y postfix at audit tuned kexec-tools firewalld-*

# 修改cloud配置文件,注释掉manage_etc_hosts: localhost这一行
sed -i '/manage_etc_hosts: localhost/s/^/#/' /etc/cloud/cloud.cfg

# 检查SELinux状态,确保其为Disabled
SELINUX_STATUS=$(getenforce)
if [ "$SELINUX_STATUS" != "Disabled" ]; then
  echo "SELinux is not disabled. Please disable SELinux before running this script."
  exit 1
fi

# 检查防火墙状态,确保firewalld未启用
FIREWALLD_STATUS=$(systemctl is-active --quiet firewalld)
if [ "$FIREWALLD_STATUS" == "active" ]; then
  echo "Firewalld is active. Please stop and disable firewalld before running this script."
  exit 1
fi

# 重启服务器
echo "Rebooting the server..."
reboot
[root@hadoop-0001 ~]# vim init_server.sh
[root@hadoop-0001 ~]# for i in 192.168.0.141 192.168.0.222 192.168.0.252; do scp init_server.sh $i:/root; done

[root@hadoop-0001 ~]# bash init_server.sh
[root@hadoop-0002 ~]# bash init_server.sh
[root@hadoop-0003 ~]# bash init_server.sh

配置主机名映射

所有节点配置 hosts文件

(hadoop-0001, hadoop-0002, hadoop-0003)

[root@hadoop-0001 ~]# cat /etc/hosts
::1     localhost       localhost.localdomain   localhost6      localhost6.localdomain6
127.0.0.1       localhost       localhost.localdomain   localhost4      localhost4.localdomain4
# 把127.0.0.1对应的 主机名这行删掉
192.168.0.141   hadoop-0001
192.168.0.222   hadoop-0002
192.168.0.252   hadoop-0003

[root@hadoop-0001 ~]# vim /etc/hosts
[root@hadoop-0001 ~]# for i in 192.168.0.141 192.168.0.222 192.168.0.252; do scp /etc/hosts $i:/etc/hosts; done

hadoop 安装环境配置

下载安装包

华为镜像站点:华为开源镜像站_软件开发服务_华为云

下载 jdk1.8

hadoop支持的jdk版本:Hadoop Java 版本 - Hadoop - Apache Software Foundation

支持的 Java 版本
Apache Hadoop 3.3 及更高版本支持 Java 8 和 Java 11(仅限运行时)
请使用 Java 8 编译 Hadoop。不支持使用 Java 11 编译 Hadoop: 哈多普-16795 - Java 11 编译支持 打开
Apache Hadoop 从 3.0.x 到 3.2.x 现在仅支持 Java 82.7.x 到 2.10.x 的 Apache Hadoop 同时支持 Java 78

在这里插入图片描述

hadoop3.4

下载二进制包

Apache Download Mirrors

https://dlcdn.apache.org/hadoop/common/hadoop-3.4.0/hadoop-3.4.0.tar.gz

Linux x64 Compressed Archive139.93 MBjdk-8u421-linux-x64.tar.gz
hadoop-3.4.0.tar.gz

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

zookeeper3.8.4

https://dlcdn.apache.org/zookeeper/zookeeper-3.8.4/apache-zookeeper-3.8.4-bin.tar.gz

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

分发安装包

所有节点 (hadoop-0001, hadoop-0002, hadoop-0003)

[root@hadoop-0001 ~]# curl -o hadoop-3.4.0.tar.gz https://dlcdn.apache.org/hadoop/common/hadoop-3.4.0/hadoop-3.4.0.tar.gz
[root@hadoop-0001 ~]# curl -o apache-zookeeper-3.8.4-bin.tar.gz https://dlcdn.apache.org/zookeeper/zookeeper-3.8.4/apache-zookeeper-3.8.4-bin.tar.gz
[root@hadoop-0001 ~]# for i in 192.168.0.222 192.168.0.252; do scp hadoop-3.4.0.tar.gz jdk-8u421-linux-x64.tar.gz apache-zookeeper-3.8.4-bin.tar.gz install_jdk.sh root@$i:/root/; done

安装jdk1.8 install_jdk.sh

所有节点 (hadoop-0001, hadoop-0002, hadoop-0003)

#!/bin/bash

# 定义变量
JDK_TAR_GZ="$1"
PROFILE_BACKUP="/etc/profile.bak.$(date +%F-%H%M%S)"
JDK_INSTALL_DIR=""
INSTALLED_JDK_VERSION=""

# 错误处理逻辑
handle_error() {
    echo "[ERROR] - [$(date +'%Y-%m-%d %H:%M:%S')] - $1" >&2
    exit 1
}

# 提示信息处理逻辑
handle_info() {
    echo "[INFO] - [$(date +'%Y-%m-%d %H:%M:%S')] - $1"
}

handle_warning() {
    echo "[WARNING] - [$(date +'%Y-%m-%d %H:%M:%S')] - $1"
}

# 检查是否传入了参数
if [[ -z "$JDK_TAR_GZ" ]]; then
    handle_error "未传入JDK安装包的文件名作为参数。用法:$0 jdk-文件名.tar.gz"
fi

# 检查JDK安装包是否在当前目录
if [[ ! -f "$JDK_TAR_GZ" ]]; then
    handle_error "未在当前目录找到JDK安装包 $JDK_TAR_GZ。"
fi

# 检查是否已经安装了JDK并获取版本
if command -v java &> /dev/null; then
    INSTALLED_JDK_VERSION=$(java -version 2>&1 | head -n 1 | awk -F'[ "]+' '{print $3}')
    INSTALLED_JDK_VERSION_MAJOR_MINOR=$(echo "$INSTALLED_JDK_VERSION" | cut -d. -f1-2)
    handle_info "已安装的JDK版本信息如下:"
    java -version

    if [[ "$INSTALLED_JDK_VERSION_MAJOR_MINOR" != "1.8" ]]; then
        handle_info "警告:已安装的JDK版本不是1.8,而是 $INSTALLED_JDK_VERSION。"

        # 提供卸载非JDK 1.8版本的指导
        if rpm -qa | grep -q "jdk|java"; then
            handle_info "发现通过rpm安装的JDK,可以使用以下命令卸载:"
            handle_info "rpm -e --nodeps $(rpm -qa | grep -E 'jdk|java')"
        elif yum list installed | grep -q "jdk|java"; then
            handle_info "发现通过yum安装的JDK,可以使用以下命令卸载:"
            handle_info "yum remove $(yum list installed | grep -E 'jdk|java' | awk '{print $1}')"
        else
            handle_info "无法确定JDK的安装方式,可能需要手动卸载。请查找相关安装文档。"
        fi

        read -p "是否继续安装新版本的JDK?(y/n): " choice
        if [[ "$choice" != "y" && "$choice" != "Y" ]]; then
            handle_info "取消安装。"
            exit 0
        fi
    fi
else
    handle_info "未检测到JDK安装。"
fi

# 备份/etc/profile
handle_info "开始备份/etc/profile到$PROFILE_BACKUP"
cp /etc/profile "$PROFILE_BACKUP" || handle_error "Failed to create backup of /etc/profile."
handle_info "备份/etc/profile完成"

# 解压JDK安装包
handle_info "开始解压JDK安装包 $JDK_TAR_GZ 到 /usr/local/"
tar -xzf "$JDK_TAR_GZ" -C /usr/local/ || handle_error "Failed to extract $JDK_TAR_GZ file."
handle_info "解压JDK安装包完成"

# 获取解压后的JDK目录名(使用find命令提高健壮性)
JDK_DIRS=($(find /usr/local/ -maxdepth 1 -type d -name "jdk[0-9]*.[0-9]*.[0-9]*_[0-9]*" 2>/dev/null))
if [[ ${#JDK_DIRS[@]} -eq 0 ]]; then
    handle_error "未找到解压后的JDK目录。"
elif [[ ${#JDK_DIRS[@]} -gt 1 ]]; then
    handle_warning "警告:发现多个可能的JDK目录,选择第一个(${JDK_DIRS[0]}):"
    for dir in "${JDK_DIRS[@]}"; do
        handle_warning "  $dir"
    done
fi
JDK_INSTALL_DIR="${JDK_DIRS[0]}"

# 将环境变量写入/etc/profile
handle_info "开始将环境变量写入/etc/profile"
{
    echo ""
    echo "export JAVA_HOME=$JDK_INSTALL_DIR"
    echo "export PATH=\$JAVA_HOME/bin:\$PATH"
} >> /etc/profile
handle_info "环境变量写入/etc/profile完成"

# 为了使更改立即生效,对当前会话加载新的环境变量(对后续登录用户无效)
handle_info "/etc/profile 是在用户登录时由系统读取的,因此任何对 /etc/profile 的更改都需要用户重新登录或手动重新加载(如使用 source /etc/profile)才能生效。"
source /etc/profile || handle_error "Failed to source /etc/profile."

# 验证JDK安装是否成功
if java -version 2>&1; then
    handle_info "JDK安装成功,版本信息如下:"
    java -version
    handle_info "安装和配置已完成。环境变量已写入/etc/profile。"
    handle_info "对于当前用户,为了使更改立即生效,请执行'source /etc/profile'。"
    handle_info "对于后续登录的用户,新的环境变量将在他们登录时自动生效。"
else
    handle_error "JDK安装验证失败。请检查JDK是否正确安装以及环境变量设置是否正确。"
fi
[root@hadoop-0001 ~]# bash install_jdk.sh jdk-8u421-linux-x64.tar.gz
[root@hadoop-0002 ~]# bash install_jdk.sh jdk-8u421-linux-x64.tar.gz
[root@hadoop-0003 ~]# bash install_jdk.sh jdk-8u421-linux-x64.tar.gz
# 退出再登陆,加载环境变量,也可以执行source /etc/profile使变量在当前会话生效

安装 zookeeper-3.8.4

所有节点 (hadoop-0001, hadoop-0002, hadoop-0003)

部署zookeeper-3.8.4 运行环境 env_zookeeper_intall.sh
#!/bin/bash

# 错误处理逻辑
handle_error() {
    echo "[ERROR] - [$(date +'%Y-%m-%d %H:%M:%S')] - $1" >&2
    exit 1
}

# 提示信息处理逻辑
handle_info() {
    echo "[INFO] - [$(date +'%Y-%m-%d %H:%M:%S')] - $1"
}

# 检查并获取 zookeeper tar.gz 文件参数
check_zookeeper_tar_gz() {
    local ZOOKEEPER_TAR_GZ="$1"
    if [ -z "$ZOOKEEPER_TAR_GZ" ]; then
        handle_error "No zookeeper tar.gz file provided!"
    elif [ ! -f "$ZOOKEEPER_TAR_GZ" ]; then
        handle_error "$ZOOKEEPER_TAR_GZ file not found!"
    fi
}

# 创建必要的目录
create_directories() {
    mkdir -p /data/zookeeper/{zookeeper_soft,zookeeper_data}
    for dir in /data/zookeeper/{zookeeper_soft,zookeeper_data}; do
        handle_info "Created directory: $dir"
    done
}

# 解压 zookeeper tar.gz 文件并获取解压后的目录名
extract_zookeeper_and_get_basename() {
    local ZOOKEEPER_TAR_GZ="$1"
    tar -xf "$ZOOKEEPER_TAR_GZ" -C /data/zookeeper/zookeeper_soft/ || handle_error "Failed to extract $ZOOKEEPER_TAR_GZ file."
    # 假设解压后的目录名格式为 apache-zookeeper-<version>-bin,获取该目录名
    local ZOOKEEPER_DIR_FULLPATH=$(ls -d /data/zookeeper/zookeeper_soft/apache-zookeeper-* | head -n 1)
    handle_info "$ZOOKEEPER_TAR_GZ extracted successfully to $ZOOKEEPER_DIR_FULLPATH"
}

# 更新 /etc/profile
update_profile() {
    local BACKUP_FILE="/etc/profile.bak.$(date +%F-%H%M%S)"
    cp /etc/profile "$BACKUP_FILE" || handle_error "Failed to create backup of /etc/profile."
    
    cat << EOF >> /etc/profile
export ZOOKEEPER_HOME=$(ls -d /data/zookeeper/zookeeper_soft/apache-zookeeper-* | head -n 1)
export PATH=\$PATH:\$ZOOKEEPER_HOME/bin
EOF
    
    source /etc/profile || handle_error "Failed to source /etc/profile."
    
    if [ -z "${ZOOKEEPER_HOME-}" ]; then
        handle_error "ZOOKEEPER_HOME environment variable not set!"
    fi
    handle_info "ZooKeeper environment variables have been set."
}

# 配置 zoo.cfg
zoo_config() {
    local CONF_DIR="$(ls -d /data/zookeeper/zookeeper_soft/apache-zookeeper-* | head -n 1)/conf"  # 假设 conf 目录在解压后的根目录下
    
    # 检查 conf 目录是否存在
    if [[ ! -d "$CONF_DIR" ]]; then
        handle_error "Configuration directory $CONF_DIR not found!"
    fi

    cat << EOF > "$CONF_DIR/zoo.cfg"
tickTime=2000
dataDir=/data/zookeeper/zookeeper_data/
clientPort=2181
initLimit=5
syncLimit=2
server.1=hadoop-0001:2888:3888
server.2=hadoop-0002:2888:3888
server.3=hadoop-0003:2888:3888
EOF
    handle_info "ZooKeeper configuration file $CONF_DIR/zoo.cfg created successfully."
}

# 主流程
check_zookeeper_tar_gz "$1"
create_directories
extract_zookeeper_and_get_basename "$1"
update_profile
zoo_config

handle_info "ZooKeeper environment setup completed successfully."
[root@hadoop-0001 ~]# vim env_zookeeper_intall.sh
[root@hadoop-0001 ~]# for i in 192.168.0.222 192.168.0.252; do scp env_zookeeper_intall.sh root@$i:/root/; done     

[root@hadoop-0001 ~]# bash env_zookeeper_intall.sh apache-zookeeper-3.8.4-bin.tar.gz
[root@hadoop-0002 ~]# bash env_zookeeper_intall.sh apache-zookeeper-3.8.4-bin.tar.gz
[root@hadoop-0003 ~]# bash env_zookeeper_intall.sh apache-zookeeper-3.8.4-bin.tar.gz
# 退出再登陆,加载环境变量,也可以执行source /etc/profile使变量在当前会话生效
所有节点创建myid文件,分别写入1 2 3

(hadoop-0001, hadoop-0002, hadoop-0003)

myid
[root@hadoop-0001 ~]# echo "1" > /data/zookeeper/zookeeper_data/myid
[root@hadoop-0002 ~]# echo "2" > /data/zookeeper/zookeeper_data/myid
[root@hadoop-0003 ~]# echo "3" > /data/zookeeper/zookeeper_data/myid
所有节点启动 zookeeper

(hadoop-0001, hadoop-0002, hadoop-0003)

[root@hadoop-0001 ~]# zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /data/zookeeper/zookeeper_soft/apache-zookeeper-3.8.4-bin/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED

[root@hadoop-0002 ~]# zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /data/zookeeper/zookeeper_soft/apache-zookeeper-3.8.4-bin/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED

[root@hadoop-0003 ~]# zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /data/zookeeper/zookeeper_soft/apache-zookeeper-3.8.4-bin/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
查看zookeeper状态

所有节点 (hadoop-0001, hadoop-0002, hadoop-0003)

# 日志正常
[root@hadoop-0001 ~]# less /data/zookeeper/zookeeper_soft/apache-zookeeper-3.8.4-bin/logs/zookeeper-root-server-hadoop-0001.out
[root@hadoop-0002 ~]# less /data/zookeeper/zookeeper_soft/apache-zookeeper-3.8.4-bin/logs/zookeeper-root-server-hadoop-0002.out
[root@hadoop-0003 ~]# less /data/zookeeper/zookeeper_soft/apache-zookeeper-3.8.4-bin/logs/zookeeper-root-server-hadoop-0003.out

# 状态正常 1个 leader 2个 follower
[root@hadoop-0001 ~]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /data/zookeeper/zookeeper_soft/apache-zookeeper-3.8.4-bin/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: follower

[root@hadoop-0002 ~]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /data/zookeeper/zookeeper_soft/apache-zookeeper-3.8.4-bin/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: leader

[root@hadoop-0003 ~]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /data/zookeeper/zookeeper_soft/apache-zookeeper-3.8.4-bin/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: follower

节点关闭的命令 zookeeper

不进行关闭

[root@hadoop-0001 ~]# zkServer.sh stop
[root@hadoop-0002 ~]# zkServer.sh stop
[root@hadoop-0003 ~]# zkServer.sh stop

安装 hadoop3.4

所有节点 (hadoop-0001, hadoop-0002, hadoop-0003)

部署 hadoop3.4 运行环境 env_hadoop_intall.sh
#!/bin/bash

# 错误处理逻辑
handle_error() {
    echo "[ERROR] - [$(date +'%Y-%m-%d %H:%M:%S')] - $1" >&2
    exit 1
}

# 提示信息处理逻辑
handle_info() {
    echo "[INFO] - [$(date +'%Y-%m-%d %H:%M:%S')] - $1"
}

# 检查并获取 Hadoop tar.gz 文件参数
check_hadoop_tar_gz() {
    local HADOOP_TAR_GZ="$1"
    if [ -z "$HADOOP_TAR_GZ" ]; then
        handle_error "No Hadoop tar.gz file provided!"
    elif [ ! -f "$HADOOP_TAR_GZ" ]; then
        handle_error "Hadoop tar.gz file not found!"
    fi
}

# 创建必要的目录
create_directories() {
    mkdir -p /data/hadoop/{hadoop_soft,hadoop_data/{tmp,hdfs/{namenode,datanode,journalnode}}}
    # 输出创建的目录
    for dir in /data/hadoop/{hadoop_soft,hadoop_data/{tmp,hdfs/{namenode,datanode,journalnode}}}; do
        handle_info "Created directory: $dir"
    done
    handle_info "Directories created successfully."
}

# 解压 Hadoop tar.gz 文件
extract_hadoop() {
    local HADOOP_TAR_GZ="$1"
    tar -xf "$HADOOP_TAR_GZ" -C /data/hadoop/hadoop_soft/ || handle_error "Failed to extract $HADOOP_TAR_GZ file."
    handle_info "Hadoop extracted successfully."
}

# 更新 /etc/profile
update_profile() {
    local BACKUP_FILE="/etc/profile.bak.$(date +%F-%H%M%S)"
    cp /etc/profile "$BACKUP_FILE" || handle_error "Failed to create backup of /etc/profile."
    
    cat << EOF >> /etc/profile
export HADOOP_HOME=$(ls -d /data/hadoop/hadoop_soft/hadoop-* | head -n 1)
export HADOOP_CONF_DIR=\$HADOOP_HOME/etc/hadoop
export PATH=\$PATH:\$HADOOP_HOME/bin:\$HADOOP_HOME/sbin
EOF
    
    source /etc/profile || handle_error "Failed to source /etc/profile."
    
    # 检查环境变量是否设置成功(可选)
    if [ -z "${HADOOP_HOME-}" ]; then
        handle_error "HADOOP_HOME environment variable not set!"
    fi
    handle_info "Hadoop environment variables have been set."
}

# 备份并更新 Hadoop 配置文件
backup_and_update_hadoop_config() {
    cd $(ls -d /data/hadoop/hadoop_soft/hadoop-* | head -n 1)/etc/hadoop || handle_error "Failed to change directory to Hadoop config directory."
    
    for file in core-site.xml hdfs-site.xml yarn-site.xml mapred-site.xml; do
        cp "$file" "${file}.$(date +%F-%H%M%S).bak" || handle_error "Failed to backup $file."
    done
    
    cp hadoop-env.sh hadoop-env.sh.$(date +%F-%H%M%S).bak || handle_error "Failed to backup hadoop-env.sh."
    
    cat << EOF >> hadoop-env.sh
export HDFS_NAMENODE_USER="hadoop"
export HDFS_DATANODE_USER="hadoop"
export HDFS_SECONDARYNAMENODE_USER="hadoop"
export JAVA_HOME=/usr/local/jdk1.8.0_421
EOF

# 检查 hadoop 用户是否存在
if ! id "hadoop" &>/dev/null; then
    # 用户不存在,创建用户并设置密码
    useradd hadoop || handle_error "Failed to create hadoop user."
    # 注意:出于安全考虑,不建议在脚本中直接设置简单密码。
    echo "hadoop:hadoop" | chpasswd || handle_error "Failed to set password for hadoop user."
    handle_info "Hadoop user created and password set."
else
    handle_info "Hadoop user already exists."
fi
    
# 更新 Hadoop 配置文件
handle_info "Hadoop configuration files have been updated."
}

# 警告信息处理逻辑
handle_warning() {
    echo "[WARNING] - [$(date +'%Y-%m-%d %H:%M:%S')] - $1"
}

# 主流程
check_hadoop_tar_gz "$1"
create_directories
extract_hadoop "$1"
update_profile
backup_and_update_hadoop_config

handle_info "Hadoop environment setup completed successfully."
[root@hadoop-0001 ~]# vim env_hadoop_intall.sh
[root@hadoop-0001 ~]# for i in 192.168.0.222 192.168.0.252; do scp env_hadoop_intall.sh root@$i:/root/; done

[root@hadoop-0001 ~]# bash env_hadoop_intall.sh hadoop-3.4.0.tar.gz
[root@hadoop-0002 ~]# bash env_hadoop_intall.sh hadoop-3.4.0.tar.gz
[root@hadoop-0003 ~]# bash env_hadoop_intall.sh hadoop-3.4.0.tar.gz
# 退出再登陆,加载环境变量,也可以执行source /etc/profile使变量在当前会话生效
配置 Hadoop3.4 核心文件

在所有节点上配置 core-site.xmlhdfs-site.xml yarn-site.xml mapred-site.xml

core-site.xml
所有节点上配置 (hadoop-0001, hadoop-0002, hadoop-0003)

文件包含了集群使用的核心配置,包括文件系统的默认设置和 I/O 缓冲区大小。

<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入用于格式化输出的XSL样式表(可选) -->
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>

    <!-- 
    指定Hadoop文件系统的默认URI。
    这是HDFS(Hadoop分布式文件系统)的逻辑名称,通常指向NameNode。
    在HDFS高可用(HA)配置中,这个URI应该指向NameNode的集群。组成集群的配置写在 hdfs-site.xml
    -->
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://mycluster</value> <!-- 指定NameNode所在的集群名和端口号 即HDFS 集群的名称-->
    </property>

    <!-- 
    设置Hadoop临时文件的存储目录。
    这个目录用于存储Hadoop守护进程(如NameNode、DataNode等)的临时文件。
    请确保这个目录在您的文件系统中存在,并且Hadoop进程有权限写入。
    -->
    <property>
        <name>hadoop.tmp.dir</name>
        <value>/data/hadoop/hadoop_data/tmp</value> <!-- 临时文件存储的本地目录  -->
    </property>

    <!-- 
    配置ZooKeeper集群的地址。
    在Hadoop的高可用配置中,ZooKeeper用于存储配置信息、集群状态和协调NameNode的故障转移。
    请列出所有ZooKeeper节点的地址,每个节点用逗号分隔。
    -->
    <property>
        <name>ha.zookeeper.quorum</name>
        <value>hadoop-0001:2181,hadoop-0002:2181,hadoop-0003:2181</value> <!-- ZooKeeper节点地址 -->
    </property>

    <!-- 
    设置文件I/O操作的缓冲区大小。
    这个值决定了Hadoop在进行文件读写操作时使用的内存缓冲区大小。
    较大的缓冲区可以提高性能,但也会增加内存使用。
    默认值可能因Hadoop版本而异,这里设置为4096字节(4KB)。
    -->
    <property>
        <name>io.file.buffer.size</name>
        <value>4096</value> <!-- 以字节为单位,根据需要调整 -->
    </property>

    <!-- 
    (可选)其他Hadoop核心配置属性
    根据您的需求和环境,您可能还需要添加其他配置属性。
    例如,您可以配置网络拓扑脚本、垃圾回收选项、Java堆大小等。
    -->

</configuration>
[root@hadoop-0001 hadoop]# cd /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/
[root@hadoop-0001 hadoop]# vim core-site.xml
[root@hadoop-0001 hadoop]# for i in 192.168.0.222 192.168.0.252; do scp core-site.xml root@$i:/data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop; done
hdfs-site.xml

所有节点,但是NameNode节点 和 DataNode 节点有区别

文件包含了 HDFS 的特定配置,包括 NameNode,DataNode,journalnode的存储目录以及数据复制的策略。

在namenode节点上配置(hadoop-0001, hadoop-0002):
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>

    <!-- HDFS 基本配置 -->
    <property>
        <name>dfs.nameservices</name>
        <value>mycluster</value> <!-- HDFS 集群的名称 -->
    </property>
    <property>
        <name>dfs.replication</name>
        <value>2</value> <!-- 每个文件块在HDFS中的副本数 -->
    </property>
    <property>
        <name>dfs.ha.namenodes.mycluster</name>
        <value>nn1,nn2</value> <!-- 列出集群中所有 NameNode 的名称或 ID -->
    </property>
    <property>
        <name>dfs.namenode.rpc-address.mycluster.nn1</name>
        <value>hadoop-0001:8020</value> <!-- nn1 的 RPC 地址 -->
    </property>
    <property>
        <name>dfs.namenode.rpc-address.mycluster.nn2</name>
        <value>hadoop-0002:8020</value> <!-- nn2 的 RPC 地址 -->
    </property>
    <property>
        <name>dfs.namenode.http-address.mycluster.nn1</name>
        <value>hadoop-0001:50070</value> <!-- nn1 的 HTTP 地址 -->
    </property>
    <property>
        <name>dfs.namenode.http-address.mycluster.nn2</name>
        <value>hadoop-0002:50070</value> <!-- nn2 的 HTTP 地址 -->
    </property>
    <!-- NameNode 配置 -->
    <property>
        <name>dfs.namenode.name.dir</name>
        <value>/data/hadoop/hadoop_data/hdfs/namenode</value> <!-- NameNode 存储元数据的本地目录 -->
    </property>

    <!-- DataNode 配置 -->
    <property>
        <name>dfs.datanode.data.dir</name>
        <value>/data/hadoop/hadoop_data/hdfs/datanode</value> <!-- DataNode 存储数据块的本地目录 -->
    </property>

    <!-- JournalNode 配置 -->
    <property>
        <name>dfs.journalnode.edits.dir</name>
        <value>/data/hadoop/hadoop_data/hdfs/journalnode</value> <!-- JournalNode 存储编辑日志的本地目录 -->
    </property>
    <property>
        <name>dfs.namenode.shared.edits.dir</name>
        <value>qjournal://hadoop-0001:8485;hadoop-0002:8485;hadoop-0003:8485/mycluster</value>
        <!-- 指定 JournalNode 集群的地址 -->
    </property>

    <!-- HDFS 高可用性配置 -->
    <property>
        <name>dfs.ha.automatic-failover.enabled</name>
        <value>true</value> <!-- 开启 NameNode 失败自动切换 -->
    </property>
    <property>
        <name>dfs.client.failover.proxy.provider.mycluster</name>
        <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
        <!-- 配置 NameNode 失败后自动切换实现方式 -->
    </property>

    <!-- 故障转移配置 -->
    <property>
        <name>dfs.ha.fencing.methods</name>
        <value>sshfence</value> <!-- 故障转移期间使用的屏蔽方法 -->
    </property>
    <property>
        <name>dfs.ha.fencing.ssh.private-key-files</name>
        <value>/home/hadoop/.ssh/id_rsa</value> <!-- hadoop 用户的私钥文件 -->
    </property>
    <property>
        <name>dfs.ha.fencing.ssh.connect-timeout</name>
        <value>30000</value> <!-- SSH 连接超时时间,单位为毫秒 -->
    </property>

    <!-- 可选配置 -->
    <property>
        <name>fs.trash.interval</name>
        <value>1440</value> <!-- HDFS 垃圾回收站保留时间,单位为分钟 -->
    </property>

    <!-- 注意:客户端故障转移的配置不在服务器 hdfs-site.xml 中设置,
         而是在客户端的 Hadoop 配置 core-site.xml 文件中设置 fs.defaultFS 为当前集群 hdfs://mycluster。
         确保您的客户端配置也已正确设置以支持 HDFS 高可用性。 -->

</configuration>

注意:在 HA 配置中,dfs.namenode.rpc-address 可能会被自动故障转移框架管理,因此通常不需要在 hdfs-site.xml 中为每个 NameNode 明确设置。但是,在某些情况下,您可能需要为管理目的提供一个逻辑名称和端口。上面的配置假设您没有使用自动配置的 RPC 地址。

[root@hadoop-0001 hadoop]# cd /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/
[root@hadoop-0001 hadoop]# vim hdfs-site.xml
[root@hadoop-0001 hadoop]# scp hdfs-site.xml root@192.168.0.222:/data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop
在datanode节点上配置(hadoop-0003):

datanode 的文件比 namenode 的文件减掉了关于 namenode 的配置 dfs.namenode.name.dir

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>

    <!-- HDFS 基本配置 -->
    <property>
        <name>dfs.nameservices</name>
        <value>mycluster</value> <!-- HDFS 集群的名称 -->
    </property>
    <property>
        <name>dfs.replication</name>
        <value>2</value> <!-- 每个文件块在HDFS中的副本数 -->
    </property>
    <property>
        <name>dfs.ha.namenodes.mycluster</name>
        <value>nn1,nn2</value> <!-- 列出集群中所有 NameNode 的名称或 ID -->
    </property>
    <property>
        <name>dfs.namenode.rpc-address.mycluster.nn1</name>
        <value>hadoop-0001:8020</value> <!-- nn1 的 RPC 地址 -->
    </property>
    <property>
        <name>dfs.namenode.rpc-address.mycluster.nn2</name>
        <value>hadoop-0002:8020</value> <!-- nn2 的 RPC 地址 -->
    </property>
    <property>
        <name>dfs.namenode.http-address.mycluster.nn1</name>
        <value>hadoop-0001:50070</value> <!-- nn1 的 HTTP 地址 -->
    </property>
    <property>
        <name>dfs.namenode.http-address.mycluster.nn2</name>
        <value>hadoop-0002:50070</value> <!-- nn2 的 HTTP 地址 -->
    </property>

    <!-- DataNode 配置 -->
    <property>
        <name>dfs.datanode.data.dir</name>
        <value>/data/hadoop/hadoop_data/hdfs/datanode</value> <!-- DataNode 存储数据块的本地目录 -->
    </property>

    <!-- JournalNode 配置 -->
    <property>
        <name>dfs.journalnode.edits.dir</name>
        <value>/data/hadoop/hadoop_data/hdfs/journalnode</value> <!-- JournalNode 存储编辑日志的本地目录 -->
    </property>
    <property>
        <name>dfs.namenode.shared.edits.dir</name>
        <value>qjournal://hadoop-0001:8485;hadoop-0002:8485;hadoop-0003:8485/mycluster</value>
        <!-- 指定 JournalNode 集群的地址 -->
    </property>

    <!-- HDFS 高可用性配置 -->
    <property>
        <name>dfs.ha.automatic-failover.enabled</name>
        <value>true</value> <!-- 开启 NameNode 失败自动切换 -->
    </property>
    <property>
        <name>dfs.client.failover.proxy.provider.mycluster</name>
        <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
        <!-- 配置 NameNode 失败后自动切换实现方式 -->
    </property>

    <!-- 故障转移配置 -->
    <property>
        <name>dfs.ha.fencing.methods</name>
        <value>sshfence</value> <!-- 故障转移期间使用的屏蔽方法 -->
    </property>
    <property>
        <name>dfs.ha.fencing.ssh.private-key-files</name>
        <value>/home/hadoop/.ssh/id_rsa</value> <!-- hadoop 用户的私钥文件 -->
    </property>
    <property>
        <name>dfs.ha.fencing.ssh.connect-timeout</name>
        <value>30000</value> <!-- SSH 连接超时时间,单位为毫秒 -->
    </property>

    <!-- 可选配置 -->
    <property>
        <name>fs.trash.interval</name>
        <value>1440</value> <!-- HDFS 垃圾回收站保留时间,单位为分钟 -->
    </property>

    <!-- 注意:客户端故障转移的配置不在服务器 hdfs-site.xml 中设置,
         而是在客户端的 Hadoop 配置 core-site.xml 文件中设置 fs.defaultFS 为当前集群 hdfs://mycluster。
         确保您的客户端配置也已正确设置以支持 HDFS 高可用性。 -->

</configuration>
[root@hadoop-0003 ~]# cd /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/
[root@hadoop-0003 hadoop]# vim hdfs-site.xml
yarn-site.xml
在所有 resourcemanager 节点和 nodemanager 节点上: (hadoop-0001, hadoop-0002, hadoop-0003)
<?xml version="1.0"?>
<configuration>
    <!-- YARN ResourceManager 高可用配置 -->
    <!-- 启用 ResourceManager 的高可用模式 -->
    <property>
        <name>yarn.resourcemanager.ha.enabled</name>
        <value>true</value>
    </property>
    <property>
        <!-- 开启ResourceManager失败自动切换 -->
        <name>yarn.resourcemanager.ha.automatic-failover.enabled</name>
        <value>true</value>
    </property>   
    <!-- 设置 YARN 集群的唯一标识符 -->
    <property>
        <name>yarn.resourcemanager.cluster-id</name>
        <value>yarn-cluster</value>
    </property>
    <!-- 指定 ResourceManager 的 ID 列表 -->
    <property>
        <name>yarn.resourcemanager.ha.rm-ids</name>
        <value>rm1,rm2</value>
    </property>
    <!-- 配置 rm1 的主机名 -->
    <property>
        <name>yarn.resourcemanager.hostname.rm1</name>
        <value>hadoop-0001</value>
    </property>
    <!-- 配置 rm2 的主机名 -->
    <property>
        <name>yarn.resourcemanager.hostname.rm2</name>
        <value>hadoop-0002</value>
    </property>

    <!-- YARN ResourceManager 服务地址配置 -->
    <!-- rm1 的 Web 应用地址 -->
    <property>
        <name>yarn.resourcemanager.webapp.address.rm1</name>
        <value>hadoop-0001:8088</value>
    </property>
    <!-- rm1 的 HTTPS Web 应用地址 -->
    <property>
        <name>yarn.resourcemanager.webapp.https.address.rm1</name>
        <value>hadoop-0001:8090</value>
    </property>
    <!-- rm2 的 Web 应用地址 -->
    <property>
        <name>yarn.resourcemanager.webapp.address.rm2</name>
        <value>hadoop-0002:8088</value>
    </property>
    <!-- rm2 的 HTTPS Web 应用地址 -->
    <property>
        <name>yarn.resourcemanager.webapp.https.address.rm2</name>
        <value>hadoop-0002:8090</value>
    </property>

    <!-- 使用 ZooKeeper 集群进行故障转移 -->
    <!-- 配置 ZooKeeper 的地址 -->
    <property>
        <name>yarn.resourcemanager.zk-address</name>
        <value>hadoop-0001:2181,hadoop-0002:2181,hadoop-0003:2181</value>
    </property>
    <property>
        <!-- 启用RM重启的功能,默认为false -->
        <name>yarn.resourcemanager.recovery.enabled</name>
        <value>true</value>
    </property>

    <!-- YARN NodeManager 配置 -->
    <!-- 配置 NodeManager 的辅助服务 -->
    <property>
        <name>yarn.nodemanager.aux-services</name>
        <value>mapreduce_shuffle</value>
    </property>

    <property>
        <!-- 用于状态存储的类 -->
        <name>yarn.resourcemanager.store.class</name>
        <value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
    </property>
    <property>
        <!-- NodeManager启用server使用算法的类 -->
        <name>yarn-nodemanager.aux-services.mapreduce.shuffle.class</name>
        <value>org.apache.hadoop.mapred.ShuffleHandler</value>
    </property>
    <property>
        <!-- 启用日志聚合功能 -->
        <name>yarn.log-aggregation-enable</name>
        <value>true</value>
    </property>
    <property>
        <!-- 聚集的日志在HDFS上保存最长的时间 -->
        <name>yarn.log-aggregation.retain-seconds</name>
        <value>106800</value>
    </property>
    <property>
        <!-- 聚集的日志在HDFS上保存最长的时间 -->
        <name>yarn.nodemanager.remote-app-log-dir</name>
        <value>/opt/hadoopHA/logs</value>
    </property>
    <!-- YARN 调度器配置 -->
    <!-- 配置 ResourceManager 使用的调度器 -->
    <property>
        <name>yarn.resourcemanager.scheduler.class</name>
        <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler</value>
    </property>
    <!-- yarn.nodemanager.hostname 和 yarn.nodemanager.address 这样的配置项可以来直接设置 NodeManager 的主机名和地址。但不是必须的。NodeManager 的主机名和地址通常是通过启动 NodeManager 服务的机器的主机名和配置的网络接口来自动确定的。NodeManager 会自动注册到 ResourceManager 上,并报告其可用的资源(如 CPU、内存和磁盘空间)。这个注册过程是基于 NodeManager 所在机器的主机名和配置的端口进行的。 -->	
    <!-- 其他 YARN 相关配置 -->
    <!-- 可以根据需要添加其他属性,例如资源限制、队列配置等 -->
</configuration>
[root@hadoop-0001 hadoop]# cd /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/
[root@hadoop-0001 hadoop]# vim yarn-site.xml
[root@hadoop-0001 hadoop]# for i in 192.168.0.222 192.168.0.252; do scp yarn-site.xml root@$i:/data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop; done
mapred-site.xml
在所有节点上(因为MapReduce客户端需要在任何节点上运行) (hadoop-0001, hadoop-0002, hadoop-0003):
<configuration>
    <!-- 设置MapReduce框架的名称,这里指定为YARN -->
    <property>
        <name>mapreduce.framework.name</name>
        <value>yarn</value> <!-- 指定MapReduce运行在YARN上 -->
    </property>

    <!-- (可选)设置MapReduce JobHistory Server的地址,通常与ResourceManager集成,因此这些配置可能不是必需的 -->
    <!-- 如果你的集群需要单独配置JobHistory Server,可以取消以下注释并根据需要修改 -->
    
<!--    <property>-->
<!--        <name>mapreduce.jobhistory.address</name>-->
<!--        <value>historyserver-hostname:10020</value> &lt;!&ndash; JobHistory Server的主机名和端口号 &ndash;&gt;-->
<!--    </property>-->

<!--    <property>-->
<!--        <name>mapreduce.jobhistory.webapp.address</name>-->
<!--        <value>historyserver-hostname:19888</value> &lt;!&ndash; JobHistory Server Web应用的主机名和端口号 &ndash;&gt;-->
<!--    </property>-->
    

    <!-- (可选)设置MapReduce作业完成后JobHistory文件的存储位置 -->
    
<!--    <property>-->
<!--        <name>mapreduce.jobhistory.done.dir</name>-->
<!--        <value>/user/history/done</value> &lt;!&ndash; 存储完成作业的JobHistory文件的HDFS路径 &ndash;&gt;-->
<!--    </property>-->
    

    <!-- (可选)设置MapReduce作业的中间输出目录 -->
    
<!--    <property>-->
<!--        <name>mapreduce.task.io.sort.mb</name>-->
<!--        <value>100</value> &lt;!&ndash; 设置排序缓冲区大小为100MB &ndash;&gt;-->
<!--    </property>-->
<!--    <property>-->
<!--        <name>mapreduce.task.io.sort.factor</name>-->
<!--        <value>10</value> &lt;!&ndash; 设置排序时合并的文件数 &ndash;&gt;-->
<!--    </property>-->


    <!-- 其他可能的自定义配置 -->
    <!-- 根据你的具体需求添加或修改 -->

</configuration>
[root@hadoop-0001 hadoop]# cd /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/
[root@hadoop-0001 hadoop]# vim mapred-site.xml
[root@hadoop-0001 hadoop]# for i in 192.168.0.222 192.168.0.252; do scp mapred-site.xml root@$i:/data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop; done
写入works文件

指定哪些主机运行DataNode和NodeManager

方便使用 start-dfs.sh脚本管理集群,需配合配置 ssh 免密登录,下方会有设置

在所有节点(hadoop-0001, hadoop-0002, hadoop-0003)上配置:

写入works文件,workers 文件用于列出所有参与集群运行的工作节点

[root@hadoop-0001 hadoop-3.4.0]# cd /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop
cat workers
hadoop-0001
hadoop-0002
hadoop-0003

[root@hadoop-0001 hadoop]# cd /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/
[root@hadoop-0001 hadoop-3.4.0]# vim workers
[root@hadoop-0001 hadoop-3.4.0]# for i in 192.168.0.222 192.168.0.252; do scp workers root@$i:/data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop; done

注意:关于mapreduce.jobhistory.addressmapreduce.jobhistory.webapp.address的注释,实际上在Hadoop 3.x中,你可能不需要单独配置这些属性,因为JobHistory Server的功能通常已经集成到ResourceManager中。这里的注释是为了解释这些属性在旧版本中的作用,并在实际配置中可能不需要。如果你的集群确实需要单独的JobHistory Server,那么你需要确保它正确配置并运行。

启动 hadoop 集群

给 hadoop 用户授权

在所有节点(hadoop-0001, hadoop-0002, hadoop-0003)

[root@hadoop-0001 ~]# chown -R hadoop:hadoop /data/hadoop/
[root@hadoop-0002 ~]# chown -R hadoop:hadoop /data/hadoop/
[root@hadoop-0003 ~]# chown -R hadoop:hadoop /data/hadoop/

故障转移配置sshfence

设置免密登录

在所有节点(hadoop-0001, hadoop-0002, hadoop-0003)

配置所有节点的 hadoop 用户都对所有节点免密登录,sshfence 故障转移期间要求,Hadoop 服务的运行用户它必须能够在不提供密码的情况下通过 SSH 连接到目标节点

[root@hadoop-0001 ~]# su hadoop
[hadoop@hadoop-0001 hadoop]$ ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa -N ""
[hadoop@hadoop-0001 hadoop]$ for i in 192.168.0.141 192.168.0.222 192.168.0.252; do ssh-copy-id $i; done

[root@hadoop-0002 ~]# su hadoop
[hadoop@hadoop-0002 hadoop]$ ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa -N ""
[hadoop@hadoop-0002 hadoop]$ for i in 192.168.0.141 192.168.0.222 192.168.0.252; do ssh-copy-id $i; done

[root@hadoop-0003 ~]# su hadoop
[hadoop@hadoop-0003 hadoop]$ ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa -N ""
[hadoop@hadoop-0003 hadoop]$ for i in 192.168.0.141 192.168.0.222 192.168.0.252; do ssh-copy-id $i; done
# 如果 hdfs-site.xml 文件和 core-site.xml文件配置了故障转移的相关配置,但是没有配置自动开启,即如果 hdfs-site.xml文件的 dfs.ha.automatic-failover.enabled没有设置或者设置为false,没有把dfs.ha.automatic-failover.enabled设置为true。则需要在启动集群 start-dfs.sh 前,在每台NameNode节点手动启动 ZKFC 守护进程,当 ZKFC 启动时,它们将自动选择其中一个 NameNode 变为活动状态。
# 手动开启命令
# [hdfs]$ $HADOOP_HOME/bin/hdfs --daemon start zkfc


# 当前  hdfs-site.xml 配置文件的 dfs.ha.automatic-failover.enabled设置为true,部署完成后可直接使用  start-dfs.sh 启动

使用用户 hadoop

在所有节点(hadoop-0001, hadoop-0002, hadoop-0003)

格式化 ZooKeeper

在其中一个 NameNode 节点(hadoop-0001)

在 ZooKeeper 中初始化 required 状态。您可以通过从其中一个 NameNode 主机运行以下命令来执行此操作

这将在 ZooKeeper 中创建一个 znode,自动故障转移系统将在其中存储其数据。

[hadoop@hadoop-0001 root]$ hdfs zkfc -formatZK
WARNING: /data/hadoop/hadoop_soft/hadoop-3.4.0/logs does not exist. Creating.
2024-11-14 10:13:34,101 INFO tools.DFSZKFailoverController: STARTUP_MSG:
/************************************************************
STARTUP_MSG: Starting DFSZKFailoverController
STARTUP_MSG:   host = hadoop-0001/192.168.0.141
STARTUP_MSG:   args = [-formatZK]
STARTUP_MSG:   version = 3.4.0
....
....
2024-11-14 10:13:34,511 INFO ha.ActiveStandbyElector: Session connected.
2024-11-14 10:13:34,527 INFO ha.ActiveStandbyElector: Successfully created /hadoop-ha/mycluster in ZK.
2024-11-14 10:13:34,631 INFO zookeeper.ZooKeeper: Session: 0x300001eed630000 closed
2024-11-14 10:13:34,632 WARN ha.ActiveStandbyElector: Ignoring stale result from old client with sessionId 0x300001eed630000
2024-11-14 10:13:34,632 INFO zookeeper.ClientCnxn: EventThread shut down for session: 0x300001eed630000
2024-11-14 10:13:34,633 INFO tools.DFSZKFailoverController: SHUTDOWN_MSG:
/************************************************************
SHUTDOWN_MSG: Shutting down DFSZKFailoverController at hadoop-0001/192.168.0.141
************************************************************/

启动 journalnode服务

  • 新集群需要在 NameNode 节点格式化 HDFS(对于新集群或重新格式化)前启动 journalnode服务

  • 不需要格式化 HDFS的,start-dfs.sh 会连带把 journalnode 启动起来

从所有节点运行以下命令来执行此操作 (hadoop-0001, hadoop-0002, hadoop-0003)

[hadoop@hadoop-0001 hadoop]$ hdfs --daemon start journalnode
[hadoop@hadoop-0002 hadoop]$ hdfs --daemon start journalnode
[hadoop@hadoop-0003 hadoop]$ hdfs --daemon start journalnode

# JournalNode 进程均已启动
# 日志无报错
# hadoop-hadoop-journalnode-hadoop-0001.log
# hadoop-hadoop-journalnode-hadoop-0002.log
# hadoop-hadoop-journalnode-hadoop-0003.log
[hadoop@hadoop-0001 root]$ jps | grep -vi jps
3496 JournalNode
[hadoop@hadoop-0001 root]$ ss -utnlp | grep 8485
tcp    LISTEN     0      256       *:8485                  *:*                   users:(("java",pid=3496,fd=346))

[hadoop@hadoop-0002 root]$ jps | grep -vi jps
3059 JournalNode
[hadoop@hadoop-0002 root]$ ss -utnlp | grep 8485
tcp    LISTEN     0      256       *:8485                  *:*                   users:(("java",pid=3059,fd=346))

[hadoop@hadoop-0003 root]$ jps | grep -vi jps
3103 JournalNode
[hadoop@hadoop-0003 root]$ ss -utnlp | grep 8485
tcp    LISTEN     0      256       *:8485                  *:*                   users:(("java",pid=3103,fd=346))

格式化 namenode

NameNode 一个格式化另一个不格式化而是同步格式化的 namenode 的数据

在 NameNode 节点在(hadoop-0001,hadoop-0002)上

首次启动 HDFS 时,必须对其进行格式化。将新的分布式文件系统格式化为 hdfs

格式化 NameNode 节点 hadoop-0001
#[hadoop@hadoop-0001 hadoop-3.4.0]$ source /etc/profile 
[hadoop@hadoop-0001 logs]$ hdfs namenode -format
2024-11-14 10:19:47,841 INFO namenode.NameNode: STARTUP_MSG:
/************************************************************
STARTUP_MSG: Starting NameNode
STARTUP_MSG:   host = hadoop-0001/192.168.0.141
STARTUP_MSG:   args = [-format]
STARTUP_MSG:   version = 3.4.0
....
....
2024-11-14 10:19:49,304 INFO common.Storage: Storage directory /data/hadoop/hadoop_data/hdfs/namenode has been successfully formatted.
2024-11-14 10:19:49,383 INFO namenode.FSImageFormatProtobuf: Saving image file /data/hadoop/hadoop_data/hdfs/namenode/current/fsimage.ckpt_0000000000000000000 using no compression
2024-11-14 10:19:49,448 INFO namenode.FSImageFormatProtobuf: Image file /data/hadoop/hadoop_data/hdfs/namenode/current/fsimage.ckpt_0000000000000000000 of size 401 bytes saved in 0 seconds .
2024-11-14 10:19:49,452 INFO namenode.NNStorageRetentionManager: Going to retain 1 images with txid >= 0
2024-11-14 10:19:49,474 INFO blockmanagement.DatanodeManager: Slow peers collection thread shutdown
2024-11-14 10:19:49,482 INFO namenode.FSNamesystem: Stopping services started for active state
2024-11-14 10:19:49,482 INFO namenode.FSNamesystem: Stopping services started for standby state
2024-11-14 10:19:49,496 INFO namenode.FSImage: FSImageSaver clean checkpoint: txid=0 when meet shutdown.
2024-11-14 10:19:49,496 INFO namenode.NameNode: SHUTDOWN_MSG:
/************************************************************
SHUTDOWN_MSG: Shutting down NameNode at hadoop-0001/192.168.0.141
************************************************************/


------------------------------------------------------------------------------------------------
# 这部分是删除数据重新格式化
## 删除 datanode 数据
#[hadoop@hadoop-0001 hadoop]$ rm -rf /data/hadoop/hadoop_data/hdfs/datanode/current/
#[hadoop@hadoop-0002 hadoop]$ rm -rf /data/hadoop/hadoop_data/hdfs/datanode/current/
#[hadoop@hadoop-0003 hadoop]$ rm -rf /data/hadoop/hadoop_data/hdfs/datanode/current/
## 删除 namenode 数据
#[hadoop@hadoop-0001 hadoop]$ rm -rf /data/hadoop/hadoop_data/hdfs/namenode/current/VERSION
#[hadoop@hadoop-0002 hadoop]$ rm -rf /data/hadoop/hadoop_data/hdfs/namenode/current/VERSION
#[hadoop@hadoop-0003 hadoop]$ rm -rf /data/hadoop/hadoop_data/hdfs/namenode/current/VERSION
#
## 删除 journalnode 数据
#[hadoop@hadoop-0001 hadoop]$ rm -rf /data/hadoop/hadoop_data/hdfs/journalnode/mycluster
#[hadoop@hadoop-0002 hadoop]$ rm -rf /data/hadoop/hadoop_data/hdfs/journalnode/mycluster
#[hadoop@hadoop-0003 hadoop]$ rm -rf /data/hadoop/hadoop_data/hdfs/journalnode/mycluster
---------------------------------------------------------------------------------------------------------
启动 namenode 在 hadoop-0001
# 格式化之后启动 namenode
[hadoop@hadoop-0001 logs]$ hdfs --daemon start namenode
[hadoop@hadoop-0001 logs]$ jps | grep -vi jps
3860 NameNode
3496 JournalNode
[hadoop@hadoop-0001 logs]$ ss -utnlp | grep 50070
tcp    LISTEN     0      500    192.168.0.141:50070                 *:*                   users:(("java",pid=3860,fd=341))
# 日志无报错
同步数据

第二个 namenode 同步第一个 namenode 的数据

hadoop-0002 的 namenode 同步 hadoop-0001 的 namenode 的数据

在第二个namenode节点 同步 第一个namenode节点数据

在备用NameNode上执行hdfs namenode -bootstrapStandby命令,这会将主NameNode的状态同步到备用NameNode。

[hadoop@hadoop-0002 logs]$ hdfs namenode -bootstrapStandby
2024-11-14 10:22:39,769 INFO namenode.NameNode: STARTUP_MSG:
/************************************************************
STARTUP_MSG: Starting NameNode
STARTUP_MSG:   host = hadoop-0002/192.168.0.222
STARTUP_MSG:   args = [-bootstrapStandby]
STARTUP_MSG:   version = 3.4.0
....
....
************************************************************/
2024-11-14 10:22:39,775 INFO namenode.NameNode: registered UNIX signal handlers for [TERM, HUP, INT]
2024-11-14 10:22:39,842 INFO namenode.NameNode: createNameNode [-bootstrapStandby]
2024-11-14 10:22:40,005 INFO ha.BootstrapStandby: Found nn: nn1, ipc: hadoop-0001/192.168.0.141:8020
2024-11-14 10:22:40,270 INFO common.Util: Assuming 'file' scheme for path /data/hadoop/hadoop_data/hdfs/namenode in configuration.
2024-11-14 10:22:40,271 INFO common.Util: Assuming 'file' scheme for path /data/hadoop/hadoop_data/hdfs/namenode in configuration.
=====================================================
About to bootstrap Standby ID nn2 from:
           Nameservice ID: mycluster
        Other Namenode ID: nn1
  Other NN's HTTP address: http://hadoop-0001:50070
  Other NN's IPC  address: hadoop-0001/192.168.0.141:8020
             Namespace ID: 1218448573
            Block pool ID: BP-822883281-192.168.0.141-1731550789288
               Cluster ID: CID-fe96f3bb-9828-4028-8aa1-b987907213ad
           Layout version: -67
   Service Layout version: -67
       isUpgradeFinalized: true
         isRollingUpgrade: false
=====================================================
2024-11-14 10:22:40,582 INFO common.Storage: Storage directory /data/hadoop/hadoop_data/hdfs/namenode has been successfully formatted.
2024-11-14 10:22:40,594 INFO common.Util: Assuming 'file' scheme for path /data/hadoop/hadoop_data/hdfs/namenode in configuration.
2024-11-14 10:22:40,595 INFO common.Util: Assuming 'file' scheme for path /data/hadoop/hadoop_data/hdfs/namenode in configuration.
2024-11-14 10:22:40,613 INFO namenode.FSEditLog: Edit logging is async:true
2024-11-14 10:22:40,672 INFO namenode.TransferFsImage: Opening connection to http://hadoop-0001:50070/imagetransfer?getimage=1&txid=0&storageInfo=-67:1218448573:1731550789288:CID-fe96f3bb-9828-4028-8aa1-b987907213ad&bootstrapstandby=true
2024-11-14 10:22:40,774 INFO common.Util: Combined time for file download and fsync to all disks took 0.00s. The file download took 0.00s at 0.00 KB/s. Synchronous (fsync) write to disk of /data/hadoop/hadoop_data/hdfs/namenode/current/fsimage.ckpt_0000000000000000000 took 0.00s.
2024-11-14 10:22:40,774 INFO namenode.TransferFsImage: Downloaded file fsimage.ckpt_0000000000000000000 size 401 bytes.
2024-11-14 10:22:40,779 INFO ha.BootstrapStandby: Skipping InMemoryAliasMap bootstrap as it was not configured
2024-11-14 10:22:40,783 INFO namenode.NameNode: SHUTDOWN_MSG:
/************************************************************
SHUTDOWN_MSG: Shutting down NameNode at hadoop-0002/192.168.0.222
************************************************************/
启动第二个 namenode 在 hadoop-0002
# 启动第二个 namenode
[hadoop@hadoop-0002 root]$ hdfs --daemon start namenode
[hadoop@hadoop-0002 logs]$ jps | grep -vi jps
3059 JournalNode
3557 NameNode
[hadoop@hadoop-0002 logs]$ ss -utnlp | grep 50070
tcp    LISTEN     0      500    192.168.0.222:50070                 *:*                   users:(("java",pid=3557,fd=341))



# 查看namenode状态,此时未开启 ZKFC 守护进程均为 standby
[hadoop@hadoop-0001 logs]$ hdfs haadmin -getServiceState nn1
standby
[hadoop@hadoop-0001 logs]$ hdfs haadmin -getServiceState nn2
standby

开启 ZKFC 守护进程

ZKFC 守护进程运行在 NameNode 节点 (hadoop-0001, hadoop-0002)

# 运行 hadoop-0001 的 datanode 和 ZKFC
# 开启 ZKFC 守护程序,这是启动zookeeper选举制度
[hadoop@hadoop-0001 logs]$ hdfs --daemon start zkfc
[hadoop@hadoop-0002 logs]$ hdfs --daemon start zkfc
# 查看namenode状态,一个active 一个standby
[hadoop@hadoop-0001 logs]$ hdfs haadmin -getServiceState nn1
active
[hadoop@hadoop-0001 logs]$ hdfs haadmin -getServiceState nn2
standby

启动 HDFS 守护进程 和

逐个启动 datanode 守护进程 和 ZKFC 守护进程

datanode 守护进程运行在所有节点 (hadoop-0001, hadoop-0002, hadoop-0003)

# 开启 datanode 守护进程 hadoop-0001
[hadoop@hadoop-0001 logs]$ hdfs --daemon start datanode
[hadoop@hadoop-0001 logs]$ jps | grep -vi jps
3496 JournalNode
26296 DataNode
25787 DFSZKFailoverController
24812 NameNode
# 开启 datanode 守护进程 hadoop-0002
[hadoop@hadoop-0002 logs]$ hdfs --daemon start datanode
[hadoop@hadoop-0002 logs]$ jps | grep -vi jps
3059 JournalNode
25668 DataNode
24184 NameNode
25341 DFSZKFailoverController
# 开启 datanode 守护进程 hadoop-0003
[hadoop@hadoop-0003 root]$ hdfs --daemon start datanode
[hadoop@hadoop-0003 root]$ jps | grep -vi jps
22086 DataNode
3103 JournalNode
# 查看日志无报错

启动 YARN 守护进程

# 在 namenode 进程所在其中一个节点 hadoop-0001 执行
[hadoop@hadoop-0001 logs]$ start-yarn.sh
Starting resourcemanagers on [ hadoop-0001 hadoop-0002]
hadoop-0001: Warning: Permanently added 'hadoop-0001' (ECDSA) to the list of known hosts.
hadoop-0002: Warning: Permanently added 'hadoop-0002' (ECDSA) to the list of known hosts.
Starting nodemanagers
hadoop-0003: Warning: Permanently added 'hadoop-0003' (ECDSA) to the list of known hosts.


# 查看 hadoop-0001
[hadoop@hadoop-0001 logs]$ jps | grep -vi jps
26951 NodeManager
3496 JournalNode
26296 DataNode
26824 ResourceManager
25787 DFSZKFailoverController
24812 NameNode
# 查看 hadoop-0002
[hadoop@hadoop-0002 logs]$ jps | grep -vi jps
26098 NodeManager
3059 JournalNode
25668 DataNode
24184 NameNode
25341 DFSZKFailoverController
25999 ResourceManager
# 查看 hadoop-0003
[hadoop@hadoop-0003 logs]$ jps | grep -vi jps
22086 DataNode
22376 NodeManager
3103 JournalNode
# 查看日志无报错

启动 MapReduce JobHistory Server,在指定的 mapred 服务器上(可选)

提供作业历史的查询接口

# 开启
[hadoop@hadoop-0001 hadoop]$ mapred --daemon start historyserver

# 关闭
[hadoop@hadoop-0001 hadoop]$ mapred --daemon stop historyserver

查看集群状态

# 最重要看日志有没有报错
#日志 namenode 
#日志 datanode 
#日志 resourcemanager 
#日志 nodemanager  
#日志 journalnode
#日志 zkfc

# 网页查看
http://121.36.222.173:8088/cluster

# 查看接口
[hadoop@hadoop-0001 logs]$ curl -s "http://hadoop-0001:8088/ws/v1/cluster/info"
{"clusterInfo":{"id":1731567290015,"startedOn":1731567290015,"state":"STARTED","haState":"STANDBY","rmStateStoreName":"org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore","resourceManagerVersion":"3.4.0","resourceManagerBuildVersion":"3.4.0 from bd8b77f398f626bb7791783192ee7a5dfaeec760 by root source checksum 934da0c5743762b7851cfcff9f8ca2","resourceManagerVersionBuiltOn":"2024-03-04T06:54Z","hadoopVersion":"3.4.0","hadoopBuildVersion":"3.4.0 from bd8b77f398f626bb7791783192ee7a5dfaeec760 by root source checksum f7fe694a3613358b38812ae9c31114e","hadoopVersionBuiltOn":"2024-03-04T06:35Z","haZooKeeperConnectionState":"CONNECTED"}}[hadoop@hadoop-0001 logs]$



# 命令行查看
# 查看 HDFS 的状态,包括数据节点、存储使用情况等信息。
[hadoop@hadoop-0001 logs]$ hdfs dfsadmin -report
Configured Capacity: 126421143552 (117.74 GB)
Present Capacity: 95679483904 (89.11 GB)
DFS Remaining: 95679397888 (89.11 GB)
DFS Used: 86016 (84 KB)
DFS Used%: 0.00%
Replicated Blocks:
        Under replicated blocks: 0
        Blocks with corrupt replicas: 0
        Missing blocks: 0
        Missing blocks (with replication factor 1): 0
        Low redundancy blocks with highest priority to recover: 0
        Pending deletion blocks: 0
Erasure Coded Block Groups:
        Low redundancy block groups: 0
        Block groups with corrupt internal blocks: 0
        Missing block groups: 0
        Low redundancy blocks with highest priority to recover: 0
        Pending deletion blocks: 0

-------------------------------------------------
Live datanodes (3):

Name: 192.168.0.141:9866 (hadoop-0001)
Hostname: hadoop-0001
Decommission Status : Normal
Configured Capacity: 42140381184 (39.25 GB)
DFS Used: 28672 (28 KB)
Non DFS Used: 8407486464 (7.83 GB)
DFS Remaining: 31890853888 (29.70 GB)
DFS Used%: 0.00%
DFS Remaining%: 75.68%
Configured Cache Capacity: 0 (0 B)
Cache Used: 0 (0 B)
Cache Remaining: 0 (0 B)
Cache Used%: 100.00%
Cache Remaining%: 0.00%
Xceivers: 0
Last contact: Thu Nov 14 15:04:16 CST 2024
Last Block Report: Thu Nov 14 14:50:01 CST 2024
Num of Blocks: 0


Name: 192.168.0.222:9866 (hadoop-0002)
Hostname: hadoop-0002
Decommission Status : Normal
Configured Capacity: 42140381184 (39.25 GB)
DFS Used: 28672 (28 KB)
Non DFS Used: 8405856256 (7.83 GB)
DFS Remaining: 31892484096 (29.70 GB)
DFS Used%: 0.00%
DFS Remaining%: 75.68%
Configured Cache Capacity: 0 (0 B)
Cache Used: 0 (0 B)
Cache Remaining: 0 (0 B)
Cache Used%: 100.00%
Cache Remaining%: 0.00%
Xceivers: 0
Last contact: Thu Nov 14 15:04:16 CST 2024
Last Block Report: Thu Nov 14 14:50:04 CST 2024
Num of Blocks: 0


Name: 192.168.0.252:9866 (hadoop-0003)
Hostname: hadoop-0003
Decommission Status : Normal
Configured Capacity: 42140381184 (39.25 GB)
DFS Used: 28672 (28 KB)
Non DFS Used: 8402280448 (7.83 GB)
DFS Remaining: 31896059904 (29.71 GB)
DFS Used%: 0.00%
DFS Remaining%: 75.69%
Configured Cache Capacity: 0 (0 B)
Cache Used: 0 (0 B)
Cache Remaining: 0 (0 B)
Cache Used%: 100.00%
Cache Remaining%: 0.00%
Xceivers: 0
Last contact: Thu Nov 14 15:04:16 CST 2024
Last Block Report: Thu Nov 14 14:50:07 CST 2024
Num of Blocks: 0

# 查看 YARN 节点的状态。
[hadoop@hadoop-0001 logs]$ yarn node -list
2024-11-14 15:04:51,798 INFO client.ConfiguredRMFailoverProxyProvider: Failing over to rm2
Total Nodes:3
         Node-Id             Node-State Node-Http-Address       Number-of-Running-Containers
hadoop-0001:42957               RUNNING  hadoop-0001:8042                                  0
hadoop-0002:39030               RUNNING  hadoop-0002:8042                                  0
hadoop-0003:43300               RUNNING  hadoop-0003:8042                                  0

# 关于默认队列的一些关键信息,如队列容量、最大容量等
[hadoop@hadoop-0001 logs]$ yarn queue -status default
2024-11-14 15:05:16,927 INFO client.ConfiguredRMFailoverProxyProvider: Failing over to rm2
Queue Information :
Scheduler Name : CapacityScheduler
Queue Name : default
Queue Path : root.default
        State : RUNNING
        Capacity : 100.00%
        Current Capacity : .00%
        Maximum Capacity : 100.00%
        Weight : -1.00
        Maximum Parallel Apps : 2147483647
        Default Node Label expression : <DEFAULT_PARTITION>
        Accessible Node Labels : *
        Preemption : disabled
        Intra-queue Preemption : disabled

# 查看 YARN 应用程序的状态,包括应用程序的状态、用户、队列、启动时间等
# 这个输出表明您的 YARN 集群目前没有任何正在运行、已提交或已接受的应用。这是一个正常的状态,特别是如果您刚刚启动集群或者还没有提交任何作业。
[hadoop@hadoop-0001 logs]$ yarn application -list
2024-11-14 15:06:15,823 INFO client.ConfiguredRMFailoverProxyProvider: Failing over to rm2
Total number of applications (application-types: [], states: [SUBMITTED, ACCEPTED, RUNNING] and tags: []):0
                Application-Id      Application-Name        Application-Type          User           Queue                   State             Final-State             Progress                          Tracking-URL

测试故障转移

测试 namenode 故障转移
# 查看活跃节点 活跃节点为 nn2
[hadoop@hadoop-0001 logs]$ hdfs haadmin -getServiceState nn1
standby
[hadoop@hadoop-0001 logs]$ hdfs haadmin -getServiceState nn2
active

# 测试故障转移
# hdfs haadmin -failover <sourceNN> <destNN>,其中 <sourceNN> 是当前的活跃NameNode,而 <destNN> 是您希望成为新的活跃NameNode。
# 在不活跃的 namenode 节点运行 hadoop-0001执行
# 将活跃的 nn2 置为不活跃,把不活跃的 nn1 置为活跃
[hadoop@hadoop-0001 logs]$ hdfs --config /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/ haadmin -failover nn2 nn1
Failover to NameNode at hadoop-0001/192.168.0.141:8020 successful
[hadoop@hadoop-0001 logs]$ hdfs haadmin -getServiceState nn1
active
[hadoop@hadoop-0001 logs]$ hdfs haadmin -getServiceState nn2
standby

# Hadoop HA管理工具拒绝了这个操作,因为它检测到自动故障转移已经启用。Hadoop为了防止可能的脑裂(split-brain)场景或其他不正确的状态,不允许手动管理HA状态,除非使用 --forcemanual 标志。
hdfs --config /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/ haadmin -transitionToStandby nn2
[hadoop@hadoop-0002 logs]$ hdfs --config /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/ haadmin -transitionToStandby nn2
Automatic failover is enabled for NameNode at hadoop-0002/192.168.0.222:8020
Refusing to manually manage HA state, since it may cause
a split-brain scenario or other incorrect state.
If you are very sure you know what you are doing, please
specify the --forcemanual flag.
测试 ResourceManager 故障转移
[hadoop@hadoop-0001 logs]$ yarn rmadmin -getServiceState rm1
standby
[hadoop@hadoop-0001 logs]$ yarn rmadmin -getServiceState rm2
active

# 测试故障转移 关闭活跃的 resourcemanager rm2 在hadoop-0002
[hadoop@hadoop-0002 logs]$ yarn --daemon stop resourcemanager

# 查看 active 切换到 rm1 hadoop-0001 
[hadoop@hadoop-0002 logs]$ yarn rmadmin -getServiceState rm1
active
[hadoop@hadoop-0002 logs]$
[hadoop@hadoop-0002 logs]$ yarn rmadmin -getServiceState rm2
2024-11-14 17:06:10,370 INFO ipc.Client: Retrying connect to server: hadoop-0002/192.168.0.222:8033. Already tried 0 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=1, sleepTime=1000 MILLISECONDS)
Operation failed: Call From hadoop-0002/192.168.0.222 to hadoop-0002:8033 failed on connection exception: java.net.ConnectException: Connection refused; For more details see:  http://wiki.apache.org/hadoop/ConnectionRefused

# 开启关闭的 rm2
[hadoop@hadoop-0002 logs]$  yarn --daemon start resourcemanager
# 活跃节点正常
[hadoop@hadoop-0002 logs]$ yarn rmadmin -getServiceState rm1
active
[hadoop@hadoop-0002 logs]$ yarn rmadmin -getServiceState rm2
standby
部署hadoop HA 集群顺序:
安装配置 `java` 环境
安装和配置 `ZooKeeper`
启动 `ZooKeeper` 服务
安装配置 `hadoop`
格式化 `ZooKeeper` 
启动 `journalnode`服务
格式化第一个 `namenode`
启动第一个 `namenode`
第二个 `namenode` 同步第一个`namenode` 数据
启动第二个 `namenode`
启动 `ZKFC` 守护进程
启动 `HDFS` 守护进程 
启动 `YARN` 守护进程
后续可以用 `start-dfs.sh` 脚本管理集群

关闭 hadoop 集群

关闭后再打开,再打开时不是新的集群了,不需要执行格式化操作

先停止 YARN 守护进程

[hadoop@hadoop-0001 hadoop]$ stop-yarn.sh

再停止 HDFS 守护进程

[hadoop@hadoop-0001 hadoop]$ stop-dfs.sh

再次启动可用 start-dfs.sh

[hadoop@hadoop-0001 logs]$ start-dfs.sh
Starting namenodes on [hadoop-0001 hadoop-0002]
Starting datanodes
Starting journal nodes [hadoop-0001 hadoop-0003 hadoop-0002]
Starting ZK Failover Controllers on NN hosts [hadoop-0001 hadoop-0002]

[hadoop@hadoop-0001 logs]$ jps | grep -vi jps
24240 DFSZKFailoverController
24017 JournalNode
23655 NameNode
23786 DataNode

[hadoop@hadoop-0001 logs]$ start-yarn.sh
Starting resourcemanagers on [ hadoop-0001 hadoop-0002]
Starting nodemanagers

[hadoop@hadoop-0001 logs]$ jps | grep -vi jps
24240 DFSZKFailoverController
24736 ResourceManager
24017 JournalNode
23655 NameNode
23786 DataNode
24875 NodeManager

补充不使用 works 文件的单独启动

对于hdfs节点

使用以下命令在指定为 hdfs 的节点上启动 HDFS NameNode:

[hdfs]$ $HADOOP_HOME/bin/hdfs --daemon start namenode

使用以下命令在每个指定为 hdfs 的节点上启动 HDFS DataNode:

[hdfs]$ $HADOOP_HOME/bin/hdfs --daemon start datanode

对应yarn节点

使用以下命令启动 YARN,在指定的 ResourceManager 上作为 yarn 运行:

[yarn]$ $HADOOP_HOME/bin/yarn --daemon start resourcemanager

运行脚本以 yarn 形式在每个指定的主机上启动 NodeManager:

[yarn]$ $HADOOP_HOME/bin/yarn --daemon start nodemanager

WebAppProxy 服务器

启动独立的 WebAppProxy 服务器。在 WebAppProxy 服务器上以 yarn 形式运行。如果多个服务器与负载均衡一起使用,则应在每个服务器上运行:

[yarn]$ $HADOOP_HOME/bin/yarn --daemon start proxyserver

MapReduce JobHistory Server

使用以下命令启动 MapReduce JobHistory Server,在指定的 mapred 服务器上运行:

[mapred]$ $HADOOP_HOME/bin/mapred --daemon start historyserver

补充不使用 works 文件的单独关闭

对于hdfs节点

使用以下命令停止 NameNode,在指定的 NameNode 上运行 hdfs

[hdfs]$ $HADOOP_HOME/bin/hdfs --daemon stop namenode

运行脚本以停止 hdfs 形式的 DataNode:

[hdfs]$ $HADOOP_HOME/bin/hdfs --daemon stop datanode

对应yarn节点

使用以下命令停止 ResourceManager,在指定的 ResourceManager 上运行 yarn

[yarn]$ $HADOOP_HOME/bin/yarn --daemon stop resourcemanager

运行脚本以 yarn 形式停止 worker 上的 NodeManager:

[yarn]$ $HADOOP_HOME/bin/yarn --daemon stop nodemanager

停止 WebAppProxy 服务器

停止 WebAppProxy 服务器。在 WebAppProxy 服务器上以 yarn 形式运行。如果多个服务器与负载均衡一起使用,则应在每个服务器上运行:

[yarn]$ $HADOOP_HOME/bin/yarn stop proxyserver

MapReduce JobHistory Server

使用以下命令停止 MapReduce JobHistory Server,并在指定的服务器上运行,如 mapred

[mapred]$ $HADOOP_HOME/bin/mapred --daemon stop historyserver

集群扩容

新增一台 datanode 节点

服务器IP地址配置系统jdkhadoop角色
hadoop-0004192.168.0.1702C4GCentOS 7.9 64bitjdk-8u421-linux-x64.tar.gzhadoop-3.4.0.tar.gz都作为 DataNode 和 NodeManager

服务器配置

配置对新节点 hadoop-0004 免密登录

[root@hadoop-0001 ~]# ssh-copy-id 192.168.0.100

上传文件到新节点 hadoop-0004

[root@hadoop-0001 ~]# scp hadoop-3.4.0.tar.gz jdk-8u421-linux-x64.tar.gz install_jdk.sh init_server.sh env_hadoop_intall.sh 192.168.0.100:/root

服务器配置初始化

[root@hadoop-0004 ~]# bash init_server.sh

所有节点配置 hosts文件

(hadoop-0001, hadoop-0002, hadoop-0003, hadoop-0004)

[root@hadoop-0001 ~]# vim /etc/hosts
# 把127.0.0.1对应的 主机名这行删掉
192.168.0.141   hadoop-0001
192.168.0.222   hadoop-0002
192.168.0.252   hadoop-0003
192.168.0.100	hadoop-0004
[root@hadoop-0001 ~]# for i in 192.168.0.141 192.168.0.222 192.168.0.252 192.168.0.100; do scp /etc/hosts $i:/etc/hosts; done

安装jdk

[root@hadoop-0004 ~]# bash install_jdk.sh jdk-8u421-linux-x64.tar.gz
# 退出再登陆,加载环境变量,也可以执行source /etc/profile使变量在当前会话生效

安装 hadoop

[root@hadoop-0004 ~]# bash env_hadoop_intall.sh hadoop-3.4.0.tar.gz
# 退出再登陆,加载环境变量,也可以执行source /etc/profile使变量在当前会话生效

配置hadoop

core-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入用于格式化输出的XSL样式表(可选) -->
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>

    <!-- 
    指定Hadoop文件系统的默认URI。
    这是HDFS(Hadoop分布式文件系统)的逻辑名称,通常指向NameNode。
    在HDFS高可用(HA)配置中,这个URI应该指向NameNode的集群。组成集群的配置写在 hdfs-site.xml
    -->
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://mycluster</value> <!-- 指定NameNode所在的集群名和端口号 即HDFS 集群的名称-->
    </property>

    <!-- 
    设置Hadoop临时文件的存储目录。
    这个目录用于存储Hadoop守护进程(如NameNode、DataNode等)的临时文件。
    请确保这个目录在您的文件系统中存在,并且Hadoop进程有权限写入。
    -->
    <property>
        <name>hadoop.tmp.dir</name>
        <value>/data/hadoop/hadoop_data/tmp</value> <!-- 临时文件存储的本地目录  -->
    </property>

    <!-- 
    配置ZooKeeper集群的地址。
    在Hadoop的高可用配置中,ZooKeeper用于存储配置信息、集群状态和协调NameNode的故障转移。
    请列出所有ZooKeeper节点的地址,每个节点用逗号分隔。
    -->
    <property>
        <name>ha.zookeeper.quorum</name>
        <value>hadoop-0001:2181,hadoop-0002:2181,hadoop-0003:2181</value> <!-- ZooKeeper节点地址 -->
    </property>

    <!-- 
    设置文件I/O操作的缓冲区大小。
    这个值决定了Hadoop在进行文件读写操作时使用的内存缓冲区大小。
    较大的缓冲区可以提高性能,但也会增加内存使用。
    默认值可能因Hadoop版本而异,这里设置为4096字节(4KB)。
    -->
    <property>
        <name>io.file.buffer.size</name>
        <value>4096</value> <!-- 以字节为单位,根据需要调整 -->
    </property>

    <!-- 
    (可选)其他Hadoop核心配置属性
    根据您的需求和环境,您可能还需要添加其他配置属性。
    例如,您可以配置网络拓扑脚本、垃圾回收选项、Java堆大小等。
    -->

</configuration>
[root@hadoop-0004 ~]# cd /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/
[root@hadoop-0004 ~]# vim core-site.xml
hdfs-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>

    <!-- HDFS 基本配置 -->
    <property>
        <name>dfs.nameservices</name>
        <value>mycluster</value> <!-- HDFS 集群的名称 -->
    </property>
    <property>
        <name>dfs.replication</name>
        <value>2</value> <!-- 每个文件块在HDFS中的副本数 -->
    </property>
    <property>
        <name>dfs.ha.namenodes.mycluster</name>
        <value>nn1,nn2</value> <!-- 列出集群中所有 NameNode 的名称或 ID -->
    </property>
    <property>
        <name>dfs.namenode.rpc-address.mycluster.nn1</name>
        <value>hadoop-0001:8020</value> <!-- nn1 的 RPC 地址 -->
    </property>
    <property>
        <name>dfs.namenode.rpc-address.mycluster.nn2</name>
        <value>hadoop-0002:8020</value> <!-- nn2 的 RPC 地址 -->
    </property>
    <property>
        <name>dfs.namenode.http-address.mycluster.nn1</name>
        <value>hadoop-0001:50070</value> <!-- nn1 的 HTTP 地址 -->
    </property>
    <property>
        <name>dfs.namenode.http-address.mycluster.nn2</name>
        <value>hadoop-0002:50070</value> <!-- nn2 的 HTTP 地址 -->
    </property>

    <!-- DataNode 配置 -->
    <property>
        <name>dfs.datanode.data.dir</name>
        <value>/data/hadoop/hadoop_data/hdfs/datanode</value> <!-- DataNode 存储数据块的本地目录 -->
    </property>

    <!-- JournalNode 配置 -->
    <property>
        <name>dfs.journalnode.edits.dir</name>
        <value>/data/hadoop/hadoop_data/hdfs/journalnode</value> <!-- JournalNode 存储编辑日志的本地目录 -->
    </property>
    <property>
        <name>dfs.namenode.shared.edits.dir</name>
        <value>qjournal://hadoop-0001:8485;hadoop-0002:8485;hadoop-0003:8485/mycluster</value>
        <!-- 指定 JournalNode 集群的地址 -->
    </property>

    <!-- HDFS 高可用性配置 -->
    <property>
        <name>dfs.ha.automatic-failover.enabled</name>
        <value>true</value> <!-- 开启 NameNode 失败自动切换 -->
    </property>
    <property>
        <name>dfs.client.failover.proxy.provider.mycluster</name>
        <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
        <!-- 配置 NameNode 失败后自动切换实现方式 -->
    </property>

    <!-- 故障转移配置 -->
    <property>
        <name>dfs.ha.fencing.methods</name>
        <value>sshfence</value> <!-- 故障转移期间使用的屏蔽方法 -->
    </property>
    <property>
        <name>dfs.ha.fencing.ssh.private-key-files</name>
        <value>/home/hadoop/.ssh/id_rsa</value> <!-- hadoop 用户的私钥文件 -->
    </property>
    <property>
        <name>dfs.ha.fencing.ssh.connect-timeout</name>
        <value>30000</value> <!-- SSH 连接超时时间,单位为毫秒 -->
    </property>

    <!-- 可选配置 -->
    <property>
        <name>fs.trash.interval</name>
        <value>1440</value> <!-- HDFS 垃圾回收站保留时间,单位为分钟 -->
    </property>

    <!-- 注意:客户端故障转移的配置不在服务器 hdfs-site.xml 中设置,
         而是在客户端的 Hadoop 配置 core-site.xml 文件中设置 fs.defaultFS 为当前集群 hdfs://mycluster。
         确保您的客户端配置也已正确设置以支持 HDFS 高可用性。 -->

</configuration>
[root@hadoop-0004 ~]# cd /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/
[root@hadoop-0004 ~]# vim hdfs-site.xml
yarn-site.xml
<?xml version="1.0"?>
<configuration>
    <!-- YARN ResourceManager 高可用配置 -->
    <!-- 启用 ResourceManager 的高可用模式 -->
    <property>
        <name>yarn.resourcemanager.ha.enabled</name>
        <value>true</value>
    </property>
    <property>
        <!-- 开启ResourceManager失败自动切换 -->
        <name>yarn.resourcemanager.ha.automatic-failover.enabled</name>
        <value>true</value>
    </property>   
    <!-- 设置 YARN 集群的唯一标识符 -->
    <property>
        <name>yarn.resourcemanager.cluster-id</name>
        <value>yarn-cluster</value>
    </property>
    <!-- 指定 ResourceManager 的 ID 列表 -->
    <property>
        <name>yarn.resourcemanager.ha.rm-ids</name>
        <value>rm1,rm2</value>
    </property>
    <!-- 配置 rm1 的主机名 -->
    <property>
        <name>yarn.resourcemanager.hostname.rm1</name>
        <value>hadoop-0001</value>
    </property>
    <!-- 配置 rm2 的主机名 -->
    <property>
        <name>yarn.resourcemanager.hostname.rm2</name>
        <value>hadoop-0002</value>
    </property>

    <!-- YARN ResourceManager 服务地址配置 -->
    <!-- rm1 的 Web 应用地址 -->
    <property>
        <name>yarn.resourcemanager.webapp.address.rm1</name>
        <value>hadoop-0001:8088</value>
    </property>
    <!-- rm1 的 HTTPS Web 应用地址 -->
    <property>
        <name>yarn.resourcemanager.webapp.https.address.rm1</name>
        <value>hadoop-0001:8090</value>
    </property>
    <!-- rm2 的 Web 应用地址 -->
    <property>
        <name>yarn.resourcemanager.webapp.address.rm2</name>
        <value>hadoop-0002:8088</value>
    </property>
    <!-- rm2 的 HTTPS Web 应用地址 -->
    <property>
        <name>yarn.resourcemanager.webapp.https.address.rm2</name>
        <value>hadoop-0002:8090</value>
    </property>

    <!-- 使用 ZooKeeper 集群进行故障转移 -->
    <!-- 配置 ZooKeeper 的地址 -->
    <property>
        <name>yarn.resourcemanager.zk-address</name>
        <value>hadoop-0001:2181,hadoop-0002:2181,hadoop-0003:2181</value>
    </property>
    <property>
        <!-- 启用RM重启的功能,默认为false -->
        <name>yarn.resourcemanager.recovery.enabled</name>
        <value>true</value>
    </property>

    <!-- YARN NodeManager 配置 -->
    <!-- 配置 NodeManager 的辅助服务 -->
    <property>
        <name>yarn.nodemanager.aux-services</name>
        <value>mapreduce_shuffle</value>
    </property>

    <property>
        <!-- 用于状态存储的类 -->
        <name>yarn.resourcemanager.store.class</name>
        <value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
    </property>
    <property>
        <!-- NodeManager启用server使用算法的类 -->
        <name>yarn-nodemanager.aux-services.mapreduce.shuffle.class</name>
        <value>org.apache.hadoop.mapred.ShuffleHandler</value>
    </property>
    <property>
        <!-- 启用日志聚合功能 -->
        <name>yarn.log-aggregation-enable</name>
        <value>true</value>
    </property>
    <property>
        <!-- 聚集的日志在HDFS上保存最长的时间 -->
        <name>yarn.log-aggregation.retain-seconds</name>
        <value>106800</value>
    </property>
    <property>
        <!-- 聚集的日志在HDFS上保存最长的时间 -->
        <name>yarn.nodemanager.remote-app-log-dir</name>
        <value>/opt/hadoopHA/logs</value>
    </property>
    <!-- YARN 调度器配置 -->
    <!-- 配置 ResourceManager 使用的调度器 -->
    <property>
        <name>yarn.resourcemanager.scheduler.class</name>
        <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler</value>
    </property>
    <!-- yarn.nodemanager.hostname 和 yarn.nodemanager.address 这样的配置项可以来直接设置 NodeManager 的主机名和地址。但不是必须的。NodeManager 的主机名和地址通常是通过启动 NodeManager 服务的机器的主机名和配置的网络接口来自动确定的。NodeManager 会自动注册到 ResourceManager 上,并报告其可用的资源(如 CPU、内存和磁盘空间)。这个注册过程是基于 NodeManager 所在机器的主机名和配置的端口进行的。 -->	
    <!-- 其他 YARN 相关配置 -->
    <!-- 可以根据需要添加其他属性,例如资源限制、队列配置等 -->
</configuration>
[root@hadoop-0004 ~]# cd /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/
[root@hadoop-0004 ~]# vim yarn-site.xml
mapred-site.xml
<configuration>
    <!-- 设置MapReduce框架的名称,这里指定为YARN -->
    <property>
        <name>mapreduce.framework.name</name>
        <value>yarn</value> <!-- 指定MapReduce运行在YARN上 -->
    </property>

    <!-- (可选)设置MapReduce JobHistory Server的地址,通常与ResourceManager集成,因此这些配置可能不是必需的 -->
    <!-- 如果你的集群需要单独配置JobHistory Server,可以取消以下注释并根据需要修改 -->
    
<!--    <property>-->
<!--        <name>mapreduce.jobhistory.address</name>-->
<!--        <value>historyserver-hostname:10020</value> &lt;!&ndash; JobHistory Server的主机名和端口号 &ndash;&gt;-->
<!--    </property>-->

<!--    <property>-->
<!--        <name>mapreduce.jobhistory.webapp.address</name>-->
<!--        <value>historyserver-hostname:19888</value> &lt;!&ndash; JobHistory Server Web应用的主机名和端口号 &ndash;&gt;-->
<!--    </property>-->
    

    <!-- (可选)设置MapReduce作业完成后JobHistory文件的存储位置 -->
    
<!--    <property>-->
<!--        <name>mapreduce.jobhistory.done.dir</name>-->
<!--        <value>/user/history/done</value> &lt;!&ndash; 存储完成作业的JobHistory文件的HDFS路径 &ndash;&gt;-->
<!--    </property>-->
    

    <!-- (可选)设置MapReduce作业的中间输出目录 -->
    
<!--    <property>-->
<!--        <name>mapreduce.task.io.sort.mb</name>-->
<!--        <value>100</value> &lt;!&ndash; 设置排序缓冲区大小为100MB &ndash;&gt;-->
<!--    </property>-->
<!--    <property>-->
<!--        <name>mapreduce.task.io.sort.factor</name>-->
<!--        <value>10</value> &lt;!&ndash; 设置排序时合并的文件数 &ndash;&gt;-->
<!--    </property>-->


    <!-- 其他可能的自定义配置 -->
    <!-- 根据你的具体需求添加或修改 -->

</configuration>
[root@hadoop-0004 ~]# cd /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/
[root@hadoop-0004 ~]# vim mapred-site.xml

配置 works文件

[root@hadoop-0001 hadoop]# cd /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/
[root@hadoop-0001 hadoop]# vim workers
hadoop-0001
hadoop-0002
hadoop-0003
hadoop-0004

[root@hadoop-0001 hadoop]# for i in 192.168.0.141 192.168.0.222 192.168.0.252 192.168.0.100; do scp workers  $i:/data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/; done

启动 hadoop

配置用户 hadoop 免密登录所有节点
# 设置hadoop免密登录所有节点
[root@hadoop-0001 ~]# su hadoop
[hadoop@hadoop-0001 hadoop]$ for i in 192.168.0.141 192.168.0.222 192.168.0.252 192.168.0.100; do ssh-copy-id $i; done

[root@hadoop-0002 ~]# su hadoop
[hadoop@hadoop-0002 root]$ for i in 192.168.0.141 192.168.0.222 192.168.0.252 192.168.0.100; do ssh-copy-id $i; done

[root@hadoop-0003 ~]# su hadoop
[hadoop@hadoop-0003 root]$ for i in 192.168.0.141 192.168.0.222 192.168.0.252 192.168.0.100; do ssh-copy-id $i; done

[root@hadoop-0004 ~]# su hadoop
[hadoop@hadoop-0004 root]$ ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa -N ""
[hadoop@hadoop-0004 root]$ for i in 192.168.0.141 192.168.0.222 192.168.0.252 192.168.0.100; do ssh-copy-id $i; done
新节点设置 hadoop 权限
# 新节点设置 hadoop 权限
[root@hadoop-0004 ~]# chown -R hadoop:hadoop /data/hadoop/

使用用户 hadoop

启动 hdfs 守护进程(datanode)
[hadoop@hadoop-0004 sbin]$ hdfs --daemon start datanode
[hadoop@hadoop-0004 logs]$ jps | grep -vi jps
2229 DataNode
# 日志无报错
启动 yarn 守护进程(启动 NodeManager)
[hadoop@hadoop-0004 sbin]$ yarn --daemon start nodemanager
[hadoop@hadoop-0004 logs]$ jps | grep -vi jps
2418 NodeManager
2229 DataNode
# 日志无报错
查看集群状态
# 看到 4 个节点
[hadoop@hadoop-0001 hadoop]$ yarn node -list
2024-11-15 09:42:15,121 INFO client.ConfiguredRMFailoverProxyProvider: Failing over to rm2
Total Nodes:4
         Node-Id             Node-State Node-Http-Address       Number-of-Running-Containers
hadoop-0001:39482               RUNNING  hadoop-0001:8042                                  0
hadoop-0004:34567               RUNNING  hadoop-0004:8042                                  0
hadoop-0003:42690               RUNNING  hadoop-0003:8042                                  0
hadoop-0002:43629               RUNNING  hadoop-0002:8042                                  0


[hadoop@hadoop-0001 hadoop]$ curl -s "http://hadoop-0001:8088/ws/v1/cluster/info"
{"clusterInfo":{"id":1731632262766,"startedOn":1731632262766,"state":"STARTED","haState":"STANDBY","rmStateStoreName":"org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore","resourceManagerVersion":"3.4.0","resourceManagerBuildVersion":"3.4.0 from bd8b77f398f626bb7791783192ee7a5dfaeec760 by root source checksum 934da0c5743762b7851cfcff9f8ca2","resourceManagerVersionBuiltOn":"2024-03-04T06:54Z","hadoopVersion":"3.4.0","hadoopBuildVersion":"3.4.0 from bd8b77f398f626bb7791783192ee7a5dfaeec760 by root source checksum f7fe694a3613358b38812ae9c31114e","hadoopVersionBuiltOn":"2024-03-04T06:35Z","haZooKeeperConnectionState":"CONNECTED"}}[hadoop@hadoop-0001 hadoop]$

缩容集群

减少一台 datanode 节点

在 Hadoop 集群中移除一个节点通常不会直接导致数据丢失,因为 Hadoop 的 HDFS 设计为高度冗余的分布式文件系统。每个数据块默认会有多个副本(通常是3个),分布在不同的节点上。

确认数据副本

确保所有数据块都有足够数量的副本分布在剩余的节点上。您可以使用以下命令来检查集群的副本分布情况:

[hadoop@hadoop-0001 hadoop]$ hdfs dfsadmin -report
Configured Capacity: 168561524736 (156.99 GB)
Present Capacity: 127591596032 (118.83 GB)
DFS Remaining: 127591251968 (118.83 GB)
DFS Used: 344064 (336 KB)
DFS Used%: 0.00%
Replicated Blocks:
        Under replicated blocks: 0
        Blocks with corrupt replicas: 0
        Missing blocks: 0
        Missing blocks (with replication factor 1): 0
        Low redundancy blocks with highest priority to recover: 0
        Pending deletion blocks: 0
Erasure Coded Block Groups:
        Low redundancy block groups: 0
        Block groups with corrupt internal blocks: 0
        Missing block groups: 0
        Low redundancy blocks with highest priority to recover: 0
        Pending deletion blocks: 0

-------------------------------------------------
Live datanodes (4):

Name: 192.168.0.100:9866 (hadoop-0004)
Hostname: hadoop-0004
Decommission Status : Normal
Configured Capacity: 42140381184 (39.25 GB)
DFS Used: 24576 (24 KB)
Non DFS Used: 8348692480 (7.78 GB)
DFS Remaining: 31949651968 (29.76 GB)
DFS Used%: 0.00%
DFS Remaining%: 75.82%
Configured Cache Capacity: 0 (0 B)
Cache Used: 0 (0 B)
Cache Remaining: 0 (0 B)
Cache Used%: 100.00%
Cache Remaining%: 0.00%
Xceivers: 0
Last contact: Fri Nov 15 09:45:49 CST 2024
Last Block Report: Fri Nov 15 09:37:22 CST 2024
Num of Blocks: 0


Name: 192.168.0.141:9866 (hadoop-0001)
Hostname: hadoop-0001
Decommission Status : Normal
Configured Capacity: 42140381184 (39.25 GB)
DFS Used: 106496 (104 KB)
Non DFS Used: 8421670912 (7.84 GB)
DFS Remaining: 31876591616 (29.69 GB)
DFS Used%: 0.00%
DFS Remaining%: 75.64%
Configured Cache Capacity: 0 (0 B)
Cache Used: 0 (0 B)
Cache Remaining: 0 (0 B)
Cache Used%: 100.00%
Cache Remaining%: 0.00%
Xceivers: 0
Last contact: Fri Nov 15 09:45:47 CST 2024
Last Block Report: Fri Nov 15 08:55:11 CST 2024
Num of Blocks: 4


Name: 192.168.0.222:9866 (hadoop-0002)
Hostname: hadoop-0002
Decommission Status : Normal
Configured Capacity: 42140381184 (39.25 GB)
DFS Used: 139264 (136 KB)
Non DFS Used: 8418676736 (7.84 GB)
DFS Remaining: 31879553024 (29.69 GB)
DFS Used%: 0.00%
DFS Remaining%: 75.65%
Configured Cache Capacity: 0 (0 B)
Cache Used: 0 (0 B)
Cache Remaining: 0 (0 B)
Cache Used%: 100.00%
Cache Remaining%: 0.00%
Xceivers: 0
Last contact: Fri Nov 15 09:45:50 CST 2024
Last Block Report: Fri Nov 15 08:55:11 CST 2024
Num of Blocks: 6


Name: 192.168.0.252:9866 (hadoop-0003)
Hostname: hadoop-0003
Decommission Status : Normal
Configured Capacity: 42140381184 (39.25 GB)
DFS Used: 73728 (72 KB)
Non DFS Used: 8412839936 (7.84 GB)
DFS Remaining: 31885455360 (29.70 GB)
DFS Used%: 0.00%
DFS Remaining%: 75.66%
Configured Cache Capacity: 0 (0 B)
Cache Used: 0 (0 B)
Cache Remaining: 0 (0 B)
Cache Used%: 100.00%
Cache Remaining%: 0.00%
Xceivers: 0
Last contact: Fri Nov 15 09:45:50 CST 2024
Last Block Report: Fri Nov 15 08:55:11 CST 2024
Num of Blocks: 2

进入安全模式

安全模式的特点:

  1. 只读访问:在安全模式下,HDFS 只允许读操作,不允许执行写操作。这意味着用户可以读取数据,但不能写入或删除文件。
  2. 保护数据完整性:安全模式确保在集群状态不稳定或正在恢复时,不会进行任何可能破坏数据一致性的操作。
  3. 自动进入和退出:HDFS 可以在启动时自动进入安全模式,直到满足一定的条件(如达到一定的 block 报告比例)后自动退出。管理员也可以手动将 HDFS 设置为安全模式。

安全模式对集群工作的影响:

  • 不影响 MapReduce 作业:在安全模式下,HDFS 仍然可以服务于读操作,因此 MapReduce 作业可以继续运行,只要它们不需要写入 HDFS。
  • 影响写操作:任何需要写入 HDFS 的操作(如新的 MapReduce 作业、HDFS 文件写入等)将被阻塞,直到安全模式被解除。
  • 不影响 YARN 资源管理:ResourceManager 可以继续调度作业,但作业可能会因为 HDFS 的写入限制而无法完成。

在执行缩容操作之前,您可以将 HDFS 设置为安全模式,以防止数据丢失:

# 进入安全模式
[hadoop@hadoop-0001 hadoop]$ [hadoop@hadoop-0001 hadoop]$ hdfs dfsadmin -safemode enter
Safe mode is ON in hadoop-0001/192.168.0.141:8020
Safe mode is ON in hadoop-0002/192.168.0.222:8020

# 查看安全模式状态
[hadoop@hadoop-0001 hadoop]$ hdfs dfsadmin -safemode get
Safe mode is ON in hadoop-0001/192.168.0.141:8020
Safe mode is ON in hadoop-0002/192.168.0.222:8020

修改配置添加黑名单

namenode 节点 hdfs-site.xml

[hadoop@hadoop-0001 hadoop]$ cd /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop
[hadoop@hadoop-0001 hadoop]$ vim hdfs-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>

    <!-- HDFS 基本配置 -->
    <property>
        <name>dfs.nameservices</name>
        <value>mycluster</value> <!-- HDFS 集群的名称 -->
    </property>
    <property>
        <name>dfs.replication</name>
        <value>2</value> <!-- 每个文件块在HDFS中的副本数 -->
    </property>
    <property>
        <name>dfs.ha.namenodes.mycluster</name>
        <value>nn1,nn2</value> <!-- 列出集群中所有 NameNode 的名称或 ID -->
    </property>
    <property>
        <name>dfs.namenode.rpc-address.mycluster.nn1</name>
        <value>hadoop-0001:8020</value> <!-- nn1 的 RPC 地址 -->
    </property>
    <property>
        <name>dfs.namenode.rpc-address.mycluster.nn2</name>
        <value>hadoop-0002:8020</value> <!-- nn2 的 RPC 地址 -->
    </property>
    <property>
        <name>dfs.namenode.http-address.mycluster.nn1</name>
        <value>hadoop-0001:50070</value> <!-- nn1 的 HTTP 地址 -->
    </property>
    <property>
        <name>dfs.namenode.http-address.mycluster.nn2</name>
        <value>hadoop-0002:50070</value> <!-- nn2 的 HTTP 地址 -->
    </property>

    <!-- DataNode 配置 -->
    <property>
        <name>dfs.datanode.data.dir</name>
        <value>/data/hadoop/hadoop_data/hdfs/datanode</value> <!-- DataNode 存储数据块的本地目录 -->
    </property>

    <!-- JournalNode 配置 -->
    <property>
        <name>dfs.journalnode.edits.dir</name>
        <value>/data/hadoop/hadoop_data/hdfs/journalnode</value> <!-- JournalNode 存储编辑日志的本地目录 -->
    </property>
    <property>
        <name>dfs.namenode.shared.edits.dir</name>
        <value>qjournal://hadoop-0001:8485;hadoop-0002:8485;hadoop-0003:8485/mycluster</value>
        <!-- 指定 JournalNode 集群的地址 -->
    </property>

    <!-- HDFS 高可用性配置 -->
    <property>
        <name>dfs.ha.automatic-failover.enabled</name>
        <value>true</value> <!-- 开启 NameNode 失败自动切换 -->
    </property>
    <property>
        <name>dfs.client.failover.proxy.provider.mycluster</name>
        <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
        <!-- 配置 NameNode 失败后自动切换实现方式 -->
    </property>

    <!-- 故障转移配置 -->
    <property>
        <name>dfs.ha.fencing.methods</name>
        <value>sshfence</value> <!-- 故障转移期间使用的屏蔽方法 -->
    </property>
    <property>
        <name>dfs.ha.fencing.ssh.private-key-files</name>
        <value>/home/hadoop/.ssh/id_rsa</value> <!-- hadoop 用户的私钥文件 -->
    </property>
    <property>
        <name>dfs.ha.fencing.ssh.connect-timeout</name>
        <value>30000</value> <!-- SSH 连接超时时间,单位为毫秒 -->
    </property>

    <!-- 可选配置 -->
    <property>
        <name>fs.trash.interval</name>
        <value>1440</value> <!-- HDFS 垃圾回收站保留时间,单位为分钟 -->
    </property>

    <!-- 注意:客户端故障转移的配置不在服务器 hdfs-site.xml 中设置,
         而是在客户端的 Hadoop 配置 core-site.xml 文件中设置 fs.defaultFS 为当前集群 hdfs://mycluster。
         确保您的客户端配置也已正确设置以支持 HDFS 高可用性。 -->
<!--    不需要白名单注释掉-->
<!--        &lt;!&ndash; 白名单配置:指定哪些DataNode被允许连接到NameNode &ndash;&gt;-->
<!--    <property>-->
<!--        <name>dfs.hosts</name>-->
<!--        <value>/data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/hosts</value>-->
<!--        <description>HDFS白名单文件路径,该文件包含允许连接到NameNode的主机名或IP地址。</description>-->
<!--    </property>-->
 
    <!-- 黑名单配置:指定哪些DataNode被禁止连接到NameNode -->
    <property>
        <name>dfs.hosts.exclude</name>
        <value>/data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/hosts.exclude</value>
        <description>HDFS黑名单文件路径,该文件包含禁止连接到NameNode的主机名或IP地址。</description>
    </property>
</configuration>
[hadoop@hadoop-0001 hadoop]$ cd /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop
[hadoop@hadoop-0001 hadoop]$ for i in 192.168.0.141 192.168.0.222 192.168.0.252 192.168.0.100; do scp hdfs-site.xml $i:/data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/; done       

配置黑名单文件 hosts.exclude

黑白名单介绍

  1. dfs.hosts 文件
    • 白名单文件:确实,dfs.hosts文件是一个白名单文件,用于指定哪些主机(或DataNode)被允许连接到NameNode。
    • 文件不存在:如果dfs.hosts文件不存在,则默认行为是允许所有主机连接到NameNode,因为没有明确的白名单限制。
    • 文件存在且空白:这里有一点需要纠正。如果dfs.hosts文件存在但为空白(即没有列出任何主机),这并不意味着不允许任何主机连接到NameNode。相反,它仍然意味着没有明确的白名单限制,因此默认情况下,所有主机都可以连接到NameNode。白名单为空和不存在白名单在效果上是相同的,即不施加任何限制。
  2. dfs.hosts.exclude 文件
    • 黑名单文件:确实,dfs.hosts.exclude文件是一个黑名单文件,用于指定哪些主机被禁止连接到NameNode。
    • 文件不存在:如果dfs.hosts.exclude文件不存在,则默认行为是不禁止任何主机连接到NameNode,因为没有明确的黑名单限制。
    • 文件存在且空白:如果dfs.hosts.exclude文件存在但为空白(即没有列出任何主机),这确实意味着不禁止任何主机连接到NameNode。因为没有明确的黑名单项,所以所有主机都可以连接。
[hadoop@hadoop-0001 hadoop]$ cd /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/
[hadoop@hadoop-0001 hadoop]$ vim hosts.exclude
192.168.0.100

[hadoop@hadoop-0001 hadoop]$ for i in 192.168.0.141 192.168.0.222 192.168.0.252 192.168.0.100; do scp hosts.exclude $i:/data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop/; done   

刷新集群

[hadoop@hadoop-0001 hadoop]$ hdfs dfsadmin -refreshNodes
Refresh nodes successful for hadoop-0001/192.168.0.141:8020
Refresh nodes successful for hadoop-0002/192.168.0.222:8020

[hadoop@hadoop-0001 hadoop]$ yarn rmadmin -refreshNodes
2024-11-15 09:58:50,980 INFO client.ConfiguredRMFailoverProxyProvider: Failing over to rm2

确认退役状态

您可以使用以下命令检查退役状态:

# 如果节点已经成功退役,您将看到该节点的状态为“Decommissioned”。
# 当一个DataNode显示为 "Decommissioned" 状态时,这意味着该节点已经完全退役,并且其上的数据已经被重新分配到了集群中的其他节点。这是一个最终状态,表明退役过程已经完成。
[hadoop@hadoop-0001 hadoop]$  hdfs dfsadmin -report | grep -B 1 Decommission
Hostname: hadoop-0004
Decommission Status : Decommissioned
--
Hostname: hadoop-0001
Decommission Status : Normal
--
Hostname: hadoop-0002
Decommission Status : Normal
--
Hostname: hadoop-0003
Decommission Status : Normal

停止 DataNode 和 nodemanager

在确认数据安全后,您可以在要移除的节点上停止 DataNode 服务:

# 停止  DataNode 
[hadoop@hadoop-0004 hadoop]$ hdfs --daemon stop datanode
[hadoop@hadoop-0004 hadoop]$ jps | grep -vi jps
2418 NodeManager

# 停止  nodemanager
[hadoop@hadoop-0004 logs]$ yarn --daemon stop nodemanager

# 查看 yarn 节点情况
[hadoop@hadoop-0001 hadoop]$ yarn node -list
2024-11-15 10:07:45,670 INFO client.ConfiguredRMFailoverProxyProvider: Failing over to rm2
Total Nodes:3
         Node-Id             Node-State Node-Http-Address       Number-of-Running-Containers
hadoop-0001:39482               RUNNING  hadoop-0001:8042                                  0
hadoop-0003:42690               RUNNING  hadoop-0003:8042                                  0
hadoop-0002:43629               RUNNING  hadoop-0002:8042                                  0

从配置中移除节点 hadoop-0004

移除 hosts 文件
[root@hadoop-0001 hadoop]# vim /etc/hosts
192.168.0.141   hadoop-0001
192.168.0.222   hadoop-0002
192.168.0.252   hadoop-0003
[root@hadoop-0001 hadoop]# for i in 192.168.0.222 192.168.0.252; do scp /etc/hosts root@$i:/etc/hosts; done
移除 works 文件
cd /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop
[root@hadoop-0001 hadoop]# vim workers
hadoop-0001
hadoop-0002
hadoop-0003
[root@hadoop-0001 hadoop]# for i in 192.168.0.222 192.168.0.252; do scp workers root@$i:/data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop; done

清理节点

如果您确定不再需要该节点上的数据,可以清理该节点上的 Hadoop 数据目录甚至释放节点。

退出安全模式

[hadoop@hadoop-0001 hadoop]$ hdfs dfsadmin -safemode leave
Safe mode is OFF in hadoop-0001/192.168.0.141:8020
Safe mode is OFF in hadoop-0002/192.168.0.222:8020

Balancer 操作(可选)

如果集群在移除节点后出现数据不平衡(即某些节点的存储使用率远高于其他节点),您可能需要运行 HDFS Balancer 工具来重新分配数据,使数据在集群中更加均匀分布。使用以下命令启动 Balancer:

[hadoop@hadoop-0001 hadoop]$ hdfs balancer

Nodes
Refresh nodes successful for hadoop-0001/192.168.0.141:8020
Refresh nodes successful for hadoop-0002/192.168.0.222:8020

[hadoop@hadoop-0001 hadoop]$ yarn rmadmin -refreshNodes
2024-11-15 09:58:50,980 INFO client.ConfiguredRMFailoverProxyProvider: Failing over to rm2


### 确认退役状态

您可以使用以下命令检查退役状态:

```shell
# 如果节点已经成功退役,您将看到该节点的状态为“Decommissioned”。
# 当一个DataNode显示为 "Decommissioned" 状态时,这意味着该节点已经完全退役,并且其上的数据已经被重新分配到了集群中的其他节点。这是一个最终状态,表明退役过程已经完成。
[hadoop@hadoop-0001 hadoop]$  hdfs dfsadmin -report | grep -B 1 Decommission
Hostname: hadoop-0004
Decommission Status : Decommissioned
--
Hostname: hadoop-0001
Decommission Status : Normal
--
Hostname: hadoop-0002
Decommission Status : Normal
--
Hostname: hadoop-0003
Decommission Status : Normal

停止 DataNode 和 nodemanager

在确认数据安全后,您可以在要移除的节点上停止 DataNode 服务:

# 停止  DataNode 
[hadoop@hadoop-0004 hadoop]$ hdfs --daemon stop datanode
[hadoop@hadoop-0004 hadoop]$ jps | grep -vi jps
2418 NodeManager

# 停止  nodemanager
[hadoop@hadoop-0004 logs]$ yarn --daemon stop nodemanager

# 查看 yarn 节点情况
[hadoop@hadoop-0001 hadoop]$ yarn node -list
2024-11-15 10:07:45,670 INFO client.ConfiguredRMFailoverProxyProvider: Failing over to rm2
Total Nodes:3
         Node-Id             Node-State Node-Http-Address       Number-of-Running-Containers
hadoop-0001:39482               RUNNING  hadoop-0001:8042                                  0
hadoop-0003:42690               RUNNING  hadoop-0003:8042                                  0
hadoop-0002:43629               RUNNING  hadoop-0002:8042                                  0

从配置中移除节点 hadoop-0004

移除 hosts 文件
[root@hadoop-0001 hadoop]# vim /etc/hosts
192.168.0.141   hadoop-0001
192.168.0.222   hadoop-0002
192.168.0.252   hadoop-0003
[root@hadoop-0001 hadoop]# for i in 192.168.0.222 192.168.0.252; do scp /etc/hosts root@$i:/etc/hosts; done
移除 works 文件
cd /data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop
[root@hadoop-0001 hadoop]# vim workers
hadoop-0001
hadoop-0002
hadoop-0003
[root@hadoop-0001 hadoop]# for i in 192.168.0.222 192.168.0.252; do scp workers root@$i:/data/hadoop/hadoop_soft/hadoop-3.4.0/etc/hadoop; done

清理节点

如果您确定不再需要该节点上的数据,可以清理该节点上的 Hadoop 数据目录甚至释放节点。

退出安全模式

[hadoop@hadoop-0001 hadoop]$ hdfs dfsadmin -safemode leave
Safe mode is OFF in hadoop-0001/192.168.0.141:8020
Safe mode is OFF in hadoop-0002/192.168.0.222:8020

Balancer 操作(可选)

如果集群在移除节点后出现数据不平衡(即某些节点的存储使用率远高于其他节点),您可能需要运行 HDFS Balancer 工具来重新分配数据,使数据在集群中更加均匀分布。使用以下命令启动 Balancer:

[hadoop@hadoop-0001 hadoop]$ hdfs balancer

官方文档: Apache Hadoop 3.4.1 – 使用 Quorum Journal Manager 实现 HDFS 高可用性

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部