Skip to content

Commit 3804bfc

Browse files
committed
Read ec2 discovery address from aws instance tags
This PR adds a new option for `host_type`: `tag:TAGNAME` where `TAGNAME` is the tag field you defined for your ec2 instance. For example if you defined a tag `my-elasticsearch-host` in ec2 and set it to `myhostname1.mydomain.com`, then setting `host_type: tag:my-elasticsearch-host` will tell Discovery Ec2 plugin to read the host name from the `my-elasticsearch-host` tag. In this case, it will be resolved to `myhostname1.mydomain.com`. Closes #22566.
1 parent 719e75b commit 3804bfc

File tree

4 files changed

+81
-26
lines changed

4 files changed

+81
-26
lines changed

docs/plugins/discovery-ec2.asciidoc

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,18 @@ The following are a list of settings (prefixed with `discovery.ec2`) that can fu
172172

173173
`host_type`::
174174

175-
The type of host type to use to communicate with other instances. Can be
176-
one of `private_ip`, `public_ip`, `private_dns`, `public_dns`. Defaults to
177-
`private_ip`.
175+
+
176+
--
177+
The type of host type to use to communicate with other instances. Can be
178+
one of `private_ip`, `public_ip`, `private_dns`, `public_dns` or `tag:TAGNAME` where
179+
`TAGNAME` is the tag field you defined for your ec2 instance.
180+
181+
For example if you defined a tag `my-elasticsearch-host` in ec2 and set it to `myhostname1.mydomain.com`, then
182+
setting `host_type: tag:my-elasticsearch-host` will tell Discovery Ec2 plugin to read the host name from the
183+
`my-elasticsearch-host` tag. In this case, it will be resolved to `myhostname1.mydomain.com`.
184+
185+
Defaults to `private_ip`.
186+
--
178187

179188
`availability_zones`::
180189

