07Hadoop NameNode HA

0 阅读10分钟

Hadoop NameNode HA

背景概述

在Hadoop1中NameNode存在一个单点故障问题,如果NameNode所在的机器发生故障,整个集群就将不可用(Hadoop1中虽然有个SecorndaryNameNode,但是它并不是NameNode的备份,它只是NameNode的一个助理,协助NameNode工作,SecorndaryNameNode会对fsimage和edits文件进行合并,并推送给NameNode,防止因edits文件过大,导致NameNode重启变慢),这是Hadoop1的不可靠实现

在Hadoop2中这个问题得以解决,Hadoop2中的高可靠性是指同时启动两个NameNode,其中一个处于active工作状态,另外一个处于随时待命standby状态。这样,当一个NameNode所在的服务器宕机时,可以在数据不丢失的情况下, 手工或者自动切换到另一个NameNode提供服务。这些NameNode之间通过共享数据,保证数据的状态一致。多个NameNode之间共享数据,可以通过Network File System或者Quorum Journal Node。前者是通过Linux共享的文件系统,属于操作系统的配置,后者是Hadoop自身的东西,属于软件的配置

总结:Hadoop2.0通过HDFS Federation联邦机制解决了内存受限问题,通过HDFS HA解决了NameNode单点故障问题。在Hadoop3.0中,NameNode高可用可以支持多台节点

Paxos 算法

Paxos算法是莱斯利·兰伯特于1990年提出的一种基于消息传递的一致性算法。这个算法被认为是类似算法中最有效的。该算法覆盖全部场景的一致性。每种技术会根据自己技术的特征选择简化算法实现。

传递:NN之间通过一个可靠的传输技术,最终数据能同步就可以(类似一种带存储能力的消息队列),我们一般假设网络等因素是稳定的

简化思路:分布式节点是否明确,节点权重是否明确,强一致性破坏可用性,过半通过可以中和一致性和可用性,最简单的自我协调实现-主从。主的选举,明确节点数量和权重;主从的职能,主增删改查,从查询,增删改传递给主;主从同步数据,对主做的修改,过半从同步成功才算修改成功

image.png

HA方案:多台NN主备模式,Active和Standby状态--Active对外提供服务;增加journalnode角色(>3台),负责同步NN的editlog--最终一致性;增加zkfc角色(与NN同台),通过zookeeper集群协调NN的主从选举和切换--事件回调机制;DN同时向所有NN汇报block清单(zk做分布式协调的,不适合存储大量数据。jn设计就是用来存储editlog数据的,存储在zk中不合适)

NameNode HA 实现原理

通过Journal Node实现NameNode集群启动时,可以通过动手方式来实现NameNodeHA也可以通过自动方式实现NameNodeHA

NameNode HA实现可以同时启动2个NameNode,这些NameNode只有一个是active的,另一个属于standby状态。active状态意味着提供服务,standby状态意味着处于休眠状态,只进行数据同步,进行数据合并工作,时刻准备着提供服务

手动实现NameNode原理如下图所示

image.png

实现NameNode高可用大体步骤如下:

  1. 一个NameNode进程处于Active状态,另1个NameNode进程处于Standby状态。Active的NameNode负责处理客户端的请求
  2. Active的NameNode修改了元数据之后,会在JNs的半数以上的节点上记录这个日志。Standby状态的NameNode会监视任何对JNs上edit log的更改。一旦edits log出现更改,Standby的NN就会根据edits log更改自己记录的元数据
  3. 当发生故障转移时,Standby主机会确保已经读取了JNs上所有的更改来同步它本身记录的元数据,然后由Standby状态切换为Active状态
  4. 为了确保在发生故障转移操作时拥有相同的数据块位置信息,DNs向所有NN发送数据块位置信息和心跳数据
  5. JNs只允许一台NameNode向JNs写edits log数据,这样就能保证不会发生“脑裂”

以上手动方式需要我们手动将Standby NamNode切换成Active NameNode,对于高可用场景时效性较低。那么可以通过zookeeper进行协调自动实现NameNode HA,实现代码通过Zookeeper来检测Activate NameNode节点是否挂掉,如果挂掉立即将Standby NameNode切换成Active NameNode,原理如下:

image.png

