[
https://issues.apache.org/jira/browse/YARN-11391?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17646454#comment-17646454
]
ASF GitHub Bot commented on YARN-11391:
---------------------------------------
slfan1989 commented on code in PR #5213:
URL: https://github.com/apache/hadoop/pull/5213#discussion_r1046700624
##########
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/HAUtil.java:
##########
@@ -262,6 +301,179 @@ public static String getRMHAId(Configuration conf) {
return currentRMId;
}
+ /**
+ * This function resolves all RMIds with their address. For multi-A DNS
records,
+ * it will resolve all of them, and generate a new Id for each of them.
+ *
+ * @param conf Configuration
+ * @return Map key as RMId, value as its address
+ */
+ public static Map<String, InetSocketAddress> getResolvedRMIdPairs(
+ Configuration conf) {
+ boolean resolveNeeded = conf.getBoolean(
+ YarnConfiguration.RESOLVE_RM_ADDRESS_NEEDED_KEY,
+ YarnConfiguration.RESOLVE_RM_ADDRESS_NEEDED_DEFAULT);
+ boolean requireFQDN = conf.getBoolean(
+ YarnConfiguration.RESOLVE_RM_ADDRESS_TO_FQDN,
+ YarnConfiguration.RESOLVE_RM_ADDRESS_TO_FQDN_DEFAULT);
+ // In case client using DIFFERENT addresses for each service address
+ // need to categorize them first
+ Map<List<String>, List<String>> addressesConfigKeysMap = new HashMap<>();
+ Collection<String> rmIds = getOriginalRMHAIds(conf);
+ for (String configKey : RM_ADDRESS_CONFIG_KEYS) {
+ List<String> addresses = new ArrayList<>();
+ for (String rmId : rmIds) {
+ String keyToRead = addSuffix(configKey, rmId);
+ InetSocketAddress address = getInetSocketAddressFromString(
+ conf.get(keyToRead));
+ if (address != null) {
+ addresses.add(address.getHostName());
+ }
+ }
+ Collections.sort(addresses);
+ List<String> configKeysOfTheseAddresses =
addressesConfigKeysMap.get(addresses);
+ if (configKeysOfTheseAddresses == null) {
+ configKeysOfTheseAddresses = new ArrayList<>();
+ addressesConfigKeysMap.put(addresses, configKeysOfTheseAddresses);
+ }
+ configKeysOfTheseAddresses.add(configKey);
+ }
+ // We need to resolve and override by group (categorized by their input
host)
+ // But since the function is called from "getRMHAId",
+ // this function would only return value which is corresponded to
YarnConfiguration.RM_ADDRESS
+ Map<String, InetSocketAddress> ret = null;
+ for (List<String> configKeys : addressesConfigKeysMap.values()) {
+ Map<String, InetSocketAddress> res = getResolvedIdPairs(conf,
resolveNeeded, requireFQDN, getOriginalRMHAIds(conf),
+ configKeys.get(0), YarnConfiguration.RM_HA_IDS, configKeys);
+ if (configKeys.contains(YarnConfiguration.RM_ADDRESS)) {
+ ret = res;
+ }
+ }
+ return ret;
+ }
+
+ private static Map<String, InetSocketAddress> getResolvedIdPairs(
+ Configuration conf, boolean resolveNeeded, boolean requireFQDN,
Collection<String> ids,
+ String configKey, String configKeyToReplace, List<String>
listOfConfigKeysToReplace) {
+ Map<String, InetSocketAddress> idAddressPairs = new HashMap<>();
+ Map<String, String> generatedIdToOriginalId = new HashMap<>();
+ for (String id : ids) {
+ String key = addSuffix(configKey, id);
+ String addr = conf.get(key); // string with port
+ InetSocketAddress address = getInetSocketAddressFromString(addr);
+ if (address == null) {
+ continue;
+ }
+ if (resolveNeeded) {
+ if (dnr == null) {
+ setDnrByConfiguration(conf);
+ }
+ // If the address needs to be resolved, get all of the IP addresses
+ // from this address and pass them into the map
+ LOG.info("Multi-A domain name " + addr +
+ " will be resolved by " + dnr.getClass().getName());
+ int port = address.getPort();
+ String[] resolvedHostNames;
+ try {
+ resolvedHostNames = dnr.getAllResolvedHostnameByDomainName(
+ address.getHostName(), requireFQDN);
+ } catch (UnknownHostException e) {
+ LOG.warn("Exception in resolving socket address "
+ + address.getHostName(), e);
+ continue;
+ }
+ LOG.info("Resolved addresses for " + addr +
+ " is " + Arrays.toString(resolvedHostNames));
+ if (resolvedHostNames == null || resolvedHostNames.length < 1) {
+ LOG.warn("Cannot resolve from address " + address.getHostName());
+ } else {
+ // If multiple address resolved, corresponding id needs to be created
+ for (int i = 0; i < resolvedHostNames.length; i++) {
+ String generatedRMId = id + "_resolved_" + (i + 1);
+ idAddressPairs.put(generatedRMId,
+ new InetSocketAddress(resolvedHostNames[i], port));
+ generatedIdToOriginalId.put(generatedRMId, id);
+ }
+ }
+ overrideIdsInConfiguration(
+ idAddressPairs, generatedIdToOriginalId, configKeyToReplace,
+ listOfConfigKeysToReplace, conf);
+ } else {
+ idAddressPairs.put(id, address);
+ }
+ }
+ return idAddressPairs;
+ }
+
+ /**
+ * This function override all RMIds and their addresses by the input Map.
+ *
+ * @param idAddressPairs key as Id, value as its address
+ * @param generatedIdToOriginalId key as generated rmId from multi-A,
+ * value as its original input Id
+ * @param configKeyToReplace key to replace
+ * @param listOfConfigKeysToReplace list of keys to replace/add
+ * @param conf Configuration
+ */
+ synchronized static void overrideIdsInConfiguration(
+ Map<String, InetSocketAddress> idAddressPairs,
+ Map<String, String> generatedIdToOriginalId,
+ String configKeyToReplace, List<String> listOfConfigKeysToReplace,
+ Configuration conf) {
+ Collection<String> currentIds = getRMHAIds(conf);
+ Set<String> resolvedIds = new HashSet<>(idAddressPairs.keySet());
+ // override rm-ids
+ if (originalRMIDs == null) {
+ originalRMIDs = currentIds;
+ }
+ // if it is already resolved, we need to form a superset
+ resolvedIds.addAll((currentIds));
+ resolvedIds.removeAll(generatedIdToOriginalId.values());
+ conf.setStrings(configKeyToReplace,
+ resolvedIds.toArray(new String[0]));
+ // override/add address configuration entries for each rm-id
+ for (Map.Entry<String, InetSocketAddress> entry :
idAddressPairs.entrySet()) {
+ String rmId = entry.getKey();
+ String addr = entry.getValue().getHostName();
+ String originalRMId = generatedIdToOriginalId.get(rmId);
+ if (originalRMId != null) {
+ // for each required configKeys, get its port and then set it back
+ for (String configKey : listOfConfigKeysToReplace) {
+ String keyToRead = addSuffix(configKey, originalRMId);
+ InetSocketAddress originalAddress = getInetSocketAddressFromString(
+ conf.get(keyToRead));
+ if (originalAddress == null) {
+ LOG.warn("Missing configuration for key " + keyToRead);
+ continue;
+ }
+ int port = originalAddress.getPort();
+ String keyToWrite = addSuffix(configKey, rmId);
+ conf.setSocketAddr(keyToWrite, new InetSocketAddress(addr, port));
+ }
+ }
+ }
+ }
+
+ /**
+ * Helper function to create InetsocketAddress from string address.
+ *
+ * @param addr string format of address accepted by NetUtils.createSocketAddr
+ * @return InetSocketAddress of input, would return null upon any kinds of
invalid inout
+ */
+ public static InetSocketAddress getInetSocketAddressFromString(String addr) {
+ if (addr == null) {
+ return null;
+ }
+ InetSocketAddress address;
+ try {
+ address = NetUtils.createSocketAddr(addr);
+ } catch (Exception e) {
+ LOG.warn("Exception in creating socket address " + addr, e);
Review Comment:
{}
> Support using DNS to resolve yarn services to IP addresses
> ----------------------------------------------------------
>
> Key: YARN-11391
> URL: https://issues.apache.org/jira/browse/YARN-11391
> Project: Hadoop YARN
> Issue Type: New Feature
> Reporter: Shuyi Zhang
> Priority: Major
> Labels: pull-request-available
>
> We have been using A-record (hostname) for discovering YARN control
> planes(RM, JHS) from both the server and client sides. The components
> discover each other using hostnames (DNS A-records) which are preconfigured
> in YARN configurations (mapred-site.xml and yarn-site.xml). However, the
> hard-coded address mapping is prohibitive to perform appropriate failure
> recovery and node replacement. Any host replacement, adding, or removing
> requires client integration, which is a quite painful process.
> It is essential to find a solution where the discovery configuration of
> different components in the cluster stays intact and is able to resolve with
> the latest hostname/records.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]