plugins/discovery-ec2/src/main/java/org/elasticsearch/cloud/aws/AwsEc2Service.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -164,20 +164,21 @@ interface CLOUD_EC2 {
164164
* Defines discovery settings for ec2. Starting with discovery.ec2.
165165
*/
166166
interface DISCOVERY_EC2 {
167-
enum HostType {
168-
PRIVATE_IP,
169-
PUBLIC_IP,
170-
PRIVATE_DNS,
171-
PUBLIC_DNS
167+
class HostType {
168+
public static final String PRIVATE_IP = "private_ip";
169+
public static final String PUBLIC_IP = "public_ip";
170+
public static final String PRIVATE_DNS = "private_dns";
171+
public static final String PUBLIC_DNS = "public_dns";
172+
public static final String TAG_PREFIX = "tag:";
172173
}
173174

174175
/**
175176
* discovery.ec2.host_type: The type of host type to use to communicate with other instances.
176-
* Can be one of private_ip, public_ip, private_dns, public_dns. Defaults to private_ip.
177+
* Can be one of private_ip, public_ip, private_dns, public_dns or meta:XXXX where
178+
* XXXX is the metadata field name we will read the address from. Defaults to private_ip.
177179
*/
178-
Setting<HostType> HOST_TYPE_SETTING =
179-
new Setting<>("discovery.ec2.host_type", HostType.PRIVATE_IP.name(), s -> HostType.valueOf(s.toUpperCase(Locale.ROOT)),
180-
Property.NodeScope);
180+
Setting<String> HOST_TYPE_SETTING =
181+
new Setting<>("discovery.ec2.host_type", HostType.PRIVATE_IP, Function.identity(), Property.NodeScope);
181182
/**
182183
* discovery.ec2.any_group: If set to false, will require all security groups to be present for the instance to be used for the
183184
* discovery. Defaults to true.

plugins/discovery-ec2/src/main/java/org/elasticsearch/discovery/ec2/AwsEc2UnicastHostsProvider.java

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.amazonaws.services.ec2.model.GroupIdentifier;
2828
import com.amazonaws.services.ec2.model.Instance;
2929
import com.amazonaws.services.ec2.model.Reservation;
30+
import com.amazonaws.services.ec2.model.Tag;
3031
import org.apache.logging.log4j.message.ParameterizedMessage;
3132
import org.apache.logging.log4j.util.Supplier;
3233
import org.elasticsearch.Version;
@@ -51,6 +52,11 @@
5152
import static java.util.Collections.disjoint;
5253
import static java.util.Collections.emptyMap;
5354
import static java.util.Collections.emptySet;
55+
import static org.elasticsearch.cloud.aws.AwsEc2Service.DISCOVERY_EC2.HostType.TAG_PREFIX;
56+
import static org.elasticsearch.cloud.aws.AwsEc2Service.DISCOVERY_EC2.HostType.PRIVATE_DNS;
57+
import static org.elasticsearch.cloud.aws.AwsEc2Service.DISCOVERY_EC2.HostType.PRIVATE_IP;
58+
import static org.elasticsearch.cloud.aws.AwsEc2Service.DISCOVERY_EC2.HostType.PUBLIC_DNS;
59+
import static org.elasticsearch.cloud.aws.AwsEc2Service.DISCOVERY_EC2.HostType.PUBLIC_IP;
5460

5561
public class AwsEc2UnicastHostsProvider extends AbstractComponent implements UnicastHostsProvider {
5662

@@ -66,7 +72,7 @@ public class AwsEc2UnicastHostsProvider extends AbstractComponent implements Uni
6672

6773
private final Set<String> availabilityZones;
6874

69-
private final DISCOVERY_EC2.HostType hostType;
75+
private final String hostType;
7076

7177
private final DiscoNodesCache discoNodes;
7278

@@ -149,19 +155,25 @@ && disjoint(securityGroupIds, groups)) {
149155
}
150156

151157
String address = null;
152-
switch (hostType) {
153-
case PRIVATE_DNS:
154-
address = instance.getPrivateDnsName();
155-
break;
156-
case PRIVATE_IP:
157-
address = instance.getPrivateIpAddress();
158-
break;
159-
case PUBLIC_DNS:
160-
address = instance.getPublicDnsName();
161-
break;
162-
case PUBLIC_IP:
163-
address = instance.getPublicIpAddress();
164-
break;
158+
if (hostType.equals(PRIVATE_DNS)) {
159+
address = instance.getPrivateDnsName();
160+
} else if (hostType.equals(PRIVATE_IP)) {
161+
address = instance.getPrivateIpAddress();
162+
} else if (hostType.equals(PUBLIC_DNS)) {
163+
address = instance.getPublicDnsName();
164+
} else if (hostType.equals(PUBLIC_IP)) {
165+
address = instance.getPublicIpAddress();
166+
} else if (hostType.startsWith(TAG_PREFIX)) {
167+
// Reading the node host from its metadata
168+
String tagName = hostType.substring(TAG_PREFIX.length());
169+
logger.debug("reading hostname from [{}] instance tag", tagName);
170+
List<Tag> tags = instance.getTags();
171+
for (Tag tag : tags) {
172+
if (tag.getKey().equals(tagName)) {
173+
address = tag.getValue();
174+
logger.debug("using [{}] as the instance address", address);
175+
}
176+
}
165177
}
166178
if (address != null) {
167179
try {

plugins/discovery-ec2/src/test/java/org/elasticsearch/discovery/ec2/Ec2DiscoveryTests.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.junit.Before;
4242
import org.junit.BeforeClass;
4343

44+
import java.net.InetAddress;
4445
import java.net.UnknownHostException;
4546
import java.util.ArrayList;
4647
import java.util.Collections;
@@ -51,6 +52,7 @@
5152
import static org.hamcrest.Matchers.containsString;
5253
import static org.hamcrest.Matchers.hasSize;
5354
import static org.hamcrest.Matchers.is;
55+
import static org.hamcrest.Matchers.isOneOf;
5456

5557
public class Ec2DiscoveryTests extends ESTestCase {
5658

@@ -259,6 +261,37 @@ public void testFilterByMultipleTags() throws InterruptedException {
259261
assertThat(discoveryNodes, hasSize(prodInstances));
260262
}
261263

264+
public void testReadHostFromTag() throws InterruptedException, UnknownHostException {
265+
int nodes = randomIntBetween(5, 10);
266+
267+
String[] addresses = new String[nodes];
268+
269+
for (int node = 0; node < nodes; node++) {
270+
addresses[node] = "192.168.0." + (node + 1);
271+
poorMansDNS.put("bar_" + node, new TransportAddress(InetAddress.getByName(addresses[node]), 9300));
272+
}
273+
274+
Settings nodeSettings = Settings.builder()
275+
.put(DISCOVERY_EC2.HOST_TYPE_SETTING.getKey(), "tag:foo")
276+
.build();
277+
278+
List<List<Tag>> tagsList = new ArrayList<>();
279+
280+
for (int node = 0; node < nodes; node++) {
281+
List<Tag> tags = new ArrayList<>();
282+
tags.add(new Tag("foo", "bar_" + node));
283+
tagsList.add(tags);
284+
}
285+
286+
logger.info("started [{}] instances", nodes);
287+
List<DiscoveryNode> discoveryNodes = buildDynamicNodes(nodeSettings, nodes, tagsList);
288+
assertThat(discoveryNodes, hasSize(nodes));
289+
for (DiscoveryNode discoveryNode : discoveryNodes) {
290+
assertThat(discoveryNode.getHostName(), isOneOf(addresses));
291+
}
292+
}
293+
294+
262295
abstract class DummyEc2HostProvider extends AwsEc2UnicastHostsProvider {
263296
public int fetchCount = 0;
264297
public DummyEc2HostProvider(Settings settings, TransportService transportService, AwsEc2Service service) {

0 commit comments

Comments
 (0)