1、editlog和fsimage问题
standby节点的editlog还是16xxx,但是fsimage已经17xxx了。而editlog16xxx还在,难道是没有删掉?我的理解是所有操作都是由active接收到然后把edit给到了journalnode吧,然后standby去同步journalnode的edit吧。fsimage不是从active那边直接拉过来的吗?
原因是这样的。standyby生成fsimage 是基于本地的image和jounal上的关闭editlog,然后把生成后的新的image上传给active,然后删除本地旧的image,standy节点不保存editlog的
。而启动的时候NameNode也是加载的journal里面的editlog。这个问题是切换 active namenode导致的,下次切换应该就会删除掉。
2、standby看到的和active看到的dead nodes不一样。
重启下那个DataNode解决。原因是触发了开源的bug https://issues.apache.org/jira/browse/HDFS-14219 重启worker-56修复了。这个bug极少触发,这个DN进程运行了大半年了。 主要是当内存不够的时候才会触发。
这台机器DN内存才2G,而每台DN block数量已经达到900w,已经很紧张了。建议将所有DN内存调大8G或者更多。
3、hdfs Rebalance还是没均衡
su -l hdfs -c "/usr/lib/hadoop-current/sbin/start-balancer.sh -threshold 10"
从日志看已经结束了。
然后看ui确实已经是10%以内了。
这里可以看到threshold是跟average比较的。
根据文档。if overall usage across all the DataNodes in the cluster is 40% of the cluster’s total disk-storage capacity, the script ensures that DataNode disk usage is between 30% and 50% of the DataNode disk-storage capacity.
对照我们上面的情况分析。最大值最小值差20%。最小值跟平均值差10%。 最大值跟平均值差20%,最大值跟最小值差20%。
原来我觉得图中的median是平均值但是实际上是集群DataNode之中使用率是中间的这个数值(使用率中位数)而不是平均值。。
详情文档参照:https://docs.cloudera.com/documentation/enterprise/6/6.3/topics/admin_hdfs_balancer.html
所以只能调整下Rebalance命令。
sudo su -l hdfs -c "/usr/lib/hadoop-current/sbin/start-balancer.sh -threshold 5"
4、DataNode和NameNode启动不来
进程启动不来,这个jstat -gc pid 这种查看下进程的gc情况。有的话调整内存大小即可。DataNode数量较大的时候建议NameNode也需要重启下,避免雪崩问题。
DataNode启动问题,进程是一直在的,也没有gc情况。日志不打印。hdfs ui页面上查看不到这个datanode,hdfs dfsadmin -report也查看不到这个DataNode。就很诡异。
然后排查到发现io占用很大,这个DataNode过会儿自己加进去了。
问题应该是这样的:
HDFS中为了统计每个DN数据节点上的存储使用量,DN节点上会对每块盘路径周期性的执行DU操作,汇报到Namenode节点上,就可以统计到总存储的使用量,每个点的存储使用量。默认10min会执行一次du操作,尽量保证数据使用量的实时性。在存储使用量不大的情况下,执行对每块盘的du操作,对整个系统的IO影响 不太明显,但是当节点存储使用率比较高的情况下,du操作引发IO高的问题对整个系统的影响就很大了,很可能会引发阻塞IO,影响整个节点上的服务。
du统计原理在于将目标路径下的当前没有被删除的文件进行大小累加,然后得出总使用量。这种计算方式在文件数量少时往往不会表现出什么问题。但是当目标路径目录多,文件多的时候,du会表现出明显的时间执行耗时,而在这一点上,df命令则用的是另一种更加高效的方式,它的统计值来通过文件系统获取的。但是df命令的一个最不适用的地方在于它不能按照具体目录进行使用量的统计。df是按照所在磁盘级别进行统计的。换句话说,用df命令在属于同一块物理盘的子路径下执行df命令,获取的值会是完全一致的。比较遗憾,这种情况将无法支持DataNode多block pool共用一块盘的情况。
解决这个问题可以适当调大datanode du执行间隔
通过调整fs.du.interval配置来加大datanode du执行间隔,减少一些存储使用量的实时性来缓解Du带来的IO高问题。
或者从Liunx层面调整cache相关配置。
linux主要是缓存inode相关信息,linux文件系统上,用户对文件、目录的访问都是先访问对应的inode信息,所以适当调整文件系统的cache配置可以提高访问效率。
vm.vfs_cache_pressure
该项表示内核回收用于directory和inode cache内存的倾向:
缺省值100表示内核将根据pagecache和swapcache,把directory和inode cache保持在一个合理的百分比
降低该值低于100,将导致内核倾向于保留directory和inode cache
增加该值超过100,将导致内核倾向于回收directory和inode cache。
也可以减少数据存储的现有目录层级[HDFS-8791]。
参考https://blog.csdn.net/breakout_alex/article/details/100879489
5、hdfs重启全量加载editslog 导致重启很慢
从日志看GC都要快10秒,需要调大jvm
2020-09-25 18:30:27,770 INFO org.apache.hadoop.hdfs.server.namenode.FSEditLogLoader: replaying edit log: 1423148/2024410 transactions completed. (70%)
2020-09-25 18:30:38,099 INFO org.apache.hadoop.util.JvmPauseMonitor: Detected pause in JVM or host machine (eg GC): pause of approximately 9830ms
调大NameNode内存。
6、磁盘满了导致jn和nn挂了一系列问题
Caught exception after scanning through 0 ops from /mnt/disk1/hdfs/journal/emr-cluster/current/edits_inprogress_0000000001662417520 while determining its valid length. Position was 462848
查到这个是因为一个节点NameNode节点下的磁盘打满。
用户侧反馈:
不正常了之后 ,先重启 nn1 、nn2发现失败 ,然后看ZK \JN 是否正常,看Jn的问题就重启了Jn。然后看 header-1 不正常 ,就从header-2 copy一份 过去的。
故障分析与恢复:
header-1之前一直没有做checkpoint,这个靠现在的日志找不到原因了。然后当header-1nn启动的时候做了次checkpoint是成功的(重启的时候就保证了不需要加载太多的edit)。header-2磁盘满了做了切换(实际上当时磁盘并不是百分百满,会保留大概1g吧差不多)。然后主备切换到了header-1,然后一直写edit写满了header2节点,直到这个时候jn出现了问题,然后发现header-1的jn也是有问题的,然后三个jn的内部状态就不一致了。导致hdfs出现的问题。所以这个时候就只有worker-1的jn是ok的,所以最后我们把worker-1的jn同步到了header1和2。然后都重启下就ok了。(这里因为同步jn的时候发现jn有41G,所以cp是很慢的,直接用的是rsync -avK同步)
checkpoin机制:
正常的 checkpoint 触发有两个维度,一个是时间,一个是edits 数量(或者命令触发也是ok的),checkpoint操作是由standby节点发起的。
2021-08-08 10:20:22,476 ERROR org.apache.hadoop.hdfs.server.common.Storage: It appears that another node 10237@emr-header-1.cluster-136706 has already locked the storage directory: /mnt/disk1/hdfs/journal/emr-cluster
分析上条日志。
这里可以看到只要写入失败, 后面状态就异常。 失败原因有很多, 磁盘满是一种猜测。 如果目录没有了也可能写不进去。所以header-1没有做checkpoint的原因可能是因为之前header-1也是有过磁盘问题或者目录问题。
7、NameNode启动异常
hdfs namenode -initializeSharedEdits
执行下,具体什么意思还不是特别明白,看网上的解释是将所有journal node的元文件的VERSION文件的参数修改成与namenode的元数据相同。应该是差不多,同步下edits的那种命令应该是。
具体问题具体排查吧,这里我已经忘记了具体的处理步骤了。
大概思路就是如果是集群崩了可以尝试修复一下,就跟这个命令一样
hdfs namenode -initializeSharedEdits
拉齐元数据然后
java.io.IOException: Gap in transactions. Expected to be able to read up until at least txid 1365 but unable to find any edit logs containing txid 1
遇到这种报错的话也是说元数据有问题执行一下以下命令
hadoop namenode -recover
在一堆提示后选择yes 然后选择C。
然而在这个过程中报错了
java.lang.IllegalStateException: Cannot skip to less than the current value (=1982323), where newValue=1632121
然后就只能重新格式化了一下NameNode
hdfs namenode -format
再执行
hadoop namenode -recover
没有报错。
Incompatible namespaceID for journal Storage Directory /xxxx/xxxxx : NameNode has nsId 2006559846 but storage has nsId 1781480752
namenode的版本号改成与journalnode的版本号一致导致。大概报错都能看懂,然后做对应处理就是了,什么namespaceid。poolid什么的这些我都处理了一遍,根据报错做对应处理就好了,不要慌。不知道用户乱操作什么了。最后弄好了。
8、记一次kerberos问题
2021-12-09 14:11:50,498 ERROR org.apache.hadoop.hdfs.qjournal.server.JournalNode: Failed to start journalnode.
java.io.IOException: Problem starting http server
at org.apache.hadoop.http.HttpServer2.start(HttpServer2.java:1312)
at org.apache.hadoop.hdfs.qjournal.server.JournalNodeHttpServer.start(JournalNodeHttpServer.java:86)
at org.apache.hadoop.hdfs.qjournal.server.JournalNode.start(JournalNode.java:238)
at org.apache.hadoop.hdfs.qjournal.server.JournalNode.run(JournalNode.java:209)
at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:76)
at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:90)
at org.apache.hadoop.hdfs.qjournal.server.JournalNode.main(JournalNode.java:437)
Caused by: javax.servlet.ServletException: javax.servlet.ServletException: Keytab does not exist: /home/hdfs/hadoop.keytab
at org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler.init(KerberosAuthenticationHandler.java:215)
at org.apache.hadoop.security.authentication.server.AuthenticationFilter.initializeAuthHandler(AuthenticationFilter.java:194)
at org.apache.hadoop.security.authentication.server.AuthenticationFilter.init(AuthenticationFilter.java:180)
at org.apache.hadoop.security.authentication.server.ProxyUserAuthenticationFilter.init(ProxyUserAuthenticationFilter.java:57)
at org.eclipse.jetty.servlet.FilterHolder.initialize(FilterHolder.java:140)
at org.eclipse.jetty.servlet.ServletHandler.lambda$initialize$0(ServletHandler.java:731)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:742)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:755)
at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:379)
at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:911)
at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:288)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:169)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:117)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:97)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:169)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:117)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:97)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:169)
at org.eclipse.jetty.server.Server.start(Server.java:423)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:110)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:97)
at org.eclipse.jetty.server.Server.doStart(Server.java:387)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73)
at org.apache.hadoop.http.HttpServer2.start(HttpServer2.java:1276)
... 6 more
就离谱,我一直确定我hdfs-site.xml文件里面都指定了keytab的目录,他还一直找我家目录下。我甚至在想是不是有个hdfs-site.xml的优先级比我这个配置文件里的hdfs-site.xml高导致没读到?(之前遇到过一个这种坑),然后排查发现不是的,而且$HADOOP_HOME $HADOOP_CONF_DIR都是ok的。那么我就反复检查了下配置文件。发现core-site.xml我改了个参数。
hadoop.http.authentication.type
这个原来是simple不小心被我改成了kerberos。然后我看了下官网,这个参数的定义解释是
Defines authentication used for Oozie HTTP endpoint. Supported values are: simple | kerberos | #AUTHENTICATION_HANDLER_CLASSNAME#
看起来就是使用oozie的时候需要用的。
我改回去就启动成功了,不过我还是没能理解他这里为什么会导致失败,因为在hadoop的Secure Mode也没看到相关参数的配置问题。。。回头再看下吧