ZooKeeper Failover Controller:监控NameNode健康状态,并向Zookeeper注册NameNode。NameNode挂掉后,ZKFC为NameNode竞争锁,获得ZKFC 锁的NameNode变为active。手动切换NameNode场景一般用于HDFS升级场合,绝大多数我们都是基于Zookeeper来实现自动NameNode HA切换

NameNode自动HA 集群搭建

准备192.168.91.31-192.168.91.344个节点,内存2G,CPU2C,硬盘20GB,主机名称node01-node04,HDFS集群划分如下

节点NNDNZKZKFCJN
node01
node02
node03
node04

准备

# 所有节点

# hosts 配置
cat >> /etc/hosts << "EOF"
192.168.91.31  node01
192.168.91.32  node02
192.168.91.33  node03
192.168.91.34  node04
EOF

# JDK安装
wget https://builds.openlogic.com/downloadJDK/openlogic-openjdk/8u392-b08/openlogic-openjdk-8u392-b08-linux-x64.tar.gz
tar xf openlogic-openjdk-8u392-b08-linux-x64.tar.gz
mv openlogic-openjdk-8u392-b08-linux-x64 /usr/local/jdk8
rm -f openlogic-openjdk-8u392-b08-linux-x64.tar.gz
echo 'export JAVA_HOME=/usr/local/jdk8' >> /etc/profile
echo 'export PATH=$PATH:${JAVA_HOME}/bin' >> /etc/profile
source /etc/profile

# 关闭防火墙
systemctl stop firewalld && systemctl disable firewalld

# 关闭selinux
sed -ri 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
setenforce 0

# 时间同步配置,最小化安装系统需要安装ntpdate软件
yum -y install ntpdate
echo "0 */1 * * * ntpdate time1.aliyun.com" >> /var/spool/cron/root
systemctl enable ntpdate && systemctl start ntpdate

# 在HDFS集群搭建完成后,在Namenode HA切换进行故障转移时采用SSH方式进行,底层会使用到fuster包,有可能我们安装Centos7系统没有fuster程序包,导致不能进行NameNode HA 切换,我们可以通过安装Psmisc包达到安装fuster目的,因为此包中包含了fuster程序,安装方式如下
yum -y install psmisc

zookeeper集群搭建

# node02、node03、node04
wget https://archive.apache.org/dist/zookeeper/zookeeper-3.6.4/apache-zookeeper-3.6.4-bin.tar.gz
tar xf apache-zookeeper-3.6.4-bin.tar.gz
mv apache-zookeeper-3.6.4-bin /usr/local/apache-zookeeper-3.6.4
rm -f apache-zookeeper-3.6.4-bin.tar.gz
echo 'export ZOOKEEPER_HOME=/usr/local/apache-zookeeper-3.6.4' >> /etc/profile
echo 'export PATH=$PATH:${ZOOKEEPER_HOME}/bin' >> /etc/profile
source /etc/profile
# 创建配置文件
cat > $ZOOKEEPER_HOME/conf/zoo.cfg << EOF
# 发送心跳的间隔时间,单位:毫秒
tickTime=2000
initLimit=10
syncLimit=5
# ZooKeeper保存数据的目录
dataDir=/var/zookeeper/data
# 日志目录
dataLogDir=/var/zookeeper/log
clientPort=2181
# 各个节点配置
server.1=node02:2881:3881
server.2=node03:2881:3881
# observer(表示对应节点不参与投票)
server.3=node04:2881:3881
EOF

# 为每个zk节点创建数据目录,并在该目录创建一个文件myid,在myid中写下当前zk的编号
# 所有zk节点
mkdir -p /var/zookeeper/data
# node02
echo 1 > /var/zookeeper/data/myid
# node03
echo 2 > /var/zookeeper/data/myid
# node04
echo 3 > /var/zookeeper/data/myid

# 在所有zk节点分别启动ZooKeeper,zkServer.sh start|stop|status
# 启动zk,这里暂不启动,后面启动hadoop时再启动
zkServer.sh start
# 停止zk
zkServer.sh stop
# 查看zk状态
zkServer.sh status

hadoop集群安装

# node01

# 免密配置
ssh-keygen -t rsa -P '' -f  ~/.ssh/id_rsa
# 启动start-dfs.sh脚本的节点需要将公钥分发给所有节点
ssh-copy-id node01
ssh-copy-id node02
ssh-copy-id node03
ssh-copy-id node04
# 在HA模式下,每一个NN身边会启动ZKFC,ZKFC会用免密的方式控制自己和其他NN节点的NN状态
# 配置NN节点之间的互相免密,node01到node02免密已经配置过了,这里配置node02到node01免密
ssh node02
ssh-keygen -t rsa -P '' -f  ~/.ssh/id_rsa
ssh-copy-id node01
ssh-copy-id node02
exit

