Skip to content

Conversation

@alb3rtobr
Copy link
Contributor

AS A geode contributor
I WANT TO be able to start members with option --bind-address=0.0.0.0, --bind-address=:: or --bind-address=*
SO THAT all TCP endpoints are bound to all interfaces.

It is not currently possible to start cluster members binding to all interfaces. That is using --bind-address=0.0.0.0 for ipv4 or --bind-address=:: for ipv6.

Geode binds the locator and server traffic port by default to 0.0.0.0, but the membership ports are bound by default to the local address.

Changing the default membership binding is not the best option, as it could cause problems in existing Geode deployments. But using --bind-address=0.0.0.0, --bind-address=:: or --bind-address=* should be accepted.

There is a use case that needs this binding, that is using Istio with Geode. One of the requirements set by Istio towards applications trying to integrate with it is that the application listening ports need to be bound to 0.0.0.0 address (which listens on all interfaces).

It is currently not possible to start a cluster using wildcard address due to if --bind-address is specified, its value will be used for all tcp endpoints and the udp membership endpoint created by JGroups. And as JGroups does not accept binding to all addresses, and exception is thrown. This behavior can be verified with WildcardAddressBindingDUnitTest.java tests.

Copy link
Contributor

@dschneider-pivotal dschneider-pivotal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see any problems with this change. Consider the minor refactor I suggested

@mhansonp
Copy link
Contributor

mhansonp commented May 6, 2021

Great description!

@alb3rtobr
Copy link
Contributor Author

@dschneider-pivotal I have implemented your suggestion. I was waiting some days to do it in case more reviews with suggestions were added. Thanks!

@alb3rtobr
Copy link
Contributor Author

CI failed due to flaky test (https://issues.apache.org/jira/browse/GEODE-9242 )

@alb3rtobr alb3rtobr force-pushed the feature/GEODE-9235 branch from 886ac86 to f2ef6cd Compare June 23, 2021 08:55
@alb3rtobr
Copy link
Contributor Author

rebase done in order to fix conflicts

Copy link
Contributor

@Bill Bill left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great PR @alb3rtobr !! In addition to comments and requests below please update the command-line options help for LocatorLauncher (bind-address) and ServerLauncher (bind-address, server-bind-address).

The bigger issue is that I don't see a test that verifies that if --bind-address=* on a multi-homed host, that both (health monitor) and (client's cache) services bind on all interfaces. I realize this isn't possible in a plain old DUnit test. But what about a Dockerized one along the lines of SingleServerSNIAcceptanceTest?

FYI and for other reviewers, this is my summary of endpoint configuration before/after this ticket:

image

}

public static boolean isWildcardAddress(String address) {
return "0.0.0.0".equals(address) || "::".equals(address) || isWildcardCharacter(address);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first two clauses in the disjunction reiterate logic already in InetAddress.isAnyLocalAddress(). Is there a reason to not construct an InetAddress and use isAnyLocalAddress()?

It's documented to do this (and the two subclasses for IPV4 and IPV6 seem to do the right thing):

    /**
     * Utility routine to check if the InetAddress in a wildcard address.
     * @return a {@code boolean} indicating if the Inetaddress is
     *         a wildcard address.
     * @since 1.4
     */
    public boolean isAnyLocalAddress() {
        return false;
    }

}
}
} else {
if (isWildcardAddress(host.toString())) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please reduce one level of nesting by moving this if up as an else if. Then the return isLocalHost… could be its own else block as before this PR.

return "0.0.0.0".equals(address) || "::".equals(address) || isWildcardCharacter(address);
}

public static boolean isWildcardCharacter(String address) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this method returns true if the string is the wildcard character defined ServerLauncher and LocatorLauncher's --bind-address (command line parameter).

Please add method-level javadoc explaining the context in which this is a "wildcard character".

Need same explanation of context in javadoc on isWildcardAddress() too.

address = LocalHostUtil.getAnyLocalAddress();
} else {
address = InetAddress.getByName(addressString);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If no bind address is specified we set bindAddress to null. Apparently, elsewhere in the code, we will interpret that null as a wildcard (per the documentation for the gfsh start locator --bind-address option.

How come we have two different paths in this method? Shouldn't we do the same thing if the user specifies * as if the user specifies nothing at all?

Properties gemfireProperties = new Properties();

StartMemberUtils.setPropertyIfNotNull(gemfireProperties, ConfigurationProperties.BIND_ADDRESS,
bindAddress);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought it was odd that we had to call setPropertyIfNotNull() in this method (doStartLocator()) but we did not over in StartServerCommand.doStartServer(). Looks like it was already being called over in that other method.

Does that mean that before this code change here, we had a bug where gfsh start locator would ignore the bind address (before this PR)?

serverSocket = createServerSocket(localAddress.getInetAddress(),
services.getConfig().getMembershipPortRange());
InetAddress address = localAddress.getInetAddress();
String bindAddrStr = services.getConfig().getBindAddress();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh good catch remembering to fix the health monitor endpoint too!

String str = config.getBindAddress();
// JGroups UDP protocol requires a bind address
if (str == null || str.length() == 0) {
if (str == null || str.length() == 0 || LocalHostUtil.isWildcardAddress(str)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes!

@alb3rtobr alb3rtobr marked this pull request as draft July 28, 2021 13:56
@alb3rtobr
Copy link
Contributor Author

Thanks for the review @Bill . I will try the dockerized test. In the meanwhile Im moving the PR to draft.

@alb3rtobr alb3rtobr closed this Oct 21, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants