Filtering by tags

-----------------

The GCE discovery can also filter machines to include in the cluster based on tags using `discovery.gce.tags` settings.
For example, setting `discovery.gce.tags` to `dev` will only filter instances having a tag set to `dev`. Several tags
set will require all of those tags to be set for the instance to be included.

One practical use for tag filtering is when an GCE cluster contains many nodes that are not running
elasticsearch. In this case (particularly with high ping_timeout values) there is a risk that a new node's discovery
phase will end before it has found the cluster (which will result in it declaring itself master of a new cluster
with the same name - highly undesirable). Adding tag on elasticsearch GCE nodes and then filtering by that
tag will resolve this issue.

Add your tag when building the new instance:

```sh
gcutil --project=es-cloud addinstance myesnode1 --service_account_scope=compute-rw --persistent_boot_disk \
       --tags=elasticsearch,dev
```

Then, define it in `elasticsearch.yml`:

```yaml
  cloud:
      gce:
          project_id: es-cloud
          zone: europe-west1-a
  discovery:
          type: gce
          gce:
                tags: elasticsearch, dev
```
Closes #2.
This commit is contained in:
David Pilato 2013-06-28 15:44:52 +02:00
parent 5e14147991
commit 703c2b3e82
3 changed files with 91 additions and 2 deletions

View File

@ -243,6 +243,54 @@ gcutil --project=es-cloud deleteinstance myesnode1 myesnode2 --zone=europe-west1
gcutil --project=es-cloud deletedisk boot-myesnode1 boot-myesnode2 --zone=europe-west1-a
```
Filtering by tags
-----------------
The GCE discovery can also filter machines to include in the cluster based on tags using `discovery.gce.tags` settings.
For example, setting `discovery.gce.tags` to `dev` will only filter instances having a tag set to `dev`. Several tags
set will require all of those tags to be set for the instance to be included.
One practical use for tag filtering is when an GCE cluster contains many nodes that are not running
elasticsearch. In this case (particularly with high ping_timeout values) there is a risk that a new node's discovery
phase will end before it has found the cluster (which will result in it declaring itself master of a new cluster
with the same name - highly undesirable). Adding tag on elasticsearch GCE nodes and then filtering by that
tag will resolve this issue.
Add your tag when building the new instance:
```sh
gcutil --project=es-cloud addinstance myesnode1 --service_account_scope=compute-rw --persistent_boot_disk \
--tags=elasticsearch,dev
```
Then, define it in `elasticsearch.yml`:
```yaml
cloud:
gce:
project_id: es-cloud
zone: europe-west1-a
discovery:
type: gce
gce:
tags: elasticsearch, dev
```
Tips
----
If you don't want to repeat the project id each time, you can save it in `~/.gcutil.flags` file using:
```sh
gcutil getproject --project=es-cloud --cache_flag_values
```
`~/.gcutil.flags` file now contains:
```
--project=es-cloud
```
License
-------

View File

@ -63,6 +63,8 @@ public class GceComputeService extends AbstractLifecycleComponent<GceComputeServ
private NetworkService networkService;
private Compute compute;
private final String[] tags;
/** Global instance of the HTTP transport. */
private static HttpTransport HTTP_TRANSPORT;
@ -76,6 +78,11 @@ public class GceComputeService extends AbstractLifecycleComponent<GceComputeServ
settingsFilter.addFilter(new GceSettingsFilter());
this.transportService = transportService;
this.networkService = networkService;
this.tags = settings.getAsArray("discovery.gce.tags");
if (logger.isDebugEnabled()) {
logger.debug("using tags {}", Lists.newArrayList(this.tags));
}
}
/**
@ -105,6 +112,37 @@ public class GceComputeService extends AbstractLifecycleComponent<GceComputeServ
String type = instance.getMachineType();
String image = instance.getImage();
String status = instance.getStatus();
// see if we need to filter by tag
boolean filterByTag = false;
if (tags.length > 0) {
if (instance.getTags() == null || instance.getTags().isEmpty()) {
// If this instance have no tag, we filter it
filterByTag = true;
} else {
// check that all tags listed are there on the instance
for (String tag : tags) {
boolean found = false;
for (String instancetag : instance.getTags().getItems()) {
if (instancetag.equals(tag)) {
found = true;
break;
}
}
if (!found) {
filterByTag = true;
break;
}
}
}
}
if (filterByTag) {
logger.trace("filtering out instance {} based tags {}, not part of {}", name, tags,
instance.getTags().getItems());
continue;
}
String ip_public = null;
String ip_private = null;
@ -133,12 +171,13 @@ public class GceComputeService extends AbstractLifecycleComponent<GceComputeServ
if (ip_private.equals(ipAddress)) {
// We found the current node.
// We can ignore it in the list of DiscoveryNode
logger.debug("current node found. Ignoring {}", ip_private);
logger.debug("current node found. Ignoring {} - {}", name, ip_private);
} else {
TransportAddress[] addresses = transportService.addressesFromString(ip_private);
// we only limit to 1 addresses, makes no sense to ping 100 ports
for (int i = 0; (i < addresses.length && i < UnicastZenPing.LIMIT_PORTS_COUNT); i++) {
logger.trace("adding {}, address {}, transport_address {}", name, ip_private, addresses[i]);
logger.trace("adding {}, type {}, image {}, address {}, transport_address {}, status {}", name, type,
image, ip_private, addresses[i], status);
discoNodes.add(new DiscoveryNode("#cloud-" + name + "-" + i, addresses[i]));
}
}

View File

@ -24,3 +24,5 @@
zone: europe-west1-a
discovery:
type: gce
gce:
tags: elasticsearch, dev