# hadoop部署
wget https://dlcdn.apache.org/hadoop/common/hadoop-3.2.4/hadoop-3.2.4.tar.gz
tar xf hadoop-3.2.4.tar.gz
chown -R root:root hadoop-3.2.4
mv hadoop-3.2.4 /usr/local/hadoop-3.2.4
echo 'export HADOOP_HOME=/usr/local/hadoop-3.2.4' >> /etc/profile
echo 'export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin' >> /etc/profile
source /etc/profile

# hadoop配置

# hadoop-env.sh脚本中JAVA_HOME配置
sed -i 's%# export JAVA_HOME=%export JAVA_HOME=/usr/local/jdk8%' $HADOOP_HOME/etc/hadoop/hadoop-env.sh
# datanode节点配置
cat > $HADOOP_HOME/etc/hadoop/workers << "EOF"
node02
node03
node04
EOF
# start-dfs.sh和stop-dfs.sh脚本中用户配置
cat > user_tmp.txt << EOF
HDFS_DATANODE_USER=root
HDFS_DATANODE_SECURE_USER=hdfs
HDFS_NAMENODE_USER=root
HDFS_JOURNALNODE_USER=root
HDFS_ZKFC_USER=root
EOF
sed -i '17r user_tmp.txt' $HADOOP_HOME/sbin/start-dfs.sh
sed -i '17r user_tmp.txt' $HADOOP_HOME/sbin/stop-dfs.sh
rm -f user_tmp.txt

# core-site.xml和hdfs-site.xml配置文件如下所示

$HADOOP_HOME/etc/hadoop/core-site.xml

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
  <property>
	<name>fs.defaultFS</name>
	<value>hdfs://mycluster</value>   
  </property>
  <property>
	<name>hadoop.tmp.dir</name>
	<value>/var/hadooptmp/ha</value>
  </property>
  <!-- 指定每个zookeeper服务器的位置和客户端端口号 -->
  <property>
	 <name>ha.zookeeper.quorum</name>
	 <value>node02:2181,node03:2181,node04:2181</value>
   </property>
  <!-- 建立连接的重试次数,ha模式下启动hdfs时,namenode需要与JournalNode建立连接,因为是同时启动的,JournalNode还没有准备好因此需要重试。这个配置默认是10,在虚拟机中的测试环境,节点性能较差,需要将这个配置改大,否则namenode可能起不来,需要单独手动启动 -->
  <property>
	<name>ipc.client.connect.max.retries</name>
	<value>100</value>   
  </property>
</configuration>

$HADOOP_HOME/etc/hadoop/hdfs-site.xml

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
  <!-- 指定副本的数量 -->
  <property>
    <name>dfs.replication</name>
    <value>3</value>
  </property>
  <!-- 以下是一对多,逻辑到物理节点的映射 -->
  <!-- 解析参数dfs.nameservices值hdfs://mycluster的地址 -->
  <property>
    <name>dfs.nameservices</name>
    <value>mycluster</value>
  </property>
  <!-- 测试环境中可以通过这个配置,关闭权限检查,方便操作 -->
  <!--
  <property>
    <name>dfs.permissions.enabled</name>
    <value>false</value>
  </property>
  -->
  <!-- mycluster由以下两个namenode支撑 -->
  <property>
    <name>dfs.ha.namenodes.mycluster</name>
    <value>nn1,nn2</value>
  </property>
  <!-- 指定nn1地址和端口号 -->
  <property>
    <name>dfs.namenode.rpc-address.mycluster.nn1</name>
    <value>node01:8020</value>
  </property>
  <!-- 指定nn2地址和端口号 -->
  <property>
    <name>dfs.namenode.rpc-address.mycluster.nn2</name>
    <value>node02:8020</value>
  </property>
  <!-- 下面两个http端口的配置,配置的是默认值,可以不用配置 -->
  <property>
    <name>dfs.namenode.http-address.mycluster.nn1</name>
    <value>node01:9870</value>
  </property>
  <property>
    <name>dfs.namenode.http-address.mycluster.nn2</name>
    <value>node02:9870</value>
  </property>
  <!-- 指定客户端查找active的namenode的策略:会给所有namenode发请求,以决定哪个是active的 -->
  <property>
    <name>dfs.client.failover.proxy.provider.mycluster</name>
    <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
  </property>
  <!-- 指定三台journal node服务器的地址,以及数据存储的目录 -->
  <!-- JournalNode可以在不同hdfs集群之间共享,不同的hdfs集群这里配置不同的存储目录即可 -->
  <property>
    <name>dfs.namenode.shared.edits.dir</name>
    <value>qjournal://node01:8485;node02:8485;node03:8485/mycluster</value>
  </property>
  <!-- journal服务数据存储目录 -->
  <property>
    <name>dfs.journalnode.edits.dir</name>
    <value>/opt/data/journal/node/local/data</value>
  </property>
  <!-- 当active nn出现故障时,免密ssh到对应的服务器,将namenode进程kill掉  -->
  <property>
    <name>dfs.ha.fencing.methods</name>
    <value>sshfence</value>
  </property>
  <!-- ssh免密公钥路径 -->
  <property>
    <name>dfs.ha.fencing.ssh.private-key-files</name>
    <value>/root/.ssh/id_rsa</value>
  </property>
  <!-- 启动NN故障自动切换,即启动zkfc -->
  <property>
    <name>dfs.ha.automatic-failover.enabled</name>
    <value>true</value>
  </property>
