[macOS] Elasticsearch – Unrecognized VM option ‘UseConcMarkSweepGC’

Sur mon ordinateur de travail, après une mise à jour avec brew update suivi d’un brew upgrade, il m’était devenu impossible de démarrer elasticsearch. L’exécution se terminait systématiquement en erreur avec le message : Unrecognized VM option 'UseConcMarkSweepGC'. Après quelques recherches, voici la solution qui a permis le démarrage du programme sans erreur.

Éditer le fichier /usr/local/etc/elasticsearch/jvm.options et commenter les lignes suivantes :

-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly

Pour remplacer ces trois lignes, ajouter les lignes suivantes :

8-13:-XX:+UseConcMarkSweepGC
8-13:-XX:CMSInitiatingOccupancyFraction=75
8-13:-XX:+UseCMSInitiatingOccupancyOnly

elasticsearch devrait désormais démarrer correctement.

GCP Private Kubernetes cluster for Helm installation of Elasticsearch

In this article, I will list the steps needed to deploy an Elasticsearch cluster on a private Google Cloud Platform (GCP) Kubernetes cluster using Helm, from creating a docker image with Elasticsearch, to the creation of a private Kubernetes cluster and more.

Let’s begin.

Continuer la lecture de « GCP Private Kubernetes cluster for Helm installation of Elasticsearch »

Découverte de la gestion de log avec ELK

Dans le cadre de mon stage, je m’intéresse actuellement au solution de monitoring et j’ai donc eu l’occasion de tester le triplet Elasticsearch Logstash Kibana connu sous l’abréviation ELK. Logstash permet d’agréger simplement des logs provenant de différentes sources, Elasticsearch s’occupe de les stocker et de les rendre disponibles et enfin Kibana les affiche sur un dashboard hautement personnalisable. Les instructions qui suivent m’ont donc permis d’avoir un rapide aperçu du fonctionnement de la solution ELK en local et dans un cas très simple de gestion de logs système.

Récupération des logiciels

wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.0.1.tar.gz
wget https://download.elasticsearch.org/logstash/logstash/logstash-1.3.3-flatjar.jar
wget https://download.elasticsearch.org/kibana/kibana/kibana-3.0.0milestone5.tar.gz

Extraction

tar xvf elasticsearch-1.0.1.tar.gz
tar xvf kibana-3.0.0milestone5.tar.gz

Elasticsearch

cd elasticsearch-1.0.1/

La configuration elasticsearch.yml se situe dans config/. Il n’est pas nécessaire d’y toucher pour un test en local, on pourrait toutefois modifier les paramètres cluster.name et node.name pour personnaliser l’installation.

Démarrer Elasticsearch:

./bin/elasticsearch

Logstash

Création d’un fichier de configuration logstash.conf:

touch logstash.conf

Nous allons lire les fichiers de log du système, de ce fait, il pourrait être nécessaire de lancer Logstash en root pour que celui-ci puisse lire les fichiers de logs. Cette solution n’est à utiliser que pendant la phase de test.

Contenu du fichier:

input {
    file {
        type => "linux-syslog"
        path => [ "/var/log/*.log", "/var/log/messages", "/var/log/syslog" ]
    }
}
output {
    stdout { }
    elasticsearch_http {
        host => "127.0.0.1"
    }
}

Documentation pour le paramètre elasticsearch_http.

Démarrer Logstash:

sudo java -jar logstash-1.3.3-flatjar.jar agent -f logstash.conf

Les nouveaux logs devraient donc maintenant être récupérés par Logstash et stockés par Elasticsearch. Nous donc pouvoir les visualiser avec Kibana.

Kibana

cd kibana-3.0.0milestone5/

Éditer le fichier config.js et changer la ligne:

elasticsearch: "http://"+window.location.hostname+":9200",

en

elasticsearch: "http://127.0.0.1:9200",

Cette modification nous permet d’ouvrir le fichier index.html directement dans notre navigateur pour accéder à Kibana sans avoir besoin de mettre en place un serveur comme Apache pour servir les fichiers.

Résultat

