HDFS-17167. Add config to startup NameNode as Observer (#6013)

This commit is contained in:
dannytbecker 2023-09-06 09:17:12 -07:00 committed by GitHub
parent e1dde3bc23
commit 07c8b69f7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 83 additions and 4 deletions

View File

@ -1177,6 +1177,8 @@ public class DFSConfigKeys extends CommonConfigurationKeys {
public static final String DFS_NAMENODE_PLUGINS_KEY = "dfs.namenode.plugins"; public static final String DFS_NAMENODE_PLUGINS_KEY = "dfs.namenode.plugins";
public static final String DFS_WEB_UGI_KEY = "dfs.web.ugi"; public static final String DFS_WEB_UGI_KEY = "dfs.web.ugi";
public static final String DFS_NAMENODE_STARTUP_KEY = "dfs.namenode.startup"; public static final String DFS_NAMENODE_STARTUP_KEY = "dfs.namenode.startup";
public static final String DFS_NAMENODE_OBSERVER_ENABLED_KEY = "dfs.namenode.observer.enabled";
public static final boolean DFS_NAMENODE_OBSERVER_ENABLED_DEFAULT = false;
public static final String DFS_DATANODE_KEYTAB_FILE_KEY = "dfs.datanode.keytab.file"; public static final String DFS_DATANODE_KEYTAB_FILE_KEY = "dfs.datanode.keytab.file";
public static final String DFS_DATANODE_KERBEROS_PRINCIPAL_KEY = public static final String DFS_DATANODE_KERBEROS_PRINCIPAL_KEY =
HdfsClientConfigKeys.DFS_DATANODE_KERBEROS_PRINCIPAL_KEY; HdfsClientConfigKeys.DFS_DATANODE_KERBEROS_PRINCIPAL_KEY;

View File

@ -435,7 +435,7 @@ protected String getNameServiceId(Configuration conf) {
} }
@Override @Override
protected HAState createHAState(StartupOption startOpt) { protected HAState createHAState(Configuration conf) {
return new BackupState(); return new BackupState();
} }

View File

@ -163,6 +163,8 @@
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_METRICS_LOGGER_PERIOD_SECONDS_DEFAULT; import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_METRICS_LOGGER_PERIOD_SECONDS_DEFAULT;
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_METRICS_LOGGER_PERIOD_SECONDS_KEY; import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_METRICS_LOGGER_PERIOD_SECONDS_KEY;
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_NAME_DIR_KEY; import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_NAME_DIR_KEY;
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_OBSERVER_ENABLED_DEFAULT;
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_OBSERVER_ENABLED_KEY;
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_PLUGINS_KEY; import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_PLUGINS_KEY;
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_RPC_ADDRESS_KEY; import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_RPC_ADDRESS_KEY;
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_RPC_BIND_HOST_KEY; import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_RPC_BIND_HOST_KEY;
@ -1125,7 +1127,7 @@ protected NameNode(Configuration conf, NamenodeRole role)
+ " this namenode/service.", clientNamenodeAddress); + " this namenode/service.", clientNamenodeAddress);
} }
this.haEnabled = HAUtil.isHAEnabled(conf, nsId); this.haEnabled = HAUtil.isHAEnabled(conf, nsId);
state = createHAState(getStartupOption(conf)); state = createHAState(conf);
this.allowStaleStandbyReads = HAUtil.shouldAllowStandbyReads(conf); this.allowStaleStandbyReads = HAUtil.shouldAllowStandbyReads(conf);
this.haContext = createHAContext(); this.haContext = createHAContext();
try { try {
@ -1161,11 +1163,17 @@ private void stopAtException(Exception e){
} }
} }
protected HAState createHAState(StartupOption startOpt) { protected HAState createHAState(Configuration conf) {
StartupOption startOpt = getStartupOption(conf);
if (!haEnabled || startOpt == StartupOption.UPGRADE if (!haEnabled || startOpt == StartupOption.UPGRADE
|| startOpt == StartupOption.UPGRADEONLY) { || startOpt == StartupOption.UPGRADEONLY) {
return ACTIVE_STATE; return ACTIVE_STATE;
} else if (startOpt == StartupOption.OBSERVER) { } else if (conf.getBoolean(DFS_NAMENODE_OBSERVER_ENABLED_KEY,
DFS_NAMENODE_OBSERVER_ENABLED_DEFAULT)
|| startOpt == StartupOption.OBSERVER) {
// Set Observer state using config instead of startup option
// This allows other startup options to be used when starting observer.
// e.g. rollingUpgrade
return OBSERVER_STATE; return OBSERVER_STATE;
} else { } else {
return STANDBY_STATE; return STANDBY_STATE;

View File

@ -2801,6 +2801,15 @@
</description> </description>
</property> </property>
<property>
<name>dfs.namenode.observer.enabled</name>
<value>false</value>
<description>
This causes NameNode on startup to become an observer node if
set to true, otherwise startup is no different.
</description>
</property>
<property> <property>
<name>dfs.namenode.enable.retrycache</name> <name>dfs.namenode.enable.retrycache</name>
<value>true</value> <value>true</value>

View File

@ -17,6 +17,7 @@
*/ */
package org.apache.hadoop.hdfs.server.namenode.ha; package org.apache.hadoop.hdfs.server.namenode.ha;
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_OBSERVER_ENABLED_KEY;
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_STATE_CONTEXT_ENABLED_KEY; import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_STATE_CONTEXT_ENABLED_KEY;
import static org.apache.hadoop.hdfs.server.namenode.NameNodeAdapter.getServiceState; import static org.apache.hadoop.hdfs.server.namenode.NameNodeAdapter.getServiceState;
import static org.apache.hadoop.hdfs.server.namenode.ha.ObserverReadProxyProvider.*; import static org.apache.hadoop.hdfs.server.namenode.ha.ObserverReadProxyProvider.*;
@ -215,6 +216,65 @@ public void testSimpleRead() throws Exception {
assertSentTo(0); assertSentTo(0);
} }
@Test
public void testConfigStartup() throws Exception {
int nnIdx = dfsCluster.getNumNameNodes() - 1;
// Transition all current observers to standby
for (int i = 0; i < dfsCluster.getNumNameNodes(); i++) {
if (dfsCluster.getNameNode(i).isObserverState()) {
dfsCluster.transitionToStandby(i);
}
}
// Confirm that the namenode at nnIdx is standby
assertTrue("The NameNode is observer despite being transitioned to standby",
dfsCluster.getNameNode(nnIdx).isStandbyState());
// Restart the NameNode with observer startup option as false
dfsCluster.getConfiguration(nnIdx)
.setBoolean(DFS_NAMENODE_OBSERVER_ENABLED_KEY, false);
dfsCluster.restartNameNode(nnIdx);
// Verify that the NameNode is not in Observer state
dfsCluster.waitNameNodeUp(nnIdx);
assertTrue("The NameNode started as Observer despite "
+ DFS_NAMENODE_OBSERVER_ENABLED_KEY + " being false",
dfsCluster.getNameNode(nnIdx).isStandbyState());
dfs.mkdir(testPath, FsPermission.getDefault());
assertSentTo(0);
// The first request goes to the active because it has not refreshed yet;
// the second would go to the observer if it was not in standby
dfsCluster.rollEditLogAndTail(0);
dfs.getFileStatus(testPath);
dfs.getFileStatus(testPath);
assertSentTo(0);
Path testPath2 = new Path(testPath, "test2");
// Restart the NameNode with the observer startup option as true
dfsCluster.getConfiguration(nnIdx)
.setBoolean(DFS_NAMENODE_OBSERVER_ENABLED_KEY, true);
dfsCluster.restartNameNode(nnIdx);
// Check that the NameNode is in Observer state
dfsCluster.waitNameNodeUp(nnIdx);
assertTrue("The NameNode did not start as Observer despite "
+ DFS_NAMENODE_OBSERVER_ENABLED_KEY + " being true",
dfsCluster.getNameNode(nnIdx).isObserverState());
dfs.mkdir(testPath2, FsPermission.getDefault());
assertSentTo(0);
// The first request goes to the active because it has not refreshed yet;
// the second will properly go to the observer
dfsCluster.rollEditLogAndTail(0);
dfs.getFileStatus(testPath2);
dfs.getFileStatus(testPath2);
assertSentTo(nnIdx);
}
@Test @Test
public void testFailover() throws Exception { public void testFailover() throws Exception {
Path testPath2 = new Path(testPath, "test2"); Path testPath2 = new Path(testPath, "test2");