</configuration>
# node01
cd /usr/local
tar -zcvf hadoop-3.2.4-config.tar.gz hadoop-3.2.4/
for i in 2 3 4; do scp hadoop-3.2.4-config.tar.gz node0$i:/usr/local; done
# node02-node04 节点
cd /usr/local
tar xf hadoop-3.2.4-config.tar.gz
rm -f hadoop-3.2.4-config.tar.gz
echo 'export HADOOP_HOME=/usr/local/hadoop-3.2.4' >> /etc/profile
echo 'export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin' >> /etc/profile
source /etc/profile

启动HA 的HDFS

# 1.启动zookeeper集群
# node02、node03、node04
$ZOOKEEPER_HOME/bin/zkServer.sh start
# 2.格式化zookeeper
# node01
hdfs zkfc -formatZK
# 3.启动Journalnode,格式化namenode时需要先启动Journalnode
# node01、node02、node03
hdfs --daemon start journalnode
# 4.选择一个Namenode格式化,格式化Namenode,会连接journalnode创建相应目录(因此journalnode需要先启动,可以通过journalnode的日志和数据目录观察到)
# node01
hdfs namenode -format
# 5.启动这个格式化的namenode
# 在node01上启动NameNode,便于后期同步Namenode
hdfs --daemon start namenode
# 6.同步元数据
# 在node02上同步NameNode元数据
hdfs namenode -bootstrapStandby
# 7.启动HDFS集群,只有第一次启动hdfs集群时需要先执行上面的步骤,后面启动hdfs集群时只需要执行start-dfs.sh即可,该脚本会同时启动NN,ZKFC、JN、DN,但是zk还是得先启动
# node01
$HADOOP_HOME/sbin/start-dfs.sh

# node02,查看zk的锁
zkCli.sh
# 可以看到node01上的NN是active状态的
get /hadoop-ha/mycluster/ActiveStandbyElectorLock

        myclusternn1node01
# 推出zkCli
quit

验证测试

访问webui

image.png

image.png

以上在node01节点访问和在node02节点访问,一个节点为active节点,另一个为standby节点,这两个节点不一定哪个为active节点,这取决于争夺zookeeper锁,哪个节点先启动争夺到锁,那么就是active节点

HDFS HA 测试

active状态的NN挂掉,会删除zk中的锁,所有standby状态的NN会去争抢这把锁,争抢到锁的NN会尝试将active状态的NN降级并将自己升级,会ssh到之前的active节点判断NN是否真的挂掉

  1. 之前的active节点,NN没有挂(ZKFC挂掉了触发了锁争抢),将该节点的NN降级为standby,并将自己升级为active;如果NN挂掉了,即确定了之前active状态的NN已经挂掉,则直接将自己升级为active
  2. 如果不能连接到之前的active节点,则不能判断之前active状态的NN是否真的挂掉,则不会升级自己为active,这种极端情况是active节点与所有的zk节点和NN节点都失去了联系才会出现,一般不会出现这种极端情况