KibanaL’ajout d’un mécanisme d’authentification pour l’accès à Kibana peut être réalisé simplement en utilisant le projet fangli/kibana-authentication-proxy.

ElasticSearch and the Mystery of Auto-completion

Few months ago, I was looking for information concerning auto-completion with ElasticSearch as a source. I found many solutions, but none of them really fit my needs. Nevertheless, it helped me building my request.

What’s the situation Doc?

I needed to be able to extract values from an indexed field in ElasticSearch according to a group of letters (user input). In fact, my indexed document contains a field named map which is an array of string. The idea is the following: if the user is looking for the value « name » for instance, let’s say he will first type « na ». So here we must be able to suggest searches to the user. Furthermore, with this 2 letters, we must proposed existing fields like « name », « native » or « nature ».

I’m using Elastical to interact with ElasticSearch.
First, I’m building a regex which will be used later in the request.

var search = req.body.searched.toLowerCase(),
firstLetter = search.charAt(0),
rest = req.body.searched.slice(1),
reg = "^["+firstLetter+firstLetter.toUpperCase()+"]"+rest+".*";

The regex is build to match with both an upper case char or a lower case one in first position.

What about the request?

var request = {
  query: {
    query_string: {
      default_field: "map",
      default_operator: "AND",
      query: req.body.searched+"*"
    }
  },
  facets:{
    map:{
      terms:{
        field: "map.exact",
        regex: reg,
        size: 10
      }
    }
  }
}

First, I’m asking ElasticSearch to retrieve all documents which match req.body.searched+ »* » where req.body.searched contains the user input. I’ve change the default operator to « AND » rather than « OR » in order to be able to deal with fields like « Nom de la gare » or « Name of the dog ». By default, ElasticSearch uses the « OR » operator, so it will ask for « name » OR « of » OR « the » OR « dog »; which is not what I wanted.

Then, I’m using facets to retrieve values in the field map of found documents matching the given regex. I’m using map.exact for the same reason I must use the « AND » operator.

This request works great with on the tests I’ve made. Remains to be seen if it can handle big indexes.

I can now ask ElasticSearch with Elastical and build a clean response:

elastical.search(request, function (err, results, full) {
  var terms = [];
  async.forEach(full.facets.map.terms, function(data, callback) {
    terms.push(data.term);
    callback();
  }, function(err) {
    res.send(terms);
  });
});

Node-Elastical: Implement stats function

Recently, I had to find the size of an index in Elasticsearch. I could have just built my query using request like this:

var request = require('request');
request.get('http://localhost:9200/' + myIndex + '/_stats'
  , function (err, res, body) {
    console.log(res._all.primaries.store.size_in_bytes);
});

Fast and easy. Since it’s not available yet in node-elastical, I found it better to add this functionality so that other people can use it. Implementing the stats function wasn’t difficult. It just require parsing options to create the right url and then making the request (with request) to Elasticsearch. I used the Indices Stats API documentation to create the function.

In file client.js

stats: function (options, callback) {
  var query = [],
  url = '',
  hasOptions;

  if (typeof options === 'function') {
    callback = options;
    options = {};
  }
  //Create a copy of options so we can modify it.
  options = util.merge(options || {});

  if (options.index) {
    url = '/' + encode(Array.isArray(options.index) ?
      options.index.join(',') : options.index);
    delete options.index;
    //Look for types only if there is an index
    if (options.types) {
      query.push(encode('types') + '=' + encode(
        Array.isArray(options.types) ?
        options.types.join(',') : options.types));
    }
    delete options.types;
  }

  url += '/_stats';

  util.each(options, function (value, name) {
    if (value === true || value === false) {
      value = value ? '1' : '0';
    }

    query.push(encode(name) + '=' + encode(value));
  });

  if (query.length) {
    url += '?' + query.join('&');
  }

  this._request(url, {
    method: 'GET'
  }, function (err, res) {
    if(err) { return callback(err, null, res), undefined; }
    callback(null, res);
  });
},
In file index.js
stats: function (options, callback) {
  if (typeof options === 'function') {
    callback = options;
    options = {};
  }
  this.client.stats(util.merge(options,{index: this.name}), callback);
},