测试HDFS HA 可以直接将对应的active NameNode节点的NameNode进程杀掉,观察Standby NameNode节点状态会自动切换成Active状态,说明NameNode HA 没有问题,否则就需要查看各个NameNode节点$HADOOP_HOME/logs目录下对应的进行日志解决问题

可以通过hdfs --daemon start namenode手动启动namenode

# node01 杀掉ZKFC
jps
2069 NameNode
2730 DFSZKFailoverController
3834 Jps
1918 JournalNode

kill -9 2730
# 等几秒再观察,NameNode依然存在,只是被降级为standby了(可以在 http://192.168.91.31:9870/ 中观察到)
jps
2069 NameNode
3850 Jps
1918 JournalNode

# node02 通过zk中的数据可以观察到 node02节点中的NN被升级成active了
zkCli.sh

get /hadoop-ha/mycluster/ActiveStandbyElectorLock

        myclusternn2node02

quit

# node01 启动zkfc
hdfs --daemon start zkfc

# node02 杀掉namenode
jps
2086 JournalNode
2235 NameNode
2475 DFSZKFailoverController
1948 QuorumPeerMain
4508 Jps
2349 DataNode

kill -9 2235

zkCli.sh
# node01的NN自动切换为active状态
get /hadoop-ha/mycluster/ActiveStandbyElectorLock

        myclusternn1node01

quit

# 启动namenode
hdfs --daemon start namenode

# node01,将网卡下线,使node01节点与所有节点失去联系
ifconfig ens33 down

# node02 zkfc抢到了锁
zkCli.sh

get /hadoop-ha/mycluster/ActiveStandbyElectorLock

        myclusternn2node02

quit
# 但是观察 http://192.168.91.32:9870/ 这个页面,node02的NN依然是standby状态,此时整个集群实际是不可用的,因为没有active状态的NN
# node01,将网卡上线
ifconfig ens33 up
# 观察 http://192.168.91.32:9870/ 这个页面,node02的NN升级为active状态,因为已经抢到了锁,现在联系上了之前的active节点,将该节点的NN降级为standby并把自己升级为active

HDFS启动脚本和停止脚本编写

每次启动HDFS集群需要首先去各个zookeeper节点上启动zookeeper,然后再去namenode节点上启动HDFS集群,关闭集群时也是一样,先在namenode节点上停止HDFS集群,然后去zookeeper每台节点上关闭zookeeper。为了操作方便我们可以编写HDFS启动脚本和HDFS关闭脚本来方便以上操作

在mynode1节点/root下创建bin目录,在此目录下编写启动和关闭HDFS集群脚本

mkdir -p /root/bin
cd /root/bin
# 启动脚本和关闭脚本见下面

HDFS 集群启动脚本 hdfs_ha_start.sh

#!/bin/bash
for zknode in node02 node03 node04
do
    ssh $zknode "source /etc/profile;zkServer.sh start"
done

sleep 1

start-dfs.sh
sleep 1

echo "=====node01 jps====="
jps

for other_node in node02 node03 node04
do
   echo "=====$other_node jps====="
   ssh $other_node "source /etc/profile;jps"
done

HDFS集群关闭脚本 hdfs_ha_stop.sh

#!/bin/bash
stop-dfs.sh
sleep 1

for zknode in node02 node03 node04
do
    ssh $zknode "source /etc/profile;zkServer.sh stop"
done

echo "=====node01 jps====="
jps

for other_node in node02 node03 node04
do
   echo "=====$other_node jps====="
   ssh $other_node "source /etc/profile;jps"
done

HDFS的权限

  1. 每个文件和目录都和一个拥有者和组相关联
  2. 文件或者目录对与拥有者、同组用户和其他用户拥有独立的权限
  3. 对于一个文件,r表示读取的权限,w表示写或者追加的权限,x代表操作文件的权限。对于目录而言,r表示列出目录内容的权限,w表示创建或者删除文件和目录的权限,x表示访问该目录子项目的权限
  4. HDFS目录及文件权限可以防止用户修改或删除文件系统的重要部分。(dfs.permissions.enabled属性)。防止好人做错事
  5. 启动HDFS进程的用户就是HDFS的超级用户。对于超级用户,系统不会执行任何权限检查

hdfs没有相关命令和接口去创建用户,hdfs信任客户端,默认情况使用操作系统提供的用户和组,可以扩展 kerberos LDAP 集成第三方用户认证系统。linux系统中超级用户是root,hdfs系统中超级用户是namenode进程的启动用户(面向操作系统,root是管理员其他用户都叫普通用户;面向操作系统的软件,谁启动管理这个进程,那么这个用户叫做这个软件的管理员)。一般在企业中不会用root做什么事情

下面创建bigdata这个用户来启动hdfs

# node01
# 停止zk和hdfs集群
/bin/bash /root/bin/hdfs_ha_stop.sh

# 所有节点
# 创建bigdata用户
useradd bigdata
passwd bigdata
# 将资源与用户绑定(1.程序所在目录,2.数据所在目录,3.日志文件或目录)
# zk
chown -R bigdata /usr/local/apache-zookeeper-3.6.4
chown -R bigdata /var/zookeeper
# hadoop
chown -R bigdata /usr/local/hadoop-3.2.4
chown -R bigdata /var/hadooptmp/ha
chown -R bigdata /opt/data/journal/node/local

# node01
# 给bigdata用户做免密
su - bigdata
ssh-keygen -t rsa -P '' -f  ~/.ssh/id_rsa
ssh-copy-id node01
ssh-copy-id node02
ssh-copy-id node03
ssh-copy-id node04
ssh node02
ssh-keygen -t rsa -P '' -f  ~/.ssh/id_rsa
ssh-copy-id node01
ssh-copy-id node02
exit
# 修改hdfs-site.xml文件中的ssh免密公钥路径,并发送到其它节点
sed -i 's#/root/.ssh/id_rsa#/home/bigdata/.ssh/id_rsa#' $HADOOP_HOME/etc/hadoop/hdfs-site.xml
for i in 2 3 4;do scp $HADOOP_HOME/etc/hadoop/hdfs-site.xml node0$i:$HADOOP_HOME/etc/hadoop/;done
# 修改start-dfs.sh和stop-dfs.sh中的用户名,并发送到其它节点
sed -i '17,23s/root/bigdata/g' $HADOOP_HOME/sbin/start-dfs.sh
sed -i '17,23s/root/bigdata/g' $HADOOP_HOME/sbin/stop-dfs.sh
for i in 2 3 4;do scp $HADOOP_HOME/sbin/*-dfs.sh node0$i:$HADOOP_HOME/sbin/;done

# 创建脚本目录
mkdir ~/bin
# 回到root用户,拷贝脚本
exit
cp /root/bin/* /home/bigdata/bin/
chown -R bigdata:bigdata /home/bigdata/bin/
# 切换到bigdata用户,启动脚本
su - bigdata
/bin/bash ~/bin/hdfs_ha_start.sh

# node04
# 切换到bigdata用户
su - bigdata
hdfs dfs -mkdir /temp
hdfs dfs -chown bigdata:bigdata /temp
hdfs dfs -chmod 770 /temp

hdfs dfs -ls /
Found 1 items
drwxrwx---   - bigdata bigdata          0 2024-01-16 17:57 /temp
# 切换回root用户
exit
useradd good
usermod -a -G bigdata good

id good
uid=1002(good) gid=1002(good) groups=1002(good),1001(bigdata)
# 切换到good用户
su - good
# 显示权限不够,在操作系统中good用户已经属于bigdata组(hdfs启动之后添加的用户),但是hdfs启动时并不知道good属于bigdata组
hdfs dfs -mkdir /temp/abc
mkdir: Permission denied: user=good, access=EXECUTE, inode="/temp":bigdata:bigdata:drwxrwx---
# hdfs中good用户没有所属的组
hdfs groups
good :

# node01
# 在active状态的namenode节点(不能是其它节点,最好在所有NN节点),创建good用户并添加到bigdata组,然后刷新hdfs
# root用户
useradd good
usermod -a -G bigdata good
su - bigdata
hdfs dfsadmin -refreshUserToGroupsMappings

# node04
# good用户
hdfs groups
good : good bigdata

# 上面添加用户、配置组、刷新hdfs,都必须在active状态的namenode节点操作,否则下面的命令还是会报权限错误
hdfs dfs -mkdir /temp/abc

hdfs dfs -ls /temp
Found 1 items
drwxr-xr-x   - good bigdata          0 2024-01-16 18:19 /temp/abc